aws-cleaner 2.0.1 → 2.1.0
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/bin/aws_cleaner.rb +24 -185
- data/lib/aws_cleaner/aws_cleaner.rb +197 -0
- metadata +62 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 634ceede119aecae922a17090cb5d18a18855e54
|
4
|
+
data.tar.gz: e1f7409e0ba5e6096bbc9d2667aba98333e47054
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d03730f5c4a09e5ba56eb1dc4cebce0c3a27fe320a776a543faa30d70f11d85a06de04010a69537d7cd1712fbf26e4a61b96474271bd4627e7e32974c081ad4
|
7
|
+
data.tar.gz: 51409d6d97e5abb81c4bdc722f1ac7b7e0ff1d6a9915fe3ac1ff9ea356d8b4cb9ce9f5e76ebb5c95c5427747270ece2540fd6e2c73e107defd2599884e2df007
|
data/bin/aws_cleaner.rb
CHANGED
@@ -4,10 +4,11 @@
|
|
4
4
|
# and remove the node from Chef and Sensu and send a notification
|
5
5
|
# to Hipchat or Slack
|
6
6
|
#
|
7
|
-
# Copyright (c) 2015
|
7
|
+
# Copyright (c) 2015-2017 Eric Heydrick
|
8
8
|
# Licensed under The MIT License
|
9
9
|
#
|
10
10
|
|
11
|
+
# ensure gems are present
|
11
12
|
begin
|
12
13
|
require 'json'
|
13
14
|
require 'yaml'
|
@@ -21,6 +22,9 @@ rescue LoadError => e
|
|
21
22
|
raise "Missing gems: #{e}"
|
22
23
|
end
|
23
24
|
|
25
|
+
# require our class
|
26
|
+
require_relative '../lib/aws_cleaner/aws_cleaner.rb'
|
27
|
+
|
24
28
|
def config(file)
|
25
29
|
YAML.load(File.read(file))
|
26
30
|
rescue StandardError => e
|
@@ -28,185 +32,21 @@ rescue StandardError => e
|
|
28
32
|
end
|
29
33
|
|
30
34
|
# get options
|
31
|
-
opts = Trollop
|
35
|
+
opts = Trollop.options do
|
32
36
|
opt :config, 'Path to config file', type: :string, default: 'config.yml'
|
33
37
|
end
|
34
38
|
|
35
39
|
@config = config(opts[:config])
|
36
40
|
|
37
|
-
@sqs = Aws::SQS::Client.new(@config[:aws])
|
38
|
-
|
39
|
-
@chef = ChefAPI::Connection.new(
|
40
|
-
endpoint: @config[:chef][:url],
|
41
|
-
client: @config[:chef][:client],
|
42
|
-
key: @config[:chef][:key]
|
43
|
-
)
|
44
|
-
|
45
|
-
# delete the message from SQS
|
46
|
-
def delete_message(id)
|
47
|
-
delete = @sqs.delete_message(
|
48
|
-
queue_url: @config[:sqs][:queue],
|
49
|
-
receipt_handle: id
|
50
|
-
)
|
51
|
-
delete ? true : false
|
52
|
-
end
|
53
|
-
|
54
|
-
# return the body of the SQS message in JSON
|
55
|
-
def parse(body)
|
56
|
-
JSON.parse(body)
|
57
|
-
rescue JSON::ParserError
|
58
|
-
return false
|
59
|
-
end
|
60
|
-
|
61
|
-
# return the instance_id of the terminated instance
|
62
|
-
def process_message(message_body)
|
63
|
-
return false if message_body['detail']['instance-id'].nil? &&
|
64
|
-
message_body['detail']['state'] != 'terminated'
|
65
|
-
|
66
|
-
instance_id = message_body['detail']['instance-id']
|
67
|
-
instance_id
|
68
|
-
end
|
69
|
-
|
70
|
-
# call the Chef API to get the node name of the instance
|
71
|
-
def get_chef_node_name(instance_id)
|
72
|
-
results = @chef.search.query(:node, "ec2_instance_id:#{instance_id} OR chef_provisioning_reference_server_id:#{instance_id}")
|
73
|
-
if results.rows.size > 0
|
74
|
-
return results.rows.first['name']
|
75
|
-
else
|
76
|
-
return false
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# call the Chef API to get the FQDN of the instance
|
81
|
-
def get_chef_fqdn(instance_id)
|
82
|
-
results = @chef.search.query(:node, "ec2_instance_id:#{instance_id} OR chef_provisioning_reference_server_id:#{instance_id}")
|
83
|
-
if results.rows.size > 0
|
84
|
-
return results.rows.first['automatic']['fqdn']
|
85
|
-
else
|
86
|
-
return false
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# check if the node exists in Sensu
|
91
|
-
def in_sensu?(node_name)
|
92
|
-
begin
|
93
|
-
RestClient::Request.execute(url: "#{@config[:sensu][:url]}/clients/#{node_name}", method: :get, timeout: 5, open_timeout: 5)
|
94
|
-
rescue RestClient::ResourceNotFound
|
95
|
-
return false
|
96
|
-
rescue => e
|
97
|
-
puts "Sensu request failed: #{e}"
|
98
|
-
return false
|
99
|
-
else
|
100
|
-
return true
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# call the Sensu API to remove the node
|
105
|
-
def remove_from_sensu(node_name)
|
106
|
-
response = RestClient::Request.execute(url: "#{@config[:sensu][:url]}/clients/#{node_name}", method: :delete, timeout: 5, open_timeout: 5)
|
107
|
-
case response.code
|
108
|
-
when 202
|
109
|
-
notify_chat('Removed ' + node_name + ' from Sensu')
|
110
|
-
return true
|
111
|
-
else
|
112
|
-
notify_chat('Failed to remove ' + node_name + ' from Sensu')
|
113
|
-
return false
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# call the Chef API to remove the node
|
118
|
-
def remove_from_chef(node_name)
|
119
|
-
begin
|
120
|
-
client = @chef.clients.fetch(node_name)
|
121
|
-
client.destroy
|
122
|
-
node = @chef.nodes.fetch(node_name)
|
123
|
-
node.destroy
|
124
|
-
rescue => e
|
125
|
-
puts "Failed to remove chef node: #{e}"
|
126
|
-
else
|
127
|
-
notify_chat('Removed ' + node_name + ' from Chef')
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# notify hipchat
|
132
|
-
def notify_hipchat(msg)
|
133
|
-
hipchat = HipChat::Client.new(
|
134
|
-
@config[:hipchat][:api_token],
|
135
|
-
api_version: 'v2'
|
136
|
-
)
|
137
|
-
room = @config[:hipchat][:room]
|
138
|
-
hipchat[room].send('AWS Cleaner', msg)
|
139
|
-
end
|
140
|
-
|
141
|
-
# notify slack
|
142
|
-
def notify_slack(msg)
|
143
|
-
slack = Slack::Poster.new(@config[:slack][:webhook_url])
|
144
|
-
slack.channel = @config[:slack][:channel]
|
145
|
-
slack.username = @config[:slack][:username] ||= 'aws-cleaner'
|
146
|
-
slack.icon_emoji = @config[:slack][:icon_emoji] ||= nil
|
147
|
-
slack.send_message(msg)
|
148
|
-
end
|
149
|
-
|
150
|
-
# generic chat notification method
|
151
|
-
def notify_chat(msg)
|
152
|
-
if @config[:hipchat][:enable]
|
153
|
-
notify_hipchat(msg)
|
154
|
-
elsif @config[:slack][:enable]
|
155
|
-
notify_slack(msg)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
# generate the URL for the webhook
|
160
|
-
def generate_template(item, template_variable_method, template_variable_argument, template_variable)
|
161
|
-
begin
|
162
|
-
replacement = send(template_variable_method, eval(template_variable_argument))
|
163
|
-
item.gsub!(/{#{template_variable}}/, replacement)
|
164
|
-
rescue Exception => e
|
165
|
-
puts "Error generating template: #{e.message}"
|
166
|
-
return false
|
167
|
-
else
|
168
|
-
item
|
169
|
-
end
|
170
|
-
end
|
41
|
+
# @sqs = Aws::SQS::Client.new(@config[:aws])
|
42
|
+
@sqs_client = AwsCleaner::SQS.client(@config)
|
171
43
|
|
172
|
-
|
173
|
-
def fire_webhook(config)
|
174
|
-
# generate templated URL
|
175
|
-
if config[:template_variables] && config[:url] =~ /\{\S+\}/
|
176
|
-
url = generate_template(
|
177
|
-
config[:url],
|
178
|
-
config[:template_variables][:method],
|
179
|
-
config[:template_variables][:argument],
|
180
|
-
config[:template_variables][:variable]
|
181
|
-
)
|
182
|
-
return false unless url
|
183
|
-
else
|
184
|
-
url = config[:url]
|
185
|
-
end
|
186
|
-
|
187
|
-
hook = { method: config[:method].to_sym, url: url }
|
188
|
-
r = RestClient::Request.execute(hook)
|
189
|
-
if r.code != 200
|
190
|
-
return false
|
191
|
-
else
|
192
|
-
# notify chat when webhook is successful
|
193
|
-
if config[:chat][:enable]
|
194
|
-
msg = generate_template(
|
195
|
-
config[:chat][:message],
|
196
|
-
config[:chat][:method],
|
197
|
-
config[:chat][:argument],
|
198
|
-
config[:chat][:variable]
|
199
|
-
)
|
200
|
-
notify_chat(msg)
|
201
|
-
end
|
202
|
-
return true
|
203
|
-
end
|
204
|
-
end
|
44
|
+
@chef_client = AwsCleaner::Chef.client(@config)
|
205
45
|
|
206
46
|
# main loop
|
207
47
|
loop do
|
208
48
|
# get messages from SQS
|
209
|
-
messages = @
|
49
|
+
messages = @sqs_client.receive_message(
|
210
50
|
queue_url: @config[:sqs][:queue],
|
211
51
|
max_number_of_messages: 10,
|
212
52
|
visibility_timeout: 3
|
@@ -216,53 +56,52 @@ loop do
|
|
216
56
|
|
217
57
|
messages.each_with_index do |message, index|
|
218
58
|
puts "Looking at message number #{index}"
|
219
|
-
body = parse(message.body)
|
59
|
+
body = AwsCleaner.new.parse(message.body)
|
220
60
|
id = message.receipt_handle
|
221
61
|
|
222
62
|
unless body
|
223
|
-
delete_message(id)
|
63
|
+
AwsCleaner.new.delete_message(id, @config)
|
224
64
|
next
|
225
65
|
end
|
226
66
|
|
227
|
-
@instance_id = process_message(body)
|
67
|
+
@instance_id = AwsCleaner.new.process_message(body)
|
228
68
|
|
229
69
|
if @instance_id
|
230
70
|
if @config[:webhooks]
|
231
|
-
@config[:webhooks].each do |hook,
|
232
|
-
if fire_webhook(config)
|
71
|
+
@config[:webhooks].each do |hook, hook_config|
|
72
|
+
if AwsCleaner::Webhooks.fire_webhook(hook_config, @config, @instance_id)
|
233
73
|
puts "Successfully ran webhook #{hook}"
|
234
74
|
else
|
235
75
|
puts "Failed to run webhook #{hook}"
|
236
76
|
end
|
237
77
|
end
|
238
|
-
delete_message(id)
|
78
|
+
AwsCleaner.new.delete_message(id, @config)
|
239
79
|
end
|
240
80
|
|
241
|
-
chef_node = get_chef_node_name(@instance_id)
|
81
|
+
chef_node = AwsCleaner::Chef.get_chef_node_name(@instance_id, @config)
|
242
82
|
|
243
83
|
if chef_node
|
244
|
-
if remove_from_chef(chef_node)
|
84
|
+
if AwsCleaner::Chef.remove_from_chef(chef_node, @chef_client, @config)
|
245
85
|
puts "Removed #{chef_node} from Chef"
|
246
|
-
delete_message(id)
|
86
|
+
AwsCleaner.new.delete_message(id, @config)
|
247
87
|
end
|
248
88
|
else
|
249
89
|
puts "Instance #{@instance_id} does not exist in Chef, deleting message"
|
250
|
-
delete_message(id)
|
90
|
+
AwsCleaner.new.delete_message(id, @config)
|
251
91
|
end
|
252
92
|
|
253
|
-
if in_sensu?(chef_node)
|
254
|
-
if remove_from_sensu(chef_node)
|
93
|
+
if AwsCleaner::Sensu.in_sensu?(chef_node, @config)
|
94
|
+
if AwsCleaner::Sensu.remove_from_sensu(chef_node, @config)
|
255
95
|
puts "Removed #{chef_node} from Sensu"
|
256
|
-
delete_message(id)
|
257
96
|
else
|
258
97
|
puts "Instance #{@instance_id} does not exist in Sensu, deleting message"
|
259
|
-
delete_message(id)
|
260
98
|
end
|
99
|
+
AwsCleaner.new.delete_message(id, @config)
|
261
100
|
end
|
262
101
|
|
263
102
|
else
|
264
103
|
puts 'Message not relevant, deleting'
|
265
|
-
delete_message(id)
|
104
|
+
AwsCleaner.new.delete_message(id, @config)
|
266
105
|
end
|
267
106
|
end
|
268
107
|
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# main aws_cleaner lib
|
2
|
+
class AwsCleaner
|
3
|
+
# SQS related stuff
|
4
|
+
module SQS
|
5
|
+
# sqs connection
|
6
|
+
def self.client(config)
|
7
|
+
Aws::SQS::Client.new(config[:aws])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# delete the message from SQS
|
12
|
+
def delete_message(id, config)
|
13
|
+
delete = AwsCleaner::SQS.client(config).delete_message(
|
14
|
+
queue_url: config[:sqs][:queue],
|
15
|
+
receipt_handle: id
|
16
|
+
)
|
17
|
+
delete ? true : false
|
18
|
+
end
|
19
|
+
|
20
|
+
module Chef
|
21
|
+
# chef connection
|
22
|
+
def self.client(config)
|
23
|
+
ChefAPI::Connection.new(
|
24
|
+
endpoint: config[:chef][:url],
|
25
|
+
client: config[:chef][:client],
|
26
|
+
key: config[:chef][:key]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# call the Chef API to get the node name of the instance
|
31
|
+
def self.get_chef_node_name(instance_id, config)
|
32
|
+
chef = client(config)
|
33
|
+
results = chef.search.query(:node, "ec2_instance_id:#{instance_id} OR chef_provisioning_reference_server_id:#{instance_id}")
|
34
|
+
return false if results.rows.empty?
|
35
|
+
results.rows.first['name']
|
36
|
+
end
|
37
|
+
|
38
|
+
# call the Chef API to get the FQDN of the instance
|
39
|
+
def self.get_chef_fqdn(instance_id, config)
|
40
|
+
chef = client(config)
|
41
|
+
results = chef.search.query(:node, "ec2_instance_id:#{instance_id} OR chef_provisioning_reference_server_id:#{instance_id}")
|
42
|
+
return false if results.rows.empty?
|
43
|
+
results.rows.first['automatic']['fqdn']
|
44
|
+
end
|
45
|
+
|
46
|
+
# call the Chef API to remove the node
|
47
|
+
def self.remove_from_chef(node_name, chef, config)
|
48
|
+
client = chef.clients.fetch(node_name)
|
49
|
+
client.destroy
|
50
|
+
node = chef.nodes.fetch(node_name)
|
51
|
+
node.destroy
|
52
|
+
rescue => e
|
53
|
+
puts "Failed to remove chef node: #{e}"
|
54
|
+
else
|
55
|
+
# puts "Removed #{node_name} from chef"
|
56
|
+
AwsCleaner::Notify.notify_chat('Removed ' + node_name + ' from Chef', config)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module Sensu
|
61
|
+
# check if the node exists in Sensu
|
62
|
+
def self.in_sensu?(node_name, config)
|
63
|
+
RestClient::Request.execute(
|
64
|
+
url: "#{config[:sensu][:url]}/clients/#{node_name}",
|
65
|
+
method: :get,
|
66
|
+
timeout: 5,
|
67
|
+
open_timeout: 5
|
68
|
+
)
|
69
|
+
rescue RestClient::ResourceNotFound
|
70
|
+
return false
|
71
|
+
rescue => e
|
72
|
+
puts "Sensu request failed: #{e}"
|
73
|
+
return false
|
74
|
+
else
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
|
78
|
+
# call the Sensu API to remove the node
|
79
|
+
def self.remove_from_sensu(node_name, config)
|
80
|
+
response = RestClient::Request.execute(
|
81
|
+
url: "#{config[:sensu][:url]}/clients/#{node_name}",
|
82
|
+
method: :delete,
|
83
|
+
timeout: 5,
|
84
|
+
open_timeout: 5
|
85
|
+
)
|
86
|
+
case response.code
|
87
|
+
when 202
|
88
|
+
AwsCleaner::Notify.notify_chat('Removed ' + node_name + ' from Sensu', config)
|
89
|
+
return true
|
90
|
+
else
|
91
|
+
AwsCleaner::Notify.notify_chat('Failed to remove ' + node_name + ' from Sensu', config)
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# return the body of the SQS message in JSON
|
98
|
+
def parse(body)
|
99
|
+
JSON.parse(body)
|
100
|
+
rescue JSON::ParserError
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
|
104
|
+
# return the instance_id of the terminated instance
|
105
|
+
def process_message(message_body)
|
106
|
+
return false if message_body['detail']['instance-id'].nil? &&
|
107
|
+
message_body['detail']['state'] != 'terminated'
|
108
|
+
|
109
|
+
instance_id = message_body['detail']['instance-id']
|
110
|
+
instance_id
|
111
|
+
end
|
112
|
+
|
113
|
+
module Notify
|
114
|
+
# notify hipchat
|
115
|
+
def self.notify_hipchat(msg, config)
|
116
|
+
hipchat = HipChat::Client.new(
|
117
|
+
config[:hipchat][:api_token],
|
118
|
+
api_version: 'v2'
|
119
|
+
)
|
120
|
+
room = config[:hipchat][:room]
|
121
|
+
hipchat[room].send('AWS Cleaner', msg)
|
122
|
+
end
|
123
|
+
|
124
|
+
# notify slack
|
125
|
+
def self.notify_slack(msg, config)
|
126
|
+
slack = Slack::Poster.new(config[:slack][:webhook_url])
|
127
|
+
slack.channel = config[:slack][:channel]
|
128
|
+
slack.username = config[:slack][:username] ||= 'aws-cleaner'
|
129
|
+
slack.icon_emoji = config[:slack][:icon_emoji] ||= nil
|
130
|
+
slack.send_message(msg)
|
131
|
+
end
|
132
|
+
|
133
|
+
# generic chat notification method
|
134
|
+
def self.notify_chat(msg, config)
|
135
|
+
if config[:hipchat][:enable]
|
136
|
+
notify_hipchat(msg, config)
|
137
|
+
elsif config[:slack][:enable]
|
138
|
+
notify_slack(msg, config)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
module Webhooks
|
144
|
+
# generate the URL for the webhook
|
145
|
+
def self.generate_template(item, template_variable_method, template_variable, config, instance_id)
|
146
|
+
if template_variable_method == 'get_chef_fqdn'
|
147
|
+
replacement = AwsCleaner::Chef.get_chef_fqdn(instance_id, config)
|
148
|
+
elsif template_variable_method == 'get_chef_node_name'
|
149
|
+
replacement = AwsCleaner::Chef.get_chef_node_name(instance_id, config)
|
150
|
+
else
|
151
|
+
raise 'Unknown templating method'
|
152
|
+
end
|
153
|
+
item.gsub!(/{#{template_variable}}/, replacement)
|
154
|
+
rescue StandardError => e
|
155
|
+
puts "Error generating template: #{e.message}"
|
156
|
+
return false
|
157
|
+
else
|
158
|
+
item
|
159
|
+
end
|
160
|
+
|
161
|
+
# call an HTTP endpoint
|
162
|
+
def self.fire_webhook(hook_config, config, instance_id)
|
163
|
+
# generate templated URL
|
164
|
+
if hook_config[:template_variables] && hook_config[:url] =~ /\{\S+\}/
|
165
|
+
url = AwsCleaner::Webhooks.generate_template(
|
166
|
+
hook_config[:url],
|
167
|
+
hook_config[:template_variables][:method],
|
168
|
+
hook_config[:template_variables][:variable],
|
169
|
+
config,
|
170
|
+
instance_id
|
171
|
+
)
|
172
|
+
return false unless url
|
173
|
+
else
|
174
|
+
url = hook_config[:url]
|
175
|
+
end
|
176
|
+
|
177
|
+
hook = { method: hook_config[:method].to_sym, url: url }
|
178
|
+
r = RestClient::Request.execute(hook)
|
179
|
+
if r.code != 200
|
180
|
+
return false
|
181
|
+
else
|
182
|
+
# notify chat when webhook is successful
|
183
|
+
if hook_config[:chat][:enable]
|
184
|
+
msg = AwsCleaner::Webhooks.generate_template(
|
185
|
+
hook_config[:chat][:message],
|
186
|
+
hook_config[:chat][:method],
|
187
|
+
hook_config[:chat][:variable],
|
188
|
+
config,
|
189
|
+
instance_id
|
190
|
+
)
|
191
|
+
AwsCleaner::Notify.notify_chat(msg, config)
|
192
|
+
end
|
193
|
+
return true
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-cleaner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Heydrick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.46.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.46.0
|
13
69
|
- !ruby/object:Gem::Dependency
|
14
70
|
name: aws-sdk-core
|
15
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +114,14 @@ dependencies:
|
|
58
114
|
requirements:
|
59
115
|
- - "~>"
|
60
116
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
117
|
+
version: '2'
|
62
118
|
type: :runtime
|
63
119
|
prerelease: false
|
64
120
|
version_requirements: !ruby/object:Gem::Requirement
|
65
121
|
requirements:
|
66
122
|
- - "~>"
|
67
123
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
124
|
+
version: '2'
|
69
125
|
- !ruby/object:Gem::Dependency
|
70
126
|
name: slack-poster
|
71
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,6 +158,7 @@ extensions: []
|
|
102
158
|
extra_rdoc_files: []
|
103
159
|
files:
|
104
160
|
- bin/aws_cleaner.rb
|
161
|
+
- lib/aws_cleaner/aws_cleaner.rb
|
105
162
|
homepage: https://github.com/eheydrick/aws-cleaner
|
106
163
|
licenses:
|
107
164
|
- MIT
|
@@ -122,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
179
|
version: '0'
|
123
180
|
requirements: []
|
124
181
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.
|
182
|
+
rubygems_version: 2.6.6
|
126
183
|
signing_key:
|
127
184
|
specification_version: 4
|
128
185
|
summary: AWS Cleaner cleans up after EC2 instances are terminated
|