Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref(docker-compose): Starting to refactor docker compose logic #198

Merged
merged 2 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion devservices/commands/down.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from sentry_sdk import capture_exception

from devservices.configs.service_config import load_service_config_from_file
from devservices.constants import CONFIG_FILE_NAME
from devservices.constants import DEPENDENCY_CONFIG_VERSION
from devservices.constants import DEVSERVICES_DEPENDENCIES_CACHE_DIR
Expand All @@ -24,8 +25,9 @@
from devservices.utils.dependencies import get_non_shared_remote_dependencies
from devservices.utils.dependencies import install_and_verify_dependencies
from devservices.utils.dependencies import InstalledRemoteDependency
from devservices.utils.docker_compose import create_docker_compose_command
from devservices.utils.docker_compose import DockerComposeCommand
from devservices.utils.docker_compose import get_docker_compose_commands_to_run
from devservices.utils.docker_compose import get_non_remote_services
from devservices.utils.docker_compose import run_cmd
from devservices.utils.services import find_matching_service
from devservices.utils.services import Service
Expand Down Expand Up @@ -163,3 +165,51 @@
]
for future in concurrent.futures.as_completed(futures):
cmd_outputs.append(future.result())


def get_docker_compose_commands_to_run(
service: Service,
remote_dependencies: list[InstalledRemoteDependency],
current_env: dict[str, str],
command: str,
options: list[str],
service_config_file_path: str,
mode_dependencies: list[str],
) -> list[DockerComposeCommand]:
docker_compose_commands = []
for dependency in remote_dependencies:
# TODO: Consider passing in service config in InstalledRemoteDependency instead of loading it here
dependency_service_config = load_service_config_from_file(dependency.repo_path)
dependency_config_path = os.path.join(

Check warning on line 183 in devservices/commands/down.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/down.py#L182-L183

Added lines #L182 - L183 were not covered by tests
dependency.repo_path, DEVSERVICES_DIR_NAME, CONFIG_FILE_NAME
)
non_remote_services = get_non_remote_services(

Check warning on line 186 in devservices/commands/down.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/down.py#L186

Added line #L186 was not covered by tests
dependency_config_path, current_env
)
services_to_use = non_remote_services.intersection(

Check warning on line 189 in devservices/commands/down.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/down.py#L189

Added line #L189 was not covered by tests
set(dependency_service_config.modes[dependency.mode])
)
docker_compose_commands.append(

Check warning on line 192 in devservices/commands/down.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/down.py#L192

Added line #L192 was not covered by tests
create_docker_compose_command(
dependency_service_config.service_name,
dependency_config_path,
services_to_use,
command,
options,
)
)

# Add docker compose command for the top level service
non_remote_services = get_non_remote_services(service_config_file_path, current_env)
services_to_use = non_remote_services.intersection(set(mode_dependencies))
if len(services_to_use) > 0:
docker_compose_commands.append(
create_docker_compose_command(
service.name,
service_config_file_path,
services_to_use,
command,
options,
)
)
return docker_compose_commands
53 changes: 52 additions & 1 deletion devservices/commands/logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from sentry_sdk import capture_exception

from devservices.configs.service_config import load_service_config_from_file
from devservices.constants import CONFIG_FILE_NAME
from devservices.constants import DEPENDENCY_CONFIG_VERSION
from devservices.constants import DEVSERVICES_DEPENDENCIES_CACHE_DIR
Expand All @@ -23,7 +24,9 @@
from devservices.utils.console import Console
from devservices.utils.dependencies import install_and_verify_dependencies
from devservices.utils.dependencies import InstalledRemoteDependency
from devservices.utils.docker_compose import get_docker_compose_commands_to_run
from devservices.utils.docker_compose import create_docker_compose_command
from devservices.utils.docker_compose import DockerComposeCommand
from devservices.utils.docker_compose import get_non_remote_services
from devservices.utils.docker_compose import run_cmd
from devservices.utils.services import find_matching_service
from devservices.utils.services import Service
Expand Down Expand Up @@ -128,3 +131,51 @@
cmd_outputs.append(future.result())

