Skip to content

Commit

Permalink
Create html based report for dry runs
Browse files Browse the repository at this point in the history
Signed-off-by: M Sajid Mansoori <[email protected]>
  • Loading branch information
msajidmansoori12 committed Aug 2, 2024
1 parent be3409b commit e134bc6
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 43 deletions.
68 changes: 68 additions & 0 deletions assets/css/reporting.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* CSS for html report generated during dry run. */
body{
font-family: sans-serif;
}
h1,h3{
margin-left: 15px;
}
table, th, td {
border-collapse: collapse;
margin-left: 0;
}

#cloud_table {
border-collapse: collapse;
margin: 25px 0;
font: 0.9em sans-serif;
min-width: 800px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
border-radius: 5px 5px 0 0;
overflow: hidden;
}

#cloud_table thead tr {
background-color: #009879;
color: #ffffff;
text-align: center;
font-weight: bold;
}

#cloud_table th, #cloud_table td {
padding: 12px 15px;
}

#cloud_table th:not(:last-child), #cloud_table td:not(:last-child) {
border-right: 0.1px solid black;
}

#cloud_table tbody tr {
border-bottom: 1px solid #dddddd;
color: #488b8b;
font-weight: bold;
}

#cloud_table tbody tr:nth-of-type(odd) {
background-color: #f3f3f3;
}

#cloud_table tbody tr:last-of-type {
border-bottom: 2px solid #009879;
}

#cloud_table tbody td {
text-align: left;
}

ul {
margin: 0;
padding: 0 0 0 20px;
list-style-type: circle;
}

ul li {
margin-top: 10px;
margin-bottom: 10px;
}
#cloud_table td {
font-size: 0.8em;
}
1 change: 1 addition & 0 deletions cloudwash/providers/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

def cleanup(**kwargs):
is_dry_run = kwargs.get("dry_run", False)
dry_data['PROVIDER'] = "AWS"
regions = settings.aws.auth.regions
if "all" in regions:
with compute_client("aws", aws_region="us-west-2") as client:
Expand Down
3 changes: 1 addition & 2 deletions cloudwash/providers/azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

def cleanup(**kwargs):
is_dry_run = kwargs["dry_run"]

dry_data['PROVIDER'] = "AZURE"
regions = settings.azure.auth.regions
groups = settings.azure.auth.resource_groups

Expand All @@ -19,7 +19,6 @@ def cleanup(**kwargs):
# as it's never accessed and is only stored within wrapper
with compute_client("azure", azure_region="us-west", resource_group="foo") as azure_client:
regions = list(zip(*azure_client.list_region()))[0]

for region in regions:
if "all" in groups:
# non-existent RG can be chosen for query
Expand Down
2 changes: 1 addition & 1 deletion cloudwash/providers/gce.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

def cleanup(**kwargs):
is_dry_run = kwargs["dry_run"]

dry_data['PROVIDER'] = "GCE"
with compute_client("gce") as gce_client:
if kwargs["vms"] or kwargs["_all"]:
allvms = gce_client.list_vms(zones=gce_zones())
Expand Down
98 changes: 58 additions & 40 deletions cloudwash/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

from cloudwash.logger import logger

import dominate
from dominate.tags import *


_vms_dict = {"VMS": {"delete": [], "stop": [], "skip": []}}
dry_data = {
"NICS": {"delete": []},
Expand All @@ -14,6 +18,7 @@
"RESOURCES": {"delete": []},
"STACKS": {"delete": []},
"IMAGES": {"delete": []},
"PROVIDER": ""
}
dry_data.update(_vms_dict)

