Skip to content

Commit 91eda1c

Browse files
authored
Merge pull request #172 from bluesliverx/main
Add support for systemd v248+
2 parents 6d3c56c + 4efc743 commit 91eda1c

File tree

7 files changed

+92
-26
lines changed

7 files changed

+92
-26
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ENV PIP_DEFAULT_TIMEOUT 60
55

66
# Install the docker client for multiplatform builds
77
RUN apt update && \
8-
apt install ca-certificates curl && \
8+
apt -y install ca-certificates curl && \
99
install -m 0755 -d /etc/apt/keyrings && \
1010
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && \
1111
chmod a+r /etc/apt/keyrings/docker.asc && \

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,12 @@ the run step:
640640
# 'BUILDRUNNER_SYSTEMD'.
641641
# If found, systemd=true will be assumed.
642642
systemd: true/false
643+
# (Ignored when systemd is not enabled)
644+
# For systemd 248+, a read-write mount for /sys/fs/cgroup is required as well as a tmpfs mounted at /run, and
645+
# this flag enables this behavior
646+
# If this is ommitted, the image will be inspected for the label
647+
# 'BUILDRUNNER_SYSTEMD_V248' and that value will be used instead.
648+
systemd_v248: true/false
643649
644650
# Docker supports certain kernel capabilities, like 'SYS_ADMIN'.
645651
# see https://goo.gl/gTQrqW for more infromation on setting these.

buildrunner/config/models_step.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class RunAndServicesBase(StepTask):
104104
ports: Optional[Dict[int, Optional[int]]] = None
105105
pull: Optional[bool] = None
106106
systemd: Optional[bool] = None
107+
systemd_v248: Optional[bool] = None
107108
containers: Optional[List[str]] = None
108109
caches: Optional[Dict[str, Union[str, List[str]]]] = None
109110

buildrunner/docker/runner.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ def start(
149149
dns_search=None,
150150
extra_hosts=None,
151151
containers=None,
152-
systemd=None,
152+
systemd: bool = False,
153+
systemd_v248: bool = False,
153154
cap_add=None,
154155
privileged=False,
155156
): # pylint: disable=too-many-arguments,too-many-locals
@@ -172,11 +173,17 @@ def start(
172173

173174
security_opt = None
174175
command = shell
176+
tmpfs = {}
177+
cgroupns = None
175178
if systemd:
176-
# If we are running in a systemd context,
177-
# the following 3 settings are necessary to
179+
# If we are running in a systemd context, the following 3 settings are necessary to
178180
# allow services to run.
179-
volumes["/sys/fs/cgroup"] = "/sys/fs/cgroup:ro"
181+
if systemd_v248:
182+
volumes["/sys/fs/cgroup/buildrunner.scope"] = "/sys/fs/cgroup:rw"
183+
tmpfs["/run"] = ""
184+
cgroupns = "host"
185+
else:
186+
volumes["/sys/fs/cgroup"] = "/sys/fs/cgroup:ro"
180187
security_opt = ["seccomp=unconfined"]
181188
command = "/usr/sbin/init"
182189

@@ -225,6 +232,8 @@ def start(
225232
security_opt=security_opt,
226233
cap_add=cap_add,
227234
privileged=privileged,
235+
tmpfs=tmpfs,
236+
cgroupns=cgroupns,
228237
),
229238
}
230239
if entrypoint:

buildrunner/steprunner/tasks/run.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ def _start_service_container(self, name, service: Service):
598598
)
599599
self._service_runners[name] = service_runner
600600
cont_name = self.step_runner.id + "-" + name
601+
systemd = self.is_systemd(service, _image)
601602
service_container_id = service_runner.start(
602603
name=cont_name,
603604
volumes=_volumes,
@@ -614,7 +615,8 @@ def _start_service_container(self, name, service: Service):
614615
extra_hosts=_extra_hosts,
615616
working_dir=_cwd,
616617
containers=_containers,
617-
systemd=self.is_systemd(service, _image, service_logger),
618+
systemd=systemd,
619+
systemd_v248=self.is_systemd_v248(systemd, service, _image),
618620
)
619621
self._service_links[cont_name] = name
620622

