Skip to content

Commit

Permalink
Merge pull request #140 from jyejare/container_provider
Browse files Browse the repository at this point in the history
Cloudwash supporting Containers cleanup
  • Loading branch information
jyejare authored Sep 30, 2024
2 parents 97ee8a4 + 4a2ff3b commit 6a26c06
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ cloudwash supports following cloud providers:
* VMWare vCenter (_Support yet To be added_)
* OCP Clusters deplyed on Public clouds (_Support yet To be added_)

And the Containerization tools:

* Podman

The list of resource types it helps to clean could be found under settings.yaml.template](https://github.com/RedHatQE/cloudwash/blob/master/settings.yaml.template) file for individual cloud providers along with cleanup criteria.

## Installation
Expand Down Expand Up @@ -104,6 +108,7 @@ azure Cleanup Azure provider
aws Cleanup Amazon provider
gce Cleanup GCE provider
openstack Cleanup OSP provider
podman Cleanup Podman provider
rhev Cleanup RHEV provider
vmware Cleanup VMWare provider
```
Expand Down
14 changes: 14 additions & 0 deletions cloudwash/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion cloudwash/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions cloudwash/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aws_data = ['VMS', 'NICS', 'DISCS', 'PIPS', 'RESOURCES', 'STACKS']
azure_data = ['VMS', 'NICS', 'DISCS', 'IMAGES', 'PIPS', 'RESOURCES']
gce_data = ['VMS', 'NICS', 'DISCS']
container_data = ['CONTAINERS']
11 changes: 11 additions & 0 deletions cloudwash/entities/providers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from cloudwash.entities.resources.containers import CleanPodmanContainers
from cloudwash.entities.resources.discs import CleanAWSDiscs
from cloudwash.entities.resources.discs import CleanAzureDiscs
from cloudwash.entities.resources.images import CleanAWSImages
Expand Down Expand Up @@ -81,3 +82,13 @@ class GCECleanup(providerCleanup):
def __init__(self, client):
self.client = client
super().__init__(client)


class PodmanCleanup(providerCleanup):
def __init__(self, client):
self.client = client
super().__init__(client)

@property
def containers(self):
return CleanPodmanContainers(client=self.client)
26 changes: 26 additions & 0 deletions cloudwash/entities/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,32 @@ def _set_dry(self):
pass


class ContainerCleanup(ResourceCleanup):
@abstractmethod
def list(self):
pass

@abstractmethod
def cleanup(self):
pass

@abstractmethod
def stop(self):
pass

@abstractmethod
def remove(self):
pass

@abstractmethod
def skip(self):
pass

@abstractmethod
def _set_dry(self):
pass


class ResourceCleanupManager:
def __init__(self):
self.resources = []
Expand Down
60 changes: 60 additions & 0 deletions cloudwash/entities/resources/containers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from cloudwash.config import settings
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):
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']['stop'] = self._stop
dry_data['CONTAINERS']['skip'] = self._skip

def list(self):
pass

def stop(self):
for container in self._stop:
self.client.get_container(key=container).stop()
logger.info(f"Stopped Podman Containers: \n{self._stop}")

def remove(self):
for container in self._delete:
self.client.get_container(key=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):

for container in self.client.containers:
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:

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_prefix):
self._delete.append(container.name)

self._set_dry()
19 changes: 19 additions & 0 deletions cloudwash/providers/podman.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Azure CR Cleanup Utilities"""
from cloudwash.client import compute_client
from cloudwash.constants import container_data as data
from cloudwash.entities.providers import PodmanCleanup
from cloudwash.utils import dry_data
from cloudwash.utils import echo_dry


def cleanup(**kwargs):
is_dry_run = kwargs.get("dry_run", False)
for items in data:
dry_data[items]['delete'] = []
with compute_client("podman") as podman_client:
podmancleanup = PodmanCleanup(client=podman_client)
# Actual Cleaning and dry execution
if kwargs["containers"]:
podmancleanup.containers.cleanup()
if is_dry_run:
echo_dry(dry_data)
15 changes: 15 additions & 0 deletions cloudwash/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": []},
Expand All @@ -16,6 +18,7 @@
"IMAGES": {"delete": []},
}
dry_data.update(_vms_dict)
dry_data.update(_containers_dict)


def echo_dry(dry_data=None) -> None:
Expand All @@ -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"]
Expand All @@ -39,6 +45,12 @@ 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\t"
f"Stoppable: {stopable_containers}\n\t"
f"Skip: {skipped_containers}"
)
if deletable_discs:
logger.info(f"DISCs:\n\tDeletable: {deletable_discs}")
if deletable_nics:
Expand All @@ -61,6 +73,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!")
Expand Down
17 changes: 17 additions & 0 deletions settings.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -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_PREFIX: 'satci'
# Container running time in minutes
SLA: 720
EXCEPTIONS:
CONTAINER:
# Containers to skip and not to delete
SKIP_LIST: []
# Containers to stop if running but not delete
STOP_LIST: []

0 comments on commit 6a26c06

Please sign in to comment.