return cmd_outputs


def get_docker_compose_commands_to_run(
service: Service,
remote_dependencies: list[InstalledRemoteDependency],
current_env: dict[str, str],
command: str,
options: list[str],
service_config_file_path: str,
mode_dependencies: list[str],
) -> list[DockerComposeCommand]:
docker_compose_commands = []
for dependency in remote_dependencies:
# TODO: Consider passing in service config in InstalledRemoteDependency instead of loading it here
dependency_service_config = load_service_config_from_file(dependency.repo_path)
dependency_config_path = os.path.join(

Check warning on line 149 in devservices/commands/logs.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/logs.py#L148-L149

Added lines #L148 - L149 were not covered by tests
dependency.repo_path, DEVSERVICES_DIR_NAME, CONFIG_FILE_NAME
)
non_remote_services = get_non_remote_services(

Check warning on line 152 in devservices/commands/logs.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/logs.py#L152

Added line #L152 was not covered by tests
dependency_config_path, current_env
)
services_to_use = non_remote_services.intersection(

Check warning on line 155 in devservices/commands/logs.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/logs.py#L155

Added line #L155 was not covered by tests
set(dependency_service_config.modes[dependency.mode])
)
docker_compose_commands.append(

Check warning on line 158 in devservices/commands/logs.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/logs.py#L158

Added line #L158 was not covered by tests
create_docker_compose_command(
dependency_service_config.service_name,
dependency_config_path,
services_to_use,
command,
options,
)
)

# Add docker compose command for the top level service
non_remote_services = get_non_remote_services(service_config_file_path, current_env)
services_to_use = non_remote_services.intersection(set(mode_dependencies))
if len(services_to_use) > 0:
docker_compose_commands.append(
create_docker_compose_command(
service.name,
service_config_file_path,
services_to_use,
command,
options,
)
)
return docker_compose_commands
53 changes: 52 additions & 1 deletion devservices/commands/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from sentry_sdk import capture_exception

from devservices.configs.service_config import load_service_config_from_file
from devservices.constants import CONFIG_FILE_NAME
from devservices.constants import DEPENDENCY_CONFIG_VERSION
from devservices.constants import DEVSERVICES_DEPENDENCIES_CACHE_DIR
Expand All @@ -24,7 +25,9 @@
from devservices.utils.console import Console
from devservices.utils.dependencies import install_and_verify_dependencies
from devservices.utils.dependencies import InstalledRemoteDependency
from devservices.utils.docker_compose import get_docker_compose_commands_to_run
from devservices.utils.docker_compose import create_docker_compose_command
from devservices.utils.docker_compose import DockerComposeCommand
from devservices.utils.docker_compose import get_non_remote_services
from devservices.utils.docker_compose import run_cmd
from devservices.utils.services import find_matching_service
from devservices.utils.services import Service
Expand Down Expand Up @@ -176,3 +179,51 @@
cmd_outputs.append(future.result())

return cmd_outputs


def get_docker_compose_commands_to_run(
service: Service,
remote_dependencies: list[InstalledRemoteDependency],
current_env: dict[str, str],
command: str,
options: list[str],
service_config_file_path: str,
mode_dependencies: list[str],
) -> list[DockerComposeCommand]:
docker_compose_commands = []
for dependency in remote_dependencies:

Check warning on line 194 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L193-L194

Added lines #L193 - L194 were not covered by tests
# TODO: Consider passing in service config in InstalledRemoteDependency instead of loading it here
dependency_service_config = load_service_config_from_file(dependency.repo_path)
dependency_config_path = os.path.join(

Check warning on line 197 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L196-L197

Added lines #L196 - L197 were not covered by tests
dependency.repo_path, DEVSERVICES_DIR_NAME, CONFIG_FILE_NAME
)
non_remote_services = get_non_remote_services(

Check warning on line 200 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L200

Added line #L200 was not covered by tests
dependency_config_path, current_env
)
services_to_use = non_remote_services.intersection(

Check warning on line 203 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L203

Added line #L203 was not covered by tests
set(dependency_service_config.modes[dependency.mode])
)
docker_compose_commands.append(

Check warning on line 206 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L206

Added line #L206 was not covered by tests
create_docker_compose_command(
dependency_service_config.service_name,
dependency_config_path,
services_to_use,
command,
options,
)
)

