aws-eni 0.2.2 → 0.3.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-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
|