aws-eni 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/aws-eni +36 -7
- data/lib/aws-eni.rb +80 -25
- data/lib/aws-eni/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe0e076295a17d9cc4c63a7227f83be289fcb4b3
|
4
|
+
data.tar.gz: 51dfdb49ec4bba211e5105f3eafed74fc210cdcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa9fd08058dfda15e1c473108105d37e6aaf1c64a322fe249a1c5f469b494399895395f2df2c18d12df7a1d5cbac8811393693e48d032d5824c0b70fc6880b72
|
7
|
+
data.tar.gz: 7da3b4bd53b7944f744e02c76bc9dc7a691cde2b76ecb708dba83006045e21a3dd30e4c8f35cc0f149762079e4d94f4a9c732e38c2bfb4e54a0fe7c886ccdfae
|
data/bin/aws-eni
CHANGED
@@ -24,6 +24,7 @@ desc 'Display all system commands and warnings'
|
|
24
24
|
switch [:V,:verbose], negatable: false
|
25
25
|
|
26
26
|
pre do |opt|
|
27
|
+
Aws::ENI.timeout 90
|
27
28
|
Aws::ENI::IFconfig.verbose = opt[:verbose]
|
28
29
|
true
|
29
30
|
end
|
@@ -236,13 +237,13 @@ arg 'security-groups', :optional
|
|
236
237
|
arg 'ip-address', :optional
|
237
238
|
command [:attach] do |c|
|
238
239
|
c.desc 'Do not configure or enable the device after attachment (implies block)'
|
239
|
-
c.switch [:n
|
240
|
+
c.switch [:n,:noconfig], negatable: false
|
240
241
|
|
241
242
|
c.desc 'Do not return until attachment is complete'
|
242
243
|
c.switch [:b,:block], negatable: false
|
243
244
|
|
244
245
|
c.action do |global,opts,args|
|
245
|
-
config = !opts[
|
246
|
+
config = !opts[:noconfig]
|
246
247
|
if args.first =~ /^eni-/
|
247
248
|
help_now! 'Too many arguments' if args.count > 1
|
248
249
|
id = args.first
|
@@ -275,6 +276,9 @@ command [:detach] do |c|
|
|
275
276
|
c.desc 'Delete (or preserve) the unused ENI resource after dataching (implies block)'
|
276
277
|
c.switch [:d,:delete], default_value: :not_provided # GLI behavior workaround
|
277
278
|
|
279
|
+
c.desc 'Release any associated public IP addresses'
|
280
|
+
c.switch [:r,:release], negatable: false
|
281
|
+
|
278
282
|
c.desc 'Do not return until detachment is complete'
|
279
283
|
c.switch [:b,:block], negatable: false
|
280
284
|
|
@@ -283,9 +287,18 @@ command [:detach] do |c|
|
|
283
287
|
params = parse_args args, :interface_id, :device_name
|
284
288
|
params[:block] = opts[:block]
|
285
289
|
params[:delete] = opts[:delete] unless opts[:delete] == :not_provided
|
290
|
+
params[:release] = opts[:release]
|
286
291
|
id = params[:device_name] || params[:interface_id]
|
287
292
|
|
288
293
|
device = Aws::ENI.detach_interface(id, params)
|
294
|
+
|
295
|
+
device[:public_ips].each do |address|
|
296
|
+
if device[:released]
|
297
|
+
puts "EIP #{address[:public_ip]} (#{address[:allocation_id]}) dissociated and released"
|
298
|
+
else
|
299
|
+
puts "EIP #{address[:public_ip]} (#{address[:allocation_id]}) dissociated"
|
300
|
+
end
|
301
|
+
end
|
289
302
|
if device[:deleted]
|
290
303
|
puts "interface #{device[:interface_id]} detached from #{device[:device_name]} and deleted"
|
291
304
|
else
|
@@ -310,10 +323,24 @@ command [:clean] do |c|
|
|
310
323
|
c.desc 'Force deletion of all unattached interfaces which meet our criteria'
|
311
324
|
c.switch [:f,:force], negatable: false
|
312
325
|
|
326
|
+
c.desc 'Release any associated public IP addresses'
|
327
|
+
c.switch [:r,:release], negatable: false
|
328
|
+
|
313
329
|
c.action do |global,opts,args|
|
314
330
|
help_now! "Too many arguments" if args.count > 1
|
315
|
-
deleted = Aws::ENI.clean_interfaces(args.first, safe_mode: !opts[:force])
|
316
|
-
|
331
|
+
deleted = Aws::ENI.clean_interfaces(args.first, safe_mode: !opts[:force], release: opts[:release])
|
332
|
+
|
333
|
+
deleted[:public_ips].each do |address|
|
334
|
+
if deleted[:released]
|
335
|
+
puts "EIP #{address[:public_ip]} (#{address[:allocation_id]}) dissociated and released"
|
336
|
+
else
|
337
|
+
puts "EIP #{address[:public_ip]} (#{address[:allocation_id]}) dissociated"
|
338
|
+
end
|
339
|
+
end
|
340
|
+
deleted[:interfaces].each do |interface_id|
|
341
|
+
puts "interface #{interface_id} deleted"
|
342
|
+
end
|
343
|
+
puts "#{deleted[:interfaces].count} interfaces deleted"
|
317
344
|
end
|
318
345
|
end
|
319
346
|
|
@@ -328,7 +355,7 @@ arg 'ip-address', :optional
|
|
328
355
|
arg 'interface-id OR device-name'
|
329
356
|
command [:assign] do |c|
|
330
357
|
c.desc 'Do not configure the interface after assignment'
|
331
|
-
c.switch [:n
|
358
|
+
c.switch [:n,:noconfig], negatable: false
|
332
359
|
|
333
360
|
c.desc 'Do not return until connection is verified'
|
334
361
|
c.switch [:b,:block], negatable: false
|
@@ -338,7 +365,7 @@ command [:assign] do |c|
|
|
338
365
|
device = params[:device_name] || params[:interface_id]
|
339
366
|
help_now! "Missing argument" if device.nil?
|
340
367
|
|
341
|
-
params.merge! configure: !opts[
|
368
|
+
params.merge! configure: !opts[:noconfig], block: opts[:block]
|
342
369
|
Aws::ENI.assert_ifconfig_access if params[:configure]
|
343
370
|
|
344
371
|
assignment = Aws::ENI.assign_secondary_ip(device, params)
|
@@ -395,10 +422,11 @@ command [:associate] do |c|
|
|
395
422
|
c.switch [:b,:block], negatable: false
|
396
423
|
|
397
424
|
c.action do |global,opts,args|
|
398
|
-
help_now! "Missing argument" if args.empty?
|
399
425
|
args.delete('new')
|
400
426
|
params = parse_args args, :private_ip, :public_ip, :allocation_id, :interface_id, :device_name
|
401
427
|
params[:block] = opts[:block]
|
428
|
+
help_now! "Missing argument" unless params[:private_ip]
|
429
|
+
|
402
430
|
assoc = Aws::ENI.associate_elastic_ip(params[:private_ip], params)
|
403
431
|
puts "EIP #{assoc[:public_ip]} (#{assoc[:allocation_id]}) associated with #{assoc[:private_ip]} on #{assoc[:device_name]} (#{assoc[:interface_id]})"
|
404
432
|
end
|
@@ -418,6 +446,7 @@ command [:dissociate] do |c|
|
|
418
446
|
|
419
447
|
c.action do |global,opts,args|
|
420
448
|
params = parse_args args, :private_ip, :public_ip, :allocation_id, :association_id, :interface_id, :device_name
|
449
|
+
params[:release] = opts[:release]
|
421
450
|
address = params[:private_ip] || params[:public_ip] || params[:association_id] || params[:allocation_id]
|
422
451
|
help_now! "Missing argument" unless address
|
423
452
|
dissoc = Aws::ENI.dissociate_elastic_ip(address, params)
|
data/lib/aws-eni.rb
CHANGED
@@ -123,6 +123,9 @@ module Aws
|
|
123
123
|
interface_id: options[:interface_id],
|
124
124
|
device_number: options[:device_number]
|
125
125
|
)
|
126
|
+
if device.name == 'eth0'
|
127
|
+
raise InvalidParameterError, "For safety, interface eth0 cannot be detached."
|
128
|
+
end
|
126
129
|
interface_id = device.interface_id
|
127
130
|
|
128
131
|
response = client.describe_network_interfaces(filters: [{
|
@@ -142,7 +145,19 @@ module Aws
|
|
142
145
|
force: true
|
143
146
|
)
|
144
147
|
created_by_us = interface.tag_set.any? { |tag| tag.key == 'created by' && tag.value == owner_tag }
|
145
|
-
do_delete = options[:delete]
|
148
|
+
do_delete = options[:delete] != false && created_by_us
|
149
|
+
do_release = !!options[:release]
|
150
|
+
|
151
|
+
public_ips = []
|
152
|
+
interface[:private_ip_addresses].each do |addr|
|
153
|
+
if assoc = addr[:association]
|
154
|
+
public_ips << {
|
155
|
+
public_ip: assoc[:public_ip],
|
156
|
+
allocation_id: assoc[:allocation_id]
|
157
|
+
}
|
158
|
+
dissociate_elastic_ip(assoc[:allocation_id], release: true) if do_release
|
159
|
+
end
|
160
|
+
end
|
146
161
|
|
147
162
|
if options[:block] || do_delete
|
148
163
|
wait_for 'the interface to detach', interval: 0.3 do
|
@@ -156,12 +171,16 @@ module Aws
|
|
156
171
|
device_number: device.device_number,
|
157
172
|
created_by_us: created_by_us,
|
158
173
|
deleted: do_delete,
|
174
|
+
released: do_release,
|
175
|
+
public_ips: public_ips,
|
159
176
|
api_response: interface
|
160
177
|
}
|
161
178
|
end
|
162
179
|
|
163
180
|
# delete unattached network interfaces
|
164
181
|
def clean_interfaces(filter = nil, options = {})
|
182
|
+
public_ips = []
|
183
|
+
do_release = !!options[:release]
|
165
184
|
safe_mode = true unless options[:safe_mode] == false
|
166
185
|
|
167
186
|
filters = [
|
@@ -186,20 +205,30 @@ module Aws
|
|
186
205
|
|
187
206
|
descriptions = client.describe_network_interfaces(filters: filters)
|
188
207
|
interfaces = descriptions[:network_interfaces].select do |interface|
|
189
|
-
|
208
|
+
created_recently = interface.tag_set.any? do |tag|
|
190
209
|
begin
|
191
210
|
tag.key == 'created on' && Time.now - Time.parse(tag.value) < 60
|
192
211
|
rescue ArgumentError
|
193
|
-
false
|
194
212
|
end
|
195
213
|
end
|
214
|
+
unless safe_mode && created_recently
|
215
|
+
interface[:private_ip_addresses].each do |addr|
|
216
|
+
if assoc = addr[:association]
|
217
|
+
public_ips << {
|
218
|
+
public_ip: assoc[:public_ip],
|
219
|
+
allocation_id: assoc[:allocation_id]
|
220
|
+
}
|
221
|
+
dissociate_elastic_ip(assoc[:allocation_id], release: true) if do_release
|
222
|
+
end
|
223
|
+
end
|
196
224
|
client.delete_network_interface(network_interface_id: interface[:network_interface_id])
|
197
225
|
true
|
198
226
|
end
|
199
227
|
end
|
200
228
|
{
|
201
|
-
|
202
|
-
|
229
|
+
interfaces: interfaces.map { |eni| eni[:network_interface_id] },
|
230
|
+
public_ips: public_ips,
|
231
|
+
released: do_release,
|
203
232
|
api_response: interfaces
|
204
233
|
}
|
205
234
|
end
|
@@ -216,7 +245,7 @@ module Aws
|
|
216
245
|
current_ips = interface_ips(interface_id)
|
217
246
|
new_ip = options[:private_ip]
|
218
247
|
|
219
|
-
if new_ip
|
248
|
+
if new_ip
|
220
249
|
if current_ips.include?(new_ip)
|
221
250
|
raise InvalidParameterError, "IP #{new_ip} already assigned to #{device.name}"
|
222
251
|
end
|
@@ -226,7 +255,8 @@ module Aws
|
|
226
255
|
allow_reassignment: false
|
227
256
|
)
|
228
257
|
wait_for 'private ip address to be assigned' do
|
229
|
-
interface_ips(interface_id).include?(new_ip)
|
258
|
+
interface_ips(interface_id).include?(new_ip) ||
|
259
|
+
device.local_ips.include?(new_ip)
|
230
260
|
end
|
231
261
|
else
|
232
262
|
client.assign_private_ip_addresses(
|
@@ -236,6 +266,7 @@ module Aws
|
|
236
266
|
)
|
237
267
|
wait_for 'new private ip address to be assigned' do
|
238
268
|
new_ips = interface_ips(interface_id) - current_ips
|
269
|
+
new_ips = device.local_ips - current_ips if new_ips.empty?
|
239
270
|
new_ip = new_ips.first if new_ips
|
240
271
|
end
|
241
272
|
end
|
@@ -279,7 +310,7 @@ module Aws
|
|
279
310
|
end
|
280
311
|
|
281
312
|
if assoc = addr_info[:association]
|
282
|
-
|
313
|
+
dissociate_elastic_ip(assoc[:allocation_id], release: do_release)
|
283
314
|
end
|
284
315
|
|
285
316
|
device.remove_alias(private_ip)
|
@@ -291,15 +322,17 @@ module Aws
|
|
291
322
|
private_ip: private_ip,
|
292
323
|
device_name: device.name,
|
293
324
|
interface_id: device.interface_id,
|
294
|
-
public_ip: assoc[:public_ip],
|
295
|
-
allocation_id: assoc[:allocation_id],
|
296
|
-
association_id: assoc[:association_id],
|
325
|
+
public_ip: assoc && assoc[:public_ip],
|
326
|
+
allocation_id: assoc && assoc[:allocation_id],
|
327
|
+
association_id: assoc && assoc[:association_id],
|
297
328
|
released: assoc && do_release
|
298
329
|
}
|
299
330
|
end
|
300
331
|
|
301
332
|
# associate a private ip with an elastic ip through the AWS api
|
302
333
|
def associate_elastic_ip(private_ip, options = {})
|
334
|
+
raise MissingParameterError, "You must specify a private ip address" unless private_ip
|
335
|
+
|
303
336
|
find = options[:device_name] || options[:device_number] || options[:interface_id] || private_ip
|
304
337
|
device = IFconfig[find].assert(
|
305
338
|
exists: true,
|
@@ -345,32 +378,54 @@ module Aws
|
|
345
378
|
|
346
379
|
# dissociate a public ip from a private ip through the AWS api and
|
347
380
|
# optionally release the public ip
|
348
|
-
def dissociate_elastic_ip(
|
381
|
+
def dissociate_elastic_ip(address, options = {})
|
349
382
|
do_release = !!options[:release]
|
350
|
-
eip = describe_address(ip)
|
351
383
|
|
352
|
-
|
384
|
+
# assert device attributes if we've specified a device
|
385
|
+
if find = options[:device_name] || options[:device_number]
|
353
386
|
device = IFconfig[find].assert(
|
354
387
|
device_name: options[:device_name],
|
355
388
|
device_number: options[:device_number],
|
356
|
-
interface_id: options[:interface_id]
|
389
|
+
interface_id: options[:interface_id],
|
390
|
+
private_ip: options[:private_ip],
|
391
|
+
public_ip: options[:public_ip]
|
357
392
|
)
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
393
|
+
end
|
394
|
+
|
395
|
+
# get our address info
|
396
|
+
eip = describe_address(address)
|
397
|
+
device ||= IFconfig.find { |dev| dev.interface_id == eip[:network_interface_id] }
|
398
|
+
|
399
|
+
# assert eip attributes if options provided
|
400
|
+
if options[:private_ip] && eip[:private_ip_address] != options[:private_ip]
|
401
|
+
raise InvalidParameterError, "#{address} is not associated with IP #{options[:private_ip]}"
|
402
|
+
end
|
403
|
+
if options[:public_ip] && eip[:public_ip] != options[:public_ip]
|
404
|
+
raise InvalidParameterError, "#{address} is not associated with public IP #{options[:public_ip]}"
|
405
|
+
end
|
406
|
+
if options[:allocation_id] && eip[:allocation_id] != options[:allocation_id]
|
407
|
+
raise InvalidParameterError, "#{address} is not associated with allocation ID #{options[:allocation_id]}"
|
408
|
+
end
|
409
|
+
if options[:association_id] && eip[:association_id] != options[:association_id]
|
410
|
+
raise InvalidParameterError, "#{address} is not associated with association ID #{options[:association_id]}"
|
411
|
+
end
|
412
|
+
if options[:interface_id] && eip[:network_interface_id] != options[:interface_id]
|
413
|
+
raise InvalidParameterError, "#{address} is not associated with interface ID #{options[:interface_id]}"
|
414
|
+
end
|
415
|
+
|
416
|
+
if device
|
417
|
+
if device.name == 'eth0' && device.local_ips.first == eip[:private_ip_address]
|
418
|
+
raise InvalidParameterError, "For safety, a public address cannot be dissociated from the primary IP on eth0"
|
366
419
|
end
|
420
|
+
elsif interface_status(eip[:network_interface_id]) != 'available'
|
421
|
+
raise InvalidParameterError, "#{address} is associated with an interface attached to another machine"
|
367
422
|
end
|
368
423
|
|
369
424
|
client.disassociate_address(association_id: eip[:association_id])
|
370
425
|
client.release_address(allocation_id: eip[:allocation_id]) if do_release
|
371
426
|
{
|
372
427
|
private_ip: eip[:private_ip_address],
|
373
|
-
device_name: device.name,
|
428
|
+
device_name: device && device.name,
|
374
429
|
interface_id: eip[:network_interface_id],
|
375
430
|
public_ip: eip[:public_ip],
|
376
431
|
allocation_id: eip[:allocation_id],
|
@@ -478,7 +533,7 @@ module Aws
|
|
478
533
|
when /^eipalloc-/
|
479
534
|
'allocation-id'
|
480
535
|
when /^eipassoc-/
|
481
|
-
'
|
536
|
+
'association-id'
|
482
537
|
else
|
483
538
|
if IPAddr.new(environment[:vpc_cidr]) === IPAddr.new(address)
|
484
539
|
'private-ip-address'
|
data/lib/aws-eni/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-eni
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Greiling
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gli
|