Skip to content

Commit

Permalink
Merge pull request #177 from bluesliverx/main
Browse files Browse the repository at this point in the history
Add ability to label all started containers
  • Loading branch information
bluesliverx authored Dec 19, 2024
2 parents 05d4e99 + 89cbafc commit a5664bc
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 4 deletions.
2 changes: 2 additions & 0 deletions buildrunner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def __init__(
local_images: bool,
platform: Optional[str],
global_config_overrides: dict,
container_labels: Optional[str] = None,
): # pylint: disable=too-many-statements,too-many-branches,too-many-locals,too-many-arguments
self.build_dir = build_dir
self.build_results_dir = build_results_dir
Expand Down Expand Up @@ -141,6 +142,7 @@ def __init__(
build_time=self.build_time,
tmp_files=self.tmp_files,
global_config_overrides=global_config_overrides,
container_labels=container_labels,
)
self.buildrunner_config = BuildRunnerConfig.get_instance()

Expand Down
10 changes: 10 additions & 0 deletions buildrunner/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ def parse_args(argv):
help="enables debug logging",
)

parser.add_argument(
"--container-labels",
default=None,
help=(
"arbitrary labels to add to every container started by buildrunner, "
"in the form of 'key1=value1,key2=value2'"
),
)

parser.add_argument(
"-n",
"--build-number",
Expand Down Expand Up @@ -396,6 +405,7 @@ def initialize_br(args: argparse.Namespace) -> BuildRunner:
local_images=args.local_images,
platform=args.platform,
global_config_overrides=_get_global_config_overrides(args),
container_labels=args.container_labels,
)


Expand Down
17 changes: 17 additions & 0 deletions buildrunner/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ def __init__(
log_generated_files: bool,
build_time: int,
global_config_overrides: dict,
# Arbitrary labels to add to all started containers, of the form key1=value1,key2=value2
container_labels: Optional[str] = None,
# May be passed in to add temporary files to this list as they are created
tmp_files: Optional[List[str]] = None,
# Used only from CLI commands that do not need a run config
Expand All @@ -83,6 +85,7 @@ def __init__(
self.build_time = build_time
if not self.build_time:
self.build_time = epoch_time()
self.container_labels = self._parse_container_labels(container_labels)
self.tmp_files = tmp_files

self.global_config = self._load_global_config(
Expand All @@ -99,6 +102,20 @@ def __init__(
self._load_run_config(run_config_file) if load_run_config else None
)

@staticmethod
def _parse_container_labels(container_labels_str: Optional[str]) -> dict:
container_labels = {}
if not container_labels_str:
return container_labels
for pair in container_labels_str.split(","):
if "=" not in pair:
raise BuildRunnerConfigurationError(
"Invalid container label format, must be key=value"
)
key, value = pair.split("=", 1)
container_labels[key] = value
return container_labels

def _load_global_config(
self, global_config_file: Optional[str], global_config_overrides: dict
) -> GlobalConfig:
Expand Down
6 changes: 4 additions & 2 deletions buildrunner/docker/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import six
import timeout_decorator

from buildrunner import BuildRunnerConfig
from buildrunner.docker import (
new_client,
force_remove_container,
Expand Down Expand Up @@ -79,10 +80,10 @@ def __init__(self, image_name, pull_image=True, platform=None):
def __init__(self, image_config, dockerd_url=None, log=None):
image_name = image_config.image_name
pull_image = image_config.pull_image
platform = image_config.platform
image_platform = image_config.platform

self.image_name = image_name.lower()
self.platform = platform
self.platform = image_platform
if log and self.image_name != image_name:
log.write(
f"Forcing image_name to lowercase: {image_name} => {self.image_name}\n"
Expand Down Expand Up @@ -230,6 +231,7 @@ def start(
"user": user,
"working_dir": working_dir,
"hostname": hostname,
"labels": BuildRunnerConfig.get_instance().container_labels,
"host_config": self.docker_client.create_host_config(
binds=_binds,
links=links,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from setuptools import setup, find_packages


BASE_VERSION = "3.14"
BASE_VERSION = "3.15"

SOURCE_DIR = os.path.dirname(os.path.abspath(__file__))
BUILDRUNNER_DIR = os.path.join(SOURCE_DIR, "buildrunner")
Expand Down
21 changes: 20 additions & 1 deletion tests/test_caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from time import sleep
from unittest import mock

from buildrunner import BuildRunner
from buildrunner import BuildRunner, BuildRunnerConfig
from buildrunner.docker.runner import DockerRunner
from buildrunner.loggers import ConsoleLogger
import pytest
Expand All @@ -28,6 +28,25 @@ def _tar_safe_extractall(tar, path=".", members=None, *, numeric_owner=False):
tar.extractall(path, members, numeric_owner=numeric_owner)


@pytest.fixture(name="initialize_config", autouse=True)
def fixture_initialize_config(tmp_path):
buildrunner_path = tmp_path / "buildrunner.yaml"
buildrunner_path.write_text("steps: {'step1': {}}")
BuildRunnerConfig.initialize_instance(
build_id="123",
vcs=None,
build_dir=str(tmp_path),
global_config_file=None,
run_config_file=str(buildrunner_path),
build_time=0,
build_number=1,
push=False,
steps_to_run=None,
log_generated_files=False,
global_config_overrides={},
)


@pytest.fixture(name="runner")
def fixture_setup_runner():
image_config = DockerRunner.ImageConfig(
Expand Down
64 changes: 64 additions & 0 deletions tests/test_config_validation/test_container_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import os
from unittest import mock

import pytest

from buildrunner import BuildRunner, BuildRunnerConfig


TEST_DIR = os.path.dirname(os.path.abspath(__file__))
BLANK_GLOBAL_CONFIG = os.path.join(TEST_DIR, "files/blank_global_config.yaml")


@pytest.mark.parametrize(
"container_labels, result_labels",
[
(None, {}),
("", {}),
("key1=val1", {"key1": "val1"}),
("key1=val1,key2=val2", {"key1": "val1", "key2": "val2"}),
("key1=val1=val3,key2=val2", {"key1": "val1=val3", "key2": "val2"}),
],
)
@mock.patch("buildrunner.detect_vcs")
def test_container_labels(
detect_vcs_mock,
container_labels,
result_labels,
tmp_path,
):
id_string = "main-921.ie02ed8.m1705616822"
type(detect_vcs_mock.return_value).id_string = mock.PropertyMock(
return_value=id_string
)
buildrunner_path = tmp_path / "buildrunner.yaml"
buildrunner_path.write_text(
"""
steps:
build-container:
build:
dockerfile: |
FROM {{ DOCKER_REGISTRY }}/nginx:latest
RUN printf '{{ BUILDRUNNER_BUILD_NUMBER }}' > /usr/share/nginx/html/index.html
"""
)
BuildRunner(
build_dir=str(tmp_path),
build_results_dir=str(tmp_path / "buildrunner.results"),
global_config_file=None,
run_config_file=str(buildrunner_path),
build_time=0,
build_number=1,
push=False,
cleanup_images=False,
cleanup_cache=False,
steps_to_run=None,
publish_ports=False,
log_generated_files=False,
docker_timeout=30,
local_images=False,
platform=None,
global_config_overrides={},
container_labels=container_labels,
)
assert BuildRunnerConfig.get_instance().container_labels == result_labels

0 comments on commit a5664bc

Please sign in to comment.