aws_ami_cleanup 0.1 → 1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/README.md +7 -1
- data/aws_ami_cleanup.gemspec +1 -1
- data/lib/aws_ami_cleanup/cleanup_amis.rb +76 -18
- data/lib/aws_ami_cleanup/commands.rb +17 -5
- data/lib/aws_ami_cleanup/version.rb +1 -1
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdb3d28f7c0eb4b2c6acd19468ff42990802239afed6d39d966bdf9e314af913
|
4
|
+
data.tar.gz: aec4c2d2bea2f67e295df587023c300075602037c093063d726e3a9dffe797b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00bc9351ee496669abbc4e5c0bb66c6ece7c7ad4f71ea3e1607785fa9f4a2890066d9d94cffc10c5b998cb99afa17ad0bf2535cc305e7655303f40151a668e2e
|
7
|
+
data.tar.gz: 3c2741cb1ae825e8ee0e6433914635839415c8365f2fdb5244e8c6a7c5d9fcfb99c8aa83f95a2936ef79a6c058e580d726dd1e36f88efc51441279eaedad374f
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-
|
1
|
+
ruby-3.1.2
|
data/README.md
CHANGED
@@ -8,6 +8,7 @@ This gem provides the `cleanup_amis` script that allows deregistering unused AMI
|
|
8
8
|
- ec2:DeregisterImage
|
9
9
|
- ec2:DeleteSnapshot
|
10
10
|
- autoscaling:DescribeAutoScalingGroups
|
11
|
+
- autoscaling:DescribeLaunchConfigurations
|
11
12
|
|
12
13
|
Script should be invoked as follows:
|
13
14
|
|
@@ -17,4 +18,9 @@ cleanup_amis clean_amis --ami_name 'my-ami' --ami_owner 'self'
|
|
17
18
|
|
18
19
|
Where `ami_owner` can be a combination of AWS account IDs, `self`, `amazon`, and `aws-marketplace`.
|
19
20
|
|
20
|
-
Additionally you can provide the
|
21
|
+
Additionally you can provide the following arguments:
|
22
|
+
|
23
|
+
- `number_of_amis_to_keep` to specify how many AMIs to keep (default is 3).
|
24
|
+
- `region` for the AWS region (default is `us-east-1`).
|
25
|
+
- `dry_run` for running without deleting any resources in AWS.
|
26
|
+
- `skip_image_under_use_verification` for skipping verification on whether the AMI is being used by any auto scaling group or reserved EC2 instance.
|
data/aws_ami_cleanup.gemspec
CHANGED
@@ -26,5 +26,5 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.add_runtime_dependency "aws-sdk-ec2", "~> 1"
|
27
27
|
s.add_runtime_dependency "aws-sdk-autoscaling", "~> 1"
|
28
28
|
s.add_runtime_dependency "thor", "~> 1"
|
29
|
-
s.add_development_dependency("
|
29
|
+
s.add_development_dependency("debug")
|
30
30
|
end
|
@@ -7,21 +7,41 @@ module AwsAmiCleanup
|
|
7
7
|
class CleanupAmis
|
8
8
|
DEFAULT_NUMBER_OF_AMIS_TO_KEEP = 3
|
9
9
|
|
10
|
-
attr_accessor :region, :number_of_amis_to_keep
|
10
|
+
attr_accessor :region, :number_of_amis_to_keep, :skip_image_under_use_verification
|
11
11
|
|
12
|
-
def initialize(region, number_of_amis_to_keep)
|
12
|
+
def initialize(region, number_of_amis_to_keep, skip_image_under_use_verification:, assume_role_for_querying_state:, aws_role_for_querying_state:)
|
13
13
|
@region = region
|
14
14
|
|
15
15
|
@number_of_amis_to_keep = number_of_amis_to_keep || DEFAULT_NUMBER_OF_AMIS_TO_KEEP
|
16
16
|
if number_of_amis_to_keep <= 0
|
17
17
|
raise 'Number of AMIs to keep must be higher than 0.'
|
18
18
|
end
|
19
|
+
|
20
|
+
@skip_image_under_use_verification = skip_image_under_use_verification
|
21
|
+
@assume_role_for_querying_state = assume_role_for_querying_state
|
22
|
+
|
23
|
+
if @skip_image_under_use_verification && @assume_role_for_querying_state
|
24
|
+
raise 'Cannot include skip image under use verification and assume role for querying state options'
|
25
|
+
end
|
26
|
+
|
27
|
+
if @assume_role_for_querying_state
|
28
|
+
raise "Must include the IAM role's ARN to assume if using a different role for querying state" if aws_role_for_querying_state.nil?
|
29
|
+
@aws_role_for_querying_state = aws_role_for_querying_state
|
30
|
+
end
|
19
31
|
end
|
20
32
|
|
21
|
-
def execute!(ami_name:, ami_owner:)
|
33
|
+
def execute!(ami_name:, ami_owner:, dry_run:)
|
34
|
+
puts "RUNNING IN DRY MODE." if dry_run
|
35
|
+
|
22
36
|
potential_amis_to_remove = amis(ami_name, ami_owner)
|
23
37
|
ami_ids = potential_amis_to_remove.collect(&:image_id)
|
24
|
-
|
38
|
+
|
39
|
+
if skip_image_under_use_verification
|
40
|
+
ami_ids_to_remove = ami_ids
|
41
|
+
else
|
42
|
+
ami_ids_to_remove = ami_ids - amis_in_use
|
43
|
+
end
|
44
|
+
|
25
45
|
potential_amis_to_remove.keep_if {|a| ami_ids_to_remove.include?(a.image_id) }
|
26
46
|
|
27
47
|
if potential_amis_to_remove.count > number_of_amis_to_keep
|
@@ -29,11 +49,18 @@ module AwsAmiCleanup
|
|
29
49
|
amis_to_keep = potential_amis_to_remove[0..(number_of_amis_to_keep-1)]
|
30
50
|
|
31
51
|
puts "Deregistering old AMIs..."
|
52
|
+
|
32
53
|
amis_to_remove.each do |ami|
|
33
54
|
ebs_mappings = ami.block_device_mappings
|
34
55
|
puts "Deregistering #{ami.image_id}"
|
35
|
-
|
36
|
-
|
56
|
+
|
57
|
+
begin
|
58
|
+
ec2_client_for_cleanup.deregister_image(image_id: ami.image_id, dry_run: dry_run)
|
59
|
+
rescue Aws::EC2::Errors::DryRunOperation
|
60
|
+
# When running in dry mode, EC2 raises this exception if operation would have succeeded, we catch them so the full process can run
|
61
|
+
end
|
62
|
+
|
63
|
+
delete_ami_snapshots(ebs_mappings, dry_run)
|
37
64
|
end
|
38
65
|
|
39
66
|
puts "Currently active AMIs..."
|
@@ -47,12 +74,40 @@ module AwsAmiCleanup
|
|
47
74
|
|
48
75
|
protected
|
49
76
|
|
50
|
-
def
|
77
|
+
def ec2_client_for_query_state
|
78
|
+
return @__ec2_client_for_query_state if defined?(@__ec2_client_for_query_state)
|
79
|
+
|
80
|
+
@__ec2_client_for_query_state =
|
81
|
+
if @assume_role_for_querying_state
|
82
|
+
role_credentials = Aws::AssumeRoleCredentials.new(
|
83
|
+
role_arn: @aws_role_for_querying_state,
|
84
|
+
role_session_name: 'ami-cleanup',
|
85
|
+
region: region
|
86
|
+
)
|
87
|
+
Aws::EC2::Client.new(credentials: role_credentials, region: region)
|
88
|
+
else
|
89
|
+
ec2_client_for_cleanup
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def ec2_client_for_cleanup
|
51
94
|
@__ec2 ||= Aws::EC2::Client.new(region: region)
|
52
95
|
end
|
53
96
|
|
54
97
|
def auto_scaling
|
55
|
-
@__auto_scaling
|
98
|
+
return @__auto_scaling if defined?(@__auto_scaling)
|
99
|
+
|
100
|
+
@__auto_scaling =
|
101
|
+
if @aws_role_for_querying_state
|
102
|
+
role_credentials = Aws::AssumeRoleCredentials.new(
|
103
|
+
role_arn: @aws_role_for_querying_state,
|
104
|
+
role_session_name: 'ami-cleanup',
|
105
|
+
region: region
|
106
|
+
)
|
107
|
+
Aws::AutoScaling::Client.new(credentials: role_credentials, region: region)
|
108
|
+
else
|
109
|
+
Aws::AutoScaling::Client.new(region: region)
|
110
|
+
end
|
56
111
|
end
|
57
112
|
|
58
113
|
def amis(ami_name, ami_owner)
|
@@ -60,7 +115,7 @@ module AwsAmiCleanup
|
|
60
115
|
|
61
116
|
# Cannot lookup by Name tag because that's only available from the owner account.
|
62
117
|
describe_images_params = { owners: [ ami_owner ] }
|
63
|
-
all_images_from_owner =
|
118
|
+
all_images_from_owner = ec2_client_for_query_state.describe_images(describe_images_params).images
|
64
119
|
name_matching_images = all_images_from_owner.filter {|i| i.name.match?(ami_name) }
|
65
120
|
|
66
121
|
@__amis = sort_by_created_at(name_matching_images)
|
@@ -80,11 +135,11 @@ module AwsAmiCleanup
|
|
80
135
|
launch_template_ids = autoscaling_groups.reject {|asg| asg.launch_template.nil? }
|
81
136
|
.collect {|asg| asg.launch_template.launch_template_id }
|
82
137
|
launch_template_ids.each do |launch_template_id|
|
83
|
-
image_ids <<
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
138
|
+
image_ids << ec2_client_for_query_state.describe_launch_template_versions(launch_template_id: launch_template_id, max_results: 1)
|
139
|
+
.launch_template_versions
|
140
|
+
.first
|
141
|
+
.launch_template_data
|
142
|
+
.image_id
|
88
143
|
end
|
89
144
|
|
90
145
|
# Find AMIs used by auto scaling groups with launch configurations
|
@@ -94,21 +149,24 @@ module AwsAmiCleanup
|
|
94
149
|
image_ids += launch_configurations.map(&:image_id)
|
95
150
|
|
96
151
|
# Finally, find AMIs used by instances not belonging to auto scaling groups
|
97
|
-
ec2_reservations =
|
152
|
+
ec2_reservations = ec2_client_for_query_state.describe_instances
|
98
153
|
image_ids += ec2_reservations.reservations.collect {|res| res.instances.map(&:image_id) }.flatten
|
99
154
|
|
100
155
|
image_ids.flatten
|
101
156
|
end
|
102
157
|
|
103
|
-
def delete_ami_snapshots(ebs_mappings)
|
158
|
+
def delete_ami_snapshots(ebs_mappings, dry_run)
|
104
159
|
ebs_mappings.each do |ebs_mapping|
|
105
160
|
# Skip ephimeral block devices
|
106
161
|
next if ebs_mapping.ebs.nil? || ebs_mapping.ebs.snapshot_id.nil?
|
107
162
|
|
108
163
|
snapshot_id = ebs_mapping.ebs.snapshot_id
|
109
164
|
puts "Deleting snapshot #{snapshot_id}"
|
110
|
-
|
111
|
-
|
165
|
+
begin
|
166
|
+
ec2_client_for_cleanup.delete_snapshot(snapshot_id: snapshot_id, dry_run: dry_run)
|
167
|
+
rescue Aws::EC2::Errors::DryRunOperation
|
168
|
+
# When running in dry mode, EC2 raises this exception if operation would have succeeded, we catch them so the full process can run
|
169
|
+
end
|
112
170
|
end
|
113
171
|
end
|
114
172
|
end
|
@@ -5,18 +5,30 @@ module AwsAmiCleanup
|
|
5
5
|
desc "clean_amis", "delete unused AMIs owned by ami_owner with ami_name name"
|
6
6
|
option :ami_name, required: true
|
7
7
|
option :ami_owner, required: true
|
8
|
-
option :number_of_amis_to_keep, required:
|
8
|
+
option :number_of_amis_to_keep, required: true
|
9
|
+
option :assume_role_for_querying_state, type: :boolean, required: false
|
10
|
+
option :aws_role_for_querying_state, required: false
|
11
|
+
option :dry_run, type: :boolean, required: false
|
9
12
|
option :region, required: false
|
13
|
+
option :skip_verification, type: :boolean, required: false
|
10
14
|
def clean_amis
|
11
|
-
cleanup_amis = AwsAmiCleanup::CleanupAmis.new(
|
15
|
+
cleanup_amis = AwsAmiCleanup::CleanupAmis.new(
|
16
|
+
region,
|
17
|
+
options[:number_of_amis_to_keep]&.to_i,
|
18
|
+
skip_image_under_use_verification: options[:skip_verification],
|
19
|
+
assume_role_for_querying_state: options[:assume_role_for_querying_state],
|
20
|
+
aws_role_for_querying_state: options[:aws_role_for_querying_state]
|
21
|
+
)
|
12
22
|
|
13
|
-
cleanup_amis.execute!(ami_name: options[:ami_name],
|
23
|
+
cleanup_amis.execute!(ami_name: options[:ami_name],
|
24
|
+
ami_owner: options[:ami_owner],
|
25
|
+
dry_run: options[:dry_run])
|
14
26
|
end
|
15
27
|
|
16
28
|
desc "console", "interactive session"
|
17
29
|
def console
|
18
|
-
require '
|
19
|
-
|
30
|
+
require 'debug'
|
31
|
+
debugger
|
20
32
|
end
|
21
33
|
|
22
34
|
protected
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws_ami_cleanup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Diego Marcet
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2021-02-19 00:00:00.000000000 Z
|
@@ -53,20 +53,20 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: debug
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
69
|
-
description:
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
70
|
email: diego@controlshiftlabs.com
|
71
71
|
executables:
|
72
72
|
- cleanup_amis
|
@@ -88,7 +88,7 @@ homepage: http://github.com/controlshift/aws_ami_cleanup
|
|
88
88
|
licenses:
|
89
89
|
- MIT
|
90
90
|
metadata: {}
|
91
|
-
post_install_message:
|
91
|
+
post_install_message:
|
92
92
|
rdoc_options: []
|
93
93
|
require_paths:
|
94
94
|
- lib
|
@@ -103,8 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: '0'
|
105
105
|
requirements: []
|
106
|
-
rubygems_version: 3.
|
107
|
-
signing_key:
|
106
|
+
rubygems_version: 3.3.19
|
107
|
+
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: Script for deleting obsolete AMIs
|
110
110
|
test_files: []
|