From 11ccb59e8e1254305143c82efe8a3b2bce070ffe Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Mon, 11 Dec 2023 14:45:46 -0500 Subject: [PATCH] cephadm: convert init containers script to use a template Convert the init containers run script to be based on a template, like the sidecar run scripts are. The new script is loosely based on the sidecars run script but only does actions in batches - logically iterating over each init container configured. Signed-off-by: John Mulligan --- src/cephadm/cephadmlib/container_types.py | 3 + src/cephadm/cephadmlib/runscripts.py | 53 ++++------------- .../templates/init_containers.run.j2 | 57 +++++++++++++++++++ src/cephadm/cephadmlib/templating.py | 1 + src/cephadm/tests/test_custom_container.py | 23 ++++---- 5 files changed, 84 insertions(+), 53 deletions(-) create mode 100644 src/cephadm/cephadmlib/templates/init_containers.run.j2 diff --git a/src/cephadm/cephadmlib/container_types.py b/src/cephadm/cephadmlib/container_types.py index 0bdbb5c80bbe7..2af16eb47504c 100644 --- a/src/cephadm/cephadmlib/container_types.py +++ b/src/cephadm/cephadmlib/container_types.py @@ -492,6 +492,9 @@ class InitContainer(BasicContainer): def rm_cmd(self, storage: bool = False) -> List[str]: return self.build_rm_cmd(storage=storage) + def stop_cmd(self, timeout: Optional[int] = None) -> List[str]: + return self.build_stop_cmd(timeout=timeout) + class SidecarContainer(BasicContainer): @classmethod diff --git a/src/cephadm/cephadmlib/runscripts.py b/src/cephadm/cephadmlib/runscripts.py index 52694b16b9c0c..b4f83ab3077f6 100644 --- a/src/cephadm/cephadmlib/runscripts.py +++ b/src/cephadm/cephadmlib/runscripts.py @@ -161,44 +161,6 @@ def _write_container_cmd_to_bash( _bash_cmd(file_obj, container.run_cmd(), background=bool(background)) -def _write_init_container_cmds( - ctx: CephadmContext, - file_obj: IO[str], - index: int, - init_container: 'InitContainer', -) -> None: - file_obj.write(f'# init container {index}: {init_container.cname}\n') - _bash_cmd(file_obj, init_container.run_cmd()) - _write_init_container_cmds_clean( - ctx, file_obj, init_container, comment='' - ) - - -def _write_init_container_cmds_clean( - ctx: CephadmContext, - file_obj: IO[str], - init_container: 'InitContainer', - comment: str = 'init container cleanup', -) -> None: - if comment: - assert '\n' not in comment - file_obj.write(f'# {comment}\n') - _bash_cmd( - file_obj, - init_container.rm_cmd(), - check=False, - stderr=False, - ) - # Sometimes, `podman rm` doesn't find the container. Then you'll have to add `--storage` - if isinstance(ctx.container_engine, Podman): - _bash_cmd( - file_obj, - init_container.rm_cmd(storage=True), - check=False, - stderr=False, - ) - - def _write_stop_actions( ctx: CephadmContext, f: TextIO, @@ -221,12 +183,17 @@ def _write_init_containers_script( ctx: CephadmContext, file_obj: IO[str], init_containers: List[InitContainer], + comment: str = 'start and stop init containers', ) -> None: - file_obj.write('set -e\n') - _write_init_container_cmds_clean(ctx, file_obj, init_containers[0]) - for idx, ic in enumerate(init_containers): - _write_init_container_cmds(ctx, file_obj, idx, ic) - file_obj.write('exit 0\n') + has_podman_engine = isinstance(ctx.container_engine, Podman) + templating.render_to_file( + file_obj, + ctx, + templating.Templates.init_ctr_run, + init_containers=init_containers, + comment=comment, + has_podman_engine=has_podman_engine, + ) def _write_sidecar_script( diff --git a/src/cephadm/cephadmlib/templates/init_containers.run.j2 b/src/cephadm/cephadmlib/templates/init_containers.run.j2 new file mode 100644 index 0000000000000..b93b7ac1aef57 --- /dev/null +++ b/src/cephadm/cephadmlib/templates/init_containers.run.j2 @@ -0,0 +1,57 @@ +#!/bin/sh +# {{ comment }} + +set -e + +stop_all_init_containers() { + {%- for ic in init_containers %} + # stop init container {{ loop.index0 }}: {{ ic.cname }} + ! {{ ic.stop_cmd() | map('shellquote') | join(' ') }} + {%- endfor %} + return 0 +} + +rm_all_init_containers() { + {%- for ic in init_containers %} + # remove init container {{ loop.index0 }}: {{ ic.cname }} + ! {{ ic.rm_cmd() | map('shellquote') | join(' ') }} 2> /dev/null + {%- if has_podman_engine %} + ! {{ ic.rm_cmd(storage=True) | map('shellquote') | join(' ') }} 2> /dev/null + {%- endif %} + {%- endfor %} + return 0 +} + +has_running_init_container() { + {%- for ic in init_containers %} + if {{ ctx.container_engine.path }} inspect {{ ic.cname | shellquote }} &>/dev/null; then return 0; fi + {%- endfor %} + return 1 +} + +run_init_containers() { + {%- for ic in init_containers %} + # run init container {{ loop.index0 }}: {{ ic.cname }} + {{ ic.run_cmd() | map('shellquote') | join(' ') }} + # clean up {{ ic.cname }} + ! {{ ic.rm_cmd() | map('shellquote') | join(' ') }} 2> /dev/null + {%- if has_podman_engine %} + ! {{ ic.rm_cmd(storage=True) | map('shellquote') | join(' ') }} 2> /dev/null + {%- endif %} + {%- endfor %} + return 0 +} + +if [ "$1" = stop ] || [ "$1" = poststop ]; then + stop_all_init_containers + if has_running_init_container; then + exit 1 + fi + exit 0 +fi + +# init container cleanup +rm_all_init_containers + +run_init_containers +exit 0 diff --git a/src/cephadm/cephadmlib/templating.py b/src/cephadm/cephadmlib/templating.py index 4604d8c14c747..8c28cde57c278 100644 --- a/src/cephadm/cephadmlib/templating.py +++ b/src/cephadm/cephadmlib/templating.py @@ -28,6 +28,7 @@ class Templates(str, enum.Enum): cluster_logrotate_config = 'cluster.logrotate.config.j2' cephadm_logrotate_config = 'cephadm.logrotate.config.j2' sidecar_run = 'sidecar.run.j2' + init_ctr_run = 'init_containers.run.j2' def __str__(self) -> str: return self.value diff --git a/src/cephadm/tests/test_custom_container.py b/src/cephadm/tests/test_custom_container.py index fec435594a738..c185b0908df6c 100644 --- a/src/cephadm/tests/test_custom_container.py +++ b/src/cephadm/tests/test_custom_container.py @@ -226,12 +226,15 @@ def test_deploy_custom_container_and_inits(cephadm_fs): idx = icfile_lines.index('# init container cleanup') assert idx >= 0 - assert icfile_lines[idx + 1].startswith('! /usr/bin/podman rm') - assert icfile_lines[idx + 2].startswith('! /usr/bin/podman rm') + assert any( + l.strip().startswith('! /usr/bin/podman rm') + for l in icfile_lines + ) - idx = icfile_lines.index('# init container 0: ceph-b01dbeef-701d-9abe-0000-e1e5a47004a7-container-tdccai-init') + slines = [l.strip() for l in icfile_lines] + idx = slines.index('# run init container 0: ceph-b01dbeef-701d-9abe-0000-e1e5a47004a7-container-tdccai-init') assert idx > 0 - assert icfile_lines[idx + 1] == ( + assert slines[idx + 1] == ( '/usr/bin/podman run' ' --stop-signal=SIGTERM' ' --entrypoint /usr/local/bin/prepare.sh' @@ -240,12 +243,12 @@ def test_deploy_custom_container_and_inits(cephadm_fs): ' -v /var/lib/ceph/b01dbeef-701d-9abe-0000-e1e5a47004a7/container.tdccai/data1:/var/lib/myapp' ' quay.io/foobar/quux:latest' ) - assert icfile_lines[idx + 2].startswith('! /usr/bin/podman rm') - assert icfile_lines[idx + 3].startswith('! /usr/bin/podman rm') + assert slines[idx + 3].startswith('! /usr/bin/podman rm') + assert slines[idx + 4].startswith('! /usr/bin/podman rm') - idx = icfile_lines.index('# init container 1: ceph-b01dbeef-701d-9abe-0000-e1e5a47004a7-container-tdccai-init') + idx = slines.index('# run init container 1: ceph-b01dbeef-701d-9abe-0000-e1e5a47004a7-container-tdccai-init') assert idx > 0 - assert icfile_lines[idx + 1] == ( + assert slines[idx + 1] == ( '/usr/bin/podman run' ' --stop-signal=SIGTERM' ' --entrypoint /usr/local/bin/populate.sh' @@ -256,5 +259,5 @@ def test_deploy_custom_container_and_inits(cephadm_fs): ' quay.io/foobar/quux:latest' ' --source=https://my.cool.example.com/samples/geo.1.txt' ) - assert icfile_lines[idx + 2].startswith('! /usr/bin/podman rm') - assert icfile_lines[idx + 3].startswith('! /usr/bin/podman rm') + assert slines[idx + 3].startswith('! /usr/bin/podman rm') + assert slines[idx + 4].startswith('! /usr/bin/podman rm') -- 2.39.5