diff --git a/roles/aws/aws_ami_asg_cleanup/defaults/main.yml b/roles/aws/aws_ami_asg_cleanup/defaults/main.yml new file mode 100644 index 000000000..9ddead478 --- /dev/null +++ b/roles/aws/aws_ami_asg_cleanup/defaults/main.yml @@ -0,0 +1,7 @@ +aws_ami_asg_cleanup: + memory_size: 128 # Memory allocation for Lambda function in MB + timeout: 30 # Time in seconds, max is 900 + handler: "clean_up_ami.lambda_handler" # Change this only if the main_file.main_function name is changed + runtime: "python3.12" # If the python version changes we need to update this as well + keep_backups: 10 + scheduler_cron: "cron(0 16 ? * SUN *)" diff --git a/roles/aws/aws_ami_asg_cleanup/tasks/main.yml b/roles/aws/aws_ami_asg_cleanup/tasks/main.yml new file mode 100644 index 000000000..ce90e52ed --- /dev/null +++ b/roles/aws/aws_ami_asg_cleanup/tasks/main.yml @@ -0,0 +1,55 @@ +--- +- name: Create a role and attach policies + amazon.aws.iam_role: + name: LambdaAsgAmiCleanupRole + assume_role_policy_document: "{{ lookup('file', 'assume_lambda_iam_policy.j2') }}" + managed_policies: + - arn:aws:iam::aws:policy/AmazonEC2FullAccess + - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess + register: _created_iam_lambda_cleanup_role + +- name: Ensure python script is removed + ansible.builtin.file: + path: "{{ _ce_provision_build_dir }}/clean_up_ami.py" + state: absent + +- name: Ensure zip file is removed + ansible.builtin.file: + path: "{{ _ce_provision_build_dir }}/clean_up_ami.zip" + state: absent + +- name: Write Lambda function + ansible.builtin.template: + src: cleanup_ami.py.j2 + dest: "{{ _ce_provision_build_dir }}/clean_up_ami.py" + +- name: Create a zip archive of cleanup_ami.py + community.general.archive: + path: "{{ _ce_provision_build_dir }}/clean_up_ami.py" + dest: "{{ _ce_provision_build_dir }}/clean_up_ami.zip" + format: zip + +- name: Create Lambda function + amazon.aws.lambda: + name: "clean_up_ami" + region: "{{ _aws_region }}" + timeout: "{{ aws_ami_asg_cleanup.timeout }}" + state: present + zip_file: "{{ _ce_provision_build_dir }}/clean_up_ami.zip" + runtime: "{{ aws_ami_asg_cleanup.runtime }}" + role: "{{ _created_iam_lambda_cleanup_role.iam_role.arn }}" + handler: '{{ aws_ami_asg_cleanup.handler }}' + tags: + Test: 'This is test tag' + register: _created_iam_lambda_cleanup_function + +- name: Create scheduler to invoke Lambda function + amazon.aws.cloudwatchevent_rule: + name: cleanup_asg_ami + schedule_expression: "{{ aws_ami_asg_cleanup.scheduler_cron }}" + description: Clean up ASG AMIs + region: "{{ _aws_region }}" + targets: + - id: 'clean_up_ami' + arn: "{{ _created_iam_lambda_cleanup_function.configuration.function_arn }}" + input: '{"asg_name": "{{ _domain_name | regex_replace("\.", "-") }}"}' diff --git a/roles/aws/aws_ami_asg_cleanup/templates/assume_lambda_iam_policy.j2 b/roles/aws/aws_ami_asg_cleanup/templates/assume_lambda_iam_policy.j2 new file mode 100644 index 000000000..fd267525d --- /dev/null +++ b/roles/aws/aws_ami_asg_cleanup/templates/assume_lambda_iam_policy.j2 @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} diff --git a/roles/aws/aws_ami_asg_cleanup/templates/cleanup_ami.py.j2 b/roles/aws/aws_ami_asg_cleanup/templates/cleanup_ami.py.j2 new file mode 100644 index 000000000..a11bb9e3c --- /dev/null +++ b/roles/aws/aws_ami_asg_cleanup/templates/cleanup_ami.py.j2 @@ -0,0 +1,27 @@ +import json +import boto3 + +def lambda_handler(event, context): + ec2 = boto3.client("ec2", "{{ _aws_region }}") + + images = ec2.describe_images( + Filters=[ + { + 'Name': 'tag:Name', + 'Values': [ + event['asg_name'] + '*' + ] + } + ] + ) + + # Order AMIs by CreationDate + ordered_images = sorted(images['Images'], key=lambda d: d['CreationDate']) + + # Remove latest 10 AMIs from list + ordered_images = ordered_images[:len(ordered_images)-{{ aws_ami_asg_cleanup.keep_backups }}] + + for x in ordered_images: + ec2.deregister_image(ImageId=x['ImageId']) + + print(len(ordered_images)) diff --git a/roles/aws/aws_ec2_autoscale_cluster/tasks/main.yml b/roles/aws/aws_ec2_autoscale_cluster/tasks/main.yml index 9f29692ff..dd9172cc0 100644 --- a/roles/aws/aws_ec2_autoscale_cluster/tasks/main.yml +++ b/roles/aws/aws_ec2_autoscale_cluster/tasks/main.yml @@ -291,6 +291,10 @@ - aws_ec2_autoscale_cluster.type == "ec2" - aws_ec2_autoscale_cluster.deploy_cluster +- name: Create ami cleanup function + ansible.builtin.include_role: + name: aws/aws_ami_asg_cleanup + - name: Gather IAM role info. amazon.aws.iam_role_info: profile: "{{ aws_ec2_autoscale_cluster.aws_profile }}"