Skip to content

Commit

Permalink
Fixes error that happens when attempting to reach a disabled region (a…
Browse files Browse the repository at this point in the history
…wslabs#33)

* Now gets list of available regions from a 'describe regions' call to an
ec2 client. This fixes an issue where an error would be thrown when
attempting to reach a disabled region.

* Linting changes to bring code in line with Pylint. Also refactors regex
compile to be outside of for loop.
  • Loading branch information
ErinLMoore authored and anshrma committed May 14, 2019
1 parent c451cb6 commit 7961463
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 45 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ s3transfer-0.1.8.dist-info
six-1.10.0.dist-info
__pycache__
s3transfer-0.1.9.dist-info
requests
botocore-1.4.68.dist-info
docutils-0.12.dist-info
requests-2.11.1.dist-info
.idea
73 changes: 32 additions & 41 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@
import argparse
import os
import re

import boto3
try:
import requests
except ImportError:
from botocore.vendored import requests

REGION = None
DRYRUN = None
Expand All @@ -46,12 +41,10 @@ def initialize():
def handler(event, context):
initialize()
if REGION == "None":
partitions = requests.get("https://raw.githubusercontent.com/boto/botocore/develop/botocore/data/endpoints.json").json()[
'partitions']
for partition in partitions:
if partition['partition'] == "aws":
for endpoint in partition['services']['ecs']['endpoints']:
discover_delete_images(endpoint)
ec2_client = boto3.client('ec2')
available_regions = ec2_client.describe_regions()['Regions']
for region in available_regions:
discover_delete_images(region['RegionName'])
else:
discover_delete_images(REGION)

Expand All @@ -66,8 +59,6 @@ def discover_delete_images(regionname):
for repo in response_listrepopaginator['repositories']:
repositories.append(repo)

# print(repositories)

ecs_client = boto3.client('ecs', region_name=regionname)

listclusters_paginator = ecs_client.get_paginator('list_clusters')
Expand Down Expand Up @@ -129,15 +120,15 @@ def discover_delete_images(regionname):
running_sha.append(image['imageDigest'])

print("Number of running images found {}".format(len(running_sha)))

ignore_tags_regex = re.compile(IGNORE_TAGS_REGEX)
for image in tagged_images:
if tagged_images.index(image) >= IMAGES_TO_KEEP:
for tag in image['imageTags']:
if "latest" not in tag and re.compile(IGNORE_TAGS_REGEX).search(tag) is None:
if "latest" not in tag and ignore_tags_regex.search(tag) is None:
if not running_sha or image['imageDigest'] not in running_sha:
append_to_list(deletesha, image['imageDigest'])
append_to_tag_list(deletetag, {"imageUrl": repository['repositoryUri'] + ":" + tag,
"pushedAt": image["imagePushedAt"]})
"pushedAt": image["imagePushedAt"]})
if deletesha:
print("Number of images to be deleted: {}".format(len(deletesha)))
delete_images(
Expand All @@ -151,23 +142,23 @@ def discover_delete_images(regionname):
print("Nothing to delete in repository : " + repository['repositoryName'])


def append_to_list(list, id):
if not {'imageDigest': id} in list:
list.append({'imageDigest': id})
def append_to_list(image_digest_list, repo_id):
if not {'imageDigest': repo_id} in image_digest_list:
image_digest_list.append({'imageDigest': repo_id})


def append_to_tag_list(list, id):
if not id in list:
list.append(id)
def append_to_tag_list(tag_list, tag_id):
if not tag_id in tag_list:
tag_list.append(tag_id)


def chunks(l, n):
def chunks(repo_list, chunk_size):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
for i in range(0, len(repo_list), chunk_size):
yield repo_list[i:i + chunk_size]


def delete_images(ecr_client, deletesha, deletetag, id, name):
def delete_images(ecr_client, deletesha, deletetag, repo_id, name):
if len(deletesha) >= 1:
## spliting list of images to delete on chunks with 100 images each
## http://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_BatchDeleteImage.html#API_BatchDeleteImage_RequestSyntax
Expand All @@ -176,13 +167,13 @@ def delete_images(ecr_client, deletesha, deletetag, id, name):
i += 1
if not DRYRUN:
delete_response = ecr_client.batch_delete_image(
registryId=id,
registryId=repo_id,
repositoryName=name,
imageIds=deletesha_chunk
)
print(delete_response)
else:
print("registryId:" + id)
print("registryId:" + repo_id)
print("repositoryName:" + name)
print("Deleting {} chank of images".format(i))
print("imageIds:", end='')
Expand All @@ -195,21 +186,21 @@ def delete_images(ecr_client, deletesha, deletetag, id, name):

# Below is the test harness
if __name__ == '__main__':
request = {"None": "None"}
parser = argparse.ArgumentParser(description='Deletes stale ECR images')
parser.add_argument('-dryrun', help='Prints the repository to be deleted without deleting them', default='true',
REQUEST = {"None": "None"}
PARSER = argparse.ArgumentParser(description='Deletes stale ECR images')
PARSER.add_argument('-dryrun', help='Prints the repository to be deleted without deleting them', default='true',
action='store', dest='dryrun')
parser.add_argument('-imagestokeep', help='Number of image tags to keep', default='100', action='store',
PARSER.add_argument('-imagestokeep', help='Number of image tags to keep', default='100', action='store',
dest='imagestokeep')
parser.add_argument('-region', help='ECR/ECS region', default=None, action='store', dest='region')
parser.add_argument('-ignoretagsregex', help='Regex of tag names to ignore', default="^$", action='store', dest='ignoretagsregex')
PARSER.add_argument('-region', help='ECR/ECS region', default=None, action='store', dest='region')
PARSER.add_argument('-ignoretagsregex', help='Regex of tag names to ignore', default="^$", action='store', dest='ignoretagsregex')

args = parser.parse_args()
if args.region:
os.environ["REGION"] = args.region
ARGS = PARSER.parse_args()
if ARGS.region:
os.environ["REGION"] = ARGS.region
else:
os.environ["REGION"] = "None"
os.environ["DRYRUN"] = args.dryrun.lower()
os.environ["IMAGES_TO_KEEP"] = args.imagestokeep
os.environ["IGNORE_TAGS_REGEX"] = args.ignoretagsregex
handler(request, None)
os.environ["DRYRUN"] = ARGS.dryrun.lower()
os.environ["IMAGES_TO_KEEP"] = ARGS.imagestokeep
os.environ["IGNORE_TAGS_REGEX"] = ARGS.ignoretagsregex
handler(REQUEST, None)
3 changes: 1 addition & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
boto3
requests
boto3

0 comments on commit 7961463

Please sign in to comment.