Skip to content

Commit

Permalink
Merge branch 'main' into mypy_core_auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Tranquility2 authored Aug 22, 2024
2 parents f875249 + 2cf5a9f commit 6e085b6
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 13 deletions.
4 changes: 2 additions & 2 deletions core/testcontainers/core/container.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import contextlib
from platform import system
from socket import socket
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Optional, Union

import docker.errors
from docker import version
Expand Down Expand Up @@ -186,7 +186,7 @@ def get_logs(self) -> tuple[bytes, bytes]:
raise ContainerStartException("Container should be started before getting logs")
return self._container.logs(stderr=False), self._container.logs(stdout=False)

def exec(self, command) -> tuple[int, bytes]:
def exec(self, command: Union[str, list[str]]) -> tuple[int, bytes]:
if not self._container:
raise ContainerStartException("Container should be started before executing a command")
return self._container.exec_run(command)
Expand Down
32 changes: 32 additions & 0 deletions modules/generic/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,35 @@ FastAPI container that is using :code:`ServerContainer`
... response = client.get("/")
... assert response.status_code == 200
... assert response.json() == {"Status": "Working"}

A more advance use-case, where we are using a FastAPI container that is using Redis container:

.. doctest::

>>> from testcontainers.redis import RedisContainer
>>> from testcontainers.generic import ServerContainer

>>> with RedisContainer() as redis:
... redis_container_port = redis.port
... redis_container_ip_address = redis.get_docker_client().bridge_ip(redis._container.id)

... with DockerImage(path="./modules/generic/tests/samples/advance_1", tag="advance-1:latest") as image:
... web_server = ServerContainer(port=80, image=image)
... web_server.with_env(key="REDIS_HOST", value=redis_container_ip_address)
... web_server.with_env(key="REDIS_PORT", value=redis_container_port)

... with web_server:
... web_server.get_api_url = lambda: web_server._create_connection_url()
... client = web_server.get_client()

... response = client.get("/")
... assert response.status_code == 200, "Server request failed"
... assert response.json() == {"Status": "ok"}

... test_data = {"key": "test_key", "value": "test_value"}
... response = client.post("/set", params=test_data)
... assert response.status_code == 200, "Failed to set data"

... response = client.get(f"/get/{test_data['key']}")
... assert response.status_code == 200, "Failed to get data"
... assert response.json() == {"key": test_data["key"], "value": test_data["value"]}
11 changes: 11 additions & 0 deletions modules/generic/tests/samples/advance_1/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.9

WORKDIR /app

RUN pip install fastapi[standard] redis

COPY ./app /app

EXPOSE 80

CMD ["fastapi", "run", "main.py", "--port", "80"]
Empty file.
30 changes: 30 additions & 0 deletions modules/generic/tests/samples/advance_1/app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This app will use redis to store given key-value pairs.

import os
import redis

from fastapi import FastAPI


app = FastAPI()

redis_host = os.getenv("REDIS_HOST")
redis_port = os.getenv("REDIS_PORT")
redis_client = redis.Redis(host=redis_host, port=redis_port)
redis_client.ping()


@app.get("/")
def health_check():
return {"status": "ok"}


@app.get("/get/{key}")
def read_item(key: str):
return {key: redis_client.get(key)}


@app.post("/set")
def create_item(key: str, value: str):
redis_client.set(key, value)
return {key: value}
2 changes: 1 addition & 1 deletion modules/generic/tests/samples/fastapi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM python:3.9

WORKDIR /app

RUN pip install fastapi
RUN pip install fastapi[standard]

COPY ./app /app

Expand Down
4 changes: 3 additions & 1 deletion modules/mssql/testcontainers/mssql/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ def _configure(self) -> None:

@wait_container_is_ready(AssertionError)
def _connect(self) -> None:
status, _ = self.exec(f"/opt/mssql-tools/bin/sqlcmd -U {self.username} -P {self.password} -Q 'SELECT 1'")
status, _ = self.exec(
["bash", "-c", '/opt/mssql-tools*/bin/sqlcmd -U "$SQLSERVER_USER" -P "$SA_PASSWORD" -Q \'SELECT 1\' -C']
)
assert status == 0, "Cannot run 'SELECT 1': container is not ready"

def get_connection_url(self) -> str:
Expand Down
16 changes: 10 additions & 6 deletions modules/mssql/tests/test_mssql.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ def test_docker_run_azure_sql_edge():
assert row[0] == "MSSQLSERVER"


# This is a feature in the generic DbContainer class
def test_microsoft_changes_the_mssql_tools_folder_name():
with SqlServerContainer("mcr.microsoft.com/mssql/server:2019-latest") as mssql:
engine = sqlalchemy.create_engine(mssql.get_connection_url())
with engine.begin() as connection:
result = connection.execute(sqlalchemy.text("select @@servicename"))
for row in result:
assert row[0] == "MSSQLSERVER"


# This is a feature in the generic DbContainer class,
# but it can't be tested on its own
# so is tested in various database modules:
# - mysql / mariadb
# - postgresql
# - sqlserver
# - mongodb
def test_quoted_password():
user = "SA"
# spaces seem to cause issues?
Expand Down
4 changes: 2 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ cosmosdb = ["azure-cosmos"]
cockroachdb = []
db2 = ["sqlalchemy", "ibm_db_sa"]
elasticsearch = []
generic = ["httpx"]
generic = ["httpx", "redis"] # The advance doctests for ServerContainer require redis
test_module_import = ["httpx"]
google = ["google-cloud-pubsub", "google-cloud-datastore"]
influxdb = ["influxdb", "influxdb-client"]
Expand Down

0 comments on commit 6e085b6

Please sign in to comment.