ec2ex 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6fd690807cff2f0f5be2b942621f1efe62ff96de
4
- data.tar.gz: 7ef5ca48952371e67172a80caa92c372b1751144
3
+ metadata.gz: 5755c9dc27c67e067cb6813e6e130a830ab2b320
4
+ data.tar.gz: a3eb2fe48d2cbec37f45dbf310222f6e22891e34
5
5
  SHA512:
6
- metadata.gz: 81c2592526c7d51688a431c99167abe994b3f1a940c22b38ec7ad56909238efc4b841e78df317ecf27d2a66692cfec228115994d44c6f0e32e0d498f56ff8cde
7
- data.tar.gz: 5ba6cbfc97e284c35de7f77e9125f4c48c0fabe740dc91a2b076803095865425d3c071d98df36ec73cd8b94666ed08d7274ed03dbf698692ff2c65768537d4ac
6
+ metadata.gz: 689bd524c9c9a9f77d77cb3c3e85d1e588d49cc9e89422e6497a7b0b1881d764995589cd778d9065146a8cf22d36a2ba2369f788f980c3eddbc0b57acc99cd74
7
+ data.tar.gz: 432de3ba88dc99d2dbae99d36e7371257eb85f6cd1454c41d50629b907d7cf4e04424c919710d04c970d1a1e17441b7da192aac1870f89dae49a51f7c8118ecf
data/README.md CHANGED
@@ -1,19 +1,67 @@
1
1
  # ec2ex [![Build Status](https://secure.travis-ci.org/toyama0919/ec2ex.png?branch=master)](http://travis-ci.org/toyama0919/ec2ex)
2
2
 
3
- TODO: Summary
3
+ ## Examples
4
4
 
5
- TODO: Description
5
+ ### Search Instance
6
6
 
7
- ## Examples
7
+ ```
8
+ $ ec2ex -s 'stgweb01'
9
+ ```
10
+
11
+ ### Copy Instance
12
+
13
+ ```
14
+ $ ec2ex copy -n "stgembulk01" -t Name:stgembulk02 --public_ip_address auto --instance_count 3
15
+ ```
16
+
17
+ ### Copy Spot Instance
18
+
19
+ ```
20
+ $ ec2ex spot -n "web01" --price 0.5 --private_ip_address 10.0.0.100 -t Name:web02
21
+ ```
22
+
23
+ ### Deployment Instance
24
+
25
+ ```
26
+ $ ec2ex run_spot -n "stgembulk01" --price 0.5
27
+ ```
28
+
29
+ ### Connect ELB Instance
30
+
31
+ ```
32
+ $ ec2ex connect_elb -n "web01" -l elbname
33
+ ```
34
+
35
+ ### Disconnect ELB Instance
36
+
37
+ ```
38
+ $ ec2ex disconnect_elb -n "web02" -l elbname
39
+ ```
40
+
41
+ ### Terminate Instance
42
+
43
+ ```
44
+ $ ec2ex terminate -n web01
45
+ ```
46
+
47
+ ### Renew Instance
48
+
49
+ ```
50
+ $ ec2ex renew -n "presto01" --private-ip-address 10.0.81.201 -p '{iam_instance_profile: { name: "iap-role"} }'
51
+ ```
52
+
53
+ ### Create AMI with tag
54
+
55
+ ```
56
+ $ ec2 create_image -n "presto01"
57
+ ```
8
58
 
9
- $ ec2ex sample
10
- #=> hoge
11
59
 
12
60
  ## Installation
13
61
 
14
62
  Add this line to your application's Gemfile:
15
63
 
16
- gem 'ec2ex'
64
+ gem 'ec2ex', github: 'ipros-team/ec2ex'
17
65
 
18
66
  And then execute:
19
67
 
@@ -21,7 +69,7 @@ And then execute:
21
69
 
22
70
  Or install it yourself as:
23
71
 
24
- $ gem install ec2ex
72
+ $ gem specific_install -l https://github.com/ipros-team/ec2ex
25
73
 
26
74
  ## Contributing
27
75
 
@@ -20,10 +20,12 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency 'thor'
21
21
  gem.add_dependency 'hashie'
22
22
  gem.add_dependency 'ipaddress'
23
- gem.add_dependency 'aws-sdk', '~> 2.0.11.pre'
23
+ gem.add_dependency 'aws-sdk'
24
24
  gem.add_dependency 'activesupport'
25
+ gem.add_dependency 'parallel'
26
+ gem.add_dependency 'net-ping'
25
27
 
26
- gem.add_development_dependency 'bundler', '~> 1.7.2'
28
+ gem.add_development_dependency 'bundler'
27
29
  gem.add_development_dependency 'pry', '~> 0.10.1'
28
30
  gem.add_development_dependency 'rake', '~> 10.3.2'
29
31
  gem.add_development_dependency 'rspec', '~> 2.4'
@@ -1,8 +1,7 @@
1
1
  require 'thor'
2
2
  require 'json'
3
3
  require 'pp'
4
- require 'hashie'
5
- require 'aws-sdk'
4
+ require 'parallel'
6
5
  require 'active_support/core_ext/hash'
7
6
 
8
7
  module Ec2ex
@@ -19,15 +18,16 @@ module Ec2ex
19
18
  super(args, options, config)
20
19
  @global_options = config[:shell].base.options
21
20
  @core = Core.new
22
- @ec2 = Aws::EC2::Client.new
23
- @elb = Aws::ElasticLoadBalancing::Client.new
21
+ @ec2 = @core.client
22
+ @elb = @core.elb_client
23
+ @logger = @core.logger
24
24
  end
25
25
 
26
26
  desc 'search', 'search instance'
27
27
  option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
28
28
  option :running_only, aliases: '--ro', type: :boolean, default: true, desc: 'grouping key'
29
- def search(name = options['name'])
30
- results = @core.instances_hash({ Name: name }, options['running_only'])
29
+ def search(name = options[:name])
30
+ results = @core.instances_hash({ Name: name }, options[:running_only])
31
31
  puts_json results
32
32
  end
33
33
 
@@ -35,7 +35,7 @@ module Ec2ex
35
35
  option :condition, aliases: '-c', type: :hash, default: {}, desc: 'grouping key'
36
36
  option :running_only, aliases: '--ro', type: :boolean, default: true, desc: 'grouping key'
37
37
  def search_by_tags
38
- puts_json @core.instances_hash(options['condition'], options['running_only'])
38
+ puts_json @core.instances_hash(options[:condition], options[:running_only])
39
39
  end
