aws-eni 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +63 -0
- data/Rakefile +2 -0
- data/aws-eni.gemspec +26 -0
- data/bin/aws-eni +442 -0
- data/lib/aws-eni.rb +278 -0
- data/lib/aws-eni/errors.rb +13 -0
- data/lib/aws-eni/ifconfig.rb +309 -0
- data/lib/aws-eni/meta.rb +76 -0
- data/lib/aws-eni/version.rb +5 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b7f9bdc9bb5d6c7427d50f1354b77317a5a4f1bc
|
4
|
+
data.tar.gz: fe7568417322ab7bfa41be38041efaf1e0aeeae7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f86aba30d2b1b0e564810648c701f144c098388d8e349ae1143817b4ee58a07c3d86008be3b79b8e9cca66bc5a92ca801b68907711914a32eeece675894f30f4
|
7
|
+
data.tar.gz: bd60223a0bc09962fb82db2cd7c413da1a08f37ff603a85b716723eaa3fecbf983de317155e8c451badf50063fa59df417d3f7c3e7b6df181651026e2be6696f
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Mike Greiling
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# aws-eni
|
2
|
+
|
3
|
+
A command line tool and client library to manage AWS Elastic Network Interfaces from within an EC2 instance.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'aws-eni'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install aws-eni
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Synchronize your EC2 instance network interface config with AWS.
|
24
|
+
|
25
|
+
$ aws-eni sync
|
26
|
+
|
27
|
+
List all interface cards, their IPs, and their associations
|
28
|
+
|
29
|
+
$ aws-eni list
|
30
|
+
eth0:
|
31
|
+
10.0.1.23
|
32
|
+
eth1:
|
33
|
+
10.0.2.54 => 54.25.169.87 (EIP)
|
34
|
+
10.0.2.72 => 52.82.17.251 (EIP)
|
35
|
+
|
36
|
+
Add a new private IP
|
37
|
+
|
38
|
+
$ aws-eni add eth1
|
39
|
+
added 10.0.2.81
|
40
|
+
|
41
|
+
Associate a new elastic IP
|
42
|
+
|
43
|
+
$ aws-eni associate 10.0.2.81
|
44
|
+
associated 10.0.2.81 => 52.171.254.36
|
45
|
+
|
46
|
+
Dissociate an elastic IP
|
47
|
+
|
48
|
+
$ aws-eni dissociate 10.0.2.81
|
49
|
+
dissociated 52.171.254.36 from 10.0.2.81
|
50
|
+
|
51
|
+
Remove a private IP
|
52
|
+
|
53
|
+
$ aws-eni remove 10.0.2.81
|
54
|
+
removed 10.0.2.81 from eth1
|
55
|
+
|
56
|
+
|
57
|
+
## Contributing
|
58
|
+
|
59
|
+
1. Fork it ( https://github.com/[my-github-username]/aws-eni/fork )
|
60
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
61
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
62
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
63
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/aws-eni.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'aws-eni/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "aws-eni"
|
8
|
+
spec.version = Aws::ENI::VERSION
|
9
|
+
spec.authors = ["Mike Greiling"]
|
10
|
+
spec.email = ["mike@pixelcog.com"]
|
11
|
+
spec.summary = "Manage and sync local network config with AWS Elastic Network Interfaces"
|
12
|
+
spec.description = "A command line tool and client library to manage AWS Elastic Network Interfaces from within an EC2 instance"
|
13
|
+
spec.homepage = "http://pixelcog.com/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "gli", "~> 2.5"
|
22
|
+
spec.add_dependency "aws-sdk", "~> 2.0"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
end
|
data/bin/aws-eni
ADDED
@@ -0,0 +1,442 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gli'
|
3
|
+
require 'resolv'
|
4
|
+
require 'ipaddr'
|
5
|
+
require 'aws-eni'
|
6
|
+
|
7
|
+
include GLI::App
|
8
|
+
|
9
|
+
program_desc 'Manage and sync local network config with AWS Elastic Network Interfaces'
|
10
|
+
|
11
|
+
version Aws::ENI::VERSION
|
12
|
+
|
13
|
+
autocomplete_commands true
|
14
|
+
subcommand_option_handling :normal
|
15
|
+
arguments :loose
|
16
|
+
sort_help :manually
|
17
|
+
|
18
|
+
# global options
|
19
|
+
|
20
|
+
desc 'Display all system commands and warnings'
|
21
|
+
switch [:v,:verbose], negatable: false
|
22
|
+
|
23
|
+
pre do |opt|
|
24
|
+
Aws::ENI::IFconfig.verbose = opt[:verbose]
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
# arg parser methods
|
29
|
+
|
30
|
+
def local_ip?(ip)
|
31
|
+
IPAddr.new(Aws::ENI.environment[:vpc_cidr]) === IPAddr.new(ip)
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_args(args, *accept)
|
35
|
+
params = {}
|
36
|
+
args.each do |arg|
|
37
|
+
if arg =~ /^eth[0-9]+/ && accept.include?(:device_name)
|
38
|
+
help_now! "You may only specify one device name." if params[:device_name]
|
39
|
+
params[:device_name] = arg
|
40
|
+
elsif arg =~ /^eni-/ && accept.include?(:interface_id)
|
41
|
+
help_now! "You may only specify one interface ID." if params[:interface_id]
|
42
|
+
params[:interface_id] = arg
|
43
|
+
elsif arg =~ /^subnet-/ && accept.include?(:subnet_id)
|
44
|
+
help_now! "You may only specify one subnet." if params[:subnet_id]
|
45
|
+
params[:subnet_id] = arg
|
46
|
+
elsif arg =~ /^sg-/ && accept.include?(:security_groups)
|
47
|
+
params[:security_groups] ||= []
|
48
|
+
params[:security_groups] << arg
|
49
|
+
elsif arg =~ /^eipalloc-/ && accept.include?(:allocation_id)
|
50
|
+
help_now! "You may only specify one allocation ID" if params[:allocation_id]
|
51
|
+
params[:allocation_id] = arg
|
52
|
+
elsif arg =~ /^eipassoc-/ && accept.include?(:association_id)
|
53
|
+
help_now! "You may only specify one association ID" if params[:association_id]
|
54
|
+
params[:association_id] = arg
|
55
|
+
elsif arg =~ Resolv::IPv4::Regex
|
56
|
+
if local_ip? arg
|
57
|
+
if accept.include?(:primary_ip)
|
58
|
+
help_now! "You may only specify one primary IP address." if params[:primary_ip]
|
59
|
+
params[:primary_ip] = arg
|
60
|
+
elsif accept.include?(:private_ip)
|
61
|
+
help_now! "You may only specify one private IP address." if params[:private_ip]
|
62
|
+
params[:private_ip] = arg
|
63
|
+
else
|
64
|
+
help_now! "Invalid IP address: #{arg}"
|
65
|
+
end
|
66
|
+
elsif accept.include?(:public_ip)
|
67
|
+
help_now! "You may only specify one public IP address." if params[:public_ip]
|
68
|
+
params[:public_ip] = arg
|
69
|
+
else
|
70
|
+
help_now! "Invalid IP address: #{arg}"
|
71
|
+
end
|
72
|
+
else
|
73
|
+
help_now! "Invalid argument: #{arg}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
params
|
77
|
+
end
|
78
|
+
|
79
|
+
# commands
|
80
|
+
|
81
|
+
desc 'List current interface configuration'
|
82
|
+
long_desc %{
|
83
|
+
List information about a set of interfaces including interface ID, interface
|
84
|
+
name, MAC address, and a list of primary and secondary IP addresses along with
|
85
|
+
any public ips associated with them.
|
86
|
+
|
87
|
+
Use the optional filter argument to limit the listing to interfaces with a
|
88
|
+
matching name, interface ID, subnet ID, or MAC address (default 'all').
|
89
|
+
}
|
90
|
+
arg 'filter', :optional
|
91
|
+
command [:list,:ls] do |c|
|
92
|
+
c.action do |global,opts,args|
|
93
|
+
help_now! "Too many arguments" if args.count > 1
|
94
|
+
args.delete('all')
|
95
|
+
Aws::ENI.list(args.first).each do |interface|
|
96
|
+
print "#{interface[:name]}:"
|
97
|
+
print "\tID #{interface[:interface_id]}"
|
98
|
+
print " HWaddr #{interface[:hwaddr]}"
|
99
|
+
print " Status " << (interface[:enabled] ? "UP" : "DOWN") << "\n"
|
100
|
+
interface[:local_ips].each do |local_ip|
|
101
|
+
if interface[:public_ips][local_ip]
|
102
|
+
puts "\t#{local_ip} => #{interface[:public_ips][local_ip]}"
|
103
|
+
else
|
104
|
+
puts "\t#{local_ip}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
puts "\ninterface config is out of sync" if Aws::ENI.configure(nil, dry_run: true) > 0
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
desc 'Configure network interfaces'
|
113
|
+
long_desc %{
|
114
|
+
Syncronize configuration for a set of interfaces to match their configuration
|
115
|
+
on AWS by managing secondary ips, routes, and rules.
|
116
|
+
|
117
|
+
Use the optional filter argument to limit this action to interfaces with a
|
118
|
+
matching name, interface ID, subnet ID, or MAC address (default 'all').
|
119
|
+
}
|
120
|
+
arg 'filter', :optional
|
121
|
+
command [:config] do |c|
|
122
|
+
c.action do |global,opts,args|
|
123
|
+
help_now! "Too many arguments" if args.count > 1
|
124
|
+
args.delete('all')
|
125
|
+
if Aws::ENI.configure(args.first) != 0
|
126
|
+
puts 'synchronized interface config'
|
127
|
+
else
|
128
|
+
puts 'network interface config already in sync'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
desc 'Remove custom configuration from network interfaces'
|
134
|
+
long_desc %{
|
135
|
+
Remove custom configuration for a set of interfaces removing any custom ips,
|
136
|
+
routes, and rules previously added (the 'eth0' primary IP is always left
|
137
|
+
untouched for safety).
|
138
|
+
|
139
|
+
Use the optional filter argument to limit this action to interfaces with a
|
140
|
+
matching name, interface ID, subnet ID, or MAC address (default 'all').
|
141
|
+
}
|
142
|
+
arg 'filter', :optional
|
143
|
+
command [:deconfig] do |c|
|
144
|
+
c.action do |global,opts,args|
|
145
|
+
help_now! "Too many arguments" if args.count > 1
|
146
|
+
args.delete('all')
|
147
|
+
Aws::ENI.deconfigure(args.first)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
desc 'Enable network interface'
|
152
|
+
long_desc %{
|
153
|
+
Enable one or more network interfaces (similar to 'ifup').
|
154
|
+
|
155
|
+
Specify one name, interface ID, subnet ID, or MAC address to enable any
|
156
|
+
matching interfaces, or specify 'all' to enable all interfaces.
|
157
|
+
}
|
158
|
+
arg 'filter'
|
159
|
+
command [:enable,:up] do |c|
|
160
|
+
c.action do |global,opts,args|
|
161
|
+
help_now! "Incorrect number of arguments" unless args.count.between?(0,1)
|
162
|
+
args.delete('all')
|
163
|
+
Aws::ENI::IFconfig.filter(args.first).each(&:enable)
|
164
|
+
puts "interfaces enabled"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
desc 'Disable network interface'
|
169
|
+
long_desc %{
|
170
|
+
Disable one or more network interfaces (similar to 'ifdown').
|
171
|
+
|
172
|
+
Specify one name, interface ID, subnet ID, or MAC address to disable any
|
173
|
+
matching interfaces, or specify 'all' to disable all interfaces.
|
174
|
+
|
175
|
+
eth0 cannot be disabled.
|
176
|
+
}
|
177
|
+
arg 'filter'
|
178
|
+
command [:disable,:down] do |c|
|
179
|
+
c.action do |global,opts,args|
|
180
|
+
help_now! "Incorrect number of arguments" unless args.count.between?(0,1)
|
181
|
+
args.delete('all')
|
182
|
+
Aws::ENI::IFconfig.filter(args.first).each do |dev|
|
183
|
+
if dev.name == 'eth0'
|
184
|
+
warn 'skipping eth0'
|
185
|
+
else
|
186
|
+
dev.disable
|
187
|
+
puts "interface #{dev.name} disabled"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
desc 'Create new network interface'
|
194
|
+
long_desc %{
|
195
|
+
Create a new Elastic Network Interface with a given set of parameters.
|
196
|
+
|
197
|
+
Optional arguments include subnet ID, security group IDs, and a primary ip
|
198
|
+
address.
|
199
|
+
|
200
|
+
If no subnet ID is provided (e.g. subnet-1a2b3c4d) the subnet for eth0 will
|
201
|
+
be used. If no security group is provided (e.g. sg-1a2b3c4d) the VPC default
|
202
|
+
security group will be used. If a private IP is provided, it must fall within
|
203
|
+
the subnet's CIDR block. Arguments can be provided in any order.
|
204
|
+
}
|
205
|
+
arg 'subnet', :optional
|
206
|
+
arg 'security-groups', :optional
|
207
|
+
arg 'ip-address', :optional
|
208
|
+
command [:create] do |c|
|
209
|
+
c.action do |global,opts,args|
|
210
|
+
params = parse_args args, :subnet_id, :security_groups, :primary_ip
|
211
|
+
interface = Aws::ENI.create_interface(params)
|
212
|
+
puts "interface #{interface[:id]} created on #{interface[:subnet_id]}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
desc 'Attach network interface'
|
217
|
+
long_desc %{
|
218
|
+
Attach an Elastic Network Interface to our instance.
|
219
|
+
|
220
|
+
If interface ID provided (e.g. eni-1a2b3c4d), that interface will be attached,
|
221
|
+
otherwise a new interface will be created with the provided parameters which
|
222
|
+
may include a subnet ID, security group IDs, and a primary IP address.
|
223
|
+
|
224
|
+
If no subnet ID is provided (e.g. subnet-1a2b3c4d) the subnet for eth0 will
|
225
|
+
be used. If no security group is provided (e.g. sg-1a2b3c4d) the VPC default
|
226
|
+
security group will be used. If a private IP is provided, it must fall within
|
227
|
+
the subnet's CIDR block. Arguments can be provided in any order.
|
228
|
+
}
|
229
|
+
arg 'interface-id', :optional
|
230
|
+
arg 'subnet-id', :optional
|
231
|
+
arg 'security-groups', :optional
|
232
|
+
arg 'ip-address', :optional
|
233
|
+
command [:attach] do |c|
|
234
|
+
c.desc 'Refresh the interface configuration after attachment'
|
235
|
+
c.switch [:r,:c,:config], negatable: false
|
236
|
+
|
237
|
+
c.action do |global,opts,args|
|
238
|
+
if args.first =~ /^eni-/
|
239
|
+
help_now! 'Too many arguments' if args.count > 1
|
240
|
+
id = args.first
|
241
|
+
else
|
242
|
+
params = parse_args args, :subnet_id, :security_groups, :primary_ip
|
243
|
+
interface = Aws::ENI.create_interface(params)
|
244
|
+
puts "interface #{interface[:id]} created on #{interface[:subnet_id]}"
|
245
|
+
id = interface[:id]
|
246
|
+
end
|
247
|
+
device = Aws::ENI.attach_interface(id, enable: opts[:config], configure: opts[:config])
|
248
|
+
puts "interface #{device[:id]} attached to #{device[:name]}"
|
249
|
+
puts "device #{device[:name]} enabled and configured" if opts[:config]
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
desc 'Detach network interface'
|
254
|
+
long_desc %{
|
255
|
+
Detach an Elastic Network Interface from our instance.
|
256
|
+
|
257
|
+
You must provide the interface ID (e.g. eni-1a2b3c4d) or the device name
|
258
|
+
(e.g. eth1) or both.
|
259
|
+
|
260
|
+
If no flag is present, the default action is to destroy the network interface
|
261
|
+
after detachment only if it was originally created by aws-eni.
|
262
|
+
}
|
263
|
+
arg 'interface-id OR device-name'
|
264
|
+
command [:detach] do |c|
|
265
|
+
c.desc 'Delete (or preserve) the unused ENI resource after dataching'
|
266
|
+
c.switch [:d,:delete], default_value: :not_provided # GLI behavior workaround
|
267
|
+
|
268
|
+
c.action do |global,opts,args|
|
269
|
+
help_now! "Missing argument" if args.empty?
|
270
|
+
params = parse_args args, :interface_id, :device_name
|
271
|
+
params[:delete] = opts[:delete] unless opts[:delete] == :not_provided
|
272
|
+
id = params[:interface_id] || params[:device_name]
|
273
|
+
|
274
|
+
device = Aws::ENI.detach_interface(id, params)
|
275
|
+
if device[:deleted]
|
276
|
+
puts "interface #{device[:id]} detached from #{device[:name]} and destroyed"
|
277
|
+
else
|
278
|
+
puts "interface #{device[:id]} detached from #{device[:name]}"
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
desc 'Clean unattached network interfaces'
|
284
|
+
long_desc %{
|
285
|
+
Delete unused Elastic Network Interfaces based on provided criteria.
|
286
|
+
|
287
|
+
You may provide a specific interface ID (e.g. eni-1a2b3c4d), a subnet ID
|
288
|
+
(e.g. subnet-1a2b3c4d), or an availability zone from this region (e.g.
|
289
|
+
us-east-1a) to act as search criteria.
|
290
|
+
|
291
|
+
By default, this will only delete ENIs which were originally created with this
|
292
|
+
script.
|
293
|
+
}
|
294
|
+
arg 'filter', :optional
|
295
|
+
command [:clean] do |c|
|
296
|
+
c.desc 'Force deletion of all unattached interfaces which meet our criteria'
|
297
|
+
c.switch [:f,:force], negatable: false
|
298
|
+
|
299
|
+
c.action do |global,opts,args|
|
300
|
+
help_now! "Too many arguments" if args.count > 1
|
301
|
+
deleted = Aws::ENI.clean_interfaces(args.first, safe_mode: !opts[:force])
|
302
|
+
puts "#{deleted[:count]} interfaces deleted"
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
desc 'Assign a new secondary private IP address'
|
307
|
+
long_desc %{
|
308
|
+
Assign an additional private IP address to a given interface.
|
309
|
+
|
310
|
+
You may optionally specify a private IP in the interface's subnet CIDR range
|
311
|
+
to assign, otherwise one will be generated automatically.
|
312
|
+
}
|
313
|
+
arg 'ip-address', :optional
|
314
|
+
arg 'interface-id OR device-name'
|
315
|
+
command [:assign] do |c|
|
316
|
+
c.action do |global,opts,args|
|
317
|
+
help_now! "Missing argument" if args.empty?
|
318
|
+
params = parse_args args, :interface_id, :device_name, :private_ip
|
319
|
+
device = params[:interface_id] || params[:device_name]
|
320
|
+
assignment = Aws::ENI.assign_secondary_ip(device, params)
|
321
|
+
puts "IP #{assignment[:private_ip]} assigned to #{assignment[:device_name]} (#{assignment[:interface_id]})"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
desc 'Unassign a secondary private IP address'
|
326
|
+
long_desc %{
|
327
|
+
Remove a private IP address from a given interface. Any associated public ip
|
328
|
+
address will be dissociated first and optionally released.
|
329
|
+
|
330
|
+
If no interface is specified, it will be inferred by the IP address.
|
331
|
+
}
|
332
|
+
arg 'ip-address'
|
333
|
+
arg 'interface-id', :optional
|
334
|
+
arg 'device-name', :optional
|
335
|
+
command [:unassign] do |c|
|
336
|
+
c.desc 'Release any associated public IP address'
|
337
|
+
c.switch [:r,:release], negatable: false
|
338
|
+
|
339
|
+
c.action do |global,opts,args|
|
340
|
+
help_now! "Missing argument" if args.empty?
|
341
|
+
params = parse_args args, :interface_id, :device_name, :private_ip
|
342
|
+
params[:release] = opts[:release]
|
343
|
+
unassign = Aws::ENI.unassign_secondary_ip(params[:private_ip], params)
|
344
|
+
if unassign[:released]
|
345
|
+
puts "EIP #{unassign[:public_ip]} (#{unassign[:allocation_id]}) dissociated from #{unassign[:private_ip]} and released"
|
346
|
+
elsif unassign[:public_ip]
|
347
|
+
puts "EIP #{unassign[:public_ip]} (#{unassign[:allocation_id]}) dissociated from #{unassign[:private_ip]}"
|
348
|
+
end
|
349
|
+
puts "IP #{unassign[:private_ip]} removed from #{unassign[:device_name]} (#{unassign[:interface_id]})"
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
desc 'Associate a public IP address with a private IP address'
|
354
|
+
long_desc %{
|
355
|
+
Associate a private IP address with a new or existing public IP address.
|
356
|
+
|
357
|
+
If no public IP or allocation ID is provided, a new Elastic IP Address will be
|
358
|
+
allocated and used.
|
359
|
+
|
360
|
+
If no interface ID or device name provided, it will be inferred from the ip
|
361
|
+
address.
|
362
|
+
}
|
363
|
+
arg 'private-ip'
|
364
|
+
arg 'public-ip', :optional
|
365
|
+
arg 'allocation-id', :optional
|
366
|
+
arg 'interface-id', :optional
|
367
|
+
arg 'device-name', :optional
|
368
|
+
command [:associate] do |c|
|
369
|
+
c.action do |global,opts,args|
|
370
|
+
help_now! "Missing argument" if args.empty?
|
371
|
+
params = parse_args args, :private_ip, :public_ip, :allocation_id, :interface_id, :device_name
|
372
|
+
assoc = Aws::ENI.associate_elastic_ip(params[:private_ip], params)
|
373
|
+
puts "EIP #{assoc[:public_ip]} (#{assoc[:allocation_id]}) associated with #{assoc[:private_ip]} on #{assoc[:device_name]} (#{assoc[:interface_id]})"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
desc 'Dissociate a public IP address from a private IP address'
|
378
|
+
long_desc %{
|
379
|
+
Remove an association between a given public IP address or private IP address
|
380
|
+
and their counterpart. The public IP address is then optionally released.
|
381
|
+
}
|
382
|
+
arg 'private-ip OR public-ip OR allocation-id'
|
383
|
+
arg 'interface-id', :optional
|
384
|
+
arg 'device-name', :optional
|
385
|
+
command [:dissociate] do |c|
|
386
|
+
c.desc 'Release the associated public IP address'
|
387
|
+
c.switch [:r,:release], negatable: false
|
388
|
+
|
389
|
+
c.action do |global,opts,args|
|
390
|
+
help_now! "Missing argument" if args.empty?
|
391
|
+
params = parse_args args, :private_ip, :public_ip, :allocation_id, :association_id, :interface_id, :device_name
|
392
|
+
ip = params[:private_ip] || params[:public_ip] || params[:association_id] || params[:allocation_id]
|
393
|
+
dissoc = Aws::ENI.dissociate_elastic_ip(ip, params)
|
394
|
+
if dissoc[:released]
|
395
|
+
puts "EIP #{dissoc[:public_ip]} (#{dissoc[:allocation_id]}) dissociated from #{dissoc[:private_ip]} on #{dissoc[:device_name]} (#{dissoc[:interface_id]}) and released"
|
396
|
+
else
|
397
|
+
puts "EIP #{dissoc[:public_ip]} (#{dissoc[:allocation_id]}) dissociated from #{dissoc[:private_ip]} on #{dissoc[:device_name]} (#{dissoc[:interface_id]})"
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
desc 'Allocate a new Elastic IP address'
|
403
|
+
long_desc %{
|
404
|
+
Allocate a new Elastic IP address for use
|
405
|
+
}
|
406
|
+
command [:allocate] do |c|
|
407
|
+
c.action do |global,opts,args|
|
408
|
+
alloc = Aws::ENI.allocate_elastic_ip
|
409
|
+
puts "EIP #{alloc[:public_ip]} allocated as #{alloc[:allocation_id]}"
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
desc 'Release one or more unassigned Elastic IP addresses'
|
414
|
+
long_desc %{
|
415
|
+
Release one or more unassigned Elastic IP addresses. If IP address or
|
416
|
+
allication, will release only that EIP, otherwise will clean all unassigned
|
417
|
+
EIPs.
|
418
|
+
}
|
419
|
+
arg 'ip-address OR allocation-id'
|
420
|
+
command [:release] do |c|
|
421
|
+
c.action do |global,opts,args|
|
422
|
+
help_now! "Missing argument" if args.empty?
|
423
|
+
params = parse_args args, :public_ip, :allocation_id
|
424
|
+
eip = params[:public_ip] || params[:allocation_id]
|
425
|
+
release = Aws::ENI.release_elastic_ip(eip, params)
|
426
|
+
puts "EIP #{release[:public_ip]} (#{release[:allocation_id]}) released"
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
# error handling
|
431
|
+
|
432
|
+
on_error do |exception|
|
433
|
+
if Aws::ENI::PermissionError === exception
|
434
|
+
warn 'error: This action requires super-user privileges (try sudo)'
|
435
|
+
false
|
436
|
+
else
|
437
|
+
true
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
ARGV << 'ls' if ARGV.empty?
|
442
|
+
exit run(ARGV)
|