knife-ec2 0.6.2 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|