40
40
 
41
41
  desc 'reserved', 'reserved instance'
@@ -50,7 +50,7 @@ module Ec2ex
50
50
  list = @core.instances_hash({}, true).select { |instance| instance[:instance_lifecycle].nil? }
51
51
  list = list.map{ |_instance|
52
52
  ['instance_type', 'placement.availability_zone'].map do |key|
53
- eval("instance.#{key} ")
53
+ eval("_instance.#{key} ")
54
54
  end.join('_')
55
55
  }
56
56
  result = {}
@@ -66,22 +66,64 @@ module Ec2ex
66
66
  end
67
67
 
68
68
  desc 'create_image', 'create image'
69
- option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
69
+ option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
70
+ option :proc, type: :numeric, default: Parallel.processor_count, desc: 'Number of parallel'
71
+ option :region, aliases: '-r', type: :string, required: false, default: nil, desc: 'region'
70
72
  def create_image
71
- results = @core.instances_hash({ Name: options['name'] }, false)
72
- results.each do |instance|
73
- @core.create_image_with_instance(instance)
73
+ results = @core.instances_hash({ Name: options[:name] }, false)
74
+ Parallel.map(results, in_threads: options[:proc]) do |instance|
75
+ begin
76
+ @core.create_image_with_instance(instance, options[:region])
77
+ rescue => e
78
+ @logger.info "\n#{e.message}\n#{e.backtrace.join("\n")}"
79
+ end
80
+ end
81
+ end
82
+
83
+ desc 'deregister_image', 'deregister image'
84
+ option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
85
+ option :older_than, aliases: '--older_than', type: :numeric, default: 30, desc: 'older than count.'
86
+ def deregister_image
87
+ @core.get_old_images(options[:name], options[:older_than]).each do |image|
88
+ image_id = image[:image_id]
89
+ @logger.info "delete AMI #{image_id} [#{image[:name]}]"
90
+ @ec2.deregister_image({image_id: image_id})
91
+ snapshot_ids = image[:block_device_mappings]
92
+ .select{ |block_device_mapping| block_device_mapping[:ebs] != nil }
93
+ .map{ |block_device_mapping| block_device_mapping[:ebs][:snapshot_id] }
94
+
95
+ snapshot_ids.each do |snapshot_id|
96
+ @logger.info "delete snapshot #{snapshot_id}"
97
+ @ec2.delete_snapshot({snapshot_id: snapshot_id})
98
+ end
74
99
  end
75
100
  end
76
101
 
102
+ desc 'deregister_image', 'deregister image'
103
+ option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
104
+ option :older_than, aliases: '--older_than', type: :numeric, default: 30, desc: 'older than count.'
105
+ def old_images
106
+ puts_json(@core.get_old_images(options[:name], options[:older_than]))
107
+ end
108
+
109
+ desc 'deregister_snapshot_no_related', 'AMI not related snapshot basis delete all'
110
+ option :owner_id, type: :string, required: true, desc: 'owner_id'
111
+ def deregister_snapshot_no_related
112
+ @core.deregister_snapshot_no_related(options[:owner_id])
113
+ end
114
+
77
115
  desc 'copy', 'copy instance'
78
116
  option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
79
117
  option :params, aliases: '-p', type: :string, default: '{}', desc: 'params'
80
118
  option :tag, aliases: '-t', type: :hash, default: {}, desc: 'name tag'
119
+ option :private_ip_address, type: :string, default: nil, desc: 'private_ip_address'
120
+ option :public_ip_address, type: :string, default: nil, desc: 'public_ip_address'
121
+ option :instance_count, type: :numeric, default: 1, desc: 'instance_count'
81
122
  def copy
82
- results = @core.instances_hash({ Name: options['name'] }, true)
83
- results.each do |instance|
84
- image_id = @core.create_image_with_instance(instance)
123
+ instance = @core.instances_hash_first_result({ Name: options[:name] }, true)
124
+ image_id = @core.create_image_with_instance(instance)
125
+ instance_count = options[:instance_count]
126
+ Parallel.map(instance_count.times.to_a, in_threads: Parallel.processor_count) do |server_index|
85
127
  security_group_ids = instance.security_groups.map { |security_group| security_group.group_id }
86
128
  request = {
87
129
  image_id: image_id,
@@ -89,43 +131,61 @@ module Ec2ex
89
131
  max_count: 1,
90
132
  security_group_ids: security_group_ids,
91
133
  instance_type: instance.instance_type,
92
- placement: instance.placement.to_hash,
93
- subnet_id: instance.subnet_id,
94
- private_ip_address: instance.private_ip_address
134
+ placement: instance.placement.to_hash
95
135
  }
96
- unless instance.iam_instance_profile.nil?
136
+ request[:private_ip_address] = options[:private_ip_address] if options[:private_ip_address]
137
+ if instance.iam_instance_profile
97
138
  request[:iam_instance_profile] = { name: instance.iam_instance_profile.arn.split('/').last }
98
139
  end
99
- request.merge!(eval(options['params']))
100
- request[:subnet_id] = @core.get_subnet(request[:private_ip_address]).subnet_id
140
+ if instance.key_name
141
+ request[:key_name] = instance.key_name
142
+ end
143
+
144
+ request.merge!(eval(options[:params]))
145
+ request[:subnet_id] = if request[:private_ip_address]
146
+ @core.get_subnet(request[:private_ip_address]).subnet_id
147
+ else
148
+ instance.subnet_id
149
+ end
101
150
 
102
151
  response = @ec2.run_instances(request)
103
152
  instance_id = response.instances.first.instance_id
104
153
  @ec2.wait_until(:instance_running, instance_ids: [instance_id])
105
154
  @ec2.create_tags(resources: [instance_id], tags: instance.tags)
106
- unless options['tag'].nil?
107
- @ec2.create_tags(resources: [instance_id], tags: @core.format_tag(options['tag']))
155
+ @ec2.create_tags(resources: [instance_id], tags: [{ key: 'InstanceIndex', value: "#{server_index}" }])
156
+ @ec2.create_tags(resources: [instance_id], tags: [{ key: 'InstanceCount', value: "#{instance_count}" }])
157
+ unless options[:tag].nil?
158
+ @ec2.create_tags(
159
+ resources: [instance_id],
160
+ tags: @core.format_tag(
161
+ options[:tag],
162
+ @core.get_tag_hash_from_id(instance_id)
163
+ )
164
+ )
108
165
  end
