Skip to content

Commit 6e085b6

Browse files
authored
Merge branch 'main' into mypy_core_auth
2 parents f875249 + 2cf5a9f commit 6e085b6

File tree

10 files changed

+92
-13
lines changed

10 files changed

+92
-13
lines changed

core/testcontainers/core/container.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import contextlib
22
from platform import system
33
from socket import socket
4-
from typing import TYPE_CHECKING, Optional
4+
from typing import TYPE_CHECKING, Optional, Union
55

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

189-
def exec(self, command) -> tuple[int, bytes]:
189+
def exec(self, command: Union[str, list[str]]) -> tuple[int, bytes]:
190190
if not self._container:
191191
raise ContainerStartException("Container should be started before executing a command")
192192
return self._container.exec_run(command)

modules/generic/README.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,35 @@ FastAPI container that is using :code:`ServerContainer`
1818
... response = client.get("/")
1919
... assert response.status_code == 200
2020
... assert response.json() == {"Status": "Working"}
21+
22+
A more advance use-case, where we are using a FastAPI container that is using Redis container:
23+
24+
.. doctest::
25+
26+
>>> from testcontainers.redis import RedisContainer
27+
>>> from testcontainers.generic import ServerContainer
28+
29+
>>> with RedisContainer() as redis:
30+
... redis_container_port = redis.port
31+
... redis_container_ip_address = redis.get_docker_client().bridge_ip(redis._container.id)
32+
33+
... with DockerImage(path="./modules/generic/tests/samples/advance_1", tag="advance-1:latest") as image:
34+
... web_server = ServerContainer(port=80, image=image)
35+
... web_server.with_env(key="REDIS_HOST", value=redis_container_ip_address)
36+
... web_server.with_env(key="REDIS_PORT", value=redis_container_port)
37+
38+
... with web_server:
39+
... web_server.get_api_url = lambda: web_server._create_connection_url()
40+
... client = web_server.get_client()
41+
42+
... response = client.get("/")
43+
... assert response.status_code == 200, "Server request failed"
44+
... assert response.json() == {"Status": "ok"}
45+
46+
... test_data = {"key": "test_key", "value": "test_value"}
47+
... response = client.post("/set", params=test_data)
48+
... assert response.status_code == 200, "Failed to set data"
49+
50+
... response = client.get(f"/get/{test_data['key']}")
51+
... assert response.status_code == 200, "Failed to get data"
52+
... assert response.json() == {"key": test_data["key"], "value": test_data["value"]}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM python:3.9
2+
3+
WORKDIR /app
4+
5+
RUN pip install fastapi[standard] redis
6+
7+
COPY ./app /app
8+
9+
EXPOSE 80
10+
11+
CMD ["fastapi", "run", "main.py", "--port", "80"]

modules/generic/tests/samples/advance_1/app/__init__.py

Whitespace-only changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This app will use redis to store given key-value pairs.
2+
3+
import os
4+
import redis
5+
6+
from fastapi import FastAPI
7+
8+
9+
app = FastAPI()
10+
11+
redis_host = os.getenv("REDIS_HOST")
12+
redis_port = os.getenv("REDIS_PORT")
13+
redis_client = redis.Redis(host=redis_host, port=redis_port)
14+
redis_client.ping()
15+
16+
17+
@app.get("/")
18+
def health_check():
19+
return {"status": "ok"}
20+
21+
22+
@app.get("/get/{key}")
23+
def read_item(key: str):
24+
return {key: redis_client.get(key)}
25+
26+
27+
@app.post("/set")
28+
def create_item(key: str, value: str):
29+
redis_client.set(key, value)
30+
return {key: value}

modules/generic/tests/samples/fastapi/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM python:3.9
22

33
WORKDIR /app
44

5-
RUN pip install fastapi
5+
RUN pip install fastapi[standard]
66

77
COPY ./app /app
88

modules/mssql/testcontainers/mssql/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ def _configure(self) -> None:
5252

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

5860
def get_connection_url(self) -> str:

modules/mssql/tests/test_mssql.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ def test_docker_run_azure_sql_edge():
2525
assert row[0] == "MSSQLSERVER"
2626

2727

28-
# This is a feature in the generic DbContainer class
28+
def test_microsoft_changes_the_mssql_tools_folder_name():
29+
with SqlServerContainer("mcr.microsoft.com/mssql/server:2019-latest") as mssql:
30+
engine = sqlalchemy.create_engine(mssql.get_connection_url())
31+
with engine.begin() as connection:
32+
result = connection.execute(sqlalchemy.text("select @@servicename"))
33+
for row in result:
34+
assert row[0] == "MSSQLSERVER"
35+
36+
37+
# This is a feature in the generic DbContainer class,
2938
# but it can't be tested on its own
30-
# so is tested in various database modules:
31-
# - mysql / mariadb
32-
# - postgresql
33-
# - sqlserver
34-
# - mongodb
3539
def test_quoted_password():
3640
user = "SA"
3741
# spaces seem to cause issues?

poetry.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ cosmosdb = ["azure-cosmos"]
129129
cockroachdb = []
130130
db2 = ["sqlalchemy", "ibm_db_sa"]
131131
elasticsearch = []
132-
generic = ["httpx"]
132+
generic = ["httpx", "redis"] # The advance doctests for ServerContainer require redis
133133
test_module_import = ["httpx"]
134134
google = ["google-cloud-pubsub", "google-cloud-datastore"]
135135
influxdb = ["influxdb", "influxdb-client"]

0 commit comments

Comments
 (0)