aws_ami_cleanup 0.1 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db5bf4d59de51127ee6dab8a547cce124a734dd1c628096e59509ea21dd572d4
4
- data.tar.gz: 5a6aa3840422b64a71be65ce11ac2a290e4e46a2e5f8730865537ce8676c3368
3
+ metadata.gz: fdb3d28f7c0eb4b2c6acd19468ff42990802239afed6d39d966bdf9e314af913
4
+ data.tar.gz: aec4c2d2bea2f67e295df587023c300075602037c093063d726e3a9dffe797b0
5
5
  SHA512:
6
- metadata.gz: 8f6000074b50a25f566478022a78a341b676a0fa10eb8cc7945043889035bf5b0b080bac0eede9748ce1886db13c0f92745f0fe2f0abe254acc2a80d93f95f16
7
- data.tar.gz: 212429abd100adba8cf1be8cbda5a322237a5114ffba2114b3266bce54e1be56d5f1a1dad184f1d2a5245b9713f039063ab2c33f6359a3d506f1d0b3769fadf3
6
+ metadata.gz: 00bc9351ee496669abbc4e5c0bb66c6ece7c7ad4f71ea3e1607785fa9f4a2890066d9d94cffc10c5b998cb99afa17ad0bf2535cc305e7655303f40151a668e2e
7
+ data.tar.gz: 3c2741cb1ae825e8ee0e6433914635839415c8365f2fdb5244e8c6a7c5d9fcfb99c8aa83f95a2936ef79a6c058e580d726dd1e36f88efc51441279eaedad374f
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.6.6
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 `number_of_amis_to_keep` argument to specify how many AMIs to keep (default is 3) and `region` for the AWS region (default is `us-east-1`).
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.
@@ -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("byebug", "~> 11")
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
- ami_ids_to_remove = ami_ids - amis_in_use
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
- ami.deregister
36
- delete_ami_snapshots(ebs_mappings)
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 ec2
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 ||= Aws::AutoScaling::Client.new(region: region)
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 = ec2.describe_images(describe_images_params).images
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 << ec2.describe_launch_template_versions(launch_template_id: launch_template_id, max_results: 1)
84
- .launch_template_versions
85
- .first
86
- .launch_template_data
87
- .image_id
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 = ec2.describe_instances
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
- snapshot = Aws::EC2::Snapshot.new(snapshot_id)
111
- snapshot.delete
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: false
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(region, options[:number_of_amis_to_keep]&.to_i)
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], ami_owner: options[:ami_owner])
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 'byebug'
19
- byebug
30
+ require 'debug'
31
+ debugger
20
32
  end
21
33
 
22
34
  protected
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AwsAmiCleanup
4
- VERSION = "0.1"
4
+ VERSION = "1.1"
5
5
  end
6
6
 
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: '0.1'
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: byebug
56
+ name: debug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '11'
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: '11'
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.0.8
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: []