166
+ public_ip_address = get_public_ip_address(options[:public_ip_address], instance.public_ip_address, false)
167
+ @core.associate_address(instance_id, public_ip_address)
168
+ @logger.info("created instance => #{instance_id}")
109
169
  end
110
170
  end
111
171
 
112
172
  desc 'renew', 'renew instance'
113
173
  option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
114
174
  option :stop, type: :boolean, default: true, desc: 'stop'
115
- option :params, aliases: '-p', type: :string, default: nil, desc: 'params'
175
+ option :params, aliases: '-p', type: :string, default: '{}', desc: 'params'
116
176
  def renew
117
- params = eval(options['params'])
118
- results = @core.instances_hash({ Name: options['name'] }, false)
177
+ params = eval(options[:params])
178
+ results = @core.instances_hash({ Name: options[:name] }, false)
119
179
  results.each do |instance|
120
180
  tags = instance.tags
121
181
  tag_hash = @core.get_tag_hash(tags)
122
- if options['stop']
182
+ if options[:stop]
123
183
  @core.stop_instance(instance.instance_id)
124
184
  end
125
185
 
126
186
  image_id = @core.create_image_with_instance(instance)
127
187
 
128
- @core.terminate_instance(instance.instance_id)
188
+ @core.terminate_instance(instance)
129
189
  security_group_ids = instance.security_groups.map { |security_group| security_group.group_id }
130
190
  request = {
131
191
  image_id: image_id,
@@ -136,9 +196,13 @@ module Ec2ex
136
196
  placement: instance.placement.to_hash,
137
197
  private_ip_address: instance.private_ip_address
138
198
  }
139
- unless instance.iam_instance_profile.nil?
199
+ if instance.iam_instance_profile
140
200
  request[:iam_instance_profile] = { name: instance.iam_instance_profile.arn.split('/').last }
141
201
  end
202
+
203
+ if instance.key_name
204
+ request[:key_name] = instance.key_name
205
+ end
142
206
  request.merge!(params)
143
207
  request[:subnet_id] = @core.get_subnet(request[:private_ip_address]).subnet_id
144
208
 
@@ -157,18 +221,26 @@ module Ec2ex
157
221
  option :price, type: :string, required: true, desc: 'price'
158
222
  option :private_ip_address, type: :string, default: nil, desc: 'private_ip_address'
159
223
  option :public_ip_address, type: :string, default: nil, desc: 'public_ip_address'
224
+ option :block_duration_minutes, type: :numeric, default: nil, desc: 'block_duration_minutes'
160
225
  option :params, aliases: '-p', type: :string, default: '{}', desc: 'params'
161
226
  option :tag, aliases: '-t', type: :hash, default: {}, desc: 'name tag'
162
227
  option :renew, aliases: '-r', type: :boolean, default: false, desc: 'renew instance'
163
228
  option :persistent, type: :boolean, default: false, desc: 'persistent request'
229
+ option :stop, type: :boolean, default: false, desc: 'stop'
230
+ option :instance_count, type: :numeric, default: 1, desc: 'instance_count'
164
231
  def spot
165
- results = @core.instances_hash({ Name: options['name'] }, true)
166
- results.each do |instance|
167
- image_id = @core.create_image_with_instance(instance)
232
+ instance = @core.instances_hash_first_result({ Name: options[:name] }, true)
233
+ if options[:stop]
234
+ @core.stop_instance(instance.instance_id)
235
+ end
236
+ image_id = @core.create_image_with_instance(instance)
237
+
238
+ instance_count = options[:instance_count]
239
+ Parallel.map(instance_count.times.to_a, in_threads: Parallel.processor_count) do |server_index|
168
240
  security_group_ids = instance.security_groups.map { |security_group| security_group.group_id }
169
241
  option = {
170
242
  instance_count: 1,
171
- spot_price: options['price'],
243
+ spot_price: options[:price],
172
244
  launch_specification: {
173
245
  image_id: image_id,
174
246
  instance_type: instance.instance_type,
@@ -176,52 +248,61 @@ module Ec2ex
176
248
  subnet_id: instance.subnet_id
177
249
  },
178
250
  }
179
- option[:type] = 'persistent' if options['persistent']
251
+ option[:type] = 'persistent' if options[:persistent]
252
+ option[:block_duration_minutes] = options[:block_duration_minutes] if options[:block_duration_minutes]
180
253
 
181
- unless instance.iam_instance_profile.nil?
254
+ if instance.iam_instance_profile
182
255
  option[:launch_specification][:iam_instance_profile] = { name: instance.iam_instance_profile.arn.split('/').last }
183
256
  end
184
257
 
185
- option[:launch_specification].merge!(eval(options['params']))
258
+ if instance.key_name
259
+ option[:launch_specification][:key_name] = instance.key_name
260
+ end
261
+
262
+ option[:launch_specification].merge!(eval(options[:params]))
186
263
 
187
264
  private_ip_address = nil
188
- if options['private_ip_address'].nil?
189
- private_ip_address = instance.private_ip_address if options['renew']
265
+ if options[:private_ip_address].nil?
266
+ private_ip_address = instance.private_ip_address if options[:renew]
190
267
  else
191
- private_ip_address = options['private_ip_address']
268
+ private_ip_address = options[:private_ip_address]
192
269
  end
193
270
 
194
- unless private_ip_address.nil?
271
+ if private_ip_address
195
272
  network_interface = {
196
273
  device_index: 0,
197
274
  subnet_id: @core.get_subnet(private_ip_address).subnet_id,
198
- groups: security_group_ids,
275
+ groups: option[:launch_specification][:security_group_ids],
199
276
  private_ip_addresses: [{ private_ip_address: private_ip_address, primary: true }]
200
277
  }
201
278
  option[:launch_specification][:network_interfaces] = [network_interface]
202
279
  option[:launch_specification].delete(:security_group_ids)
203
280
  option[:launch_specification].delete(:subnet_id)
204
281
  end
205
- @core.terminate_instance(instance.instance_id) if options['renew']
282
+ @core.terminate_instance(instance) if options[:renew]
206
283
 
207
284
  response = @ec2.request_spot_instances(option)
208
285
  spot_instance_request_id = response.spot_instance_requests.first.spot_instance_request_id
209
286
  sleep 5
210
287
  instance_id = @core.wait_spot_running(spot_instance_request_id)
288
+ @core.set_delete_on_termination(@core.instances_hash_with_id(instance_id))
211
289
 
