2022-02-20 11:34:44 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import logging
|
|
|
|
import pathlib
|
|
|
|
from typing import Set
|
|
|
|
|
|
|
|
import click
|
|
|
|
import sh
|
|
|
|
from sh import systemctl
|
|
|
|
from sh import podman
|
|
|
|
|
|
|
|
SERVICES_BASE_PATH = "/docker/services/"
|
|
|
|
|
|
|
|
|
|
|
|
def resolve_image_units():
|
|
|
|
services_path = pathlib.Path(SERVICES_BASE_PATH)
|
|
|
|
services_list = list(map(lambda p: str(p.name), services_path.iterdir()))
|
|
|
|
image_units: Set[str] = set()
|
|
|
|
|
2022-03-18 14:41:25 +00:00
|
|
|
logging.info(f"Found {len(services_list)} services: {str(services_list)}")
|
|
|
|
|
2022-02-20 11:34:44 +00:00
|
|
|
def process_pod_systemctl_show(line: str):
|
|
|
|
search_str = "Wants="
|
|
|
|
if line.startswith(search_str):
|
|
|
|
for unit in line[len(search_str) :].split(" "):
|
|
|
|
if unit.startswith("image@") and unit.endswith(".service"):
|
|
|
|
image_units.add(unit)
|
|
|
|
|
|
|
|
with click.progressbar(
|
|
|
|
length=len(services_list) * 2, label="Collecting container image services.."
|
|
|
|
) as bar:
|
|
|
|
started_processes = []
|
|
|
|
for service in services_list:
|
|
|
|
process = systemctl.show(
|
|
|
|
f"pod@{service}.service",
|
|
|
|
_out=process_pod_systemctl_show,
|
|
|
|
_bg=True,
|
|
|
|
_done=lambda cmd, success, exit_code: bar.update(1),
|
|
|
|
)
|
|
|
|
started_processes.append(process)
|
|
|
|
# join processes
|
|
|
|
[p.wait() for p in started_processes]
|
|
|
|
|
|
|
|
first = True
|
|
|
|
new_image_units: Set[str] = set(image_units)
|
|
|
|
previous_image_units: Set[str] = set(image_units)
|
|
|
|
bar.length = len(image_units) * 2
|
|
|
|
|
|
|
|
while first or len(new_image_units) > 0:
|
|
|
|
first = False
|
|
|
|
started_processes = []
|
|
|
|
for service in new_image_units:
|
|
|
|
process = systemctl.show(
|
|
|
|
service,
|
|
|
|
_out=process_pod_systemctl_show,
|
|
|
|
_bg=True,
|
|
|
|
_done=lambda cmd, success, exit_code: bar.update(1),
|
|
|
|
)
|
|
|
|
started_processes.append(process)
|
|
|
|
# join processes
|
|
|
|
[p.wait() for p in started_processes]
|
|
|
|
new_image_units = image_units.difference(previous_image_units)
|
|
|
|
bar.length += len(new_image_units)
|
|
|
|
previous_image_units = set(image_units)
|
|
|
|
|
2022-03-18 14:41:25 +00:00
|
|
|
logging.info(f"Found {len(image_units)} images: {str(image_units)}")
|
2022-02-20 11:34:44 +00:00
|
|
|
return image_units
|
|
|
|
|
|
|
|
|
2022-03-18 14:41:25 +00:00
|
|
|
@click.command()
|
|
|
|
@click.option("--verbose", is_flag=True, default=False, help="Enable INFO logging")
|
|
|
|
def main(verbose):
|
|
|
|
if verbose:
|
|
|
|
loglevel = logging.INFO
|
|
|
|
else:
|
|
|
|
loglevel = logging.CRITICAL
|
|
|
|
|
|
|
|
logging.basicConfig(level=loglevel)
|
2022-02-20 11:34:44 +00:00
|
|
|
image_units = resolve_image_units()
|
|
|
|
image_tags: Set[str] = set()
|
|
|
|
|
|
|
|
def process_image_systemctl_show(line: str):
|
|
|
|
search_str = "Environment="
|
|
|
|
if line.startswith(search_str):
|
|
|
|
for unit in line[len(search_str) :].split(" "):
|
|
|
|
search_str = "IMAGE_TAG="
|
|
|
|
if unit.startswith(search_str):
|
|
|
|
image_tags.add(unit[len(search_str) :])
|
|
|
|
|
|
|
|
started_processes = []
|
2022-03-18 14:08:56 +00:00
|
|
|
with click.progressbar(
|
|
|
|
length=len(image_units), label="Collecting container images.."
|
|
|
|
) as bar:
|
|
|
|
for image_service in image_units:
|
2022-02-20 11:34:44 +00:00
|
|
|
process = systemctl.show(
|
|
|
|
image_service,
|
|
|
|
_out=process_image_systemctl_show,
|
|
|
|
_bg=True,
|
|
|
|
_done=lambda cmd, success, exit_code: bar.update(1),
|
|
|
|
)
|
|
|
|
started_processes.append(process)
|
|
|
|
# join processes
|
|
|
|
[p.wait() for p in started_processes]
|
|
|
|
|
|
|
|
started_processes = []
|
|
|
|
with click.progressbar(
|
2022-03-18 14:08:56 +00:00
|
|
|
length=len(image_tags), label="Untagging container images..", show_pos=True
|
2022-02-20 11:34:44 +00:00
|
|
|
) as bar:
|
2022-03-18 14:08:56 +00:00
|
|
|
for image_tag in image_tags:
|
2022-02-20 11:34:44 +00:00
|
|
|
process = podman.untag(
|
|
|
|
image_tag,
|
|
|
|
_bg=True,
|
|
|
|
_done=lambda cmd, success, exit_code: bar.update(1),
|
|
|
|
)
|
|
|
|
started_processes.append(process)
|
|
|
|
# join processes
|
|
|
|
for p in started_processes:
|
|
|
|
try:
|
|
|
|
p.wait()
|
|
|
|
except sh.ErrorReturnCode:
|
|
|
|
# ignore missing tags
|
|
|
|
if "image not known".encode() not in p.stderr:
|
|
|
|
raise
|
|
|
|
|
|
|
|
started_processes = []
|
|
|
|
with click.progressbar(
|
2022-03-18 14:08:56 +00:00
|
|
|
length=len(image_units), label="Building images..", show_pos=True
|
2022-02-20 11:34:44 +00:00
|
|
|
) as bar:
|
2022-03-18 14:08:56 +00:00
|
|
|
for image_service in image_units:
|
2022-02-20 11:34:44 +00:00
|
|
|
process = systemctl.restart(
|
|
|
|
image_service,
|
|
|
|
_bg=True,
|
|
|
|
_done=lambda cmd, success, exit_code: bar.update(1),
|
|
|
|
)
|
|
|
|
started_processes.append(process)
|
|
|
|
# join processes
|
|
|
|
[p.wait() for p in started_processes]
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|