# Add docker compose command for the top level service
non_remote_services = get_non_remote_services(service_config_file_path, current_env)
services_to_use = non_remote_services.intersection(set(mode_dependencies))
if len(services_to_use) > 0:
docker_compose_commands.append(

Check warning on line 220 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L217-L220

Added lines #L217 - L220 were not covered by tests
create_docker_compose_command(
service.name,
service_config_file_path,
services_to_use,
command,
options,
)
)
return docker_compose_commands

Check warning on line 229 in devservices/commands/status.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/status.py#L229

Added line #L229 was not covered by tests
52 changes: 51 additions & 1 deletion devservices/commands/up.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from sentry_sdk import capture_exception

from devservices.configs.service_config import load_service_config_from_file
from devservices.constants import CONFIG_FILE_NAME
from devservices.constants import DEPENDENCY_CONFIG_VERSION
from devservices.constants import DEVSERVICES_DEPENDENCIES_CACHE_DIR
Expand All @@ -27,9 +28,10 @@
from devservices.utils.dependencies import install_and_verify_dependencies
from devservices.utils.dependencies import InstalledRemoteDependency
from devservices.utils.docker import check_all_containers_healthy
from devservices.utils.docker_compose import create_docker_compose_command
from devservices.utils.docker_compose import DockerComposeCommand
from devservices.utils.docker_compose import get_container_names_for_project
from devservices.utils.docker_compose import get_docker_compose_commands_to_run
from devservices.utils.docker_compose import get_non_remote_services
from devservices.utils.docker_compose import run_cmd
from devservices.utils.services import find_matching_service
from devservices.utils.services import Service
Expand Down Expand Up @@ -187,3 +189,51 @@
stderr=subprocess.DEVNULL,
check=True,
)


def get_docker_compose_commands_to_run(
service: Service,
remote_dependencies: list[InstalledRemoteDependency],
current_env: dict[str, str],
command: str,
options: list[str],
service_config_file_path: str,
mode_dependencies: list[str],
) -> list[DockerComposeCommand]:
docker_compose_commands = []
for dependency in remote_dependencies:
# TODO: Consider passing in service config in InstalledRemoteDependency instead of loading it here
dependency_service_config = load_service_config_from_file(dependency.repo_path)
dependency_config_path = os.path.join(

Check warning on line 207 in devservices/commands/up.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/up.py#L206-L207

Added lines #L206 - L207 were not covered by tests
dependency.repo_path, DEVSERVICES_DIR_NAME, CONFIG_FILE_NAME
)
non_remote_services = get_non_remote_services(

Check warning on line 210 in devservices/commands/up.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/up.py#L210

Added line #L210 was not covered by tests
dependency_config_path, current_env
)
services_to_use = non_remote_services.intersection(

Check warning on line 213 in devservices/commands/up.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/up.py#L213

Added line #L213 was not covered by tests
set(dependency_service_config.modes[dependency.mode])
)
docker_compose_commands.append(

Check warning on line 216 in devservices/commands/up.py

View check run for this annotation

Codecov / codecov/patch

devservices/commands/up.py#L216

Added line #L216 was not covered by tests
create_docker_compose_command(
dependency_service_config.service_name,
dependency_config_path,
services_to_use,
command,
options,
)
)

# Add docker compose command for the top level service
non_remote_services = get_non_remote_services(service_config_file_path, current_env)
services_to_use = non_remote_services.intersection(set(mode_dependencies))
if len(services_to_use) > 0:
docker_compose_commands.append(
create_docker_compose_command(
service.name,
service_config_file_path,
services_to_use,
command,
options,
)
)
return docker_compose_commands
57 changes: 7 additions & 50 deletions devservices/utils/docker_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
import platform
import re
import subprocess
from collections.abc import Callable
from typing import cast
from typing import NamedTuple