212
290
  @ec2.create_tags(resources: [instance_id], tags: instance.tags)
213
291
  @ec2.create_tags(resources: [instance_id], tags: [{ key: 'Spot', value: 'true' }])
214
-
215
- unless options['tag'].empty?
216
- @ec2.create_tags(resources: [instance_id], tags: @core.format_tag(options['tag']))
292
+ @ec2.create_tags(resources: [instance_id], tags: [{ key: 'InstanceIndex', value: "#{server_index}" }])
293
+ @ec2.create_tags(resources: [instance_id], tags: [{ key: 'InstanceCount', value: "#{instance_count}" }])
294
+
295
+ unless options[:tag].empty?
296
+ @ec2.create_tags(
297
+ resources: [instance_id],
298
+ tags: @core.format_tag(
299
+ options[:tag],
300
+ @core.get_tag_hash_from_id(instance_id)
301
+ )
302
+ )
217
303
  end
218
304
 
219
- public_ip_address = nil
220
- if options['public_ip_address'].nil?
221
- public_ip_address = instance.public_ip_address if options['renew']
222
- else
223
- public_ip_address = options['public_ip_address']
224
- end
305
+ public_ip_address = get_public_ip_address(options[:public_ip_address], instance.public_ip_address, options[:renew])
225
306
  @core.associate_address(instance_id, public_ip_address)
226
307
  end
227
308
  end
@@ -229,34 +310,49 @@ module Ec2ex
229
310
  desc 'run_spot', 'run_spot latest image'
230
311
  option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
231
312
  option :price, type: :string, required: true, desc: 'price'
313
+ option :private_ip_address, type: :string, default: nil, desc: 'private_ip_address'
314
+ option :params, aliases: '-p', type: :string, default: '{}', desc: 'params'
315
+ option :block_duration_minutes, type: :numeric, default: nil, desc: 'block_duration_minutes'
232
316
  def run_spot
233
- image = @core.latest_image_with_name(options['name'])
317
+ image = @core.latest_image_with_name(options[:name])
318
+
234
319
  tag_hash = @core.get_tag_hash(image[:tags])
320
+ private_ip_address = options[:private_ip_address] || tag_hash.private_ip_address
321
+ exit 0 if @core.ping?(private_ip_address)
322
+
235
323
  option = {
236
324
  instance_count: 1,
237
- spot_price: options['price'],
325
+ spot_price: options[:price],
238
326
  launch_specification: {
239
327
  image_id: image[:image_id],
240
328
  instance_type: tag_hash.instance_type
241
329
  },
242
330
  }
243
331
 
332
+ option[:block_duration_minutes] = options[:block_duration_minutes] if options[:block_duration_minutes]
333
+
244
334
  if tag_hash.iam_instance_profile
245
335
  option[:launch_specification][:iam_instance_profile] = { name: tag_hash.iam_instance_profile }
246
336
  end
247
337
 
338
+ if tag_hash.key_name
339
+ option[:launch_specification][:key_name] = tag_hash.key_name
340
+ end
341
+
248
342
  network_interface = {
249
343
  device_index: 0,
250
- subnet_id: @core.get_subnet(tag_hash.private_ip_address).subnet_id,
344
+ subnet_id: @core.get_subnet(private_ip_address).subnet_id,
251
345
  groups: JSON.parse(tag_hash.security_groups),
252
- private_ip_addresses: [{ private_ip_address: tag_hash.private_ip_address, primary: true }]
346
+ private_ip_addresses: [{ private_ip_address: private_ip_address, primary: true }]
253
347
  }
254
348
  option[:launch_specification][:network_interfaces] = [network_interface]
349
+ option[:launch_specification].merge!(eval(options[:params]))
255
350
 
256
351
  response = @ec2.request_spot_instances(option)
257
352
  spot_instance_request_id = response.spot_instance_requests.first.spot_instance_request_id
258
353
  sleep 5
259
354
  instance_id = @core.wait_spot_running(spot_instance_request_id)
355
+ @core.set_delete_on_termination(@core.instances_hash_with_id(instance_id))
260
356
  @ec2.create_tags(resources: [instance_id], tags: JSON.parse(tag_hash[:tags]))
261
357
 
262
358
  if tag_hash.public_ip_address
@@ -268,7 +364,7 @@ module Ec2ex
268
364
  option :acl_id, type: :string, default: '', required: true, desc: 'name tag'
269
365
  option :ip_address, type: :string, default: '', required: true, desc: 'name tag'
270
366
  def regist_deny_acl
271
- acls = @ec2.describe_network_acls(network_acl_ids: [options['acl_id']])
367
+ acls = @ec2.describe_network_acls(network_acl_ids: [options[:acl_id]])
272
368
 