@@ -1022,8 +1024,9 @@ def run(self, context: dict): # pylint: disable=too-many-statements,too-many-br
10221024
log=self.step_runner.log,
10231025
)
10241026
# Figure out if we should be running systemd. Has to happen after docker pull
1025-
container_args["systemd"] = self.is_systemd(
1026-
self.step, _run_image, self.step_runner.log
1027+
container_args["systemd"] = self.is_systemd(self.step, _run_image)
1028+
container_args["systemd_v248"] = self.is_systemd_v248(
1029+
container_args["systemd"], self.step, _run_image
10271030
)
10281031

10291032
container_id = self.runner.start(
@@ -1143,22 +1146,34 @@ def cleanup(self, context): # pylint: disable=unused-argument
11431146
for image in self.images_to_remove:
11441147
python_on_whales.docker.image.remove(image, force=True)
11451148

1146-
def is_systemd(self, run_service: RunAndServicesBase, image, logger):
1147-
"""Check if an image runs systemd"""
1148-
# Unused argument
1149-
_ = logger
1149+
def _get_label_is_truthy(self, image, label_name: str) -> bool:
1150+
labels = (
1151+
self._docker_client.inspect_image(image).get("Config", {}).get("Labels", {})
1152+
)
1153+
if not labels or label_name not in labels:
1154+
return False
1155+
# Labels will be set as the string value. Make sure we handle '0' and 'False'
1156+
value = labels.get(label_name, False)
1157+
return bool(value and value != "0" and value != "False")
11501158

1151-
rval = False
1152-
if run_service.systemd:
1153-
rval = run_service.systemd
1154-
else:
1155-
labels = (
1156-
self._docker_client.inspect_image(image)
1157-
.get("Config", {})
1158-
.get("Labels", {})
1159-
)
1160-
if labels and "BUILDRUNNER_SYSTEMD" in labels:
1161-
rval = labels.get("BUILDRUNNER_SYSTEMD", False)
1159+
def is_systemd(self, run_service: RunAndServicesBase, image: str) -> bool:
1160+
"""
1161+
Check if an image runs systemd
1162+
"""
1163+
if run_service.systemd is not None:
1164+
return run_service.systemd
1165+
return self._get_label_is_truthy(image, "BUILDRUNNER_SYSTEMD")
11621166

1163-
# Labels will be set as the string value. Make sure we handle '0' and 'False'
1164-
return bool(rval and rval != "0" and rval != "False")
1167+
def is_systemd_v248(
1168+
self, systemd: bool, run_service: RunAndServicesBase, image: str
1169+
) -> bool:
1170+
"""
1171+
Check if an image needs the changes for systemd v248+
1172+
"""
1173+
if not systemd:
1174+
# Do not run any other checks if we are not using systemd at all
1175+
return False
1176+
1177+
if run_service.systemd_v248 is not None:
1178+
return run_service.systemd_v248
1179+
return self._get_label_is_truthy(image, "BUILDRUNNER_SYSTEMD_V248")

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from setuptools import setup, find_packages
1414

1515

16-
BASE_VERSION = "3.13"
16+
BASE_VERSION = "3.14"
1717

1818
SOURCE_DIR = os.path.dirname(os.path.abspath(__file__))
1919
BUILDRUNNER_DIR = os.path.join(SOURCE_DIR, "buildrunner")

tests/test-files/test-systemd.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ steps:
6161
run:
6262
systemd: true
6363
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init
64+
test-systemd-v248-on:
65+
build:
66+
dockerfile: |
67+
# Rocky linux 9 has 248+ installed
68+
FROM {{ DOCKER_REGISTRY }}/rockylinux:9.0
69+
RUN yum install -y procps-ng && yum clean all
70+
run:
71+
systemd: true
72+
systemd_v248: true
73+
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init
6474

6575
test-systemd-on-built:
6676
build:
@@ -71,6 +81,16 @@ steps:
7181
run:
7282
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init
7383

84+
test-systemd-v248-on-built:
85+
build:
86+
dockerfile: |
87+
FROM {{ DOCKER_REGISTRY }}/rockylinux:9.0
88+
RUN yum install -y procps-ng && yum clean all
89+
LABEL BUILDRUNNER_SYSTEMD=1
90+
LABEL BUILDRUNNER_SYSTEMD_V248=1
91+
run:
92+
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init
93+
7494
{% for v in ["", "0", "False"]: %}
7595
test-systemd-off-built-{{ v }}:
7696
build:
@@ -98,3 +118,18 @@ steps:
98118
image: {{ DOCKER_REGISTRY }}/rockylinux:8.5
99119
pull: false
100120
cmd: curl http://s1:8001 1>/dev/null 2>&1
121+
test-systemd-v248-service:
122+
run:
123+
services:
124+
s1:
125+
build:
126+
dockerfile: |
127+
FROM {{ DOCKER_REGISTRY }}/rockylinux:9.0
128+
RUN yum -y install python3 procps-ng && yum clean all
129+
LABEL BUILDRUNNER_SYSTEMD=1
130+
LABEL BUILDRUNNER_SYSTEMD_V248=1
131+
systemd: true
132+
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init && python3 -m http.server 8001
133+
image: {{ DOCKER_REGISTRY }}/rockylinux:8.5
134+
pull: false
135+
cmd: curl http://s1:8001 1>/dev/null 2>&1

0 commit comments

Comments
 (0)