knife-ec2 0.6.2 → 0.6.4
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.
- data/Rakefile +1 -1
- data/lib/chef/knife/ec2_server_create.rb +63 -7
- data/lib/knife-ec2/version.rb +1 -1
- data/spec/unit/ec2_server_create_spec.rb +51 -3
- metadata +2 -2
data/Rakefile
CHANGED
@@ -62,6 +62,10 @@ class Chef
|
|
62
62
|
:description => "The security group ids for this server; required when using VPC",
|
63
63
|
:proc => Proc.new { |security_group_ids| security_group_ids.split(',') }
|
64
64
|
|
65
|
+
option :associate_eip,
|
66
|
+
:long => "--associate-eip IP_ADDRESS",
|
67
|
+
:description => "Associate existing elastic IP address with instance after launch"
|
68
|
+
|
65
69
|
option :tags,
|
66
70
|
:short => "-T T=V[,T=V,...]",
|
67
71
|
:long => "--tags Tag=Value[,Tag=Value...]",
|
@@ -110,7 +114,6 @@ class Chef
|
|
110
114
|
:description => "The ssh gateway server",
|
111
115
|
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
|
112
116
|
|
113
|
-
|
114
117
|
option :identity_file,
|
115
118
|
:short => "-i IDENTITY_FILE",
|
116
119
|
:long => "--identity-file IDENTITY_FILE",
|
@@ -167,6 +170,11 @@ class Chef
|
|
167
170
|
:description => "create node in this Virtual Private Cloud Subnet ID (implies VPC mode)",
|
168
171
|
:proc => Proc.new { |key| Chef::Config[:knife][:subnet_id] = key }
|
169
172
|
|
173
|
+
option :private_ip_address,
|
174
|
+
:long => "--private-ip-address IP-ADDRESS",
|
175
|
+
:description => "allows to specify the private IP address of the instance in VPC mode",
|
176
|
+
:proc => Proc.new { |ip| Chef::Config[:knife][:private_ip_address] = ip }
|
177
|
+
|
170
178
|
option :host_key_verify,
|
171
179
|
:long => "--[no-]host-key-verify",
|
172
180
|
:description => "Verify host key, enabled by default.",
|
@@ -225,6 +233,11 @@ class Chef
|
|
225
233
|
|
226
234
|
validate!
|
227
235
|
|
236
|
+
requested_elastic_ip = config[:associate_eip] if config[:associate_eip]
|
237
|
+
|
238
|
+
# For VPC EIP assignment we need the allocation ID so fetch full EIP details
|
239
|
+
elastic_ip = connection.addresses.detect{|addr| addr if addr.public_ip == requested_elastic_ip}
|
240
|
+
|
228
241
|
@server = connection.servers.create(create_server_def)
|
229
242
|
|
230
243
|
hashed_tags={}
|
@@ -235,10 +248,6 @@ class Chef
|
|
235
248
|
hashed_tags["Name"] = locate_config_value(:chef_node_name) || @server.id
|
236
249
|
end
|
237
250
|
|
238
|
-
hashed_tags.each_pair do |key,val|
|
239
|
-
connection.tags.create :key => key, :value => val, :resource_id => @server.id
|
240
|
-
end
|
241
|
-
|
242
251
|
msg_pair("Instance ID", @server.id)
|
243
252
|
msg_pair("Flavor", @server.flavor_id)
|
244
253
|
msg_pair("Image", @server.image_id)
|
@@ -260,15 +269,30 @@ class Chef
|
|
260
269
|
msg_pair("Tags", hashed_tags)
|
261
270
|
msg_pair("SSH Key", @server.key_name)
|
262
271
|
|
263
|
-
print "\n#{ui.color("Waiting for
|
272
|
+
print "\n#{ui.color("Waiting for instance", :magenta)}"
|
264
273
|
|
265
|
-
# wait for
|
274
|
+
# wait for instance to come up before acting against it
|
266
275
|
@server.wait_for { print "."; ready? }
|
267
276
|
|
268
277
|
puts("\n")
|
269
278
|
|
279
|
+
# occasionally 'ready?' isn't, so retry a couple times if needed.
|
280
|
+
tries = 6
|
281
|
+
begin
|
282
|
+
create_tags(hashed_tags) unless hashed_tags.empty?
|
283
|
+
associate_eip(elastic_ip) if config[:associate_eip]
|
284
|
+
rescue Fog::Compute::AWS::NotFound => e
|
285
|
+
raise if (tries -= 1) <= 0
|
286
|
+
ui.warn("server not ready, retrying tag application (retries left: #{tries})")
|
287
|
+
sleep 5
|
288
|
+
retry
|
289
|
+
end
|
290
|
+
|
270
291
|
if vpc_mode?
|
271
292
|
msg_pair("Subnet ID", @server.subnet_id)
|
293
|
+
if elastic_ip
|
294
|
+
msg_pair("Public IP Address", @server.public_ip_address)
|
295
|
+
end
|
272
296
|
else
|
273
297
|
msg_pair("Public DNS Name", @server.dns_name)
|
274
298
|
msg_pair("Public IP Address", @server.public_ip_address)
|
@@ -373,7 +397,19 @@ class Chef
|
|
373
397
|
ui.error("You are using a VPC, security groups specified with '-G' are not allowed, specify one or more security group ids with '-g' instead.")
|
374
398
|
exit 1
|
375
399
|
end
|
400
|
+
if !vpc_mode? and !!config[:private_ip_address]
|
401
|
+
ui.error("You can only specify a private IP address if you are using VPC.")
|
402
|
+
exit 1
|
403
|
+
end
|
404
|
+
|
405
|
+
if config[:associate_eip]
|
406
|
+
eips = connection.addresses.collect{|addr| addr if addr.domain == eip_scope}.compact
|
376
407
|
|
408
|
+
unless eips.detect{|addr| addr.public_ip == config[:associate_eip] && addr.server_id == nil}
|
409
|
+
ui.error("Elastic IP requested is not available.")
|
410
|
+
exit 1
|
411
|
+
end
|
412
|
+
end
|
377
413
|
end
|
378
414
|
|
379
415
|
def tags
|
@@ -385,6 +421,14 @@ class Chef
|
|
385
421
|
tags
|
386
422
|
end
|
387
423
|
|
424
|
+
def eip_scope
|
425
|
+
if vpc_mode?
|
426
|
+
"vpc"
|
427
|
+
else
|
428
|
+
"standard"
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
388
432
|
def create_server_def
|
389
433
|
server_def = {
|
390
434
|
:image_id => locate_config_value(:image),
|
@@ -395,6 +439,7 @@ class Chef
|
|
395
439
|
:availability_zone => locate_config_value(:availability_zone)
|
396
440
|
}
|
397
441
|
server_def[:subnet_id] = locate_config_value(:subnet_id) if vpc_mode?
|
442
|
+
server_def[:private_ip_address] = locate_config_value(:private_ip_address) if vpc_mode?
|
398
443
|
|
399
444
|
if Chef::Config[:knife][:aws_user_data]
|
400
445
|
begin
|
@@ -486,6 +531,17 @@ class Chef
|
|
486
531
|
vpc_mode? ? server.private_ip_address : server.dns_name
|
487
532
|
end
|
488
533
|
end
|
534
|
+
|
535
|
+
def create_tags(hashed_tags)
|
536
|
+
hashed_tags.each_pair do |key,val|
|
537
|
+
connection.tags.create :key => key, :value => val, :resource_id => @server.id
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
def associate_eip(elastic_ip)
|
542
|
+
connection.associate_address(server.id, elastic_ip.public_ip, nil, elastic_ip.allocation_id)
|
543
|
+
@server.wait_for { public_ip_address == elastic_ip.public_ip }
|
544
|
+
end
|
489
545
|
end
|
490
546
|
end
|
491
547
|
end
|
data/lib/knife-ec2/version.rb
CHANGED
@@ -38,6 +38,13 @@ describe Chef::Knife::Ec2ServerCreate do
|
|
38
38
|
@ec2_connection = mock(Fog::Compute::AWS)
|
39
39
|
@ec2_connection.stub_chain(:tags).and_return mock('create', :create => true)
|
40
40
|
@ec2_connection.stub_chain(:images, :get).and_return mock('ami', :root_device_type => 'not_ebs')
|
41
|
+
@ec2_connection.stub_chain(:addresses).and_return [mock('addesses', {
|
42
|
+
:domain => 'standard',
|
43
|
+
:public_ip => '111.111.111.111',
|
44
|
+
:server_id => nil,
|
45
|
+
:allocation_id => ''})]
|
46
|
+
|
47
|
+
|
41
48
|
@ec2_servers = mock()
|
42
49
|
@new_ec2_server = mock()
|
43
50
|
|
@@ -60,30 +67,56 @@ describe Chef::Knife::Ec2ServerCreate do
|
|
60
67
|
end
|
61
68
|
|
62
69
|
describe "run" do
|
63
|
-
|
64
|
-
@new_ec2_server.should_receive(:wait_for).and_return(true)
|
70
|
+
before do
|
65
71
|
@ec2_servers.should_receive(:create).and_return(@new_ec2_server)
|
66
72
|
@ec2_connection.should_receive(:servers).and_return(@ec2_servers)
|
73
|
+
@ec2_connection.should_receive(:addresses)
|
67
74
|
|
75
|
+
@eip = "111.111.111.111"
|
68
76
|
Fog::Compute::AWS.should_receive(:new).and_return(@ec2_connection)
|
69
77
|
|
70
78
|
@knife_ec2_create.stub!(:puts)
|
71
79
|
@knife_ec2_create.stub!(:print)
|
72
80
|
@knife_ec2_create.config[:image] = '12345'
|
73
81
|
|
74
|
-
|
75
82
|
@bootstrap = Chef::Knife::Bootstrap.new
|
76
83
|
Chef::Knife::Bootstrap.stub!(:new).and_return(@bootstrap)
|
77
84
|
@bootstrap.should_receive(:run)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "creates an EC2 instance and bootstraps it" do
|
88
|
+
@new_ec2_server.should_receive(:wait_for).and_return(true)
|
89
|
+
@knife_ec2_create.run
|
90
|
+
@knife_ec2_create.server.should_not == nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "creates an EC2 instance, assigns existing EIP and bootstraps it" do
|
94
|
+
@knife_ec2_create.config[:associate_eip] = @eip
|
95
|
+
|
96
|
+
@new_ec2_server.stub!(:public_ip_address).and_return(@eip)
|
97
|
+
@ec2_connection.should_receive(:associate_address).with(@ec2_server_attribs[:id], @eip, nil, '')
|
98
|
+
@new_ec2_server.should_receive(:wait_for).at_least(:twice).and_return(true)
|
99
|
+
|
78
100
|
@knife_ec2_create.run
|
79
101
|
@knife_ec2_create.server.should_not == nil
|
80
102
|
end
|
103
|
+
|
104
|
+
it "retries if it receives Fog::Compute::AWS::NotFound" do
|
105
|
+
@new_ec2_server.should_receive(:wait_for).and_return(true)
|
106
|
+
@knife_ec2_create.should_receive(:create_tags).and_raise(Fog::Compute::AWS::NotFound)
|
107
|
+
@knife_ec2_create.should_receive(:create_tags).and_return(true)
|
108
|
+
@knife_ec2_create.should_receive(:sleep).and_return(true)
|
109
|
+
@knife_ec2_create.ui.should_receive(:warn).with(/retrying/)
|
110
|
+
@knife_ec2_create.run
|
111
|
+
end
|
81
112
|
end
|
113
|
+
|
82
114
|
describe "when setting tags" do
|
83
115
|
before do
|
84
116
|
Fog::Compute::AWS.should_receive(:new).and_return(@ec2_connection)
|
85
117
|
@knife_ec2_create.stub!(:bootstrap_for_node).and_return mock("bootstrap", :run => true)
|
86
118
|
@ec2_connection.stub!(:servers).and_return(@ec2_servers)
|
119
|
+
@ec2_connection.should_receive(:addresses)
|
87
120
|
@new_ec2_server.stub!(:wait_for).and_return(true)
|
88
121
|
@ec2_servers.stub!(:create).and_return(@new_ec2_server)
|
89
122
|
@knife_ec2_create.stub!(:puts)
|
@@ -216,6 +249,12 @@ describe Chef::Knife::Ec2ServerCreate do
|
|
216
249
|
|
217
250
|
lambda { @knife_ec2_create.validate! }.should raise_error SystemExit
|
218
251
|
end
|
252
|
+
|
253
|
+
it "disallows private ips when not using a VPC" do
|
254
|
+
@knife_ec2_create.config[:private_ip_address] = '10.0.0.10'
|
255
|
+
|
256
|
+
lambda { @knife_ec2_create.validate! }.should raise_error SystemExit
|
257
|
+
end
|
219
258
|
end
|
220
259
|
|
221
260
|
describe "when creating the server definition" do
|
@@ -270,6 +309,15 @@ describe Chef::Knife::Ec2ServerCreate do
|
|
270
309
|
{ "VirtualName" => "ephemeral2", "DeviceName" => "/dev/sdd" },
|
271
310
|
{ "VirtualName" => "ephemeral3", "DeviceName" => "/dev/sde" }]
|
272
311
|
end
|
312
|
+
|
313
|
+
it "sets the specified private ip address" do
|
314
|
+
@knife_ec2_create.config[:subnet_id] = 'subnet-1a2b3c4d'
|
315
|
+
@knife_ec2_create.config[:private_ip_address] = '10.0.0.10'
|
316
|
+
server_def = @knife_ec2_create.create_server_def
|
317
|
+
|
318
|
+
server_def[:subnet_id].should == 'subnet-1a2b3c4d'
|
319
|
+
server_def[:private_ip_address].should == '10.0.0.10'
|
320
|
+
end
|
273
321
|
end
|
274
322
|
|
275
323
|
describe "ssh_connect_host" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-ec2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: fog
|