Expand All @@ -24,48 +29,61 @@ def echo_dry(dry_data=None) -> None:
:param dict dry_data: The deletable resources dry data of a Compute Resource,
it follows the format of module scoped `dry_data` variable in this module
"""

logger.info("\n=========== DRY SUMMARY ============\n")
deletable_vms = dry_data["VMS"]["delete"]
stopable_vms = dry_data["VMS"]["stop"]
skipped_vms = dry_data["VMS"]["skip"]
deletable_discs = dry_data["DISCS"]["delete"]
deletable_nics = dry_data["NICS"]["delete"]
deletable_images = dry_data["IMAGES"]["delete"]
deletable_pips = dry_data["PIPS"]["delete"] if "PIPS" in dry_data else None
deletable_resources = dry_data["RESOURCES"]["delete"]
deletable_stacks = dry_data["STACKS"]["delete"] if "STACKS" in dry_data else None
if deletable_vms or stopable_vms or skipped_vms:
logger.info(
f"VMs:\n\tDeletable: {deletable_vms}\n\tStoppable: {stopable_vms}\n\t"
f"Skip: {skipped_vms}"
)
if deletable_discs:
logger.info(f"DISCs:\n\tDeletable: {deletable_discs}")
if deletable_nics:
logger.info(f"NICs:\n\tDeletable: {deletable_nics}")
if deletable_images:
logger.info(f"IMAGES:\n\tDeletable: {deletable_images}")
if deletable_pips:
logger.info(f"PIPs:\n\tDeletable: {deletable_pips}")
if deletable_resources:
logger.info(f"RESOURCEs:\n\tDeletable: {deletable_resources}")
if deletable_stacks:
logger.info(f"STACKs:\n\tDeletable: {deletable_stacks}")
if not any(
[
deletable_vms,
stopable_vms,
deletable_discs,
deletable_nics,
deletable_pips,
deletable_resources,
deletable_stacks,
deletable_images,
]
):
logger.info("\nNo resources are eligible for cleanup!")
logger.info("\n====================================\n")
resource_data = {
"provider": dry_data.get('PROVIDER'),
"deletable_vms": dry_data["VMS"]["delete"],
"stopable_vms": dry_data["VMS"]["stop"],
"skipped_vms": dry_data["VMS"]["skip"],
"deletable_discs": dry_data["DISCS"]["delete"],
"deletable_nics": dry_data["NICS"]["delete"],
"deletable_images": dry_data["IMAGES"]["delete"],
"deletable_pips": dry_data["PIPS"]["delete"] if "PIPS" in dry_data else None,
"deletable_resources": dry_data["RESOURCES"]["delete"],
"deletable_stacks": dry_data["STACKS"]["delete"] if "STACKS" in dry_data else None
}
if any(value for key, value in resource_data.items() if key != 'provider'):
logger.info("Resources eligible for cleanup:")
for key, value in resource_data.items():
if value and key!="provider":
logger.info(f"{key.replace('_', ' ').title()}:\n\t{key.split('_')[0].title()}: {value}")

logger.info("\n====================================\n")

create_html(**resource_data)
else:
logger.info("\nNo resources are eligible for cleanup!\n")

def create_html(**kwargs):
''' Creates a html based report file with deletable resources.'''
doc = dominate.document(title="Cloud resources page")

with doc.head:
with open('assets/css/reporting.css','r') as css:
style(css.read())

with doc:
with div(cls='cloud_box'):
h1('CLOUDWASH REPORT')
h3(f"{kwargs.get('provider')} RESOURCES")
with table(id='cloud_table'):
with thead():
with tr():
for table_head in kwargs.keys():
if kwargs[table_head] and table_head!="provider":
th(table_head.replace("_"," ").title())
with tbody():
for key,values in kwargs.items():
if key!="provider" and values:
if isinstance(values,list):
with td():
with ul():
[li(resource_name) for resource_name in values]
else:
td(values)
with open('cleanup_resource.html','w') as file:
file.write(doc.render())

def total_running_time(vm_obj) -> namedtuple:
"""Calculates the VMs total running time
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ install_requires =
dynaconf
click
wget
dominate
packages = find:

[options.extras_require]
Expand Down

0 comments on commit e134bc6

Please sign in to comment.