from packaging import version

from devservices.configs.service_config import load_service_config_from_file
from devservices.constants import CONFIG_FILE_NAME
from devservices.constants import DEVSERVICES_DIR_NAME
from devservices.constants import DOCKER_COMPOSE_DOWNLOAD_URL
from devservices.constants import DOCKER_USER_PLUGIN_DIR
from devservices.constants import LOGGER_NAME
Expand All @@ -22,10 +18,8 @@
from devservices.exceptions import DockerComposeError
from devservices.exceptions import DockerComposeInstallationError
from devservices.utils.console import Console
from devservices.utils.dependencies import InstalledRemoteDependency
from devservices.utils.docker import check_docker_daemon_running
from devservices.utils.install_binary import install_binary
from devservices.utils.services import Service


class DockerComposeCommand(NamedTuple):
Expand Down Expand Up @@ -170,7 +164,7 @@ def check_docker_compose_version() -> None:


# TODO: Consider removing this in favor of in house logic for determining non-remote services
def _get_non_remote_services(
def get_non_remote_services(
service_config_path: str, current_env: dict[str, str]
) -> set[str]:
config_command = [
Expand All @@ -195,19 +189,14 @@ def _get_non_remote_services(
return set(config_services.splitlines())


def get_docker_compose_commands_to_run(
service: Service,
remote_dependencies: list[InstalledRemoteDependency],
current_env: dict[str, str],
def create_docker_compose_command(
name: str,
config_path: str,
services_to_use: set[str],
command: str,
options: list[str],
service_config_file_path: str,
mode_dependencies: list[str],
) -> list[DockerComposeCommand]:
docker_compose_commands = []
create_docker_compose_command: Callable[
[str, str, set[str]], DockerComposeCommand
] = lambda name, config_path, services_to_use: DockerComposeCommand(
) -> DockerComposeCommand:
return DockerComposeCommand(
full_command=[
"docker",
"compose",
Expand All @@ -223,38 +212,6 @@ def get_docker_compose_commands_to_run(
config_path=config_path,
services=sorted(list(services_to_use)),
)
for dependency in remote_dependencies:
# TODO: Consider passing in service config in InstalledRemoteDependency instead of loading it here
dependency_service_config = load_service_config_from_file(dependency.repo_path)
dependency_config_path = os.path.join(
dependency.repo_path, DEVSERVICES_DIR_NAME, CONFIG_FILE_NAME
)
non_remote_services = _get_non_remote_services(
dependency_config_path, current_env
)
services_to_use = non_remote_services.intersection(
set(dependency_service_config.modes[dependency.mode])
)
docker_compose_commands.append(
create_docker_compose_command(
dependency_service_config.service_name,
dependency_config_path,
services_to_use,
)
)

# Add docker compose command for the top level service
non_remote_services = _get_non_remote_services(
service_config_file_path, current_env
)
services_to_use = non_remote_services.intersection(set(mode_dependencies))
if len(services_to_use) > 0:
docker_compose_commands.append(
create_docker_compose_command(
service.name, service_config_file_path, services_to_use
)
)
return docker_compose_commands


def run_cmd(cmd: list[str], env: dict[str, str]) -> subprocess.CompletedProcess[str]:
Expand Down
2 changes: 1 addition & 1 deletion tests/commands/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_logs_no_specified_service_not_running(
@mock.patch("devservices.commands.logs.find_matching_service")
@mock.patch("devservices.utils.state.State.get_started_services")
@mock.patch("devservices.commands.logs.install_and_verify_dependencies")
@mock.patch("devservices.utils.docker_compose._get_non_remote_services")
@mock.patch("devservices.commands.logs.get_non_remote_services")
def test_logs_no_specified_service_success(
mock_get_non_remote_services: mock.Mock,
mock_install_and_verify_dependencies: mock.Mock,
Expand Down
Loading
Loading