273
369
  allow_any_rule_number = acls.network_acls.first.entries.select {|r|
274
370
  !r.egress && r.cidr_block == '0.0.0.0/0' && r.rule_action == 'allow'
@@ -280,13 +376,13 @@ module Ec2ex
280
376
 
281
377
  next_rule_number = deny_rules.empty? ? 1 : deny_rules.last.rule_number + 1
282
378
 
283
- unless deny_rules.any? { |r| r.cidr_block == "#{options['ip_address']}/32" }
379
+ unless deny_rules.any? { |r| r.cidr_block == "#{options[:ip_address]}/32" }
284
380
  option = {
285
- network_acl_id: options['acl_id'],
381
+ network_acl_id: options[:acl_id],
286
382
  rule_number: next_rule_number,
287
383
  rule_action: 'deny',
288
384
  protocol: '-1',
289
- cidr_block: "#{options['ip_address']}/32",
385
+ cidr_block: "#{options[:ip_address]}/32",
290
386
  egress: false
291
387
  }
292
388
  @ec2.create_network_acl_entry(option)
@@ -296,7 +392,7 @@ module Ec2ex
296
392
  desc 'delete_deny_acl_all', 'delete deny acl'
297
393
  option :acl_id, type: :string, required: true, desc: 'name tag'
298
394
  def delete_deny_acl_all
299
- acls = @ec2.describe_network_acls(network_acl_ids: [options['acl_id']])
395
+ acls = @ec2.describe_network_acls(network_acl_ids: [options[:acl_id]])
300
396
 
301
397
  allow_any_rule_number = acls.network_acl_set.first.entries.select {|r|
302
398
  !r.egress && r.cidr_block == '0.0.0.0/0' && r.rule_action == 'allow'
@@ -308,7 +404,7 @@ module Ec2ex
308
404
 
309
405
  deny_rules.each do |deny_rule|
310
406
  option = {
311
- network_acl_id: options['acl_id'],
407
+ network_acl_id: options[:acl_id],
312
408
  rule_number: deny_rule.rule_number,
313
409
  egress: false
314
410
  }
@@ -334,25 +430,34 @@ module Ec2ex
334
430
  desc 'copy_tag', 'request spot instances'
335
431
  option :source, aliases: '--src', type: :string, default: nil, required: true, desc: 'name tag'
336
432
  option :dest, aliases: '--dest', type: :string, default: nil, required: true, desc: 'name tag'
337
- def copy_tag(_name = options['name'])
338
- source = @core.instances_hash({ Name: options['source'] }, true)
339
- dest = @core.instances_hash({ Name: options['dest'] }, true)
433
+ def copy_tag(_name = options[:name])
434
+ source = @core.instances_hash({ Name: options[:source] }, true)
435
+ dest = @core.instances_hash({ Name: options[:dest] }, true)
340
436
  @ec2.create_tags(resources: dest.map { |instance| instance.instance_id }, tags: source.first.tags)
341
- @ec2.create_tags(resources: dest.map { |instance| instance.instance_id }, tags: [{ key: 'Name', value: options['dest'] }])
437
+ @ec2.create_tags(resources: dest.map { |instance| instance.instance_id }, tags: [{ key: 'Name', value: options[:dest] }])
342
438
  end
343
439
 
344
440
  desc 'set_tag', 'set tag'
345
441
  option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
346
442
  option :tag, aliases: '-t', type: :hash, required: true, desc: 'name tag'
347
443
  def set_tag
348
- instances = @core.instances_hash({ Name: options['name'] }, true)
349
- tags = @core.format_tag(options['tag'])
444
+ instances = @core.instances_hash({ Name: options[:name] }, true)
445
+ tags = @core.format_tag(options[:tag])
350
446
  @ec2.create_tags(resources: instances.map { |instance| instance.instance_id }, tags: tags)
351
447
  end
352
448
 
449
+ desc 'set_delete_on_termination', 'set delete on termination instance'
450
+ option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
451
+ def set_delete_on_termination
452
+ @core.instances_hash({ Name: options[:name] }, true).each do |instance|
453
+ @core.set_delete_on_termination(instance)
454
+ @logger.info "set delete on termination => #{instance.instance_id}"
455
+ end
456
+ end
457
+
353
458
  desc 'search_images', 'search images'
354
459
  option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
355
- def search_images(name = options['name'])
460
+ def search_images(name = options[:name])
356
461
  puts_json @core.images(name)
357
462
  end
358
463
 
@@ -361,8 +466,8 @@ module Ec2ex
361
466
  option :key, aliases: '-k', type: :array, required: true, desc: 'grouping key'
362
467
  option :running_only, aliases: '--ro', type: :boolean, default: true, desc: 'grouping key'
363
468
  def aggregate
364
- list = @core.instances_hash(options['condition'], options['running_only']).map do |_instance|
365
- options['key'].map do |key|
469
+ list = @core.instances_hash(options[:condition], options[:running_only]).map do |instance|
470
+ options[:key].map do |key|
366
471
  eval("instance.#{key} ")
367
472
  end.join('_')
368
473
  end
@@ -372,7 +477,7 @@ module Ec2ex
372
477
  desc 'reboot', 'reboot instance'
373
478
  option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
374
479
  def reboot
375
- @core.instances_hash({ Name: options['name'] }, true).each do |instance|
480
+ @core.instances_hash({ Name: options[:name] }, true).each do |instance|
376
481
  @ec2.reboot_instances(instance_ids: [instance.instance_id])
377
482
  sleep 5
378
483
  @ec2.wait_until(:instance_running, instance_ids: [instance.instance_id])
@@ -382,13 +487,13 @@ module Ec2ex
382
487
  desc 'stop_start', 'stop after start instance'
383
488
  option :names, aliases: '-n', type: :array, default: [], required: true, desc: 'name tag'
384
489
  def stop_start
385
- options['names'].each do |name|
490
+ options[:names].each do |name|
386
491
  @core.instances_hash({ Name: name }, true).each do |instance|
387
492
  instance.stop
388
493
  @ec2.wait_until(:instance_stopped, instance_ids: [instance.instance_id])
389
494
  instance.start
390
495
  @ec2.wait_until(:instance_running, instance_ids: [instance.instance_id])
391
- puts "#{instance.tags['Name']} restart complete!"
496
+ @logger.info "#{instance.tags['Name']} restart complete!"
392
497
  end
393
498
  end
394
499
  end
@@ -396,25 +501,34 @@ module Ec2ex
396
501
  desc 'terminate', 'terminate instance'
397
502
  option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
398
503
  def terminate
399
- @core.instances_hash({ Name: options['name'] }, false).each do |instance|
400
- @core.terminate_instance(instance.instance_id)
504
+ instances = @core.instances_hash({ Name: options[:name] }, false)
505
+ Parallel.map(instances, in_threads: Parallel.processor_count) do |instance|
506
+ @core.terminate_instance(instance)
401
507
  end
402
508
  end
403
509
 
404
- desc 'terminate', 'terminate instance'
510
+ desc 'start', 'start instance'
405
511
  option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
406
512
  def start
407
- @core.instances_hash({ Name: options['name'] }, false).each do |instance|
513
+ @core.instances_hash({ Name: options[:name] }, false).each do |instance|
408
514
  @core.start_instance(instance.instance_id)
409
515
  end
410
516
  end
411
517
 
518
+ desc 'stop', 'stop instance'
519
+ option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
520
+ def stop
521
+ @core.instances_hash({ Name: options[:name] }, false).each do |instance|
522
+ @core.stop_instance(instance.instance_id)
523
+ end
524
+ end
525
+
412
526
  desc 'connect elb', 'connect elb'
413
527
  option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
414
528
  option :load_balancer_name, aliases: '-l', type: :string, default: '', required: true, desc: 'name tag'
415
- def connect_elb(_name = options['name'])
416
- @core.instances_hash({ Name: options['name'] }, true).each do |instance|
417
- option = { load_balancer_name: options['load_balancer_name'], instances: [instance_id: instance.instance_id] }
529
+ def connect_elb(_name = options[:name])
530
+ @core.instances_hash({ Name: options[:name] }, true).each do |instance|
531
+ option = { load_balancer_name: options[:load_balancer_name], instances: [instance_id: instance.instance_id] }
418
532
  @elb.deregister_instances_from_load_balancer(option)
419
533
  @elb.register_instances_with_load_balancer(option)
420
534
  print 'connecting ELB...'
@@ -426,6 +540,16 @@ module Ec2ex
426
540
  end
427
541
  end
428
542
 
543
+ desc 'disconnect elb', 'disconnect elb'
544
+ option :name, aliases: '-n', type: :string, default: '', required: true, desc: 'name tag'
545
+ option :load_balancer_name, aliases: '-l', type: :string, default: '', required: true, desc: 'name tag'
546
+ def disconnect_elb
547
+ @core.instances_hash({ Name: options[:name] }, true).each do |instance|
548
+ option = { load_balancer_name: options[:load_balancer_name], instances: [instance_id: instance.instance_id] }
549
+ @elb.deregister_instances_from_load_balancer(option)
550
+ end
551
+ end
552
+
429
553
  desc 'elbs', 'show elbs'
430
554
  def elbs
431
555
  puts_json @elb.describe_load_balancers.data.to_h[:load_balancer_descriptions]
@@ -452,25 +576,56 @@ module Ec2ex
452
576
  desc 'latest_image', 'show elbs'
453
577
  option :name, aliases: '-n', type: :string, required: true, desc: 'name tag'
454
578
  def latest_image
455
- puts_json @core.latest_image_with_name(options['name'])
579
+ puts_json @core.latest_image_with_name(options[:name])
456
580
  end
457
581
 
458
582
  desc 'allocate_address', 'allocate address'
459
- def allocate_address
460
- response = @ec2.allocate_address(domain: 'vpc')
583
+ def allocate_address_vpc
584
+ response = @core.allocate_address_vpc
585
+ puts response.data
586
+ end
587
+
588
+ desc 'instance_metadata', 'instance metadata'
589
+ option :path, type: :string, required: true, desc: 'path'
590
+ def instance_metadata
591
+ response = @core.get_metadata(options[:path])
461
592
  puts response
462
593
  end
463
594
 
595
+ desc 'own_tag', 'own tag'
596
+ option :key, type: :string, desc: 'key'
597
+ def own_tag
598
+ response = @core.own_tag
599
+ if options[:key]
600
+ puts response[options[:key]]
601
+ else
602
+ puts_json response
603
+ end
604
+ end
605
+
464
606
  private
465
607
  def instances(name, _running_only = true)
466
608
  @ec2.instances.with_tag('Name', "#{name}")
467
609
  end
468
610
 
469
611
  def puts_json(data)
470
- unless @global_options['fields'].nil?
471
- data = @core.extract_fields(data, @global_options['fields'])
612
+ unless @global_options[:fields].nil?
613
+ data = @core.extract_fields(data, @global_options[:fields])
472
614
  end
473
615
  puts JSON.pretty_generate(data)
474
616
  end
617
+
618
+ def get_public_ip_address(define_public_ip_address, instance_public_ip_address, renew)
619
+ public_ip_address = nil
620
+ if define_public_ip_address == 'auto'
621
+ allocate_address_result = @core.allocate_address_vpc
622
+ public_ip_address = allocate_address_result.public_ip
623
+ elsif define_public_ip_address.nil?
624
+ public_ip_address = instance_public_ip_address if renew
625
+ else
626
+ public_ip_address = define_public_ip_address
627
+ end
628
+ public_ip_address
629
+ end
475
630
  end
476
631
  end
@@ -1,10 +1,47 @@
1
1
  require 'aws-sdk'
2
2
  require 'ipaddress'
3
+ require 'open-uri'
4
+ require "logger"
5
+ require 'hashie'
6
+ require 'net/ping'
3
7
 
8
+ TIME_OUT = 3
4
9
  module Ec2ex
5
10
  class Core
6
11
  def initialize
12
+ ENV['AWS_REGION'] = ENV['AWS_REGION'] || get_document['region']
7
13
  @ec2 = Aws::EC2::Client.new
14
+ @elb = Aws::ElasticLoadBalancing::Client.new
15
+ @logger = Logger.new(STDOUT);
16
+ end
17
+
18
+ def client
19
+ @ec2
20
+ end
21
+
22
+ def logger
23
+ @logger
24
+ end
25
+
26
+ def get_document
27
+ JSON.parse(get_metadata('/latest/dynamic/instance-identity/document/'))
28
+ end
29
+
30
+ def get_metadata(path)
31
+ begin
32
+ result = {}
33
+ ::Timeout.timeout(TIME_OUT) {
34
+ body = open('http://169.254.169.254' + path).read
35
+ return body
36
+ }
37
+ return result
38
+ rescue TimeoutError => e
39
+ raise "not EC2 instance"
40
+ end
41
+ end
42
+
43
+ def elb_client
44
+ @elb
8
45
  end
9
46
 
10
47
  def extract_fields(data, fields)
@@ -24,10 +61,11 @@ module Ec2ex
24
61
  Hash[list.group_by { |e| e }.map { |k, v| [k, v.length] }]
25
62
  end
26
63
 
27
- def format_tag(tag)
64
+ def format_tag(tag, preset_tag_hash = {})
28
65
  tags = []
29
66
  tag.each do |k, v|
30
- tags << { key: k, value: v }
67
+ value = v ? ERB.new(v.gsub(/\$\{([^}]+)\}/, "<%=preset_tag_hash['" + '\1' + "'] %>")).result(binding) : ''
68
+ tags << { key: k, value: value }
31
69
  end
32
70
  tags
33
71
  end
@@ -40,6 +78,14 @@ module Ec2ex
40
78
  Hashie::Mash.new(result)
41
79
  end
42
80
 
81
+ def get_tag_hash_from_id(instance_id)
82
+ preset_tag = {}
83
+ @ec2.describe_tags(filters: [{ name: 'resource-id', values: [instance_id] }]).tags.each do |tag|
84
+ preset_tag[tag.key] = tag.value
85
+ end
86
+ preset_tag
87
+ end
88
+
43
89
  def instances_hash(condition, running_only = true)
44
90
  filter = []
45
91
  condition.each do |key, value|
@@ -55,66 +101,113 @@ module Ec2ex
55
101
  ).data.to_h[:reservations].map { |instance| Hashie::Mash.new(instance[:instances].first) }
