aws-eni 0.2.2 → 0.3.0
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 +86 -31
- data/lib/aws-eni.rb +112 -27
- data/lib/aws-eni/client.rb +9 -4
- data/lib/aws-eni/interface.rb +3 -1
- data/lib/aws-eni/meta.rb +1 -1
- 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: f19e4e251a90092251316683eb8f3562300422e5
|
4
|
+
data.tar.gz: eb37b04707d8d8817fd247a3d440bc44d310dae2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56f2fca8525b755a14d3a78d654bdb5e148e593e53ba74bf193ad57e18ba25955ef5a8697ab2fc83184c6e5c43a3e3c67e80bedeb268884f2fe1c6af7e255497
|
7
|
+
data.tar.gz: ae0239c63b23e14433074b71afad75f0ceda79954d5aa5adacbae4f9fcc559d577fe1280029aedf8da181777e4d11e113153cc413598926db8dedb9d3108e5ac
|
data/bin/aws-eni
CHANGED
@@ -11,7 +11,7 @@ program_desc 'Manage and sync local network config with AWS Elastic Network Inte
|
|
11
11
|
@version = Aws::ENI::VERSION
|
12
12
|
|
13
13
|
autocomplete_commands true
|
14
|
-
subcommand_option_handling :
|
14
|
+
subcommand_option_handling :legacy
|
15
15
|
arguments :loose
|
16
16
|
sort_help :manually
|
17
17
|
|
@@ -65,13 +65,13 @@ def parse_args(args, *accept)
|
|
65
65
|
help_now! "You may only specify one private IP address." if params[:private_ip]
|
66
66
|
params[:private_ip] = arg
|
67
67
|
else
|
68
|
-
help_now! "Invalid
|
68
|
+
help_now! "Invalid argument: #{arg}"
|
69
69
|
end
|
70
70
|
elsif accept.include?(:public_ip)
|
71
71
|
help_now! "You may only specify one public IP address." if params[:public_ip]
|
72
72
|
params[:public_ip] = arg
|
73
73
|
else
|
74
|
-
help_now! "Invalid
|
74
|
+
help_now! "Invalid argument: #{arg}"
|
75
75
|
end
|
76
76
|
else
|
77
77
|
help_now! "Invalid argument: #{arg}"
|
@@ -82,6 +82,8 @@ end
|
|
82
82
|
|
83
83
|
# commands
|
84
84
|
|
85
|
+
default_command :list
|
86
|
+
|
85
87
|
desc 'List current interface configuration'
|
86
88
|
long_desc %{
|
87
89
|
List information about a set of interfaces including interface ID, interface
|
@@ -230,14 +232,15 @@ arg 'subnet-id', :optional
|
|
230
232
|
arg 'security-groups', :optional
|
231
233
|
arg 'ip-address', :optional
|
232
234
|
command [:attach] do |c|
|
233
|
-
c.desc 'Do not configure
|
234
|
-
c.switch [:
|
235
|
+
c.desc 'Do not configure and enable the device after attachment'
|
236
|
+
c.switch [:noconfig], negatable: false
|
235
237
|
|
236
|
-
c.desc 'Do not
|
237
|
-
c.switch [:
|
238
|
+
c.desc 'Do not wait for attachment to complete (implies noconfig)'
|
239
|
+
c.switch [:n,:noblock], negatable: false
|
238
240
|
|
239
241
|
c.action do |global,opts,args|
|
240
|
-
|
242
|
+
block = !opts[:noblock]
|
243
|
+
config = block && !opts[:noconfig]
|
241
244
|
if args.first =~ /^eni-/
|
242
245
|
help_now! 'Too many arguments' if args.count > 1
|
243
246
|
id = args.first
|
@@ -251,7 +254,7 @@ command [:attach] do |c|
|
|
251
254
|
new_interface = true
|
252
255
|
end
|
253
256
|
begin
|
254
|
-
device = Aws::ENI.attach_interface(id, enable: config, configure: config, block:
|
257
|
+
device = Aws::ENI.attach_interface(id, enable: config, configure: config, block: block)
|
255
258
|
rescue Aws::ENI::Errors::ClientOperationError => e
|
256
259
|
warn e.message
|
257
260
|
if new_interface && Aws::ENI.clean_interfaces(id, safe_mode: false)
|
@@ -276,20 +279,25 @@ long_desc %{
|
|
276
279
|
}
|
277
280
|
arg 'interface-id OR device-name'
|
278
281
|
command [:detach] do |c|
|
279
|
-
c.desc 'Delete
|
280
|
-
c.switch [:d,:delete],
|
282
|
+
c.desc 'Delete the unused ENI resource after dataching (implies block)'
|
283
|
+
c.switch [:d,:delete], negatable: false
|
284
|
+
|
285
|
+
c.desc 'Do not delete the unused ENI resource after dataching'
|
286
|
+
c.switch [:p,:preserve], negatable: false
|
281
287
|
|
282
288
|
c.desc 'Release any associated public IP addresses'
|
283
289
|
c.switch [:r,:release], negatable: false
|
284
290
|
|
285
|
-
c.desc 'Do not
|
286
|
-
c.switch [:
|
291
|
+
c.desc 'Do not wait until detachment is complete'
|
292
|
+
c.switch [:n,:noblock], negatable: false
|
287
293
|
|
288
294
|
c.action do |global,opts,args|
|
289
295
|
help_now! "Missing argument" if args.empty?
|
296
|
+
help_now! "--delete and --preserve flags cannot be used together" if opts[:delete] && opts[:preserve]
|
290
297
|
params = parse_args args, :interface_id, :device_name
|
291
|
-
params[:block] = opts[:
|
292
|
-
params[:delete] =
|
298
|
+
params[:block] = !opts[:noblock]
|
299
|
+
params[:delete] = true if opts[:delete]
|
300
|
+
params[:delete] = false if opts[:preserve]
|
293
301
|
params[:release] = opts[:release]
|
294
302
|
id = params[:device_name] || params[:interface_id]
|
295
303
|
|
@@ -357,18 +365,18 @@ long_desc %{
|
|
357
365
|
arg 'ip-address', :optional
|
358
366
|
arg 'interface-id OR device-name'
|
359
367
|
command [:assign] do |c|
|
360
|
-
c.desc 'Do not configure the interface after assignment'
|
361
|
-
c.switch [:
|
368
|
+
c.desc 'Do not configure the interface after assignment (implies noblock)'
|
369
|
+
c.switch [:noconfig], negatable: false
|
362
370
|
|
363
|
-
c.desc 'Do not
|
364
|
-
c.switch [:
|
371
|
+
c.desc 'Do not wait for the connection to be verified'
|
372
|
+
c.switch [:n,:noblock], negatable: false
|
365
373
|
|
366
374
|
c.action do |global,opts,args|
|
367
375
|
params = parse_args args, :interface_id, :device_name, :private_ip
|
368
376
|
device = params[:device_name] || params[:interface_id]
|
369
377
|
help_now! "Missing argument" if device.nil?
|
370
378
|
|
371
|
-
params.merge! configure: !opts[:noconfig], block: opts[:
|
379
|
+
params.merge! configure: !opts[:noconfig], block: !opts[:noblock] && !opts[:noconfig]
|
372
380
|
Aws::ENI.assert_interface_access if params[:configure]
|
373
381
|
|
374
382
|
assignment = Aws::ENI.assign_secondary_ip(device, params)
|
@@ -409,11 +417,15 @@ desc 'Associate a public IP address with a private IP address'
|
|
409
417
|
long_desc %{
|
410
418
|
Associate a private IP address with a new or existing public IP address.
|
411
419
|
|
412
|
-
If no public IP or allocation ID is provided,
|
413
|
-
|
420
|
+
If no public IP or allocation ID is provided, an IP address will be selected
|
421
|
+
from among the unattached Elastic IP addresses available on tha account. If
|
422
|
+
no EIP is available, a new Elastic IP Address will be allocated and used.
|
414
423
|
|
415
|
-
If
|
416
|
-
|
424
|
+
If -n or the keyword "new" is uesd, it will always allocate a new address
|
425
|
+
by default rather than using one that is already available.
|
426
|
+
|
427
|
+
If no interface ID or device name provided, it will be inferred from the
|
428
|
+
private IP address provided.
|
417
429
|
}
|
418
430
|
arg 'private-ip'
|
419
431
|
arg 'public-ip', :optional
|
@@ -421,16 +433,20 @@ arg 'allocation-id', :optional
|
|
421
433
|
arg 'interface-id', :optional
|
422
434
|
arg 'device-name', :optional
|
423
435
|
command [:associate] do |c|
|
424
|
-
c.desc 'Do not
|
425
|
-
c.switch [:
|
436
|
+
c.desc 'Do not wait for the connection to be verified'
|
437
|
+
c.switch [:noblock], negatable: false
|
438
|
+
|
439
|
+
c.desc 'Allocate a new public IP address (can also pass "new" as a parameter)'
|
440
|
+
c.switch [:n,:new], negatable: false
|
426
441
|
|
427
442
|
c.action do |global,opts,args|
|
428
|
-
args.delete('new')
|
443
|
+
opts[:new] = !!args.delete('new') || opts[:new]
|
429
444
|
params = parse_args args, :private_ip, :public_ip, :allocation_id, :interface_id, :device_name
|
430
|
-
params[:
|
445
|
+
params.merge! new: opts[:new], block: !opts[:noblock]
|
431
446
|
help_now! "Missing argument" unless params[:private_ip]
|
432
447
|
|
433
448
|
assoc = Aws::ENI.associate_elastic_ip(params[:private_ip], params)
|
449
|
+
puts "EIP #{assoc[:public_ip]} allocated as #{assoc[:allocation_id]}" if assoc[:allocated]
|
434
450
|
puts "EIP #{assoc[:public_ip]} (#{assoc[:allocation_id]}) associated with #{assoc[:private_ip]} on #{assoc[:device_name]} (#{assoc[:interface_id]})"
|
435
451
|
end
|
436
452
|
end
|
@@ -491,13 +507,51 @@ command [:release] do |c|
|
|
491
507
|
end
|
492
508
|
end
|
493
509
|
|
494
|
-
desc 'Test
|
510
|
+
desc 'Test a LAN or WAN connection through a specific IP'
|
511
|
+
long_desc %{
|
512
|
+
Test a LAN or WAN connection with ICMP. Provide a local IP address to test
|
513
|
+
its connection to the subnet gateway, or provide a public IP address to test
|
514
|
+
its connection to 8.8.8.8.
|
515
|
+
}
|
516
|
+
arg 'private-ip OR public-ip OR allocation-id'
|
517
|
+
arg 'interface-id', :optional
|
518
|
+
arg 'device-name', :optional
|
519
|
+
command [:test] do |c|
|
520
|
+
|
521
|
+
c.desc 'How many seconds to wait for a response to the ICMP packets'
|
522
|
+
c.flag [:t,:timeout], default_value: 30, type: Integer
|
523
|
+
|
524
|
+
c.action do |global,opts,args|
|
525
|
+
params = parse_args args, :private_ip, :public_ip, :allocation_id, :association_id, :interface_id, :device_name
|
526
|
+
params[:timeout] = opts[:timeout]
|
527
|
+
|
528
|
+
if address = params[:public_ip] || params[:association_id] || params[:allocation_id]
|
529
|
+
if Aws::ENI.test_association(address, params)
|
530
|
+
puts "EIP #{address} connection successful"
|
531
|
+
else
|
532
|
+
puts "EIP #{address} failed to connect after #{opts[:timeout]} seconds"
|
533
|
+
exit! 1
|
534
|
+
end
|
535
|
+
elsif address = params[:private_ip]
|
536
|
+
if Aws::ENI.test_secondary_ip(address, params)
|
537
|
+
puts "IP #{address} connection successful"
|
538
|
+
else
|
539
|
+
puts "IP #{address} failed to connect after #{opts[:timeout]} seconds"
|
540
|
+
exit! 1
|
541
|
+
end
|
542
|
+
else
|
543
|
+
help_now! "Missing argument"
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
desc 'Check access to AWS EC2 and our machine\'s network config'
|
495
549
|
long_desc %{
|
496
550
|
Check for sufficient privileges to alter the local machine's network interface
|
497
551
|
configuration and verify that the AWS access credentials include permissions
|
498
552
|
necessary to perform all network related functions.
|
499
553
|
}
|
500
|
-
command [:
|
554
|
+
command [:check] do |c|
|
501
555
|
c.action do |global,opts,args|
|
502
556
|
help_now! "Too many arguments" if args.count > 1
|
503
557
|
|
@@ -535,5 +589,6 @@ on_error do |error|
|
|
535
589
|
end
|
536
590
|
end
|
537
591
|
|
538
|
-
|
592
|
+
# work around GLI's odd -v option detection
|
593
|
+
exit run %w[-v help] if (ARGV & %w[-v --version]).any?
|
539
594
|
exit run(ARGV)
|
data/lib/aws-eni.rb
CHANGED
@@ -98,24 +98,25 @@ module Aws
|
|
98
98
|
end
|
99
99
|
|
100
100
|
# attach network interface
|
101
|
-
def attach_interface(
|
102
|
-
|
103
|
-
|
101
|
+
def attach_interface(interface_id, options = {})
|
102
|
+
do_block = options[:block] != false
|
103
|
+
do_enable = options[:enable] != false
|
104
|
+
do_config = options[:configure] != false
|
104
105
|
assert_interface_access if do_config || do_enable
|
105
106
|
|
106
107
|
device = Interface[options[:device_number] || options[:name]].assert(exists: false)
|
107
108
|
|
108
109
|
begin
|
109
110
|
response = Client.attach_network_interface(
|
110
|
-
network_interface_id:
|
111
|
+
network_interface_id: interface_id,
|
111
112
|
instance_id: environment[:instance_id],
|
112
113
|
device_index: device.device_number
|
113
114
|
)
|
114
115
|
rescue EC2::Errors::AttachmentLimitExceeded
|
115
|
-
raise Errors::ClientOperationError, "Unable to attach #{
|
116
|
+
raise Errors::ClientOperationError, "Unable to attach #{interface_id} to #{device.name} (attachment limit exceeded)"
|
116
117
|
end
|
117
118
|
|
118
|
-
if
|
119
|
+
if do_block || do_config || do_enable
|
119
120
|
wait_for 'the interface to attach', rescue: Errors::MetaNotFound do
|
120
121
|
device.exists? && Client.interface_attached(device.interface_id)
|
121
122
|
end
|
@@ -123,7 +124,7 @@ module Aws
|
|
123
124
|
device.configure if do_config
|
124
125
|
device.enable if do_enable
|
125
126
|
{
|
126
|
-
interface_id:
|
127
|
+
interface_id: interface_id,
|
127
128
|
device_name: device.name,
|
128
129
|
device_number: device.device_number,
|
129
130
|
enabled: do_enable,
|
@@ -133,8 +134,8 @@ module Aws
|
|
133
134
|
end
|
134
135
|
|
135
136
|
# detach network interface
|
136
|
-
def detach_interface(
|
137
|
-
device = Interface[
|
137
|
+
def detach_interface(selector, options = {})
|
138
|
+
device = Interface[selector].assert(
|
138
139
|
exists: true,
|
139
140
|
device_name: options[:device_name],
|
140
141
|
interface_id: options[:interface_id],
|
@@ -142,24 +143,18 @@ module Aws
|
|
142
143
|
)
|
143
144
|
interface = Client.describe_interface(device.interface_id)
|
144
145
|
|
146
|
+
do_release = !!options[:release]
|
147
|
+
created_by_us = interface.tag_set.any? { |tag| tag.key == 'created by' && tag.value == owner_tag }
|
148
|
+
do_delete = options[:delete] != false && created_by_us
|
149
|
+
do_block = options[:block] != false
|
150
|
+
|
145
151
|
if device.name == 'eth0'
|
146
152
|
raise Errors::InvalidInterface, 'For safety, interface eth0 cannot be detached.'
|
147
153
|
end
|
148
|
-
|
149
154
|
unless interface[:attachment] && interface[:attachment][:instance_id] == environment[:instance_id]
|
150
|
-
raise Errors::
|
155
|
+
raise Errors::InvalidInterface, "Interface #{interface_id} is not attached to this machine"
|
151
156
|
end
|
152
157
|
|
153
|
-
device.disable
|
154
|
-
device.deconfigure
|
155
|
-
Client.detach_network_interface(
|
156
|
-
attachment_id: interface[:attachment][:attachment_id],
|
157
|
-
force: true
|
158
|
-
)
|
159
|
-
created_by_us = interface.tag_set.any? { |tag| tag.key == 'created by' && tag.value == owner_tag }
|
160
|
-
do_delete = options[:delete] != false && created_by_us
|
161
|
-
do_release = !!options[:release]
|
162
|
-
|
163
158
|
public_ips = []
|
164
159
|
interface[:private_ip_addresses].each do |addr|
|
165
160
|
if assoc = addr[:association]
|
@@ -171,7 +166,13 @@ module Aws
|
|
171
166
|
end
|
172
167
|
end
|
173
168
|
|
174
|
-
|
169
|
+
device.disable
|
170
|
+
device.deconfigure
|
171
|
+
Client.detach_network_interface(
|
172
|
+
attachment_id: interface[:attachment][:attachment_id],
|
173
|
+
force: true
|
174
|
+
)
|
175
|
+
if do_block || do_delete
|
175
176
|
wait_for 'the interface to detach', interval: 0.3 do
|
176
177
|
!device.exists? && !Client.interface_attached(interface[:network_interface_id])
|
177
178
|
end
|
@@ -193,7 +194,7 @@ module Aws
|
|
193
194
|
def clean_interfaces(filter = nil, options = {})
|
194
195
|
public_ips = []
|
195
196
|
do_release = !!options[:release]
|
196
|
-
safe_mode =
|
197
|
+
safe_mode = options[:safe_mode] != false
|
197
198
|
|
198
199
|
filters = [
|
199
200
|
{ name: 'vpc-id', values: [environment[:vpc_id]] },
|
@@ -255,8 +256,14 @@ module Aws
|
|
255
256
|
)
|
256
257
|
interface_id = device.interface_id
|
257
258
|
current_ips = Client.interface_private_ips(interface_id)
|
259
|
+
do_config = options[:configure] != false
|
260
|
+
do_block = options[:block] != false
|
258
261
|
new_ip = options[:private_ip]
|
259
262
|
|
263
|
+
if do_block && !device.enabled?
|
264
|
+
raise Errors::InvalidParameter, "Interface #{device.name} is not enabled (cannot block)"
|
265
|
+
end
|
266
|
+
|
260
267
|
if new_ip
|
261
268
|
if current_ips.include?(new_ip)
|
262
269
|
raise Errors::ClientOperationError, "IP #{new_ip} already assigned to #{device.name}"
|
@@ -283,9 +290,9 @@ module Aws
|
|
283
290
|
end
|
284
291
|
end
|
285
292
|
|
286
|
-
|
293
|
+
if do_config
|
287
294
|
device.add_alias(new_ip)
|
288
|
-
if
|
295
|
+
if do_block && !Interface.test(new_ip, target: device.gateway)
|
289
296
|
raise Errors::TimeoutError, 'Timed out waiting for IP address to become active'
|
290
297
|
end
|
291
298
|
end
|
@@ -339,9 +346,27 @@ module Aws
|
|
339
346
|
}
|
340
347
|
end
|
341
348
|
|
349
|
+
# validate a local area connection on a secondary ip address
|
350
|
+
def test_secondary_ip(private_ip, options = {})
|
351
|
+
timeout = options[:timeout] || self.timeout
|
352
|
+
|
353
|
+
find = options[:device_name] || options[:device_number] || options[:interface_id] || private_ip
|
354
|
+
device = Interface[find].assert(
|
355
|
+
exists: true,
|
356
|
+
enabled: true,
|
357
|
+
device_name: options[:device_name],
|
358
|
+
interface_id: options[:interface_id],
|
359
|
+
device_number: options[:device_number],
|
360
|
+
private_ip: private_ip
|
361
|
+
)
|
362
|
+
Interface.test(private_ip, target: device.gateway, timeout: timeout)
|
363
|
+
end
|
364
|
+
|
342
365
|
# associate a private ip with an elastic ip through the AWS api
|
343
366
|
def associate_elastic_ip(private_ip, options = {})
|
344
367
|
raise Errors::MissingInput, 'You must specify a private IP address' unless private_ip
|
368
|
+
do_alloc = !!options[:new]
|
369
|
+
do_block = options[:block] != false
|
345
370
|
|
346
371
|
find = options[:device_name] || options[:device_number] || options[:interface_id] || private_ip
|
347
372
|
device = Interface[find].assert(
|
@@ -353,6 +378,9 @@ module Aws
|
|
353
378
|
)
|
354
379
|
options[:public_ip] ||= options[:allocation_id]
|
355
380
|
|
381
|
+
if do_block && !device.enabled?
|
382
|
+
raise Errors::InvalidParameter, "Interface #{device.name} is not enabled (cannot block)"
|
383
|
+
end
|
356
384
|
if public_ip = device.public_ips[private_ip]
|
357
385
|
raise Errors::ClientOperationError, "IP #{private_ip} already has an associated EIP (#{public_ip})"
|
358
386
|
end
|
@@ -362,7 +390,8 @@ module Aws
|
|
362
390
|
if options[:allocation_id] && eip[:allocation_id] != options[:allocation_id]
|
363
391
|
raise Errors::InvalidAddress, "EIP #{eip[:public_ip]} (#{eip[:allocation_id]}) does not match #{options[:allocation_id]}"
|
364
392
|
end
|
365
|
-
|
393
|
+
elsif do_alloc || !eip = Client.available_addresses.first
|
394
|
+
allocated = true
|
366
395
|
eip = allocate_elastic_ip
|
367
396
|
end
|
368
397
|
|
@@ -373,13 +402,14 @@ module Aws
|
|
373
402
|
allow_reassociation: false
|
374
403
|
)
|
375
404
|
|
376
|
-
if
|
405
|
+
if do_block && !Interface.test(private_ip)
|
377
406
|
raise Errors::TimeoutError, 'Timed out waiting for ip address to become active'
|
378
407
|
end
|
379
408
|
{
|
380
409
|
private_ip: private_ip,
|
381
410
|
device_name: device.name,
|
382
411
|
interface_id: device.interface_id,
|
412
|
+
allocated: !!allocated,
|
383
413
|
public_ip: eip[:public_ip],
|
384
414
|
allocation_id: eip[:allocation_id],
|
385
415
|
association_id: resp[:association_id]
|
@@ -444,9 +474,64 @@ module Aws
|
|
444
474
|
}
|
445
475
|
end
|
446
476
|
|
477
|
+
# validate an internet connection on a secondary ip address with an
|
478
|
+
# associated elastic ip
|
479
|
+
def test_association(address, options = {})
|
480
|
+
timeout = options[:timeout] || self.timeout
|
481
|
+
|
482
|
+
# assert device attributes if we've specified a device
|
483
|
+
if find = options[:device_name] || options[:device_number]
|
484
|
+
device = Interface[find].assert(
|
485
|
+
device_name: options[:device_name],
|
486
|
+
device_number: options[:device_number],
|
487
|
+
interface_id: options[:interface_id],
|
488
|
+
private_ip: options[:private_ip],
|
489
|
+
public_ip: options[:public_ip]
|
490
|
+
)
|
491
|
+
end
|
492
|
+
|
493
|
+
# get our address info
|
494
|
+
eip = Client.describe_address(address)
|
495
|
+
device ||= Interface.find { |dev| dev.interface_id == eip[:network_interface_id] }
|
496
|
+
|
497
|
+
# assert eip attributes if options provided
|
498
|
+
if options[:private_ip] && eip[:private_ip_address] != options[:private_ip]
|
499
|
+
raise Errors::InvalidAddress, "#{address} is not associated with IP #{options[:private_ip]}"
|
500
|
+
end
|
501
|
+
if options[:public_ip] && eip[:public_ip] != options[:public_ip]
|
502
|
+
raise Errors::InvalidAddress, "#{address} is not associated with public IP #{options[:public_ip]}"
|
503
|
+
end
|
504
|
+
if options[:allocation_id] && eip[:allocation_id] != options[:allocation_id]
|
505
|
+
raise Errors::InvalidAddress, "#{address} is not associated with allocation ID #{options[:allocation_id]}"
|
506
|
+
end
|
507
|
+
if options[:association_id] && eip[:association_id] != options[:association_id]
|
508
|
+
raise Errors::InvalidAddress, "#{address} is not associated with association ID #{options[:association_id]}"
|
509
|
+
end
|
510
|
+
if options[:interface_id] && eip[:network_interface_id] != options[:interface_id]
|
511
|
+
raise Errors::InvalidAddress, "#{address} is not associated with interface ID #{options[:interface_id]}"
|
512
|
+
end
|
513
|
+
|
514
|
+
# assert that this eip attached to an enabled, configured interface on this machine
|
515
|
+
unless device
|
516
|
+
raise Errors::InvalidAddress, "#{address} is not associated with an interface on this machine"
|
517
|
+
end
|
518
|
+
unless device.enabled?
|
519
|
+
raise Errors::InvalidAddress, "#{address} cannot be tested while #{device.name} is disabled"
|
520
|
+
end
|
521
|
+
unless device.local_ips.include?(eip[:private_ip_address])
|
522
|
+
raise Errors::InvalidAddress, "#{address} cannot be tested until #{device.name} is configured"
|
523
|
+
end
|
524
|
+
|
525
|
+
Interface.test(eip[:private_ip_address], timeout: timeout)
|
526
|
+
end
|
527
|
+
|
447
528
|
# allocate a new elastic ip address
|
448
529
|
def allocate_elastic_ip
|
449
530
|
eip = Client.allocate_address(domain: 'vpc')
|
531
|
+
wait_for 'new elastic ip to become available', rescue: Errors::UnknownAddress do
|
532
|
+
# strangely this doesn't happen immediately in some cases
|
533
|
+
Client.describe_address(eip[:allocation_id])
|
534
|
+
end
|
450
535
|
{
|
451
536
|
public_ip: eip[:public_ip],
|
452
537
|
allocation_id: eip[:allocation_id]
|
data/lib/aws-eni/client.rb
CHANGED
@@ -41,7 +41,7 @@ module Aws
|
|
41
41
|
|
42
42
|
# retrieve a single interface resource
|
43
43
|
def describe_interface(id)
|
44
|
-
resp = describe_network_interfaces(
|
44
|
+
resp = describe_network_interfaces(filters: [{ name: 'network-interface-id', values: [id] }])
|
45
45
|
raise Errors::UnknownInterface, "Interface #{id} could not be located" if resp[:network_interfaces].empty?
|
46
46
|
resp[:network_interfaces].first
|
47
47
|
end
|
@@ -65,10 +65,16 @@ module Aws
|
|
65
65
|
{ name: 'domain', values: ['vpc'] },
|
66
66
|
{ name: filter_by, values: [address] }
|
67
67
|
])
|
68
|
-
raise Errors::UnknownAddress, "
|
68
|
+
raise Errors::UnknownAddress, "No EIP with #{address} could be located" if resp[:addresses].empty?
|
69
69
|
resp[:addresses].first
|
70
70
|
end
|
71
71
|
|
72
|
+
# retrieve a list of available addresses
|
73
|
+
def available_addresses
|
74
|
+
filters = [{ name: 'domain', values: ['vpc'] }]
|
75
|
+
describe_addresses(filters: filters)[:addresses].select{ |addr| !addr.association_id }
|
76
|
+
end
|
77
|
+
|
72
78
|
# retrieve an array of private ips associated with the given interface
|
73
79
|
def interface_private_ips(id)
|
74
80
|
interface = describe_interface(id)
|
@@ -135,8 +141,7 @@ module Aws
|
|
135
141
|
client.public_send(method, params.merge(dry_run: true))
|
136
142
|
rescue EC2::Errors::DryRunOperation
|
137
143
|
true
|
138
|
-
rescue EC2::Errors::InvalidAllocationIDNotFound
|
139
|
-
# release_address does not properly support dry_run
|
144
|
+
rescue EC2::Errors::InvalidAllocationIDNotFound, EC2::Errors::InvalidAssociationIDNotFound
|
140
145
|
true
|
141
146
|
rescue EC2::Errors::UnauthorizedOperation
|
142
147
|
false
|
data/lib/aws-eni/interface.rb
CHANGED
@@ -169,7 +169,7 @@ module Aws
|
|
169
169
|
hwaddr = self.hwaddr
|
170
170
|
unless @meta_cache && @meta_cache[:hwaddr] == hwaddr
|
171
171
|
@meta_cache = Meta.connection do
|
172
|
-
raise MetaBadResponse unless Meta.interface(hwaddr, '')
|
172
|
+
raise Errors::MetaBadResponse unless Meta.interface(hwaddr, '', not_found: nil)
|
173
173
|
{
|
174
174
|
hwaddr: hwaddr,
|
175
175
|
interface_id: Meta.interface(hwaddr, 'interface-id'),
|
@@ -179,6 +179,8 @@ module Aws
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
@meta_cache
|
182
|
+
rescue Errors::MetaConnectionFailed
|
183
|
+
raise Errors::InvalidInterface, "Interface #{name} could not be found in the EC2 instance meta-data"
|
182
184
|
end
|
183
185
|
|
184
186
|
def interface_id
|
data/lib/aws-eni/meta.rb
CHANGED
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.
|
4
|
+
version: 0.3.0
|
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-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gli
|