diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a3baac40..d749a65e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,6 +30,7 @@ jobs: - selenium.py - webdriver.py - keycloak.py + - arangodb.py runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 diff --git a/README.rst b/README.rst index ddc4272c..ea6461f1 100644 --- a/README.rst +++ b/README.rst @@ -22,6 +22,7 @@ Currently available features: * ClickHouse container * Microsoft SQL Server container * Generic docker containers +* ArangoDB container * LocalStack * RabbitMQ * Keycloak diff --git a/docs/conf.py b/docs/conf.py index 7270d20d..6077599e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -66,7 +66,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. diff --git a/docs/database.rst b/docs/database.rst index be984370..49d82eeb 100644 --- a/docs/database.rst +++ b/docs/database.rst @@ -1,7 +1,7 @@ Database containers =================== -Allows to spin up database images such as MySQL, PostgreSQL, MariaDB, Oracle XE, MongoDb, ClickHouse or Neo4j. +Allows to spin up database images such as MySQL, PostgreSQL, MariaDB, Oracle XE, MongoDb, ClickHouse, Neo4j or ArangoDB .. autoclass:: testcontainers.mysql.MySqlContainer .. autoclass:: testcontainers.mysql.MariaDbContainer @@ -12,3 +12,4 @@ Allows to spin up database images such as MySQL, PostgreSQL, MariaDB, Oracle XE, .. autoclass:: testcontainers.mssql.SqlServerContainer .. autoclass:: testcontainers.clickhouse.ClickHouseContainer .. autoclass:: testcontainers.neo4j.Neo4jContainer +.. autoclass:: testcontainers.arangodb.ArangoDbContainer diff --git a/requirements.in b/requirements.in index d6f22ece..4309c1d7 100644 --- a/requirements.in +++ b/requirements.in @@ -1,4 +1,4 @@ --e file:.[docker-compose,mysql,oracle,postgresql,selenium,google-cloud-pubsub,mongo,redis,mssqlserver,neo4j,kafka,rabbitmq,clickhouse,keycloak] +-e file:.[docker-compose,mysql,oracle,postgresql,selenium,google-cloud-pubsub,mongo,redis,mssqlserver,neo4j,kafka,rabbitmq,clickhouse,keycloak,arangodb] codecov>=2.1.0 cryptography<37 flake8<3.8.0 # 3.8.0 adds a dependency on importlib-metadata which conflicts with other packages. diff --git a/requirements/3.10.txt b/requirements/3.10.txt index 5ae26cd9..09d9c9fa 100644 --- a/requirements/3.10.txt +++ b/requirements/3.10.txt @@ -26,9 +26,9 @@ babel==2.10.1 # via sphinx bcrypt==3.2.2 # via paramiko -cachetools==5.0.0 +cachetools==5.2.0 # via google-auth -certifi==2021.10.8 +certifi==2022.5.18.1 # via # requests # urllib3 @@ -43,7 +43,7 @@ clickhouse-driver==0.2.3 # via testcontainers codecov==2.1.12 # via -r requirements.in -coverage[toml]==6.3.2 +coverage[toml]==6.4.1 # via # codecov # pytest-cov @@ -71,7 +71,7 @@ dockerpty==0.4.1 # via docker-compose docopt==0.6.2 # via docker-compose -docutils==0.17.1 +docutils==0.18.1 # via sphinx ecdsa==0.17.0 # via python-jose @@ -79,13 +79,13 @@ entrypoints==0.3 # via flake8 flake8==3.7.9 # via -r requirements.in -google-api-core[grpc]==2.7.3 +google-api-core[grpc]==2.8.1 # via google-cloud-pubsub google-auth==2.6.6 # via google-api-core google-cloud-pubsub==1.7.1 # via testcontainers -googleapis-common-protos[grpc]==1.56.0 +googleapis-common-protos[grpc]==1.56.2 # via # google-api-core # grpc-google-iam-v1 @@ -94,13 +94,13 @@ greenlet==1.1.2 # via sqlalchemy grpc-google-iam-v1==0.12.4 # via google-cloud-pubsub -grpcio==1.46.0 +grpcio==1.46.3 # via # google-api-core # googleapis-common-protos # grpc-google-iam-v1 # grpcio-status -grpcio-status==1.46.0 +grpcio-status==1.46.3 # via google-api-core h11==0.13.0 # via wsproto @@ -123,7 +123,7 @@ markupsafe==2.1.1 # via jinja2 mccabe==0.6.1 # via flake8 -neo4j==4.4.3 +neo4j==4.4.4 # via testcontainers outcome==1.1.0 # via trio @@ -133,9 +133,9 @@ packaging==21.3 # pytest # redis # sphinx -paramiko==2.10.4 +paramiko==2.11.0 # via docker -pg8000==1.26.1 +pg8000==1.29.1 # via -r requirements.in pika==1.2.1 # via testcontainers @@ -165,6 +165,8 @@ pyflakes==2.1.1 # via flake8 pygments==2.12.0 # via sphinx +pyjwt==2.4.0 + # via python-arango pymongo==4.1.1 # via testcontainers pymssql==2.2.5 @@ -175,7 +177,7 @@ pynacl==1.5.0 # via paramiko pyopenssl==22.0.0 # via urllib3 -pyparsing==3.0.8 +pyparsing==3.0.9 # via packaging pyrsistent==0.18.1 # via jsonschema @@ -187,11 +189,13 @@ pytest==7.1.2 # pytest-cov pytest-cov==3.0.0 # via -r requirements.in +python-arango==7.3.4 + # via testcontainers python-dotenv==0.20.0 # via docker-compose python-jose==3.3.0 # via python-keycloak -python-keycloak==0.27.0 +python-keycloak==1.5.0 # via testcontainers pytz==2022.1 # via @@ -202,7 +206,7 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==5.4.1 # via docker-compose -redis==4.3.0 +redis==4.3.3 # via testcontainers requests==2.27.1 # via @@ -210,15 +214,19 @@ requests==2.27.1 # docker # docker-compose # google-api-core + # python-arango # python-keycloak + # requests-toolbelt # sphinx +requests-toolbelt==0.9.1 + # via python-arango rsa==4.8 # via # google-auth # python-jose scramp==1.4.1 # via pg8000 -selenium==4.1.5 +selenium==4.2.0 # via testcontainers six==1.16.0 # via @@ -235,7 +243,7 @@ snowballstemmer==2.2.0 # via sphinx sortedcontainers==2.4.0 # via trio -sphinx==4.5.0 +sphinx==5.0.1 # via -r requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx @@ -249,7 +257,7 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -sqlalchemy==1.4.36 +sqlalchemy==1.4.37 # via testcontainers texttable==1.6.4 # via docker-compose @@ -269,6 +277,8 @@ tzlocal==4.2 # via clickhouse-driver urllib3[secure,socks]==1.26.9 # via + # python-arango + # python-keycloak # requests # selenium websocket-client==0.59.0 diff --git a/requirements/3.7.txt b/requirements/3.7.txt index 455fc9e4..ebc2f128 100644 --- a/requirements/3.7.txt +++ b/requirements/3.7.txt @@ -32,9 +32,9 @@ bcrypt==3.2.2 # via paramiko cached-property==1.5.2 # via docker-compose -cachetools==5.0.0 +cachetools==5.2.0 # via google-auth -certifi==2021.10.8 +certifi==2022.5.18.1 # via # requests # urllib3 @@ -49,7 +49,7 @@ clickhouse-driver==0.2.3 # via testcontainers codecov==2.1.12 # via -r requirements.in -coverage[toml]==6.3.2 +coverage[toml]==6.4.1 # via # codecov # pytest-cov @@ -77,7 +77,7 @@ dockerpty==0.4.1 # via docker-compose docopt==0.6.2 # via docker-compose -docutils==0.17.1 +docutils==0.18.1 # via sphinx ecdsa==0.17.0 # via python-jose @@ -85,13 +85,13 @@ entrypoints==0.3 # via flake8 flake8==3.7.9 # via -r requirements.in -google-api-core[grpc]==2.7.3 +google-api-core[grpc]==2.8.1 # via google-cloud-pubsub google-auth==2.6.6 # via google-api-core google-cloud-pubsub==1.7.1 # via testcontainers -googleapis-common-protos[grpc]==1.56.0 +googleapis-common-protos[grpc]==1.56.2 # via # google-api-core # grpc-google-iam-v1 @@ -100,13 +100,13 @@ greenlet==1.1.2 # via sqlalchemy grpc-google-iam-v1==0.12.4 # via google-cloud-pubsub -grpcio==1.46.0 +grpcio==1.46.3 # via # google-api-core # googleapis-common-protos # grpc-google-iam-v1 # grpcio-status -grpcio-status==1.46.0 +grpcio-status==1.46.3 # via google-api-core h11==0.13.0 # via wsproto @@ -117,9 +117,10 @@ idna==3.3 # urllib3 imagesize==1.3.0 # via sphinx -importlib-metadata==4.11.3 +importlib-metadata==4.11.4 # via # jsonschema + # pg8000 # pluggy # pytest # redis @@ -137,7 +138,7 @@ markupsafe==2.1.1 # via jinja2 mccabe==0.6.1 # via flake8 -neo4j==4.4.3 +neo4j==4.4.4 # via testcontainers outcome==1.1.0 # via trio @@ -147,9 +148,9 @@ packaging==21.3 # pytest # redis # sphinx -paramiko==2.10.4 +paramiko==2.11.0 # via docker -pg8000==1.26.1 +pg8000==1.29.1 # via -r requirements.in pika==1.2.1 # via testcontainers @@ -179,6 +180,8 @@ pyflakes==2.1.1 # via flake8 pygments==2.12.0 # via sphinx +pyjwt==2.4.0 + # via python-arango pymongo==4.1.1 # via testcontainers pymssql==2.2.5 @@ -189,7 +192,7 @@ pynacl==1.5.0 # via paramiko pyopenssl==22.0.0 # via urllib3 -pyparsing==3.0.8 +pyparsing==3.0.9 # via packaging pyrsistent==0.18.1 # via jsonschema @@ -201,11 +204,13 @@ pytest==7.1.2 # pytest-cov pytest-cov==3.0.0 # via -r requirements.in +python-arango==7.3.4 + # via testcontainers python-dotenv==0.20.0 # via docker-compose python-jose==3.3.0 # via python-keycloak -python-keycloak==0.27.0 +python-keycloak==1.5.0 # via testcontainers pytz==2022.1 # via @@ -216,7 +221,7 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==5.4.1 # via docker-compose -redis==4.2.2 +redis==4.3.3 # via testcontainers requests==2.27.1 # via @@ -224,15 +229,19 @@ requests==2.27.1 # docker # docker-compose # google-api-core + # python-arango # python-keycloak + # requests-toolbelt # sphinx +requests-toolbelt==0.9.1 + # via python-arango rsa==4.8 # via # google-auth # python-jose scramp==1.4.1 # via pg8000 -selenium==4.1.3 +selenium==4.2.0 # via testcontainers six==1.16.0 # via @@ -249,7 +258,7 @@ snowballstemmer==2.2.0 # via sphinx sortedcontainers==2.4.0 # via trio -sphinx==4.5.0 +sphinx==5.0.1 # via -r requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx @@ -263,7 +272,7 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -sqlalchemy==1.4.36 +sqlalchemy==1.4.37 # via testcontainers texttable==1.6.4 # via docker-compose @@ -289,6 +298,8 @@ tzlocal==4.2 # via clickhouse-driver urllib3[secure,socks]==1.26.9 # via + # python-arango + # python-keycloak # requests # selenium websocket-client==0.59.0 diff --git a/requirements/3.8.txt b/requirements/3.8.txt index 7189bc0b..823b0a9d 100644 --- a/requirements/3.8.txt +++ b/requirements/3.8.txt @@ -30,9 +30,9 @@ backports-zoneinfo==0.2.1 # tzlocal bcrypt==3.2.2 # via paramiko -cachetools==5.0.0 +cachetools==5.2.0 # via google-auth -certifi==2021.10.8 +certifi==2022.5.18.1 # via # requests # urllib3 @@ -47,7 +47,7 @@ clickhouse-driver==0.2.3 # via testcontainers codecov==2.1.12 # via -r requirements.in -coverage[toml]==6.3.2 +coverage[toml]==6.4.1 # via # codecov # pytest-cov @@ -75,7 +75,7 @@ dockerpty==0.4.1 # via docker-compose docopt==0.6.2 # via docker-compose -docutils==0.17.1 +docutils==0.18.1 # via sphinx ecdsa==0.17.0 # via python-jose @@ -83,13 +83,13 @@ entrypoints==0.3 # via flake8 flake8==3.7.9 # via -r requirements.in -google-api-core[grpc]==2.7.3 +google-api-core[grpc]==2.8.1 # via google-cloud-pubsub google-auth==2.6.6 # via google-api-core google-cloud-pubsub==1.7.1 # via testcontainers -googleapis-common-protos[grpc]==1.56.0 +googleapis-common-protos[grpc]==1.56.2 # via # google-api-core # grpc-google-iam-v1 @@ -98,13 +98,13 @@ greenlet==1.1.2 # via sqlalchemy grpc-google-iam-v1==0.12.4 # via google-cloud-pubsub -grpcio==1.46.0 +grpcio==1.46.3 # via # google-api-core # googleapis-common-protos # grpc-google-iam-v1 # grpcio-status -grpcio-status==1.46.0 +grpcio-status==1.46.3 # via google-api-core h11==0.13.0 # via wsproto @@ -115,7 +115,7 @@ idna==3.3 # urllib3 imagesize==1.3.0 # via sphinx -importlib-metadata==4.11.3 +importlib-metadata==4.11.4 # via sphinx iniconfig==1.1.1 # via pytest @@ -129,7 +129,7 @@ markupsafe==2.1.1 # via jinja2 mccabe==0.6.1 # via flake8 -neo4j==4.4.3 +neo4j==4.4.4 # via testcontainers outcome==1.1.0 # via trio @@ -139,9 +139,9 @@ packaging==21.3 # pytest # redis # sphinx -paramiko==2.10.4 +paramiko==2.11.0 # via docker -pg8000==1.26.1 +pg8000==1.29.1 # via -r requirements.in pika==1.2.1 # via testcontainers @@ -171,6 +171,8 @@ pyflakes==2.1.1 # via flake8 pygments==2.12.0 # via sphinx +pyjwt==2.4.0 + # via python-arango pymongo==4.1.1 # via testcontainers pymssql==2.2.5 @@ -181,7 +183,7 @@ pynacl==1.5.0 # via paramiko pyopenssl==22.0.0 # via urllib3 -pyparsing==3.0.8 +pyparsing==3.0.9 # via packaging pyrsistent==0.18.1 # via jsonschema @@ -193,11 +195,13 @@ pytest==7.1.2 # pytest-cov pytest-cov==3.0.0 # via -r requirements.in +python-arango==7.3.4 + # via testcontainers python-dotenv==0.20.0 # via docker-compose python-jose==3.3.0 # via python-keycloak -python-keycloak==0.27.0 +python-keycloak==1.5.0 # via testcontainers pytz==2022.1 # via @@ -208,7 +212,7 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==5.4.1 # via docker-compose -redis==4.2.2 +redis==4.3.3 # via testcontainers requests==2.27.1 # via @@ -216,15 +220,19 @@ requests==2.27.1 # docker # docker-compose # google-api-core + # python-arango # python-keycloak + # requests-toolbelt # sphinx +requests-toolbelt==0.9.1 + # via python-arango rsa==4.8 # via # google-auth # python-jose scramp==1.4.1 # via pg8000 -selenium==4.1.3 +selenium==4.2.0 # via testcontainers six==1.16.0 # via @@ -241,7 +249,7 @@ snowballstemmer==2.2.0 # via sphinx sortedcontainers==2.4.0 # via trio -sphinx==4.5.0 +sphinx==5.0.1 # via -r requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx @@ -255,7 +263,7 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -sqlalchemy==1.4.36 +sqlalchemy==1.4.37 # via testcontainers texttable==1.6.4 # via docker-compose @@ -275,6 +283,8 @@ tzlocal==4.2 # via clickhouse-driver urllib3[secure,socks]==1.26.9 # via + # python-arango + # python-keycloak # requests # selenium websocket-client==0.59.0 diff --git a/requirements/3.9.txt b/requirements/3.9.txt index eef7dbce..8d9d6a15 100644 --- a/requirements/3.9.txt +++ b/requirements/3.9.txt @@ -26,9 +26,9 @@ babel==2.10.1 # via sphinx bcrypt==3.2.2 # via paramiko -cachetools==5.0.0 +cachetools==5.2.0 # via google-auth -certifi==2021.10.8 +certifi==2022.5.18.1 # via # requests # urllib3 @@ -43,7 +43,7 @@ clickhouse-driver==0.2.3 # via testcontainers codecov==2.1.12 # via -r requirements.in -coverage[toml]==6.3.2 +coverage[toml]==6.4.1 # via # codecov # pytest-cov @@ -71,7 +71,7 @@ dockerpty==0.4.1 # via docker-compose docopt==0.6.2 # via docker-compose -docutils==0.17.1 +docutils==0.18.1 # via sphinx ecdsa==0.17.0 # via python-jose @@ -79,13 +79,13 @@ entrypoints==0.3 # via flake8 flake8==3.7.9 # via -r requirements.in -google-api-core[grpc]==2.7.3 +google-api-core[grpc]==2.8.1 # via google-cloud-pubsub google-auth==2.6.6 # via google-api-core google-cloud-pubsub==1.7.1 # via testcontainers -googleapis-common-protos[grpc]==1.56.0 +googleapis-common-protos[grpc]==1.56.2 # via # google-api-core # grpc-google-iam-v1 @@ -94,13 +94,13 @@ greenlet==1.1.2 # via sqlalchemy grpc-google-iam-v1==0.12.4 # via google-cloud-pubsub -grpcio==1.46.0 +grpcio==1.46.3 # via # google-api-core # googleapis-common-protos # grpc-google-iam-v1 # grpcio-status -grpcio-status==1.46.0 +grpcio-status==1.46.3 # via google-api-core h11==0.13.0 # via wsproto @@ -111,7 +111,7 @@ idna==3.3 # urllib3 imagesize==1.3.0 # via sphinx -importlib-metadata==4.11.3 +importlib-metadata==4.11.4 # via sphinx iniconfig==1.1.1 # via pytest @@ -125,7 +125,7 @@ markupsafe==2.1.1 # via jinja2 mccabe==0.6.1 # via flake8 -neo4j==4.4.3 +neo4j==4.4.4 # via testcontainers outcome==1.1.0 # via trio @@ -135,9 +135,9 @@ packaging==21.3 # pytest # redis # sphinx -paramiko==2.10.4 +paramiko==2.11.0 # via docker -pg8000==1.26.1 +pg8000==1.29.1 # via -r requirements.in pika==1.2.1 # via testcontainers @@ -167,6 +167,8 @@ pyflakes==2.1.1 # via flake8 pygments==2.12.0 # via sphinx +pyjwt==2.4.0 + # via python-arango pymongo==4.1.1 # via testcontainers pymssql==2.2.5 @@ -177,7 +179,7 @@ pynacl==1.5.0 # via paramiko pyopenssl==22.0.0 # via urllib3 -pyparsing==3.0.8 +pyparsing==3.0.9 # via packaging pyrsistent==0.18.1 # via jsonschema @@ -189,11 +191,13 @@ pytest==7.1.2 # pytest-cov pytest-cov==3.0.0 # via -r requirements.in +python-arango==7.3.4 + # via testcontainers python-dotenv==0.20.0 # via docker-compose python-jose==3.3.0 # via python-keycloak -python-keycloak==0.27.0 +python-keycloak==1.5.0 # via testcontainers pytz==2022.1 # via @@ -204,7 +208,7 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==5.4.1 # via docker-compose -redis==4.2.2 +redis==4.3.3 # via testcontainers requests==2.27.1 # via @@ -212,15 +216,19 @@ requests==2.27.1 # docker # docker-compose # google-api-core + # python-arango # python-keycloak + # requests-toolbelt # sphinx +requests-toolbelt==0.9.1 + # via python-arango rsa==4.8 # via # google-auth # python-jose scramp==1.4.1 # via pg8000 -selenium==4.1.3 +selenium==4.2.0 # via testcontainers six==1.16.0 # via @@ -237,7 +245,7 @@ snowballstemmer==2.2.0 # via sphinx sortedcontainers==2.4.0 # via trio -sphinx==4.5.0 +sphinx==5.0.1 # via -r requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx @@ -251,7 +259,7 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -sqlalchemy==1.4.36 +sqlalchemy==1.4.37 # via testcontainers texttable==1.6.4 # via docker-compose @@ -271,6 +279,8 @@ tzlocal==4.2 # via clickhouse-driver urllib3[secure,socks]==1.26.9 # via + # python-arango + # python-keycloak # requests # selenium websocket-client==0.59.0 diff --git a/setup.py b/setup.py index de1293dc..5eb48545 100644 --- a/setup.py +++ b/setup.py @@ -67,6 +67,7 @@ 'rabbitmq': ['pika'], 'clickhouse': ['clickhouse-driver'], 'keycloak': ['python-keycloak'], + 'arangodb': ['python-arango'], }, long_description_content_type="text/x-rst", long_description=long_description, diff --git a/testcontainers/arangodb.py b/testcontainers/arangodb.py new file mode 100644 index 00000000..bb956330 --- /dev/null +++ b/testcontainers/arangodb.py @@ -0,0 +1,80 @@ +""" +ArangoDB container support. +""" +from os import environ +from testcontainers.core.config import MAX_TRIES +from testcontainers.core.generic import DbContainer +from testcontainers.core.waiting_utils import wait_for_logs + + +class ArangoDbContainer(DbContainer): + """ + ArangoDB container. + + Example + ------- + The example will spin up a ArangoDB container. + You may use the :code:`get_connection_url()` method which returns a arangoclient-compatible url + in format :code:`scheme://host:port`. As of now, only a single host is supported (over HTTP). + :: + + with ArangoContainer("arangodb:3.9.1") as arango: + client = ArangoClient(hosts=arango.get_connection_url()) + + # Connect + sys_db = arango_client.db(username='root', password='') + + # Create a new database named "test". + sys_db.create_database("test") + """ + def __init__(self, + image="arangodb:latest", + port_to_expose=8529, + arango_root_password='passwd', + arango_no_auth=False, + arango_random_root_password=False, + **kwargs): + """ + Args: + image (str, optional): Actual docker image/tag to pull. Defaults to "arangodb:latest". + port_to_expose (int, optional): Port the container needs to expose. Defaults to 8529. + arango_root_password (str, optional): Start ArangoDB with the + given password for root. Defaults to 'passwd'. + arango_no_auth (bool, optional): Disable authentication completely. + Defaults to False. + arango_random_root_password (bool, optional): Let ArangoDB generate a + random root password. Defaults to False. + """ + super().__init__(image=image) + self.port_to_expose = port_to_expose + self.with_exposed_ports(self.port_to_expose) + + # https://www.arangodb.com/docs/stable/deployment-single-instance-manual-start.html + self.arango_no_auth = arango_no_auth or \ + environ.get("ARANGO_NO_AUTH") + self.arango_root_password = arango_root_password or \ + environ.get('ARANGO_ROOT_PASSWORD') + self.arango_random_root_password = arango_random_root_password or \ + environ.get('ARANGO_RANDOM_ROOT_PASSWORD') + + def _configure(self): + self.with_env( + "ARANGO_NO_AUTH", self.arango_no_auth) + self.with_env( + "ARANGO_ROOT_PASSWORD", self.arango_root_password) + self.with_env( + "ARANGO_RANDOM_ROOT_PASSWORD", self.arango_random_root_password) + + def get_connection_url(self): + # for now, single host over HTTP + scheme = 'http' + port = self.get_exposed_port(self.port_to_expose) + url = f"{scheme}://{self.get_container_host_ip()}:{port}" + + return url + + def _connect(self): + wait_for_logs( + self, + predicate="is ready for business", + timeout=MAX_TRIES) diff --git a/tests/test_arangodb.py b/tests/test_arangodb.py new file mode 100644 index 00000000..574a9fd9 --- /dev/null +++ b/tests/test_arangodb.py @@ -0,0 +1,120 @@ +""" +ArangoDB Container Tests +""" +import pytest +from arango import ArangoClient +from arango.exceptions import DatabaseCreateError, ServerVersionError +from testcontainers.arangodb import ArangoDbContainer + +ARANGODB_IMAGE_NAME = 'arangodb' + + +def arango_test_ops(arango_client, expeced_version, db_user='root', db_pass=''): + """ + Basic ArangoDB operations to test DB really up and running. + """ + students_to_insert_cnt = 3 + + # Taken from https://github.com/ArangoDB-Community/python-arango/blob/main/README.md + # Connect to "_system" database as root user. + sys_db = arango_client.db("_system", username=db_user, password=db_pass) + assert sys_db.version() == expeced_version + + # Create a new database named "test". + sys_db.create_database("test") + + # Connect to "test" database as root user. + database = arango_client.db("test", username=db_user, password=db_pass) + + # Create a new collection named "students". + students = database.create_collection("students") + + # Add a hash index to the collection. + students.add_hash_index(fields=["name"], unique=True) + + # Insert new documents into the collection. (students_to_insert_cnt) + students.insert({"name": "jane", "age": 39}) + students.insert({"name": "josh", "age": 18}) + students.insert({"name": "judy", "age": 21}) + + # Execute an AQL query and iterate through the result cursor. + cursor = database.aql.execute("FOR doc IN students RETURN doc") + student_names = [document["name"] for document in cursor] + + assert len(student_names) == students_to_insert_cnt + + +def test_docker_run_arango(): + """ + Test ArangoDB container with default settings. + """ + image_version = '3.9.1' + image = f'{ARANGODB_IMAGE_NAME}:{image_version}' + arango_db_root_password = 'passwd' + + with ArangoDbContainer(image) as arango: + client = ArangoClient(hosts=arango.get_connection_url()) + + # Test invalid auth + with pytest.raises(DatabaseCreateError): + sys_db = client.db("_system", username="root", password='notTheRightPass') + sys_db.create_database("test") + + arango_test_ops( + arango_client=client, + expeced_version=image_version, + db_pass=arango_db_root_password) + + +def test_docker_run_arango_without_auth(): + """ + Test ArangoDB container with ARANGO_NO_AUTH var set. + """ + image_version = '3.9.1' + image = f'{ARANGODB_IMAGE_NAME}:{image_version}' + + with ArangoDbContainer(image, arango_no_auth=True) as arango: + client = ArangoClient(hosts=arango.get_connection_url()) + + arango_test_ops( + arango_client=client, + expeced_version=image_version, + db_pass='') + + +def test_docker_run_arango_older_version(): + """ + Test ArangoDB container with older tag/version. + the idea behind it hides in the logic of arangodb._connect() -> + Where it waits the container to sign "ready for business" - + If someone will change the logic in the future + we must verify older image tags still supported. (without that logic - we'll face race issues + where we try to create & populate DB when ArangoDB not really ready. + """ + image_version = '3.1.7' + image = f'{ARANGODB_IMAGE_NAME}:{image_version}' + + with ArangoDbContainer(image, arango_no_auth=True) as arango: + client = ArangoClient(hosts=arango.get_connection_url()) + + arango_test_ops( + arango_client=client, + expeced_version=image_version, + db_pass='') + + +def test_docker_run_arango_random_root_password(): + """ + Test ArangoDB container with ARANGO_RANDOM_ROOT_PASSWORD var set. + """ + image_version = '3.9.1' + image = f'{ARANGODB_IMAGE_NAME}:{image_version}' + arango_db_root_password = 'passwd' + + with ArangoDbContainer(image, arango_random_root_password=True) as arango: + client = ArangoClient(hosts=arango.get_connection_url()) + + # Test invalid auth (we don't know the password in random mode) + with pytest.raises(ServerVersionError): + sys_db = client.db("_system", username='root', password=arango_db_root_password) + assert sys_db.version() == image_version