56
102
  end
57
103
 
58
- def images(name)
59
- filter = [{ name: 'is-public', values: ['false'] }]
60
- filter << { name: 'name', values: ["#{name}"] }
61
- @ec2.describe_images(
62
- filters: filter
63
- ).data.to_h[:images]
104
+ def instances_hash_first_result(condition, running_only = true)
105
+ results = instances_hash(condition, running_only)
106
+ instance = results.first
107
+ unless instance
108
+ @logger.warn("not match instance => #{condition}")
109
+ exit 1
110
+ end
111
+ instance
64
112
  end
65
113
 
66
- def create_image_with_instance(instance)
67
- puts 'image creating...'
68
- tags = get_tag_hash(instance.tags)
69
- snapshot = {
114
+ def instances_hash_with_id(instance_id)
115
+ @ec2.describe_instances(
116
+ instance_ids: [instance_id]
117
+ ).data.to_h[:reservations].map { |instance| Hashie::Mash.new(instance[:instances].first) }.first
118
+ end
119
+
120
+ def own_tag
121
+ get_tag_hash(instances_hash_with_id(get_metadata('/latest/meta-data/instance-id')).tags)
122
+ end
123
+
124
+ def get_ami_tag_hash(instance, tags)
125
+ ami_tag_hash = {
70
126
  'created' => Time.now.strftime('%Y%m%d%H%M%S'),
71
127
  'tags' => instance.tags.map(&:to_hash).to_json,
72
128
  'Name' => tags['Name']
73
129
  }
74
- snapshot['security_groups'] = instance.security_groups.map(&:group_id).to_json
75
- snapshot['private_ip_address'] = instance.private_ip_address
130
+ ami_tag_hash['security_groups'] = instance.security_groups.map(&:group_id).to_json
131
+ ami_tag_hash['private_ip_address'] = instance.private_ip_address
76
132
  unless instance.public_ip_address.nil?
77
- snapshot['public_ip_address'] = instance.public_ip_address
133
+ ami_tag_hash['public_ip_address'] = instance.public_ip_address
78
134
  end
79
- snapshot['instance_type'] = instance.instance_type
80
- snapshot['placement'] = instance.placement.to_hash.to_json
135
+ ami_tag_hash['instance_type'] = instance.instance_type
136
+ ami_tag_hash['placement'] = instance.placement.to_hash.to_json
81
137
  unless instance.iam_instance_profile.nil?
82
- snapshot['iam_instance_profile'] = instance.iam_instance_profile.arn.split('/').last
138
+ ami_tag_hash['iam_instance_profile'] = instance.iam_instance_profile.arn.split('/').last
83
139
  end
140
+ unless instance.key_name.nil?
141
+ ami_tag_hash['key_name'] = instance.key_name
142
+ end
143
+ ami_tag_hash
144
+ end
84
145
 
146
+ def create_image_with_instance(instance, region = nil)
147
+ tags = get_tag_hash(instance.tags)
148
+ @logger.info "#{tags['Name']} image creating..."
149
+
150
+ image_name = tags['Name'] + ".#{Time.now.strftime('%Y%m%d%H%M%S')}"
85
151
  image_response = @ec2.create_image(
86
152
  instance_id: instance.instance_id,
87
- name: tags['Name'] + ".#{Time.now.strftime('%Y%m%d%H%M%S')}",
153
+ name: image_name,
88
154
  no_reboot: true
89
155
  )
90
156
  sleep 10
91
157
  @ec2.wait_until(:image_available, image_ids: [image_response.image_id]) do |w|
92
158
  w.interval = 15
93
- w.max_attempts = 720
159
+ w.max_attempts = 1440
94
160
  end
95
- puts "image create complete! image_id => [#{image_response.image_id}]"
161
+ @logger.info "image create complete #{tags['Name']}! image_id => [#{image_response.image_id}]"
96
162
 
97
- ami_tag = format_tag(snapshot)
163
+ ami_tag = format_tag(get_ami_tag_hash(instance, tags))
98
164
  @ec2.create_tags(resources: [image_response.image_id], tags: ami_tag)
165
+
166
+ if region
167
+ @logger.info "copying another region... [#{ENV['AWS_REGION']}] => [#{region}]"
168
+ dest_ec2 = Aws::EC2::Client.new(region: region)
169
+ copy_image_response = dest_ec2.copy_image(
170
+ source_region: ENV['AWS_REGION'],
171
+ source_image_id: image_response.image_id,
172
+ name: image_name
173
+ )
174
+ dest_ec2.create_tags(resources: [copy_image_response.image_id], tags: ami_tag)
175
+ end
176
+
99
177
  image_response.image_id
100
178
  end
101
179
 
102
180
  def wait_spot_running(spot_instance_request_id)
103
- puts 'spot instance creating...'
181
+ @logger.info 'spot instance creating...'
104
182
  instance_id = nil
105
183
  while true
106
184
  spot_instance_request = @ec2.describe_spot_instance_requests(spot_instance_request_ids: [spot_instance_request_id]).spot_instance_requests.first
107
185
  if spot_instance_request.state == 'active'
108
186
  instance_id = spot_instance_request.instance_id
109
187
  break
188
+ elsif spot_instance_request.state == 'failed'
189
+ @logger.info spot_instance_request.fault.code
190
+ @ec2.cancel_spot_instance_requests({ spot_instance_request_ids: [spot_instance_request_id] })
191
+ raise spot_instance_request.fault.message
110
192
  end
111
193
  sleep 10
112
194
  end
113
195
  @ec2.wait_until(:instance_running, instance_ids: [instance_id])
114
- puts "spot instance create complete! instance_id => [#{instance_id}]"
196
+ @logger.info "spot instance create complete! instance_id => [#{instance_id}]"
115
197
  instance_id
116
198
  end
117
199
 
200
+ def set_delete_on_termination(instance)
201
+ block_device_mappings = instance.block_device_mappings.map{ |block_device_mapping|
202
+ ebs = block_device_mapping.ebs
203
+ {
204
+ device_name: block_device_mapping.device_name,
205
+ ebs: { volume_id: block_device_mapping.ebs.volume_id, delete_on_termination: true }
206
+ }
207
+ }
208
+ @ec2.modify_instance_attribute({instance_id: instance.instance_id, block_device_mappings: block_device_mappings})
209
+ end
210
+
118
211
  def get_allocation(public_ip_address)
119
212
  @ec2.describe_addresses(public_ips: [public_ip_address]).addresses.first
120
213
  end
@@ -128,29 +221,30 @@ module Ec2ex
128
221
  end
129
222
 
130
223
  def stop_instance(instance_id)
131
- puts 'stopping...'
224
+ @logger.info 'stopping...'
132
225
  @ec2.stop_instances(
133
226
  instance_ids: [instance_id],
134
227
  force: true
135
228
  )
136
229
  @ec2.wait_until(:instance_stopped, instance_ids: [instance_id])
137
- puts "stop instance complete! instance_id => [#{instance_id}]"
230
+ @logger.info "stop instance complete! instance_id => [#{instance_id}]"
138
231
  end
139
232
 
140
233
  def start_instance(instance_id)
141
- puts 'starting...'
234
+ @logger.info 'starting...'
142
235
  @ec2.start_instances(
143
236
  instance_ids: [instance_id]
144
237
  )
145
238
  @ec2.wait_until(:instance_running, instance_ids: [instance_id])
146
- puts "start instance complete! instance_id => [#{instance_id}]"
239
+ @logger.info "start instance complete! instance_id => [#{instance_id}]"
147
240
  end
148
241
 
149
- def terminate_instance(instance_id)
150
- puts 'terminating...'
242
+ def terminate_instance(instance)
243
+ instance_id = instance.instance_id
244
+ @logger.info 'terminating...'
151
245
  @ec2.terminate_instances(instance_ids: [instance_id])
152
246
  @ec2.wait_until(:instance_terminated, instance_ids: [instance_id])
153
- puts "terminate instance complete! instance_id => [#{instance_id}]"
247
+ @logger.info "terminate instance complete! instance_id => [#{instance_id}]"
154
248
  end
155
249
 
156
250
  def associate_address(instance_id, public_ip_address)
@@ -161,16 +255,84 @@ module Ec2ex
161
255
  end
162
256
 
163
257
  def latest_image_with_name(name)
164
- filter = [{ name: 'is-public', values: ['false'] }]
165
- filter << { name: 'tag:Name', values: [name] }
166
- result = @ec2.describe_images(
167
- filters: filter
168
- ).data.to_h[:images]
258
+ result = search_image_with_name(name)
169
259
  result = result.sort_by{ |image|
170
260
  tag_hash = get_tag_hash(image[:tags])
171
261
  tag_hash['created'].nil? ? '' : tag_hash['created']
172
262
  }
173
263
  result.empty? ? {} : result.last
174
264
  end
265
+
266
+ def get_old_images(name, num = 10)
267
+ result = search_image_with_name(name)
268
+ return [] if result.empty?
269
+ map = Hash.new{|h,k| h[k] = []}
270
+ result = result.each{ |image|
271
+ tag_hash = get_tag_hash(image[:tags])
272
+ next if tag_hash['Name'].nil? || tag_hash['created'].nil?
273
+ map[tag_hash['Name']] << image
274
+ }
275
+ old_images = []
276
+ map.each do |name, images|
277
+ sorted_images = images.sort_by{ |image|
278
+ tag_hash = get_tag_hash(image[:tags])
279
+ Time.parse(tag_hash['created'])
280
+ }
281
+ newly_images = sorted_images.last(num)
282
+ old_images = old_images + (sorted_images - newly_images)
283
+ end
284
+ old_images
285
+ end
286
+
287
+ def images(name)
288
+ filter = [{ name: 'is-public', values: ['false'] }]
289
+ filter << { name: 'name', values: [name] }
290
+ @ec2.describe_images(
291
+ filters: filter
292
+ ).data.to_h[:images]
293
+ end
294
+
295
+ def search_image_with_name(name)
296
+ filter = [{ name: 'is-public', values: ['false'] }]
297
+ filter << { name: 'tag:Name', values: [name] }
298
+ @ec2.describe_images(
299
+ filters: filter
300
+ ).data.to_h[:images]
301
+ end
302
+
303
+ def deregister_snapshot_no_related(owner_id)
304
+ enable_snapshot_ids = []
305
+ images('*').each do |image|
306
+ image_id = image[:image_id]
307
+ snapshot_ids = image[:block_device_mappings]
308
+ .select{ |block_device_mapping| block_device_mapping[:ebs] != nil }
309
+ .map{ |block_device_mapping| block_device_mapping[:ebs][:snapshot_id] }
310
+ enable_snapshot_ids.concat(snapshot_ids)
311
+ end
312
+ filter = [{ name: 'owner-id', values: [owner_id] }]
313
+ all_snapshot_ids = @ec2.describe_snapshots(
314
+ filters: filter
315
+ ).data.to_h[:snapshots].map{ |snapshot| snapshot[:snapshot_id] }
316
+ disable_snapshot_ids = (all_snapshot_ids - enable_snapshot_ids)
317
+ disable_snapshot_ids.each do |disable_snapshot_id|
318
+ @ec2.delete_snapshot({snapshot_id: disable_snapshot_id})
319
+ @logger.info "delete snapshot #{disable_snapshot_id}"
320
+ end
321
+ end
322
+
323
+ def ping?(private_ip_address)
324
+ if private_ip_address
325
+ pinger = Net::Ping::External.new(private_ip_address)
326
+ if pinger.ping?
327
+ @logger.info "already exists private_ip_address => #{private_ip_address}"
328
+ return true
329
+ end
330
+ end
331
+ return false
332
+ end
333
+
334
+ def allocate_address_vpc
335
+ @ec2.allocate_address(domain: 'vpc').data
336
+ end
175
337
  end
176
338
  end
@@ -1,4 +1,4 @@
1
1
  module Ec2ex
2
2
  # ec2ex version
3
- VERSION = '0.1.0'
3
+ VERSION = '0.2.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ec2ex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroshi Toyama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-14 00:00:00.000000000 Z
11
+ date: 2016-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: aws-sdk
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 2.0.11.pre
61
+ version: '0'
62
62
  type: :runtime
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: 2.0.11.pre
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activesupport
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,48 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: parallel
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: net-ping
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: bundler
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - "~>"
115
+ - - ">="
88
116
  - !ruby/object:Gem::Version
89
- version: 1.7.2
117
+ version: '0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - "~>"
122
+ - - ">="
95
123
  - !ruby/object:Gem::Version
96
- version: 1.7.2
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: pry
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -225,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
253
  version: '0'
226
254
  requirements: []
227
255
  rubyforge_project:
228
- rubygems_version: 2.4.2
256
+ rubygems_version: 2.5.1
229
257
  signing_key:
230
258
  specification_version: 4
231
259
  summary: ec2 expand command line