diff --git a/arangodb/testcontainers/arangodb/__init__.py b/arangodb/testcontainers/arangodb/__init__.py index f56f1eab7..07590939a 100644 --- a/arangodb/testcontainers/arangodb/__init__.py +++ b/arangodb/testcontainers/arangodb/__init__.py @@ -24,7 +24,7 @@ class ArangoDbContainer(DbContainer): >>> from testcontainers.arangodb import ArangoDbContainer >>> from arango import ArangoClient - >>> with ArangoDbContainer("arangodb:3.9.1") as arango: + >>> with ArangoDbContainer("arangodb:3.11.1") as arango: ... client = ArangoClient(hosts=arango.get_connection_url()) ... ... # Connect diff --git a/arangodb/tests/test_arangodb.py b/arangodb/tests/test_arangodb.py index 7933c2fd1..bad837e28 100644 --- a/arangodb/tests/test_arangodb.py +++ b/arangodb/tests/test_arangodb.py @@ -48,7 +48,7 @@ def test_docker_run_arango(): """ Test ArangoDB container with default settings. """ - image_version = '3.9.1' + image_version = '3.11.1' image = f'{ARANGODB_IMAGE_NAME}:{image_version}' arango_root_password = 'passwd' @@ -70,7 +70,7 @@ def test_docker_run_arango_without_auth(): """ Test ArangoDB container with ARANGO_NO_AUTH var set. """ - image_version = '3.9.1' + image_version = '3.11.1' image = f'{ARANGODB_IMAGE_NAME}:{image_version}' with ArangoDbContainer(image, arango_no_auth=True) as arango: @@ -107,7 +107,7 @@ def test_docker_run_arango_random_root_password(): """ Test ArangoDB container with ARANGO_RANDOM_ROOT_PASSWORD var set. """ - image_version = '3.9.1' + image_version = '3.11.1' image = f'{ARANGODB_IMAGE_NAME}:{image_version}' arango_root_password = 'passwd' diff --git a/elasticsearch/tests/test_elasticsearch.py b/elasticsearch/tests/test_elasticsearch.py index 6bbc57fd0..22f74d8eb 100644 --- a/elasticsearch/tests/test_elasticsearch.py +++ b/elasticsearch/tests/test_elasticsearch.py @@ -5,8 +5,8 @@ from testcontainers.elasticsearch import ElasticSearchContainer -# The versions below were the current supported versions at time of writing (2022-08-11) -@pytest.mark.parametrize('version', ['6.8.23', '7.17.5', '8.3.3']) +# The versions below should reflect the latest stable releases of maintained versions +@pytest.mark.parametrize('version', ['7.17.10', '8.8.1']) def test_docker_run_elasticsearch(version): with ElasticSearchContainer(f'elasticsearch:{version}') as es: resp = urllib.request.urlopen(es.get_url()) diff --git a/google/tests/test_google.py b/google/tests/test_google.py index 6fa506e26..e8236e4a6 100644 --- a/google/tests/test_google.py +++ b/google/tests/test_google.py @@ -5,8 +5,8 @@ def test_pubsub_container(): pubsub: PubSubContainer - with PubSubContainer() as pubsub: - wait_for_logs(pubsub, r"Server started, listening on \d+", timeout=60) + with PubSubContainer("google/cloud-sdk:316.0.0-emulators") as pubsub: + wait_for_logs(pubsub, r"Server started, listening on \d+", timeout=120) # Create a new topic publisher = pubsub.get_publisher_client() topic_path = publisher.topic_path(pubsub.project, "my-topic") diff --git a/keycloak/testcontainers/keycloak/__init__.py b/keycloak/testcontainers/keycloak/__init__.py index aeb9a4c78..28fcf97a5 100644 --- a/keycloak/testcontainers/keycloak/__init__.py +++ b/keycloak/testcontainers/keycloak/__init__.py @@ -11,12 +11,11 @@ # License for the specific language governing permissions and limitations # under the License. import os -import requests from keycloak import KeycloakAdmin from testcontainers.core.container import DockerContainer -from testcontainers.core.waiting_utils import wait_container_is_ready +from testcontainers.core.waiting_utils import wait_for_logs from typing import Optional @@ -33,45 +32,33 @@ class KeycloakContainer(DockerContainer): >>> with KeycloakContainer() as kc: ... keycloak = kc.get_client() """ - def __init__(self, image="jboss/keycloak:latest", username: Optional[str] = None, + def __init__(self, image="quay.io/keycloak/keycloak:latest", username: Optional[str] = None, password: Optional[str] = None, port: int = 8080) -> None: super(KeycloakContainer, self).__init__(image=image) - self.username = username or os.environ.get("KEYCLOAK_USER", "test") - self.password = password or os.environ.get("KEYCLOAK_PASSWORD", "test") + self.username = username or os.environ.get("KEYCLOAK_ADMIN", "test") + self.password = password or os.environ.get("KEYCLOAK_ADMIN_PASSWORD", "test") self.port = port self.with_exposed_ports(self.port) def _configure(self) -> None: - self.with_env("KEYCLOAK_USER", self.username) - self.with_env("KEYCLOAK_PASSWORD", self.password) + self.with_env("KEYCLOAK_ADMIN", self.username) + self.with_env("KEYCLOAK_ADMIN_PASSWORD", self.password) + self.with_command("start-dev") def get_url(self) -> str: host = self.get_container_host_ip() port = self.get_exposed_port(self.port) return f"http://{host}:{port}" - @wait_container_is_ready(requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) - def _connect(self) -> None: - url = self.get_url() - response = requests.get(f"{url}/auth", timeout=1) - response.raise_for_status() - def start(self) -> "KeycloakContainer": self._configure() - super().start() - self._connect() + container = super().start() + wait_for_logs(container, 'Listening on:') return self def get_client(self, **kwargs) -> KeycloakAdmin: - default_kwargs = dict( - server_url=f"{self.get_url()}/auth/", + return KeycloakAdmin( + server_url=f"{self.get_url()}/", username=self.username, password=self.password, - realm_name="master", - verify=True, - ) - kwargs = { - **default_kwargs, - **kwargs - } - return KeycloakAdmin(**kwargs) + verify=True) diff --git a/keycloak/tests/test_keycloak.py b/keycloak/tests/test_keycloak.py index 900ee0ddf..79545644a 100644 --- a/keycloak/tests/test_keycloak.py +++ b/keycloak/tests/test_keycloak.py @@ -5,5 +5,5 @@ @pytest.mark.parametrize("version", ["16.1.1"]) def test_docker_run_keycloak(version: str): - with KeycloakContainer(f'jboss/keycloak:{version}') as kc: - kc.get_client().users_count() + with KeycloakContainer(f'quay.io/keycloak/keycloak:latest') as kc: + assert kc.get_client().users_count() == 1 diff --git a/mssql/testcontainers/mssql/__init__.py b/mssql/testcontainers/mssql/__init__.py index 9de6edf00..6351c6515 100644 --- a/mssql/testcontainers/mssql/__init__.py +++ b/mssql/testcontainers/mssql/__init__.py @@ -15,7 +15,8 @@ class SqlServerContainer(DbContainer): >>> import sqlalchemy >>> from testcontainers.mssql import SqlServerContainer - >>> with SqlServerContainer() as mssql: + >>> # Use azure-sql-edge for Apple Silicon compatibility + >>> with SqlServerContainer('mcr.microsoft.com/azure-sql-edge') as mssql: ... engine = sqlalchemy.create_engine(mssql.get_connection_url()) ... with engine.begin() as connection: ... result = connection.execute(sqlalchemy.text("select @@VERSION")) @@ -37,6 +38,7 @@ def __init__(self, image: str = "mcr.microsoft.com/mssql/server:2019-latest", def _configure(self) -> None: self.with_env("SA_PASSWORD", self.password) + self.with_env("MSSQL_SA_PASSWORD", self.password) self.with_env("SQLSERVER_USER", self.username) self.with_env("SQLSERVER_DBNAME", self.dbname) self.with_env("ACCEPT_EULA", 'Y') diff --git a/nginx/README.rst b/nginx/README.rst index ff1504759..2e362ad3e 100644 --- a/nginx/README.rst +++ b/nginx/README.rst @@ -1 +1,7 @@ .. autoclass:: testcontainers.nginx.NginxContainer + +Creates a container with the `nginx `_ image +and waits for the container to accept connections. + +Defaults to the latest release of nginx, and supports version 1.20+. +For older versions, use the generic DockerContainer class from `testcontainers-core`. diff --git a/nginx/testcontainers/nginx/__init__.py b/nginx/testcontainers/nginx/__init__.py index 0226d700b..e8b44b243 100644 --- a/nginx/testcontainers/nginx/__init__.py +++ b/nginx/testcontainers/nginx/__init__.py @@ -12,11 +12,17 @@ # under the License. from testcontainers.core.container import DockerContainer from testcontainers.core.utils import raise_for_deprecated_parameter +from testcontainers.core.waiting_utils import wait_for_logs class NginxContainer(DockerContainer): def __init__(self, image: str = "nginx:latest", port: int = 80, **kwargs) -> None: raise_for_deprecated_parameter(kwargs, "port_to_expose", "port") - super(NginxContainer, self).__init__(image, **kwargs) + super().__init__(image, **kwargs) self.port = port self.with_exposed_ports(self.port) + + def start(self) -> DockerContainer: + container = super().start() + wait_for_logs(container, 'ready for start up') + return container diff --git a/nginx/tests/test_nginx.py b/nginx/tests/test_nginx.py index 0d369bf71..54b11d3eb 100644 --- a/nginx/tests/test_nginx.py +++ b/nginx/tests/test_nginx.py @@ -4,8 +4,7 @@ def test_docker_run_nginx(): - nginx_container = NginxContainer("nginx:1.13.8") - with nginx_container as nginx: + with NginxContainer("nginx:1.24.0") as nginx: url = f"http://{nginx.get_container_host_ip()}:{nginx.get_exposed_port(nginx.port)}/" r = requests.get(url) assert (r.status_code == 200) diff --git a/redis/README.rst b/redis/README.rst index 333cb246f..2aa71e8f7 100644 --- a/redis/README.rst +++ b/redis/README.rst @@ -1 +1,9 @@ .. autoclass:: testcontainers.redis.RedisContainer + + + +Creates a container with the `redis `_ image +and waits for the container to accept connections. + +Defaults to the latest release of redis, and supports version 6.0+. +For older versions, use the generic DockerContainer class from `testcontainers-core`. diff --git a/redis/testcontainers/redis/__init__.py b/redis/testcontainers/redis/__init__.py index 12d473644..6df624cdf 100644 --- a/redis/testcontainers/redis/__init__.py +++ b/redis/testcontainers/redis/__init__.py @@ -14,7 +14,7 @@ import redis from testcontainers.core.container import DockerContainer from testcontainers.core.utils import raise_for_deprecated_parameter -from testcontainers.core.waiting_utils import wait_container_is_ready +from testcontainers.core.waiting_utils import wait_container_is_ready, wait_for_logs from typing import Optional @@ -65,6 +65,7 @@ def get_client(self, **kwargs) -> redis.Redis: ) def start(self) -> "RedisContainer": - super().start() + container = super().start() + wait_for_logs(container, 'Ready to accept connections') self._connect() return self diff --git a/redis/tests/test_redis.py b/redis/tests/test_redis.py index 9bf946442..36813d477 100644 --- a/redis/tests/test_redis.py +++ b/redis/tests/test_redis.py @@ -1,36 +1,12 @@ -import time +import pytest from testcontainers.redis import RedisContainer -def test_docker_run_redis(): - config = RedisContainer() - with config as redis: - client = redis.get_client() - p = client.pubsub() - p.subscribe('test') - client.publish('test', 'new_msg') - msg = wait_for_message(p) - assert 'data' in msg - assert b'new_msg', msg['data'] - - -def test_docker_run_redis_with_password(): - config = RedisContainer(password="mypass") - with config as redis: +@pytest.mark.parametrize('version', ['7.0.11', '6.2.12']) +def test_redis_container(version: str): + image_name = f'redis:{version}' + with RedisContainer(image_name, password="mypass") as redis: client = redis.get_client(decode_responses=True) client.set("hello", "world") assert client.get("hello") == "world" - - -def wait_for_message(pubsub, timeout=1, ignore_subscribe_messages=True): - now = time.time() - timeout = now + timeout - while now < timeout: - message = pubsub.get_message( - ignore_subscribe_messages=ignore_subscribe_messages) - if message is not None: - return message - time.sleep(0.01) - now = time.time() - return None