Skip to content

Commit 7961463

Browse files
ErinLMooreanshrma
authored andcommitted
Fixes error that happens when attempting to reach a disabled region (awslabs#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.
1 parent c451cb6 commit 7961463

File tree

3 files changed

+33
-45
lines changed

3 files changed

+33
-45
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ s3transfer-0.1.8.dist-info
1717
six-1.10.0.dist-info
1818
__pycache__
1919
s3transfer-0.1.9.dist-info
20-
requests
2120
botocore-1.4.68.dist-info
2221
docutils-0.12.dist-info
23-
requests-2.11.1.dist-info
2422
.idea

main.py

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,7 @@
1515
import argparse
1616
import os
1717
import re
18-
1918
import boto3
20-
try:
21-
import requests
22-
except ImportError:
23-
from botocore.vendored import requests
2419

2520
REGION = None
2621
DRYRUN = None
@@ -46,12 +41,10 @@ def initialize():
4641
def handler(event, context):
4742
initialize()
4843
if REGION == "None":
49-
partitions = requests.get("https://raw.githubusercontent.com/boto/botocore/develop/botocore/data/endpoints.json").json()[
50-
'partitions']
51-
for partition in partitions:
52-
if partition['partition'] == "aws":
53-
for endpoint in partition['services']['ecs']['endpoints']:
54-
discover_delete_images(endpoint)
44+
ec2_client = boto3.client('ec2')
45+
available_regions = ec2_client.describe_regions()['Regions']
46+
for region in available_regions:
47+
discover_delete_images(region['RegionName'])
5548
else:
5649
discover_delete_images(REGION)
5750

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

69-
# print(repositories)
70-
7162
ecs_client = boto3.client('ecs', region_name=regionname)
7263

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

131122
print("Number of running images found {}".format(len(running_sha)))
132-
123+
ignore_tags_regex = re.compile(IGNORE_TAGS_REGEX)
133124
for image in tagged_images:
134125
if tagged_images.index(image) >= IMAGES_TO_KEEP:
135126
for tag in image['imageTags']:
136-
if "latest" not in tag and re.compile(IGNORE_TAGS_REGEX).search(tag) is None:
127+
if "latest" not in tag and ignore_tags_regex.search(tag) is None:
137128
if not running_sha or image['imageDigest'] not in running_sha:
138129
append_to_list(deletesha, image['imageDigest'])
139130
append_to_tag_list(deletetag, {"imageUrl": repository['repositoryUri'] + ":" + tag,
140-
"pushedAt": image["imagePushedAt"]})
131+
"pushedAt": image["imagePushedAt"]})
141132
if deletesha:
142133
print("Number of images to be deleted: {}".format(len(deletesha)))
143134
delete_images(
@@ -151,23 +142,23 @@ def discover_delete_images(regionname):
151142
print("Nothing to delete in repository : " + repository['repositoryName'])
152143

153144

154-
def append_to_list(list, id):
155-
if not {'imageDigest': id} in list:
156-
list.append({'imageDigest': id})
145+
def append_to_list(image_digest_list, repo_id):
146+
if not {'imageDigest': repo_id} in image_digest_list:
147+
image_digest_list.append({'imageDigest': repo_id})
157148

158149

159-
def append_to_tag_list(list, id):
160-
if not id in list:
161-
list.append(id)
150+
def append_to_tag_list(tag_list, tag_id):
151+
if not tag_id in tag_list:
152+
tag_list.append(tag_id)
162153

163154

164-
def chunks(l, n):
155+
def chunks(repo_list, chunk_size):
165156
"""Yield successive n-sized chunks from l."""
166-
for i in range(0, len(l), n):
167-
yield l[i:i + n]
157+
for i in range(0, len(repo_list), chunk_size):
158+
yield repo_list[i:i + chunk_size]
168159

169160

170-
def delete_images(ecr_client, deletesha, deletetag, id, name):
161+
def delete_images(ecr_client, deletesha, deletetag, repo_id, name):
171162
if len(deletesha) >= 1:
172163
## spliting list of images to delete on chunks with 100 images each
173164
## http://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_BatchDeleteImage.html#API_BatchDeleteImage_RequestSyntax
@@ -176,13 +167,13 @@ def delete_images(ecr_client, deletesha, deletetag, id, name):
176167
i += 1
177168
if not DRYRUN:
178169
delete_response = ecr_client.batch_delete_image(
179-
registryId=id,
170+
registryId=repo_id,
180171
repositoryName=name,
181172
imageIds=deletesha_chunk
182173
)
183174
print(delete_response)
184175
else:
185-
print("registryId:" + id)
176+
print("registryId:" + repo_id)
186177
print("repositoryName:" + name)
187178
print("Deleting {} chank of images".format(i))
188179
print("imageIds:", end='')
@@ -195,21 +186,21 @@ def delete_images(ecr_client, deletesha, deletetag, id, name):
195186

196187
# Below is the test harness
197188
if __name__ == '__main__':
198-
request = {"None": "None"}
199-
parser = argparse.ArgumentParser(description='Deletes stale ECR images')
200-
parser.add_argument('-dryrun', help='Prints the repository to be deleted without deleting them', default='true',
189+
REQUEST = {"None": "None"}
190+
PARSER = argparse.ArgumentParser(description='Deletes stale ECR images')
191+
PARSER.add_argument('-dryrun', help='Prints the repository to be deleted without deleting them', default='true',
201192
action='store', dest='dryrun')
202-
parser.add_argument('-imagestokeep', help='Number of image tags to keep', default='100', action='store',
193+
PARSER.add_argument('-imagestokeep', help='Number of image tags to keep', default='100', action='store',
203194
dest='imagestokeep')
204-
parser.add_argument('-region', help='ECR/ECS region', default=None, action='store', dest='region')
205-
parser.add_argument('-ignoretagsregex', help='Regex of tag names to ignore', default="^$", action='store', dest='ignoretagsregex')
195+
PARSER.add_argument('-region', help='ECR/ECS region', default=None, action='store', dest='region')
196+
PARSER.add_argument('-ignoretagsregex', help='Regex of tag names to ignore', default="^$", action='store', dest='ignoretagsregex')
206197

207-
args = parser.parse_args()
208-
if args.region:
209-
os.environ["REGION"] = args.region
198+
ARGS = PARSER.parse_args()
199+
if ARGS.region:
200+
os.environ["REGION"] = ARGS.region
210201
else:
211202
os.environ["REGION"] = "None"
212-
os.environ["DRYRUN"] = args.dryrun.lower()
213-
os.environ["IMAGES_TO_KEEP"] = args.imagestokeep
214-
os.environ["IGNORE_TAGS_REGEX"] = args.ignoretagsregex
215-
handler(request, None)
203+
os.environ["DRYRUN"] = ARGS.dryrun.lower()
204+
os.environ["IMAGES_TO_KEEP"] = ARGS.imagestokeep
205+
os.environ["IGNORE_TAGS_REGEX"] = ARGS.ignoretagsregex
206+
handler(REQUEST, None)

requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
boto3
2-
requests
1+
boto3

0 commit comments

Comments
 (0)