Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Deploy code to Lambda
on: push

env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
REPO_NAME: ${{ github.event.repository.name }}

jobs:
deploy-lambda:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Setup python 3.8'
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: 'Zip it all'
run: |
mkdir -p zip_folder
cp -R src/* zip_folder
pip install -r requirements.txt --target=zip_folder
cd zip_folder
zip -r ../${REPO_NAME}.zip .
- name: 'Setup terraform'
uses: hashicorp/setup-terraform@v1
with:
terraform_version: '>=0.13.0 <0.14.0'
- name: 'Terraform init'
working-directory: terraform
run: terraform init
- name: 'Terraform validate'
working-directory: terraform
run: terraform validate
- name: 'Terraform plan'
working-directory: terraform
run: |
terraform plan -out="${REPO_NAME}.tfplan"
- name: 'Terraform apply'
working-directory: terraform
run: terraform apply -auto-approve "${REPO_NAME}.tfplan"
38 changes: 38 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy code to Lambda
on: push

env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
REPO_NAME: ${{ github.event.repository.name }}

jobs:
deploy-lambda:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Setup python 3.8'
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: 'Zip it all'
run: |
mkdir -p zip_folder
cp -R src/* zip_folder
pip install -r requirements.txt --target=zip_folder
cd zip_folder
zip -r ../${REPO_NAME}.zip .
- name: 'Setup terraform'
uses: hashicorp/setup-terraform@v1
with:
terraform_version: '>=0.13.0 <0.14.0'
- name: 'Terraform init'
working-directory: terraform
run: terraform init
- name: 'Terraform validate'
working-directory: terraform
run: terraform validate
- name: Lint Terraform
working-directory: terraform
uses: actionshub/terraform-lint@master
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,18 @@ s3transfer-0.1.9.dist-info
botocore-1.4.68.dist-info
docutils-0.12.dist-info
.idea
DS_Store

### Terraform ###
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

zip_folder
*.zip
10 changes: 0 additions & 10 deletions LICENSE

This file was deleted.

2 changes: 0 additions & 2 deletions NOTICE

This file was deleted.

73 changes: 24 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,40 @@
# Automated Image Cleanup for Amazon ECR
The Python script and Lambda function described here help clean up images in [Amazon ECR](https://aws.amazon.com/ecr). The script looks for images that are not used in running [Amazon ECS](https://aws.amazon.com/ecs) tasks that can be deleted. You can configure the script to print the image list first to confirm deletions, specify a region, or specify a number of images to keep for potential rollbacks.
The Python script and Lambda function described here help clean up images in [Amazon ECR](https://aws.amazon.com/ecr).
- The script looks for images that are not used in running [Amazon ECS](https://aws.amazon.com/ecs) tasks that can be deleted.
- Only looks images in repos specified in GitHubActions env var ECR_REPOS_LIFECYCLE ex: ECR_REPOS_LIFECYCLE='apache, nginx'
- You can configure the script to print the image list first to confirm deletions, specify a region, or specify a number of images to keep for potential rollbacks with DRYRUN=true
- You can skip images followin a REGEX in their tag.

## Authenticate with AWS
[Configuring the AWS Command Line Interface.](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)

## Use virtualenv for Python execution

To prevent any problems with your system Python version conflicting with the application, we recommend using virtualenv.
## Usage in local

Install Python:
`pip install python 3`

Install virtualenv:

$ pip install virtualenv
$ virtualenv -p PATH_TO_YOUR_PYTHON_3 cloudformtion
$ virtualenv ~/.virtualenvs/cloudformtion
$ source ~/.virtualenvs/cloudformtion/bin/activate

## Generate the Lambda package
Getting info about local env:
`which python3`

1. CD to the folder that contains main.py.
1. Run the following command:
`pip install -r requirements.txt -t `pwd``
1. Compress the contents of folder (not the folder).

## Upload the package to Lambda

1. Run the following command:
`aws lambda create-function --function-name {NAME_OF_FUNCTION} --runtime python2.7
--role {ARN_NUMBER} --handler main.handler --timeout 15
--zip-file fileb://{ZIP_FILE_PATH}`

## Send the package update to Lambda
Install virtualenv:

1. Run the following command:
pip install virtualenv
virtualenv --python=/usr/local/bin/python3 ~/venv-ecr-cleanup-lambda
source ~/venv-ecr-cleanup-lambda/bin/activate

`aws lambda update-function-code --function-name {NAME_OF_FUNCTION} --zip-file fileb://{ZIP_FILE_PATH}`


## Examples
Prints the images that are not used by running tasks and which are older than the last 100 versions, in all regions:

`python main.py`


Deletes the images that are not used by running tasks and which are older than the last 100 versions, in all regions:

`python main.py –dryrun False`


Deletes the images that are not used by running tasks and which are older than the last 20 versions (in each repository), in all regions:
## Install dependencies

`python main.py –dryrun False –imagestokeep 20`
`pip install -r requirements.txt`

## Example

Deletes the images that are not used by running tasks and which are older than the last 20 versions (in each repository), in Oregon only:
Deletes the images that:
- are not used by ECS running tasks .
- are older than the last 20 versions (in each repository).
- in Oregon only.
- ignore image tags that contains `release` or `archive`.
- skip images with tags that contain alpine and apache.

`python main.py –dryrun False –imagestokeep 20 –region us-west-2`
`python main.py –dryrun False –imagestokeep 20 –region us-west-2 -ignoretagsregex 'release|archive' -ecr_repos_lifecycle 'alpine,apache'`

Deletes the images that are not used by running tasks and which are older than the last 20 versions (in each repository), in Oregon only, and ignore image tags that contains `release` or `archive`:

`python main.py –dryrun False –imagestokeep 20 –region us-west-2 -ignoretagsregex release|archive`
## Credits

Fork of awslabs/ecr-cleanup-lambda adding functionality of ECR_REPOS_LIFECYCLE var.
78 changes: 0 additions & 78 deletions lambda-cloudformation.yaml

This file was deleted.

19 changes: 6 additions & 13 deletions main.py → src/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
'''
Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
the License. A copy of the License is located at

http://aws.amazon.com/apache2.0/

or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and
limitations under the License.
'''
from __future__ import print_function

import argparse
Expand All @@ -21,13 +9,15 @@
DRYRUN = None
IMAGES_TO_KEEP = None
IGNORE_TAGS_REGEX = None
ECR_REPOS_LIFECYCLE = None


def initialize():
global REGION
global DRYRUN
global IMAGES_TO_KEEP
global IGNORE_TAGS_REGEX
global ECR_REPOS_LIFECYCLE

REGION = os.environ.get('REGION', "None")
DRYRUN = os.environ.get('DRYRUN', "false").lower()
Expand All @@ -37,6 +27,8 @@ def initialize():
DRYRUN = True
IMAGES_TO_KEEP = int(os.environ.get('IMAGES_TO_KEEP', 100))
IGNORE_TAGS_REGEX = os.environ.get('IGNORE_TAGS_REGEX', "^$")
ECR_REPOS_LIFECYCLE = os.environ.get('ECR_REPOS_LIFECYCLE', "None")


def handler(event, context):
initialize()
Expand All @@ -57,7 +49,8 @@ def discover_delete_images(regionname):
describe_repo_paginator = ecr_client.get_paginator('describe_repositories')
for response_listrepopaginator in describe_repo_paginator.paginate():
for repo in response_listrepopaginator['repositories']:
repositories.append(repo)
if repo['repositoryName'] in ECR_REPOS_LIFECYCLE.split(','):
repositories.append(repo)

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

Expand Down
Loading