Skip to content

Commit

Permalink
feat(compose): support for setting profiles (#738)
Browse files Browse the repository at this point in the history
# Change

Adds `profiles` support for docker compose.

# Context

I've had to use a workaround in a company project for compose profiles
leading to multiple compose profile files.
This should help by supporting profiles in compose which is a very handy
feature when your service has some variety of ways to run (contextual,
environmental, etc)

Without this, it's still possible to run profiles buy setting the
`COMPOSE_PROFILES` env variable, but this is certainly cleaner and
easier on test writing.


# Docker Docs


https://docs.docker.com/compose/how-tos/profiles/#assigning-profiles-to-services
  • Loading branch information
totallyzen authored Nov 26, 2024
1 parent 24e354f commit 3e00e71
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
3 changes: 3 additions & 0 deletions core/testcontainers/compose/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class DockerCompose:
env_file: Optional[str] = None
services: Optional[list[str]] = None
docker_command_path: Optional[str] = None
profiles: Optional[list[str]] = None

def __post_init__(self):
if isinstance(self.compose_file_name, str):
Expand Down Expand Up @@ -198,6 +199,8 @@ def compose_command_property(self) -> list[str]:
if self.compose_file_name:
for file in self.compose_file_name:
docker_compose_cmd += ["-f", file]
if self.profiles:
docker_compose_cmd += [item for profile in self.profiles for item in ["--profile", profile]]
if self.env_file:
docker_compose_cmd += ["--env-file", self.env_file]
return docker_compose_cmd
Expand Down
16 changes: 16 additions & 0 deletions core/tests/compose_fixtures/profile_support/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
runs-always: &simple-service
image: alpine:latest
init: true
command:
- sh
- -c
- 'while true; do sleep 0.1 ; date -Ins; done'
runs-profile-a:
<<: *simple-service
profiles:
- profile-a
runs-profile-b:
<<: *simple-service
profiles:
- profile-b
26 changes: 25 additions & 1 deletion core/tests/test_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pathlib import Path
from re import split
from time import sleep
from typing import Union
from typing import Union, Optional
from urllib.request import urlopen, Request

import pytest
Expand Down Expand Up @@ -352,3 +352,27 @@ def fetch(req: Union[Request, str]):
if 200 < res.getcode() >= 400:
raise Exception(f"HTTP Error: {res.getcode()} - {res.reason}: {body}")
return res.getcode(), body


@pytest.mark.parametrize(
argnames=["profiles", "running", "not_running"],
argvalues=[
pytest.param(None, ["runs-always"], ["runs-profile-a", "runs-profile-b"], id="default"),
pytest.param(
["profile-a"], ["runs-always", "runs-profile-a"], ["runs-profile-b"], id="one-additional-profile-via-str"
),
pytest.param(
["profile-a", "profile-b"],
["runs-always", "runs-profile-a", "runs-profile-b"],
[],
id="all-profiles-explicitly",
),
],
)
def test_compose_profile_support(profiles: Optional[list[str]], running: list[str], not_running: list[str]):
with DockerCompose(context=FIXTURES / "profile_support", profiles=profiles) as compose:
for service in running:
assert compose.get_container(service) is not None
for service in not_running:
with pytest.raises(ContainerIsNotRunning):
compose.get_container(service)

0 comments on commit 3e00e71

Please sign in to comment.