From c5dac60d35dcd8feb418d49e32d0bb0b0165c15d Mon Sep 17 00:00:00 2001 From: jyejare Date: Mon, 16 Sep 2024 13:55:50 +0530 Subject: [PATCH] Cloudwash solidifying podman cleanup --- cloudwash/cli.py | 14 +++++++ cloudwash/client.py | 7 +++- cloudwash/entities/resources/containers.py | 43 +++++++++++++++------- cloudwash/providers/podman.py | 6 +-- cloudwash/utils.py | 14 +++++++ settings.yaml.template | 17 +++++++++ 6 files changed, 81 insertions(+), 20 deletions(-) diff --git a/cloudwash/cli.py b/cloudwash/cli.py index bbcff222f..ec96a2a32 100644 --- a/cloudwash/cli.py +++ b/cloudwash/cli.py @@ -6,6 +6,7 @@ from cloudwash.providers.aws import cleanup as awsCleanup from cloudwash.providers.azure import cleanup as azureCleanup from cloudwash.providers.gce import cleanup as gceCleanup +from cloudwash.providers.podman import cleanup as podmanCleanup # Adding the pythonpath for importing modules from cloudwash packages # sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))) @@ -115,6 +116,19 @@ def aws(ctx, vms, discs, nics, images, pips, stacks, _all): ) +@cleanup_providers.command(help="Cleanup Podman provider") +@click.option("--containers", is_flag=True, help="Remove containers from the podman host") +@click.pass_context +def podman(ctx, containers): + # Validate Podman Settings + validate_provider(ctx.command.name) + is_dry_run = ctx.parent.params["dry"] + podmanCleanup( + containers=containers, + dry_run=is_dry_run, + ) + + @cleanup_providers.command(help="Cleanup VMWare provider") @common_options @click.pass_context diff --git a/cloudwash/client.py b/cloudwash/client.py index 3db7f46d9..b155dec50 100644 --- a/cloudwash/client.py +++ b/cloudwash/client.py @@ -34,11 +34,16 @@ def compute_client(compute_resource, **kwargs): password=settings.aws.auth.secret_key, region=kwargs['aws_region'], ) + elif compute_resource == "podman": + client = wrapanapi.Podman( + hostname=settings.podman.auth.hostname, + username=settings.podman.auth.username, + port=settings.podman.auth.ssh_port, + ) else: raise ValueError( f"{compute_resource} is an incorrect value. It should be one of azure or gce or ec2" ) - try: yield client finally: diff --git a/cloudwash/entities/resources/containers.py b/cloudwash/entities/resources/containers.py index 9a8a21ad4..47deec84b 100644 --- a/cloudwash/entities/resources/containers.py +++ b/cloudwash/entities/resources/containers.py @@ -2,6 +2,7 @@ from cloudwash.entities.resources.base import ContainerCleanup from cloudwash.logger import logger from cloudwash.utils import dry_data +from cloudwash.utils import total_running_time class CleanContainers(ContainerCleanup): @@ -9,38 +10,52 @@ def __init__(self, client): self.client = client self._delete = [] self._stop = [] + self._skip = [] self.list() def _set_dry(self): dry_data['CONTAINERS']['delete'] = self._delete - dry_data['CONTAINERS']['delete'] = self._stop + dry_data['CONTAINERS']['stop'] = self._stop + dry_data['CONTAINERS']['skip'] = self._skip def list(self): pass def stop(self): - pass + for container in self._stop: + self.client.get_container(container).stop() + logger.info(f"Stopped Podman Containers: \n{self._stop}") def remove(self): - pass + for container in self._delete: + self.client.get_container(container).delete(force=True) + logger.info(f"Removed Podman Containers: \n{self._delete}") + + def skip(self): + logger.info(f"Skipped VMs: \n{self._skip}") def cleanup(self): if not settings.dry_run: self.remove() + self.stop() + self.skip() class CleanPodmanContainers(CleanContainers): def list(self): - if settings.podman.criteria.containers.something: - pass - # rdiscs = self.client.get_all_unattached_volumes() - # rdiscs = [rdisc["VolumeId"] for rdisc in rdiscs] - # self._delete.extend(rdiscs) - self._set_dry() - def stop(self): - pass + for container in self.client.containers: + container_name = container.name + if container_name in settings.podman.exceptions.container.skip_list: + self._skip.append(container_name) + continue + elif total_running_time(container).minutes >= settings.podman.criteria.container.sla: - def remove(self): - # self.client.remove_all_unused_volumes() - logger.info(f"Removed Podman Containers: \n{self._delete}") + if container_name in settings.podman.exceptions.container.stop_list: + self._stop.append(container_name) + continue + + elif container_name.startswith(settings.podman.criteria.container.name_prepend): + self._delete.append(container_name) + + self._set_dry() diff --git a/cloudwash/providers/podman.py b/cloudwash/providers/podman.py index d2af7e0ed..759686065 100644 --- a/cloudwash/providers/podman.py +++ b/cloudwash/providers/podman.py @@ -1,9 +1,7 @@ """Azure CR Cleanup Utilities""" from cloudwash.client import compute_client -from cloudwash.config import settings from cloudwash.constants import container_data as data from cloudwash.entities.providers import PodmanCleanup -from cloudwash.logger import logger from cloudwash.utils import dry_data from cloudwash.utils import echo_dry @@ -15,9 +13,7 @@ def cleanup(**kwargs): with compute_client("podman") as podman_client: podmancleanup = PodmanCleanup(client=podman_client) # Actual Cleaning and dry execution - if kwargs["containers"] or kwargs["_all"]: + if kwargs["containers"]: podmancleanup.containers.cleanup() - if kwargs["images"] or kwargs["_all"]: - podmancleanup.images.cleanup() if is_dry_run: echo_dry(dry_data) diff --git a/cloudwash/utils.py b/cloudwash/utils.py index e450b9919..705379002 100644 --- a/cloudwash/utils.py +++ b/cloudwash/utils.py @@ -7,6 +7,8 @@ from cloudwash.logger import logger _vms_dict = {"VMS": {"delete": [], "stop": [], "skip": []}} +_containers_dict = {"CONTAINERS": {"delete": [], "stop": [], "skip": []}} + dry_data = { "NICS": {"delete": []}, "DISCS": {"delete": []}, @@ -16,6 +18,7 @@ "IMAGES": {"delete": []}, } dry_data.update(_vms_dict) +dry_data.update(_containers_dict) def echo_dry(dry_data=None) -> None: @@ -28,6 +31,9 @@ def echo_dry(dry_data=None) -> None: deletable_vms = dry_data["VMS"]["delete"] stopable_vms = dry_data["VMS"]["stop"] skipped_vms = dry_data["VMS"]["skip"] + deletable_containers = dry_data["CONTAINERS"]["delete"] + stopable_containers = dry_data["CONTAINERS"]["stop"] + skipped_containers = dry_data["CONTAINERS"]["skip"] deletable_discs = dry_data["DISCS"]["delete"] deletable_nics = dry_data["NICS"]["delete"] deletable_images = dry_data["IMAGES"]["delete"] @@ -39,6 +45,11 @@ def echo_dry(dry_data=None) -> None: f"VMs:\n\tDeletable: {deletable_vms}\n\tStoppable: {stopable_vms}\n\t" f"Skip: {skipped_vms}" ) + if deletable_containers or stopable_containers or skipped_containers: + logger.info( + f"Containers:\n\tDeletable: {deletable_containers}\n\tStoppable: {stopable_containers}\n\t" + f"Skip: {skipped_containers}" + ) if deletable_discs: logger.info(f"DISCs:\n\tDeletable: {deletable_discs}") if deletable_nics: @@ -61,6 +72,9 @@ def echo_dry(dry_data=None) -> None: deletable_resources, deletable_stacks, deletable_images, + deletable_containers, + stopable_containers, + skipped_containers ] ): logger.info("\nNo resources are eligible for cleanup!") diff --git a/settings.yaml.template b/settings.yaml.template index 70c65165b..ee19551ea 100644 --- a/settings.yaml.template +++ b/settings.yaml.template @@ -109,3 +109,20 @@ AWS: # CloudFormations names that would be skipped from cleanup STACK_LIST: [] IMAGES: [] +PODMAN: + AUTH: + HOSTNAME: + USERNAME: root + SSH_PORT: 22 + CRITERIA: + CONTAINER: + # Container Prepended Test + NAME_PREPEND: 'satci' + # Container running time in minutes + SLA: 720 + EXCEPTIONS: + CONTAINER: + # Containers to skip and not to delete + SKIP_LIST: [] + # Contsiners to stop if running but not delete + STOP_LIST: []