knife-ec2 0.19.16 → 1.0.1
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/lib/chef/knife/ec2_ami_list.rb +48 -37
- data/lib/chef/knife/ec2_base.rb +108 -36
- data/lib/chef/knife/ec2_eip_list.rb +88 -0
- data/lib/chef/knife/ec2_flavor_list.rb +3 -34
- data/lib/chef/knife/ec2_securitygroup_list.rb +68 -0
- data/lib/chef/knife/ec2_server_create.rb +429 -554
- data/lib/chef/knife/ec2_server_delete.rb +99 -48
- data/lib/chef/knife/ec2_server_list.rb +83 -44
- data/lib/chef/knife/ec2_subnet_list.rb +79 -0
- data/lib/chef/knife/ec2_vpc_list.rb +75 -0
- data/lib/chef/knife/s3_source.rb +27 -9
- data/lib/knife-ec2/version.rb +1 -1
- metadata +29 -20
@@ -0,0 +1,68 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2018 Chef Software, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef/knife/ec2_base"
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class Ec2SecuritygroupList < Knife
|
24
|
+
|
25
|
+
include Knife::Ec2Base
|
26
|
+
|
27
|
+
banner "knife ec2 securitygroup list (options)"
|
28
|
+
|
29
|
+
def run
|
30
|
+
validate_aws_config!
|
31
|
+
custom_warnings!
|
32
|
+
|
33
|
+
sg_list = [
|
34
|
+
ui.color("ID", :bold),
|
35
|
+
ui.color("Name", :bold),
|
36
|
+
ui.color("VPC ID", :bold)
|
37
|
+
].flatten.compact
|
38
|
+
|
39
|
+
output_column_count = sg_list.length
|
40
|
+
|
41
|
+
if config[:format] == "summary"
|
42
|
+
sg_hash.each_pair do |_k, v|
|
43
|
+
sg_list << v["group_id"]
|
44
|
+
sg_list << v["group_name"]
|
45
|
+
sg_list << v["vpc_id"]
|
46
|
+
end
|
47
|
+
puts ui.list(sg_list, :uneven_columns_across, output_column_count)
|
48
|
+
else
|
49
|
+
output(format_for_display(sg_hash))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def sg_hash
|
56
|
+
all_data = {}
|
57
|
+
ec2_connection.describe_security_groups.first.security_groups.each do |s|
|
58
|
+
s_data = {}
|
59
|
+
%w{group_name group_id vpc_id}.each do |id|
|
60
|
+
s_data[id] = s.send(id)
|
61
|
+
end
|
62
|
+
all_data[s_data["group_id"]] = s_data
|
63
|
+
end
|
64
|
+
all_data
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -19,20 +19,18 @@
|
|
19
19
|
|
20
20
|
require "chef/knife/ec2_base"
|
21
21
|
require "chef/knife/s3_source"
|
22
|
-
require "chef/knife/
|
23
|
-
require "chef/knife/bootstrap_windows_base"
|
22
|
+
require "chef/knife/bootstrap"
|
24
23
|
|
25
24
|
class Chef
|
26
25
|
class Knife
|
27
|
-
class Ec2ServerCreate < Knife
|
26
|
+
class Ec2ServerCreate < Chef::Knife::Bootstrap
|
28
27
|
|
29
28
|
include Knife::Ec2Base
|
30
|
-
|
31
|
-
include Knife::BootstrapWindowsBase
|
29
|
+
|
32
30
|
deps do
|
33
31
|
require "tempfile"
|
34
32
|
require "uri"
|
35
|
-
require "
|
33
|
+
require "net/ssh"
|
36
34
|
Chef::Knife::Bootstrap.load_deps
|
37
35
|
end
|
38
36
|
|
@@ -119,70 +117,12 @@ class Chef
|
|
119
117
|
description: "The Availability Zone",
|
120
118
|
proc: Proc.new { |key| Chef::Config[:knife][:availability_zone] = key }
|
121
119
|
|
122
|
-
option :chef_node_name,
|
123
|
-
short: "-N NAME",
|
124
|
-
long: "--node-name NAME",
|
125
|
-
description: "The Chef node name for your new node",
|
126
|
-
proc: Proc.new { |key| Chef::Config[:knife][:chef_node_name] = key }
|
127
|
-
|
128
120
|
option :ssh_key_name,
|
129
121
|
short: "-S KEY",
|
130
122
|
long: "--ssh-key KEY",
|
131
123
|
description: "The AWS SSH key id",
|
132
124
|
proc: Proc.new { |key| Chef::Config[:knife][:ssh_key_name] = key }
|
133
125
|
|
134
|
-
option :ssh_user,
|
135
|
-
short: "-x USERNAME",
|
136
|
-
long: "--ssh-user USERNAME",
|
137
|
-
description: "The ssh username",
|
138
|
-
default: "root"
|
139
|
-
|
140
|
-
option :ssh_password,
|
141
|
-
short: "-P PASSWORD",
|
142
|
-
long: "--ssh-password PASSWORD",
|
143
|
-
description: "The ssh password"
|
144
|
-
|
145
|
-
option :ssh_port,
|
146
|
-
short: "-p PORT",
|
147
|
-
long: "--ssh-port PORT",
|
148
|
-
description: "The ssh port",
|
149
|
-
default: "22",
|
150
|
-
proc: Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
|
151
|
-
|
152
|
-
option :ssh_gateway,
|
153
|
-
short: "-w GATEWAY",
|
154
|
-
long: "--ssh-gateway GATEWAY",
|
155
|
-
description: "The ssh gateway server. Any proxies configured in your ssh config are automatically used by default.",
|
156
|
-
proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
|
157
|
-
|
158
|
-
option :ssh_gateway_identity,
|
159
|
-
long: "--ssh-gateway-identity IDENTITY_FILE",
|
160
|
-
description: "The private key for ssh gateway server",
|
161
|
-
proc: Proc.new { |key| Chef::Config[:knife][:ssh_gateway_identity] = key }
|
162
|
-
|
163
|
-
option :identity_file,
|
164
|
-
short: "-i IDENTITY_FILE",
|
165
|
-
long: "--identity-file IDENTITY_FILE",
|
166
|
-
description: "The SSH identity file used for authentication"
|
167
|
-
|
168
|
-
option :prerelease,
|
169
|
-
long: "--prerelease",
|
170
|
-
description: "Install the pre-release chef gems"
|
171
|
-
|
172
|
-
option :bootstrap_version,
|
173
|
-
long: "--bootstrap-version VERSION",
|
174
|
-
description: "The version of Chef to install",
|
175
|
-
proc: Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
176
|
-
|
177
|
-
option :bootstrap_proxy,
|
178
|
-
long: "--bootstrap-proxy PROXY_URL",
|
179
|
-
description: "The proxy server for the node being bootstrapped",
|
180
|
-
proc: Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
181
|
-
|
182
|
-
option :bootstrap_template,
|
183
|
-
long: "--bootstrap-template TEMPLATE",
|
184
|
-
description: "Bootstrap Chef using a built-in or custom template. Set to the full path of an erb template or use one of the built-in templates."
|
185
|
-
|
186
126
|
option :ebs_size,
|
187
127
|
long: "--ebs-size SIZE",
|
188
128
|
description: "The size of the EBS volume in GB, for EBS-backed instances"
|
@@ -195,13 +135,6 @@ class Chef
|
|
195
135
|
long: "--ebs-no-delete-on-term",
|
196
136
|
description: "Do not delete EBS volume on instance termination"
|
197
137
|
|
198
|
-
option :run_list,
|
199
|
-
short: "-r RUN_LIST",
|
200
|
-
long: "--run-list RUN_LIST",
|
201
|
-
description: "Comma separated list of roles/recipes to apply",
|
202
|
-
proc: lambda { |o| o.split(/[\s,]+/) },
|
203
|
-
default: []
|
204
|
-
|
205
138
|
option :secret,
|
206
139
|
long: "--secret ",
|
207
140
|
description: "The secret key to use to encrypt data bag item values",
|
@@ -227,18 +160,6 @@ class Chef
|
|
227
160
|
description: "allows to specify the private IP address of the instance in VPC mode",
|
228
161
|
proc: Proc.new { |ip| Chef::Config[:knife][:private_ip_address] = ip }
|
229
162
|
|
230
|
-
option :host_key_verify,
|
231
|
-
long: "--[no-]host-key-verify",
|
232
|
-
description: "Verify host key, enabled by default.",
|
233
|
-
boolean: true,
|
234
|
-
default: true
|
235
|
-
|
236
|
-
option :bootstrap_protocol,
|
237
|
-
long: "--bootstrap-protocol protocol",
|
238
|
-
description: "protocol to bootstrap windows servers. options: winrm/ssh",
|
239
|
-
proc: Proc.new { |key| Chef::Config[:knife][:bootstrap_protocol] = key },
|
240
|
-
default: nil
|
241
|
-
|
242
163
|
option :fqdn,
|
243
164
|
long: "--fqdn FQDN",
|
244
165
|
description: "Pre-defined FQDN. This is used for Kerberos Authentication purpose only",
|
@@ -252,15 +173,6 @@ class Chef
|
|
252
173
|
proc: Proc.new { |m| Chef::Config[:knife][:aws_user_data] = m },
|
253
174
|
default: nil
|
254
175
|
|
255
|
-
option :hint,
|
256
|
-
long: "--hint HINT_NAME[=HINT_FILE]",
|
257
|
-
description: "Specify Ohai Hint to be set on the bootstrap target. Use multiple --hint options to specify multiple hints.",
|
258
|
-
proc: Proc.new { |h|
|
259
|
-
Chef::Config[:knife][:hints] ||= {}
|
260
|
-
name, path = h.split("=")
|
261
|
-
Chef::Config[:knife][:hints][name] = path ? JSON.parse(::File.read(path)) : Hash.new
|
262
|
-
}
|
263
|
-
|
264
176
|
option :ephemeral,
|
265
177
|
long: "--ephemeral EPHEMERAL_DEVICES",
|
266
178
|
description: "Comma separated list of device locations (eg - /dev/sdb) to map ephemeral devices",
|
@@ -291,11 +203,6 @@ class Chef
|
|
291
203
|
proc: Proc.new { |key| Chef::Config[:knife][:provisioned_iops] = key },
|
292
204
|
default: nil
|
293
205
|
|
294
|
-
option :auth_timeout,
|
295
|
-
long: "--windows-auth-timeout MINUTES",
|
296
|
-
description: "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 25 minutes.",
|
297
|
-
default: 25
|
298
|
-
|
299
206
|
option :validation_key_url,
|
300
207
|
long: "--validation-key-url URL",
|
301
208
|
description: "Path to the validation key",
|
@@ -331,76 +238,6 @@ class Chef
|
|
331
238
|
proc: proc { |t| t = t.to_i * 60; Chef::Config[:aws_connection_timeout] = t },
|
332
239
|
default: 600
|
333
240
|
|
334
|
-
option :node_ssl_verify_mode,
|
335
|
-
long: "--node-ssl-verify-mode [peer|none]",
|
336
|
-
description: "Whether or not to verify the SSL cert for all HTTPS requests.",
|
337
|
-
proc: Proc.new { |v|
|
338
|
-
valid_values = %w{none peer}
|
339
|
-
unless valid_values.include?(v)
|
340
|
-
raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}"
|
341
|
-
end
|
342
|
-
}
|
343
|
-
|
344
|
-
option :node_verify_api_cert,
|
345
|
-
long: "--[no-]node-verify-api-cert",
|
346
|
-
description: "Verify the SSL cert for HTTPS requests to the Chef server API.",
|
347
|
-
boolean: true
|
348
|
-
|
349
|
-
option :bootstrap_no_proxy,
|
350
|
-
long: "--bootstrap-no-proxy [NO_PROXY_URL|NO_PROXY_IP]",
|
351
|
-
description: "Do not proxy locations for the node being bootstrapped; this option is used internally by Opscode",
|
352
|
-
proc: Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
|
353
|
-
|
354
|
-
option :bootstrap_url,
|
355
|
-
long: "--bootstrap-url URL",
|
356
|
-
description: "URL to a custom installation script",
|
357
|
-
proc: Proc.new { |u| Chef::Config[:knife][:bootstrap_url] = u }
|
358
|
-
|
359
|
-
option :bootstrap_install_command,
|
360
|
-
long: "--bootstrap-install-command COMMANDS",
|
361
|
-
description: "Custom command to install chef-client",
|
362
|
-
proc: Proc.new { |ic| Chef::Config[:knife][:bootstrap_install_command] = ic }
|
363
|
-
|
364
|
-
option :bootstrap_wget_options,
|
365
|
-
long: "--bootstrap-wget-options OPTIONS",
|
366
|
-
description: "Add options to wget when installing chef-client",
|
367
|
-
proc: Proc.new { |wo| Chef::Config[:knife][:bootstrap_wget_options] = wo }
|
368
|
-
|
369
|
-
option :bootstrap_curl_options,
|
370
|
-
long: "--bootstrap-curl-options OPTIONS",
|
371
|
-
description: "Add options to curl when install chef-client",
|
372
|
-
proc: Proc.new { |co| Chef::Config[:knife][:bootstrap_curl_options] = co }
|
373
|
-
|
374
|
-
option :bootstrap_vault_file,
|
375
|
-
long: "--bootstrap-vault-file VAULT_FILE",
|
376
|
-
description: "A JSON file with a list of vault(s) and item(s) to be updated"
|
377
|
-
|
378
|
-
option :bootstrap_vault_json,
|
379
|
-
long: "--bootstrap-vault-json VAULT_JSON",
|
380
|
-
description: "A JSON string with the vault(s) and item(s) to be updated"
|
381
|
-
|
382
|
-
option :bootstrap_vault_item,
|
383
|
-
long: "--bootstrap-vault-item VAULT_ITEM",
|
384
|
-
description: 'A single vault and item to update as "vault:item"',
|
385
|
-
proc: Proc.new { |i|
|
386
|
-
(vault, item) = i.split(/:/)
|
387
|
-
Chef::Config[:knife][:bootstrap_vault_item] ||= {}
|
388
|
-
Chef::Config[:knife][:bootstrap_vault_item][vault] ||= []
|
389
|
-
Chef::Config[:knife][:bootstrap_vault_item][vault].push(item)
|
390
|
-
Chef::Config[:knife][:bootstrap_vault_item]
|
391
|
-
}
|
392
|
-
|
393
|
-
option :use_sudo_password,
|
394
|
-
long: "--use-sudo-password",
|
395
|
-
description: "Execute the bootstrap via sudo with password",
|
396
|
-
boolean: false
|
397
|
-
|
398
|
-
option :forward_agent,
|
399
|
-
short: "-A",
|
400
|
-
long: "--forward-agent",
|
401
|
-
description: "Enable SSH agent forwarding",
|
402
|
-
boolean: true
|
403
|
-
|
404
241
|
option :create_ssl_listener,
|
405
242
|
long: "--[no-]create-ssl-listener",
|
406
243
|
description: "Create ssl listener, enabled by default.",
|
@@ -409,7 +246,7 @@ class Chef
|
|
409
246
|
|
410
247
|
option :network_interfaces,
|
411
248
|
short: "-n",
|
412
|
-
long: "--attach-network-interface
|
249
|
+
long: "--attach-network-interface ENI_ID1,ENI_ID2",
|
413
250
|
description: "Attach additional network interfaces during bootstrap",
|
414
251
|
proc: proc { |nics| nics.split(",") }
|
415
252
|
|
@@ -465,22 +302,18 @@ class Chef
|
|
465
302
|
Chef::Config[:knife][:aws_tag]
|
466
303
|
}
|
467
304
|
|
468
|
-
def
|
469
|
-
$stdout.sync = true
|
470
|
-
validate!
|
471
|
-
|
305
|
+
def plugin_create_instance!
|
472
306
|
requested_elastic_ip = config[:associate_eip] if config[:associate_eip]
|
473
307
|
|
474
308
|
# For VPC EIP assignment we need the allocation ID so fetch full EIP details
|
475
|
-
elastic_ip =
|
309
|
+
elastic_ip = ec2_connection.describe_addresses.addresses.detect { |addr| addr if addr.public_ip == requested_elastic_ip }
|
476
310
|
|
477
|
-
if
|
478
|
-
server_def =
|
479
|
-
|
480
|
-
|
481
|
-
msg_pair("Spot Request
|
482
|
-
msg_pair("Spot
|
483
|
-
msg_pair("Spot Price", spot_request.price)
|
311
|
+
if config_value(:spot_price)
|
312
|
+
server_def = spot_instances_attributes
|
313
|
+
spot_request = ec2_connection.request_spot_instances(server_def)
|
314
|
+
msg_pair("Spot Request ID", spot_request.spot_instance_request_id)
|
315
|
+
msg_pair("Spot Request Type", spot_request.type)
|
316
|
+
msg_pair("Spot Price", spot_request.spot_price)
|
484
317
|
|
485
318
|
case config[:spot_wait_mode]
|
486
319
|
when "prompt", "", nil
|
@@ -501,16 +334,18 @@ class Chef
|
|
501
334
|
end
|
502
335
|
|
503
336
|
print ui.color("Waiting for Spot Request fulfillment: ", :cyan)
|
504
|
-
spot_request.
|
505
|
-
|
506
|
-
|
507
|
-
ready?
|
508
|
-
end
|
509
|
-
puts("\n")
|
510
|
-
@server = connection.servers.get(spot_request.instance_id)
|
337
|
+
spot_response = spot_instances_wait_until_ready(spot_request.spot_instance_request_id)
|
338
|
+
|
339
|
+
@server = fetch_ec2_instance(spot_response.instance_id)
|
511
340
|
else
|
512
341
|
begin
|
513
|
-
|
342
|
+
response_obj = create_ec2_instance(server_attributes)
|
343
|
+
instance_id = response_obj.instances[0].instance_id
|
344
|
+
print "\n#{ui.color("Waiting for EC2 to create the instance\n", :magenta)}"
|
345
|
+
|
346
|
+
# wait for instance to come up before acting against it
|
347
|
+
instances_wait_until_ready(instance_id)
|
348
|
+
@server = fetch_ec2_instance(instance_id)
|
514
349
|
rescue => error
|
515
350
|
error.message.sub("download completed, but downloaded file not found", "Verify that you have public internet access.")
|
516
351
|
ui.error error.message
|
@@ -519,53 +354,19 @@ class Chef
|
|
519
354
|
end
|
520
355
|
end
|
521
356
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
else
|
530
|
-
hashed_tags["Name"] = server.id
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
printed_aws_tags = hashed_tags.map { |tag, val| "#{tag}: #{val}" }.join(", ")
|
535
|
-
|
536
|
-
hashed_volume_tags = {}
|
537
|
-
volume_tags = locate_config_value(:volume_tags)
|
538
|
-
volume_tags.map { |t| key, val = t.split("="); hashed_volume_tags[key] = val } unless volume_tags.nil?
|
539
|
-
printed_volume_tags = hashed_volume_tags.map { |tag, val| "#{tag}: #{val}" }.join(", ")
|
540
|
-
|
541
|
-
msg_pair("Instance ID", @server.id)
|
542
|
-
msg_pair("Flavor", @server.flavor_id)
|
543
|
-
msg_pair("Image", @server.image_id)
|
544
|
-
msg_pair("Region", connection.instance_variable_get(:@region))
|
545
|
-
msg_pair("Availability Zone", @server.availability_zone)
|
546
|
-
|
547
|
-
# If we don't specify a security group or security group id, Fog will
|
548
|
-
# pick the appropriate default one. In case of a VPC we don't know the
|
549
|
-
# default security group id at this point unless we look it up, hence
|
550
|
-
# 'default' is printed if no id was specified.
|
551
|
-
printed_security_groups = "default"
|
552
|
-
printed_security_groups = @server.groups.join(", ") if @server.groups
|
553
|
-
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (@server.groups.nil? && @server.security_group_ids)
|
357
|
+
msg_pair("Instance ID", server.id)
|
358
|
+
msg_pair("Flavor", server.instance_type)
|
359
|
+
msg_pair("Image", server.image_id)
|
360
|
+
msg_pair("Region", fetch_region)
|
361
|
+
msg_pair("Availability Zone", server.availability_zone)
|
362
|
+
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (server.groups && server.security_groups_ids)
|
363
|
+
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || server.security_groups_ids
|
554
364
|
|
555
|
-
|
556
|
-
printed_security_group_ids = @server.security_group_ids.join(", ") if @server.security_group_ids
|
557
|
-
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || @server.security_group_ids
|
558
|
-
|
559
|
-
msg_pair("IAM Profile", locate_config_value(:iam_instance_profile))
|
365
|
+
msg_pair("IAM Profile", config_value(:iam_instance_profile))
|
560
366
|
|
561
367
|
msg_pair("AWS Tags", printed_aws_tags)
|
562
368
|
msg_pair("Volume Tags", printed_volume_tags)
|
563
|
-
msg_pair("SSH Key",
|
564
|
-
|
565
|
-
print "\n#{ui.color("Waiting for EC2 to create the instance", :magenta)}"
|
566
|
-
|
567
|
-
# wait for instance to come up before acting against it
|
568
|
-
@server.wait_for(locate_config_value(:aws_connection_timeout)) { print "."; ready? }
|
369
|
+
msg_pair("SSH Key", server.key_name)
|
569
370
|
|
570
371
|
puts("\n")
|
571
372
|
|
@@ -574,9 +375,9 @@ class Chef
|
|
574
375
|
begin
|
575
376
|
create_tags(hashed_tags) unless hashed_tags.empty?
|
576
377
|
create_volume_tags(hashed_volume_tags) unless hashed_volume_tags.empty?
|
577
|
-
|
378
|
+
associate_address(elastic_ip) if config[:associate_eip]
|
578
379
|
enable_classic_link(config[:classic_link_vpc_id], config[:classic_link_vpc_security_group_ids]) if config[:classic_link_vpc_id]
|
579
|
-
rescue
|
380
|
+
rescue Aws::EC2::Errors::ServiceError, Aws::EC2::Errors::Error
|
580
381
|
raise if (tries -= 1) <= 0
|
581
382
|
ui.warn("server not ready, retrying tag application (retries left: #{tries})")
|
582
383
|
sleep 5
|
@@ -586,115 +387,131 @@ class Chef
|
|
586
387
|
attach_nics if config[:network_interfaces]
|
587
388
|
|
588
389
|
if vpc_mode?
|
589
|
-
msg_pair("Subnet ID",
|
590
|
-
msg_pair("Tenancy",
|
390
|
+
msg_pair("Subnet ID", server.subnet_id)
|
391
|
+
msg_pair("Tenancy", server.tenancy)
|
591
392
|
if config[:associate_public_ip]
|
592
|
-
msg_pair("Public DNS Name",
|
393
|
+
msg_pair("Public DNS Name", server.public_dns_name)
|
593
394
|
end
|
594
395
|
if elastic_ip
|
595
|
-
msg_pair("Public IP Address",
|
396
|
+
msg_pair("Public IP Address", server.public_ip_address)
|
596
397
|
end
|
597
398
|
else
|
598
|
-
msg_pair("Public DNS Name",
|
599
|
-
msg_pair("Public IP Address",
|
600
|
-
msg_pair("Private DNS Name",
|
399
|
+
msg_pair("Public DNS Name", server.public_dns_name)
|
400
|
+
msg_pair("Public IP Address", server.public_ip_address)
|
401
|
+
msg_pair("Private DNS Name", server.private_dns_name)
|
601
402
|
end
|
602
|
-
msg_pair("Private IP Address",
|
403
|
+
msg_pair("Private IP Address", server.private_ip_address)
|
603
404
|
|
604
405
|
if Chef::Config[:knife][:validation_key_url]
|
605
406
|
download_validation_key(validation_key_path)
|
606
407
|
Chef::Config[:validation_key] = validation_key_path
|
607
408
|
end
|
608
409
|
|
410
|
+
config[:connection_protocol] ||= connection_protocol
|
411
|
+
config[:connection_port] ||= connection_port
|
412
|
+
|
609
413
|
# Check if Server is Windows or Linux
|
610
414
|
if is_image_windows?
|
611
|
-
|
612
|
-
protocol ||= "winrm"
|
613
|
-
if protocol == "winrm"
|
614
|
-
load_winrm_deps
|
415
|
+
if winrm?
|
615
416
|
print "\n#{ui.color("Waiting for winrm access to become available", :magenta)}"
|
616
|
-
print(".") until tcp_test_winrm(
|
417
|
+
print(".") until tcp_test_winrm(connection_host, connection_port) do
|
617
418
|
sleep 10
|
618
419
|
puts("done")
|
619
420
|
end
|
620
421
|
else
|
621
422
|
print "\n#{ui.color("Waiting for sshd access to become available", :magenta)}"
|
622
423
|
# If FreeSSHd, winsshd etc are available
|
623
|
-
print(".") until tcp_test_ssh(
|
424
|
+
print(".") until tcp_test_ssh(connection_host, connection_port) do
|
624
425
|
sleep @initial_sleep_delay ||= (vpc_mode? ? 40 : 10)
|
625
426
|
puts("done")
|
626
427
|
end
|
627
|
-
ssh_override_winrm
|
628
428
|
end
|
629
|
-
bootstrap_for_windows_node(@server, ssh_connect_host).run
|
630
429
|
else
|
631
430
|
print "\n#{ui.color("Waiting for sshd access to become available", :magenta)}"
|
632
|
-
wait_for_sshd(
|
633
|
-
ssh_override_winrm
|
634
|
-
bootstrap_for_linux_node(@server, ssh_connect_host).run
|
431
|
+
wait_for_sshd(connection_host)
|
635
432
|
end
|
636
433
|
|
434
|
+
fqdn = connection_host
|
435
|
+
if winrm?
|
436
|
+
if config_value(:kerberos_realm)
|
437
|
+
# Fetch AD/WINS based fqdn if any for Kerberos-based Auth
|
438
|
+
fqdn = config_value(:fqdn) || fetch_server_fqdn(server.private_ip_address)
|
439
|
+
end
|
440
|
+
config[:connection_password] = windows_password
|
441
|
+
end
|
442
|
+
@name_args = [fqdn]
|
443
|
+
|
444
|
+
if config_value(:chef_node_name)
|
445
|
+
config[:chef_node_name] = evaluate_node_name(config_value(:chef_node_name))
|
446
|
+
else
|
447
|
+
config[:chef_node_name] = server.id
|
448
|
+
end
|
449
|
+
bootstrap_common_params
|
450
|
+
end
|
451
|
+
|
452
|
+
def plugin_finalize
|
637
453
|
puts "\n"
|
638
|
-
msg_pair("Instance ID",
|
639
|
-
msg_pair("Flavor",
|
640
|
-
msg_pair("Placement Group",
|
641
|
-
msg_pair("Image",
|
642
|
-
msg_pair("Region",
|
643
|
-
msg_pair("Availability Zone",
|
644
|
-
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (
|
645
|
-
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? ||
|
646
|
-
msg_pair("IAM Profile",
|
647
|
-
msg_pair("Primary ENI",
|
454
|
+
msg_pair("Instance ID", server.id)
|
455
|
+
msg_pair("Flavor", server.instance_type)
|
456
|
+
msg_pair("Placement Group", server.placement_group) unless server.placement_group.nil?
|
457
|
+
msg_pair("Image", server.image_id)
|
458
|
+
msg_pair("Region", fetch_region)
|
459
|
+
msg_pair("Availability Zone", server.availability_zone)
|
460
|
+
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (server.groups.nil? && server.security_group_ids)
|
461
|
+
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || server.security_group_ids
|
462
|
+
msg_pair("IAM Profile", config_value(:iam_instance_profile)) if config_value(:iam_instance_profile)
|
463
|
+
msg_pair("Primary ENI", config_value(:primary_eni)) if config_value(:primary_eni)
|
648
464
|
msg_pair("AWS Tags", printed_aws_tags)
|
649
|
-
msg_pair("Chef Tags",
|
650
|
-
msg_pair("SSH Key",
|
651
|
-
msg_pair("Root Device Type",
|
465
|
+
msg_pair("Chef Tags", config_value(:chef_tag)) if config_value(:chef_tag)
|
466
|
+
msg_pair("SSH Key", server.key_name)
|
467
|
+
msg_pair("Root Device Type", server.root_device_type)
|
652
468
|
msg_pair("Root Volume Tags", printed_volume_tags)
|
653
|
-
if
|
654
|
-
device_map =
|
655
|
-
msg_pair("Root
|
656
|
-
msg_pair("Root
|
657
|
-
msg_pair("Root Device Delete on Terminate", device_map
|
658
|
-
msg_pair("Standard or Provisioned IOPS", device_map
|
659
|
-
msg_pair("IOPS rate", device_map
|
469
|
+
if server.root_device_type == "ebs"
|
470
|
+
device_map = server.block_device_mappings.first
|
471
|
+
msg_pair("Root Device Name", device_map.device_name)
|
472
|
+
msg_pair("Root Volume ID", device_map.ebs.volume_id)
|
473
|
+
msg_pair("Root Device Delete on Terminate", device_map.ebs.delete_on_termination)
|
474
|
+
msg_pair("Standard or Provisioned IOPS", device_map.ebs.volume_type) if device_map.ebs.respond_to?("volume_type")
|
475
|
+
msg_pair("IOPS rate", device_map.ebs.iops) if device_map.ebs.respond_to?("iops")
|
660
476
|
|
661
477
|
print "\n#{ui.color("Block devices", :magenta)}\n"
|
662
478
|
print "#{ui.color("===========================", :magenta)}\n"
|
663
|
-
|
664
|
-
msg_pair("Device Name", device_map
|
665
|
-
msg_pair("Volume ID", device_map
|
666
|
-
msg_pair("Delete on Terminate", device_map
|
667
|
-
msg_pair("Standard or Provisioned IOPS", device_map
|
668
|
-
msg_pair("IOPS rate", device_map
|
479
|
+
server.block_device_mappings.each do |device_map|
|
480
|
+
msg_pair("Device Name", device_map.device_name)
|
481
|
+
msg_pair("Volume ID", device_map.ebs.volume_id)
|
482
|
+
msg_pair("Delete on Terminate", device_map.ebs.delete_on_termination.to_s)
|
483
|
+
msg_pair("Standard or Provisioned IOPS", device_map.ebs.volume_type) if device_map.ebs.respond_to?("volume_type")
|
484
|
+
msg_pair("IOPS rate", device_map.ebs.iops) if device_map.ebs.respond_to?("iops")
|
669
485
|
print "\n"
|
670
486
|
end
|
671
487
|
print "#{ui.color("===========================", :magenta)}\n"
|
672
488
|
|
673
489
|
if config[:ebs_size]
|
674
|
-
|
490
|
+
volume_size = ami.block_device_mappings[0].ebs.volume_size
|
491
|
+
if volume_size.to_i < config[:ebs_size].to_i
|
675
492
|
volume_too_large_warning = "#{config[:ebs_size]}GB " +
|
676
493
|
"EBS volume size is larger than size set in AMI of " +
|
677
|
-
"#{
|
494
|
+
"#{volume_size}GB.\n" +
|
678
495
|
"Use file system tools to make use of the increased volume size."
|
679
496
|
msg_pair("Warning", volume_too_large_warning, :yellow)
|
680
497
|
end
|
681
498
|
end
|
682
499
|
end
|
683
500
|
if config[:ebs_optimized]
|
684
|
-
msg_pair("EBS is Optimized",
|
501
|
+
msg_pair("EBS is Optimized", server.ebs_optimized.to_s)
|
685
502
|
end
|
686
503
|
if vpc_mode?
|
687
|
-
msg_pair("Subnet ID",
|
688
|
-
msg_pair("Tenancy",
|
504
|
+
msg_pair("Subnet ID", server.subnet_id)
|
505
|
+
msg_pair("Tenancy", server.tenancy)
|
689
506
|
if config[:associate_public_ip]
|
690
|
-
msg_pair("Public DNS Name",
|
507
|
+
msg_pair("Public DNS Name", server.public_dns_name)
|
691
508
|
end
|
692
509
|
else
|
693
|
-
msg_pair("Public DNS Name",
|
694
|
-
msg_pair("Public IP Address",
|
695
|
-
msg_pair("Private DNS Name",
|
510
|
+
msg_pair("Public DNS Name", server.public_dns_name)
|
511
|
+
msg_pair("Public IP Address", server.public_ip_address)
|
512
|
+
msg_pair("Private DNS Name", server.private_dns_name)
|
696
513
|
end
|
697
|
-
msg_pair("Private IP Address",
|
514
|
+
msg_pair("Private IP Address", server.private_ip_address)
|
698
515
|
msg_pair("Environment", config[:environment] || "_default")
|
699
516
|
msg_pair("Run List", (config[:run_list] || []).join(", "))
|
700
517
|
if config[:first_boot_attributes] || config[:first_boot_attributes_from_file]
|
@@ -742,54 +559,30 @@ class Chef
|
|
742
559
|
|
743
560
|
def s3_secret
|
744
561
|
@s3_secret ||= begin
|
745
|
-
return false unless
|
746
|
-
Chef::Knife::S3Source.fetch(
|
562
|
+
return false unless config_value(:s3_secret)
|
563
|
+
Chef::Knife::S3Source.fetch(config_value(:s3_secret))
|
747
564
|
end
|
748
565
|
end
|
749
566
|
|
750
|
-
def bootstrap_common_params
|
751
|
-
|
752
|
-
|
753
|
-
bootstrap.config[:policy_name] = locate_config_value(:policy_name)
|
754
|
-
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
755
|
-
bootstrap.config[:environment] = locate_config_value(:environment)
|
756
|
-
bootstrap.config[:prerelease] = config[:prerelease]
|
757
|
-
bootstrap.config[:first_boot_attributes] = locate_config_value(:first_boot_attributes)
|
758
|
-
bootstrap.config[:first_boot_attributes_from_file] = locate_config_value(:first_boot_attributes_from_file)
|
759
|
-
bootstrap.config[:encrypted_data_bag_secret] = s3_secret || locate_config_value(:secret)
|
760
|
-
bootstrap.config[:encrypted_data_bag_secret_file] = locate_config_value(:secret_file)
|
567
|
+
def bootstrap_common_params
|
568
|
+
config[:encrypted_data_bag_secret] = s3_secret || config_value(:secret)
|
569
|
+
config[:encrypted_data_bag_secret_file] = config_value(:secret_file)
|
761
570
|
# retrieving the secret from S3 is unique to knife-ec2, so we need to set "command line secret" to the value fetched from S3
|
762
571
|
# When linux vm is spawned, the chef's secret option proc function sets the value "command line secret" and this value is used by
|
763
572
|
# chef's code to check if secret option is passed through command line or not
|
764
|
-
Chef::Knife::DataBagSecretOptions.set_cl_secret(s3_secret) if
|
765
|
-
|
766
|
-
|
767
|
-
bootstrap.config[:node_ssl_verify_mode] = locate_config_value(:node_ssl_verify_mode)
|
768
|
-
bootstrap.config[:node_verify_api_cert] = locate_config_value(:node_verify_api_cert)
|
769
|
-
bootstrap.config[:bootstrap_no_proxy] = locate_config_value(:bootstrap_no_proxy)
|
770
|
-
bootstrap.config[:bootstrap_url] = locate_config_value(:bootstrap_url)
|
771
|
-
bootstrap.config[:bootstrap_install_command] = locate_config_value(:bootstrap_install_command)
|
772
|
-
bootstrap.config[:bootstrap_wget_options] = locate_config_value(:bootstrap_wget_options)
|
773
|
-
bootstrap.config[:bootstrap_curl_options] = locate_config_value(:bootstrap_curl_options)
|
774
|
-
bootstrap.config[:bootstrap_vault_file] = locate_config_value(:bootstrap_vault_file)
|
775
|
-
bootstrap.config[:bootstrap_vault_json] = locate_config_value(:bootstrap_vault_json)
|
776
|
-
bootstrap.config[:bootstrap_vault_item] = locate_config_value(:bootstrap_vault_item)
|
777
|
-
bootstrap.config[:bootstrap_template] = locate_config_value(:bootstrap_template)
|
778
|
-
bootstrap.config[:use_sudo_password] = locate_config_value(:use_sudo_password)
|
779
|
-
bootstrap.config[:yes] = locate_config_value(:yes)
|
573
|
+
Chef::Knife::DataBagSecretOptions.set_cl_secret(s3_secret) if config_value(:s3_secret)
|
574
|
+
config[:secret] = s3_secret || config_value(:secret)
|
575
|
+
|
780
576
|
# If --chef-tag is provided then it will be set in chef as single value e.g. --chef-tag "myTag"
|
781
577
|
# Otherwise if --tag-node-in-chef is provided then it will tag the chef in key=value pair of --tags option
|
782
578
|
# e.g. --tags "key=value"
|
783
|
-
if
|
784
|
-
|
785
|
-
elsif locate_config_value(:tag_node_in_chef)
|
786
|
-
bootstrap.config[:tags] = config[:tags]
|
579
|
+
if config_value(:chef_tag)
|
580
|
+
config[:tags] = config_value(:chef_tag)
|
787
581
|
end
|
788
582
|
# Modify global configuration state to ensure hint gets set by
|
789
583
|
# knife-bootstrap
|
790
584
|
Chef::Config[:knife][:hints] ||= {}
|
791
585
|
Chef::Config[:knife][:hints]["ec2"] ||= {}
|
792
|
-
bootstrap
|
793
586
|
end
|
794
587
|
|
795
588
|
def fetch_server_fqdn(ip_addr)
|
@@ -797,91 +590,29 @@ class Chef
|
|
797
590
|
Resolv.getname(ip_addr)
|
798
591
|
end
|
799
592
|
|
800
|
-
def bootstrap_for_windows_node(server, fqdn)
|
801
|
-
if locate_config_value(:bootstrap_protocol) == "winrm" || locate_config_value(:bootstrap_protocol).nil?
|
802
|
-
if locate_config_value(:kerberos_realm)
|
803
|
-
# Fetch AD/WINS based fqdn if any for Kerberos-based Auth
|
804
|
-
fqdn = locate_config_value(:fqdn) || fetch_server_fqdn(server.private_ip_address)
|
805
|
-
end
|
806
|
-
bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
|
807
|
-
bootstrap.config[:winrm_user] = locate_config_value(:winrm_user)
|
808
|
-
bootstrap.config[:winrm_password] = windows_password
|
809
|
-
bootstrap.config[:winrm_transport] = locate_config_value(:winrm_transport)
|
810
|
-
bootstrap.config[:kerberos_keytab_file] = locate_config_value(:kerberos_keytab_file)
|
811
|
-
bootstrap.config[:kerberos_realm] = locate_config_value(:kerberos_realm)
|
812
|
-
bootstrap.config[:kerberos_service] = locate_config_value(:kerberos_service)
|
813
|
-
bootstrap.config[:ca_trust_file] = locate_config_value(:ca_trust_file)
|
814
|
-
bootstrap.config[:winrm_port] = locate_config_value(:winrm_port)
|
815
|
-
bootstrap.config[:auth_timeout] = locate_config_value(:auth_timeout)
|
816
|
-
bootstrap.config[:winrm_ssl_verify_mode] = locate_config_value(:winrm_ssl_verify_mode)
|
817
|
-
elsif locate_config_value(:bootstrap_protocol) == "ssh"
|
818
|
-
bootstrap = Chef::Knife::BootstrapWindowsSsh.new
|
819
|
-
bootstrap.config[:ssh_user] = locate_config_value(:ssh_user)
|
820
|
-
bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
|
821
|
-
bootstrap.config[:ssh_port] = locate_config_value(:ssh_port)
|
822
|
-
bootstrap.config[:identity_file] = locate_config_value(:identity_file)
|
823
|
-
bootstrap.config[:no_host_key_verify] = locate_config_value(:no_host_key_verify)
|
824
|
-
bootstrap.config[:forward_agent] = locate_config_value(:forward_agent)
|
825
|
-
else
|
826
|
-
ui.error("Unsupported Bootstrapping Protocol. Supported : winrm, ssh")
|
827
|
-
exit 1
|
828
|
-
end
|
829
|
-
bootstrap.name_args = [fqdn]
|
830
|
-
bootstrap.config[:msi_url] = locate_config_value(:msi_url)
|
831
|
-
bootstrap.config[:install_as_service] = locate_config_value(:install_as_service)
|
832
|
-
bootstrap.config[:session_timeout] = locate_config_value(:session_timeout)
|
833
|
-
|
834
|
-
if locate_config_value(:chef_node_name)
|
835
|
-
bootstrap.config[:chef_node_name] = evaluate_node_name(locate_config_value(:chef_node_name))
|
836
|
-
else
|
837
|
-
bootstrap.config[:chef_node_name] = server.id
|
838
|
-
end
|
839
|
-
bootstrap_common_params(bootstrap)
|
840
|
-
end
|
841
|
-
|
842
|
-
def bootstrap_for_linux_node(server, ssh_host)
|
843
|
-
bootstrap = Chef::Knife::Bootstrap.new
|
844
|
-
bootstrap.name_args = [ssh_host]
|
845
|
-
bootstrap.config[:ssh_user] = config[:ssh_user]
|
846
|
-
bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
|
847
|
-
bootstrap.config[:ssh_port] = config[:ssh_port]
|
848
|
-
bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
|
849
|
-
bootstrap.config[:identity_file] = config[:identity_file]
|
850
|
-
|
851
|
-
if locate_config_value(:chef_node_name)
|
852
|
-
bootstrap.config[:chef_node_name] = evaluate_node_name(locate_config_value(:chef_node_name))
|
853
|
-
else
|
854
|
-
bootstrap.config[:chef_node_name] = server.id
|
855
|
-
end
|
856
|
-
bootstrap.config[:use_sudo] = true unless config[:ssh_user] == "root"
|
857
|
-
# may be needed for vpc_mode
|
858
|
-
bootstrap.config[:host_key_verify] = config[:host_key_verify]
|
859
|
-
bootstrap_common_params(bootstrap)
|
860
|
-
end
|
861
|
-
|
862
593
|
def vpc_mode?
|
863
594
|
# Amazon Virtual Private Cloud requires a subnet_id. If
|
864
595
|
# present, do a few things differently
|
865
|
-
!!
|
596
|
+
!!config_value(:subnet_id)
|
866
597
|
end
|
867
598
|
|
868
|
-
def
|
869
|
-
|
599
|
+
def validate_name_args!
|
600
|
+
# We don't know the name of our instance yet
|
870
601
|
end
|
871
602
|
|
872
|
-
def
|
603
|
+
def plugin_validate_options!
|
873
604
|
if Chef::Config[:knife].keys.include? :aws_ssh_key_id
|
874
605
|
Chef::Config[:knife][:ssh_key_name] = Chef::Config[:knife][:aws_ssh_key_id] if !Chef::Config[:knife][:ssh_key_name]
|
875
606
|
Chef::Config[:knife].delete(:aws_ssh_key_id)
|
876
607
|
ui.warn("Use of aws_ssh_key_id option in knife.rb/config.rb config is deprecated, use ssh_key_name option instead.")
|
877
608
|
end
|
878
609
|
|
879
|
-
|
610
|
+
validate_aws_config!([:image, :ssh_key_name, :aws_access_key_id, :aws_secret_access_key])
|
880
611
|
|
881
|
-
validate_nics! if
|
612
|
+
validate_nics! if config_value(:network_interfaces)
|
882
613
|
|
883
614
|
if ami.nil?
|
884
|
-
ui.error("The provided AMI value '#{
|
615
|
+
ui.error("The provided AMI value '#{config_value(:image)}' could not be found. Is this AMI availble in the provided region #{config_value(:region)}?")
|
885
616
|
exit 1
|
886
617
|
end
|
887
618
|
|
@@ -906,9 +637,9 @@ class Chef
|
|
906
637
|
end
|
907
638
|
|
908
639
|
if config[:associate_eip]
|
909
|
-
eips =
|
640
|
+
eips = ec2_connection.describe_addresses.addresses.collect { |addr| addr if addr.domain == eip_scope }.compact
|
910
641
|
|
911
|
-
unless eips.detect { |addr| addr.public_ip == config[:associate_eip] && addr.
|
642
|
+
unless eips.detect { |addr| addr.public_ip == config[:associate_eip] && addr.instance_id.nil? }
|
912
643
|
ui.error("Elastic IP requested is not available.")
|
913
644
|
exit 1
|
914
645
|
end
|
@@ -936,7 +667,7 @@ class Chef
|
|
936
667
|
end
|
937
668
|
|
938
669
|
# Validation for security_group_ids passed through knife.rb/config.rb. It will raise error if values are not provided in Array.
|
939
|
-
if
|
670
|
+
if config_value(:security_group_ids) && config_value(:security_group_ids).class == String
|
940
671
|
ui.error("Invalid value type for knife[:security_group_ids] in knife configuration file (i.e knife.rb/config.rb). Type should be array. e.g - knife[:security_group_ids] = ['sgroup1']")
|
941
672
|
exit 1
|
942
673
|
end
|
@@ -951,14 +682,14 @@ class Chef
|
|
951
682
|
exit 1
|
952
683
|
end
|
953
684
|
|
954
|
-
if
|
685
|
+
if config_value(:ebs_encrypted)
|
955
686
|
error_message = ""
|
956
687
|
errors = []
|
957
688
|
# validation for flavor and ebs_encrypted
|
958
|
-
if !
|
689
|
+
if !config_value(:flavor)
|
959
690
|
ui.error("--ebs-encrypted option requires valid flavor to be specified.")
|
960
691
|
exit 1
|
961
|
-
elsif
|
692
|
+
elsif config_value(:ebs_encrypted) && ! %w{m3.medium m3.large m3.xlarge m3.2xlarge m4.large m4.xlarge
|
962
693
|
m4.2xlarge m4.4xlarge m4.10xlarge m4.16xlarge t2.nano t2.micro t2.small
|
963
694
|
t2.medium t2.large t2.xlarge t2.2xlarge d2.xlarge d2.2xlarge d2.4xlarge
|
964
695
|
d2.8xlarge c4.large c4.xlarge c4.2xlarge c4.4xlarge c4.8xlarge c3.large
|
@@ -966,19 +697,19 @@ class Chef
|
|
966
697
|
r3.2xlarge r3.4xlarge r3.8xlarge r4.large r4.xlarge r4.2xlarge r4.4xlarge
|
967
698
|
r4.8xlarge r4.16xlarge x1.16xlarge x1.32xlarge i2.xlarge i2.2xlarge i2.4xlarge
|
968
699
|
i2.8xlarge i3.large i3.xlarge i3.2xlarge i3.4xlarge i3.8xlarge i3.16xlarge
|
969
|
-
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge}.include?(
|
970
|
-
ui.error("--ebs-encrypted option is not supported for #{
|
700
|
+
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge}.include?(config_value(:flavor))
|
701
|
+
ui.error("--ebs-encrypted option is not supported for #{config_value(:flavor)} flavor.")
|
971
702
|
exit 1
|
972
703
|
end
|
973
704
|
|
974
705
|
# validation for ebs_size and ebs_volume_type and ebs_encrypted
|
975
|
-
if !
|
706
|
+
if !config_value(:ebs_size)
|
976
707
|
errors << "--ebs-encrypted option requires valid --ebs-size to be specified."
|
977
|
-
elsif (
|
708
|
+
elsif (config_value(:ebs_volume_type) == "gp2") && ! config_value(:ebs_size).to_i.between?(1, 16384)
|
978
709
|
errors << "--ebs-size should be in between 1-16384 for 'gp2' ebs volume type."
|
979
|
-
elsif (
|
710
|
+
elsif (config_value(:ebs_volume_type) == "io1") && ! config_value(:ebs_size).to_i.between?(4, 16384)
|
980
711
|
errors << "--ebs-size should be in between 4-16384 for 'io1' ebs volume type."
|
981
|
-
elsif (
|
712
|
+
elsif (config_value(:ebs_volume_type) == "standard") && ! config_value(:ebs_size).to_i.between?(1, 1024)
|
982
713
|
errors << "--ebs-size should be in between 1-1024 for 'standard' ebs volume type."
|
983
714
|
end
|
984
715
|
|
@@ -988,23 +719,25 @@ class Chef
|
|
988
719
|
end
|
989
720
|
end
|
990
721
|
|
991
|
-
if
|
722
|
+
if config_value(:spot_price) && config_value(:disable_api_termination)
|
992
723
|
ui.error("spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances.")
|
993
724
|
exit 1
|
994
725
|
end
|
995
726
|
|
996
|
-
if
|
997
|
-
|
998
|
-
|
727
|
+
if config_value(:spot_price).nil? && config_value(:spot_wait_mode)
|
728
|
+
if !(config_value(:spot_wait_mode).casecmp("prompt") == 0)
|
729
|
+
ui.error("spot-wait-mode option requires that a spot-price option is set.")
|
730
|
+
exit 1
|
731
|
+
end
|
999
732
|
end
|
1000
733
|
|
1001
|
-
volume_tags =
|
734
|
+
volume_tags = config_value(:volume_tags)
|
1002
735
|
if !volume_tags.nil? && (volume_tags.length != volume_tags.to_s.count("="))
|
1003
736
|
ui.error("Volume Tags should be entered in a key = value pair")
|
1004
737
|
exit 1
|
1005
738
|
end
|
1006
739
|
|
1007
|
-
if
|
740
|
+
if winrm? && config_value(:connection_password).to_s.length > 14
|
1008
741
|
ui.warn("The password provided is longer than 14 characters. Computers with Windows prior to Windows 2000 will not be able to use this account. Do you want to continue this operation? (Y/N):")
|
1009
742
|
password_promt = STDIN.gets.chomp.upcase
|
1010
743
|
if password_promt == "N"
|
@@ -1016,17 +749,17 @@ class Chef
|
|
1016
749
|
end
|
1017
750
|
end
|
1018
751
|
|
1019
|
-
if
|
752
|
+
if config_value(:tag_node_in_chef)
|
1020
753
|
ui.warn("[DEPRECATED] --tag-node-in-chef option is deprecated. Use --chef-tag option instead.")
|
1021
754
|
end
|
1022
755
|
|
1023
|
-
if
|
756
|
+
if config_value(:tags)
|
1024
757
|
ui.warn("[DEPRECATED] --tags option is deprecated. Use --aws-tag option instead.")
|
1025
758
|
end
|
1026
759
|
end
|
1027
760
|
|
1028
761
|
def tags
|
1029
|
-
tags =
|
762
|
+
tags = config_value(:tags) || config_value(:aws_tag)
|
1030
763
|
if !tags.nil? && (tags.length != tags.to_s.count("="))
|
1031
764
|
ui.error("AWS Tags should be entered in a key = value pair")
|
1032
765
|
exit 1
|
@@ -1044,12 +777,12 @@ class Chef
|
|
1044
777
|
|
1045
778
|
def ssl_config_user_data
|
1046
779
|
user_related_commands = ""
|
1047
|
-
|
1048
|
-
if (
|
780
|
+
user = connection_user.split("\\")
|
781
|
+
if (user[0] == ".") || (user[0] == "") || (user.length == 1)
|
1049
782
|
user_related_commands = <<~EOH
|
1050
|
-
net user /add #{
|
1051
|
-
net localgroup Administrators /add #{
|
1052
|
-
|
783
|
+
net user /add #{connection_user.delete('.\\')} #{windows_password} #{@allow_long_password};
|
784
|
+
net localgroup Administrators /add #{connection_user.delete('.\\')};
|
785
|
+
EOH
|
1053
786
|
end
|
1054
787
|
<<~EOH
|
1055
788
|
#{user_related_commands}
|
@@ -1096,11 +829,11 @@ class Chef
|
|
1096
829
|
$create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
|
1097
830
|
iex $create_listener_cmd
|
1098
831
|
netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
|
1099
|
-
EOH
|
832
|
+
EOH
|
1100
833
|
end
|
1101
834
|
|
1102
835
|
def ssl_config_data_already_exist?
|
1103
|
-
File.read(
|
836
|
+
File.read(config_value(:aws_user_data)).gsub(/\\\\/, "\\").include? ssl_config_user_data.strip
|
1104
837
|
end
|
1105
838
|
|
1106
839
|
def process_user_data(script_lines)
|
@@ -1122,80 +855,99 @@ EOH
|
|
1122
855
|
script_lines
|
1123
856
|
end
|
1124
857
|
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
858
|
+
# base64-encoded text
|
859
|
+
def encode_data(text)
|
860
|
+
require "base64"
|
861
|
+
Base64.encode64(text)
|
862
|
+
end
|
863
|
+
|
864
|
+
def spot_instances_attributes
|
865
|
+
attributes = {
|
866
|
+
instance_count: 1,
|
867
|
+
launch_specification: server_attributes,
|
868
|
+
spot_price: config_value(:spot_price),
|
869
|
+
type: config_value(:spot_request_type),
|
1134
870
|
}
|
871
|
+
end
|
1135
872
|
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
873
|
+
def server_attributes
|
874
|
+
attributes = {
|
875
|
+
image_id: config_value(:image),
|
876
|
+
instance_type: config_value(:flavor),
|
877
|
+
groups: config[:security_groups],
|
878
|
+
key_name: config_value(:ssh_key_name),
|
879
|
+
max_count: 1,
|
880
|
+
min_count: 1,
|
881
|
+
placement: {
|
882
|
+
availability_zone: config_value(:availability_zone),
|
883
|
+
},
|
884
|
+
}
|
885
|
+
network_attrs = {}
|
886
|
+
if primary_eni = config_value(:primary_eni)
|
887
|
+
network_attrs[:network_interface_id] = primary_eni
|
888
|
+
network_attrs[:device_index] = 0
|
1143
889
|
else
|
1144
|
-
|
1145
|
-
|
890
|
+
attributes[:security_group_ids] = config_value(:security_group_ids)
|
891
|
+
network_attrs[:subnet_id] = config_value(:subnet_id) if vpc_mode?
|
892
|
+
end
|
893
|
+
|
894
|
+
if vpc_mode?
|
895
|
+
network_attrs[:groups] = attributes[:security_group_ids]
|
896
|
+
network_attrs[:private_ip_address] = config_value(:private_ip_address)
|
897
|
+
network_attrs[:associate_public_ip_address] = config_value(:associate_public_ip) if config[:associate_public_ip]
|
898
|
+
end
|
899
|
+
|
900
|
+
if network_attrs.length > 0
|
901
|
+
attributes[:network_interfaces] = [network_attrs]
|
1146
902
|
end
|
1147
903
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
server_def[:associate_public_ip] = locate_config_value(:associate_public_ip) if vpc_mode? && config[:associate_public_ip]
|
904
|
+
attributes[:placement][:group_name] = config_value(:placement_group)
|
905
|
+
attributes[:placement][:tenancy] = "dedicated" if vpc_mode? && config_value(:dedicated_instance)
|
906
|
+
attributes[:iam_instance_profile] = {}
|
907
|
+
attributes[:iam_instance_profile][:name] = config_value(:iam_instance_profile)
|
1153
908
|
|
1154
|
-
if
|
1155
|
-
if
|
909
|
+
if config_value(:winrm_ssl)
|
910
|
+
if config_value(:aws_user_data)
|
1156
911
|
begin
|
1157
|
-
user_data = File.readlines(
|
912
|
+
user_data = File.readlines(config_value(:aws_user_data))
|
1158
913
|
if config[:create_ssl_listener]
|
1159
914
|
user_data = process_user_data(user_data)
|
1160
915
|
end
|
1161
916
|
user_data = user_data.join
|
1162
|
-
|
917
|
+
attributes.merge!(user_data: encode_data(user_data))
|
1163
918
|
rescue
|
1164
|
-
ui.warn("Cannot read #{
|
919
|
+
ui.warn("Cannot read #{config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
|
1165
920
|
end
|
1166
921
|
else
|
1167
922
|
if config[:create_ssl_listener]
|
1168
|
-
|
923
|
+
attributes[:user_data] = encode_data("<powershell>\n" + ssl_config_user_data + "</powershell>\n")
|
1169
924
|
end
|
1170
925
|
end
|
1171
926
|
else
|
1172
|
-
if
|
927
|
+
if config_value(:aws_user_data)
|
1173
928
|
begin
|
1174
|
-
|
929
|
+
user_data = File.read(config_value(:aws_user_data))
|
930
|
+
attributes.merge!(user_data: encode_data(user_data))
|
1175
931
|
rescue
|
1176
|
-
ui.warn("Cannot read #{
|
932
|
+
ui.warn("Cannot read #{config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
|
1177
933
|
end
|
1178
934
|
end
|
1179
935
|
end
|
1180
936
|
|
1181
|
-
|
1182
|
-
server_def[:ebs_optimized] = "true"
|
1183
|
-
else
|
1184
|
-
server_def[:ebs_optimized] = "false"
|
1185
|
-
end
|
937
|
+
attributes[:ebs_optimized] = !!config_value(:ebs_optimized)
|
1186
938
|
|
1187
939
|
if ami.root_device_type == "ebs"
|
1188
|
-
if
|
1189
|
-
ami_map = ami.
|
940
|
+
if config_value(:ebs_encrypted)
|
941
|
+
ami_map = ami.block_device_mappings[1]
|
1190
942
|
else
|
1191
|
-
ami_map = ami.
|
943
|
+
ami_map = ami.block_device_mappings.first
|
1192
944
|
end
|
1193
945
|
|
1194
946
|
ebs_size = begin
|
1195
947
|
if config[:ebs_size]
|
1196
948
|
Integer(config[:ebs_size]).to_s
|
1197
949
|
else
|
1198
|
-
ami_map
|
950
|
+
ami_map.ebs.volume_size.to_s if ami_map.ebs.respond_to?(:volume_size)
|
1199
951
|
end
|
1200
952
|
rescue ArgumentError
|
1201
953
|
puts "--ebs-size must be an integer"
|
@@ -1205,13 +957,13 @@ EOH
|
|
1205
957
|
delete_term = if config[:ebs_no_delete_on_term]
|
1206
958
|
"false"
|
1207
959
|
else
|
1208
|
-
ami_map
|
960
|
+
ami_map.ebs.delete_on_termination if ami_map.ebs.respond_to?(:delete_on_termination)
|
1209
961
|
end
|
1210
962
|
iops_rate = begin
|
1211
963
|
if config[:ebs_provisioned_iops]
|
1212
964
|
Integer(config[:ebs_provisioned_iops]).to_s
|
1213
965
|
else
|
1214
|
-
ami_map
|
966
|
+
ami_map.ebs.iops.to_s if ami_map.ebs.respond_to?(:iops)
|
1215
967
|
end
|
1216
968
|
rescue ArgumentError
|
1217
969
|
puts "--provisioned-iops must be an integer"
|
@@ -1219,32 +971,69 @@ EOH
|
|
1219
971
|
exit 1
|
1220
972
|
end
|
1221
973
|
|
1222
|
-
|
974
|
+
attributes[:block_device_mappings] =
|
1223
975
|
[{
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
976
|
+
device_name: ami_map.device_name,
|
977
|
+
ebs: {
|
978
|
+
delete_on_termination: delete_term,
|
979
|
+
volume_size: ebs_size,
|
980
|
+
volume_type: config[:ebs_volume_type], # accepts standard, io1, gp2, sc1, st1
|
981
|
+
},
|
1228
982
|
}]
|
1229
|
-
|
1230
|
-
|
983
|
+
attributes[:block_device_mappings][0][:ebs][:iops] = iops_rate unless iops_rate.nil? || iops_rate.empty?
|
984
|
+
attributes[:block_device_mappings][0][:ebs][:encrypted] = true if config_value(:ebs_encrypted)
|
1231
985
|
end
|
1232
986
|
|
1233
|
-
|
1234
|
-
|
987
|
+
if config[:ephemeral] && config[:ephemeral].length > 0
|
988
|
+
ephemeral_blocks = []
|
989
|
+
config[:ephemeral].each_with_index do |device_name, i|
|
990
|
+
ephemeral_blocks << { virtual_name: "ephemeral#{i}", device_name: device_name }
|
991
|
+
end
|
992
|
+
attributes[:block_device_mappings] += ephemeral_blocks
|
1235
993
|
end
|
1236
994
|
|
1237
995
|
## cannot pass disable_api_termination option to the API when using spot instances ##
|
1238
|
-
|
996
|
+
attributes[:disable_api_termination] = config_value(:disable_api_termination) if config_value(:spot_price).nil?
|
997
|
+
|
998
|
+
attributes[:instance_initiated_shutdown_behavior] = config_value(:instance_initiated_shutdown_behavior)
|
999
|
+
attributes[:chef_tag] = config_value(:chef_tag)
|
1000
|
+
attributes
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
def create_ec2_instance(attributes)
|
1004
|
+
ec2_connection.run_instances(attributes)
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
def spot_instances_wait_until_ready(spot_request_id)
|
1008
|
+
ec2_connection.wait_until(
|
1009
|
+
:spot_instance_request_fulfilled,
|
1010
|
+
spot_instance_request_ids: [spot_request_id]
|
1011
|
+
).spot_instance_requests[0]
|
1012
|
+
rescue Aws::Waiters::Errors::WaiterFailed => error
|
1013
|
+
puts "failed waiting for spot request fulfill: #{error.message}"
|
1014
|
+
end
|
1239
1015
|
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1016
|
+
def instances_wait_until_ready(instance_id)
|
1017
|
+
ec2_connection.wait_until(:instance_running, instance_ids: [instance_id]) do |w|
|
1018
|
+
w.max_attempts = max_attempts
|
1019
|
+
end
|
1020
|
+
rescue Aws::Waiters::Errors::WaiterFailed => error
|
1021
|
+
puts "failed waiting for instance running: #{error.message}"
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
def max_attempts
|
1025
|
+
delay = 15 # Default Delay for waiter
|
1026
|
+
attempts = 40 # Default max attempts for waiter
|
1027
|
+
|
1028
|
+
if config_value(:aws_connection_timeout)
|
1029
|
+
attempts = (config_value(:aws_connection_timeout).to_f / delay).to_i
|
1030
|
+
end
|
1031
|
+
attempts
|
1243
1032
|
end
|
1244
1033
|
|
1245
1034
|
def wait_for_sshd(hostname)
|
1246
1035
|
ssh_gateway = get_ssh_gateway_for(hostname)
|
1247
|
-
ssh_gateway ? wait_for_tunnelled_sshd(ssh_gateway, hostname) : wait_for_direct_sshd(hostname,
|
1036
|
+
ssh_gateway ? wait_for_tunnelled_sshd(ssh_gateway, hostname) : wait_for_direct_sshd(hostname, connection_port)
|
1248
1037
|
end
|
1249
1038
|
|
1250
1039
|
def get_ssh_gateway_for(hostname)
|
@@ -1294,7 +1083,7 @@ EOH
|
|
1294
1083
|
def tunnel_test_ssh(ssh_gateway, hostname, &block)
|
1295
1084
|
status = false
|
1296
1085
|
gateway = configure_ssh_gateway(ssh_gateway)
|
1297
|
-
gateway.open(hostname,
|
1086
|
+
gateway.open(hostname, connection_port) do |local_tunnel_port|
|
1298
1087
|
status = tcp_test_ssh("localhost", local_tunnel_port, &block)
|
1299
1088
|
end
|
1300
1089
|
status
|
@@ -1322,7 +1111,7 @@ EOH
|
|
1322
1111
|
|
1323
1112
|
# Use the keys specificed on the command line if available (overrides SSH Config)
|
1324
1113
|
if config[:ssh_gateway_identity]
|
1325
|
-
gateway_keys = Array(
|
1114
|
+
gateway_keys = Array(config_value(:ssh_gateway_identity))
|
1326
1115
|
end
|
1327
1116
|
|
1328
1117
|
unless gateway_keys.nil?
|
@@ -1345,12 +1134,15 @@ EOH
|
|
1345
1134
|
end
|
1346
1135
|
end
|
1347
1136
|
|
1137
|
+
# @return [Boolean]
|
1348
1138
|
def subnet_public_ip_on_launch?
|
1349
|
-
|
1139
|
+
return false unless server.subnet_id
|
1140
|
+
subnet = fetch_subnet(server.subnet_id)
|
1141
|
+
subnet.map_public_ip_on_launch
|
1350
1142
|
end
|
1351
1143
|
|
1352
|
-
def
|
1353
|
-
unless @
|
1144
|
+
def connection_host
|
1145
|
+
unless @connection_host
|
1354
1146
|
if config[:server_connect_attribute]
|
1355
1147
|
connect_attribute = config[:server_connect_attribute]
|
1356
1148
|
server.send(config[:server_connect_attribute])
|
@@ -1358,52 +1150,74 @@ EOH
|
|
1358
1150
|
connect_attribute = "private_ip_address"
|
1359
1151
|
server.private_ip_address
|
1360
1152
|
else
|
1361
|
-
connect_attribute = server.
|
1153
|
+
connect_attribute = server.public_dns_name ? "public_dns_name" : "public_ip_address"
|
1362
1154
|
server.send(connect_attribute)
|
1363
1155
|
end
|
1364
|
-
@
|
1156
|
+
@connection_host = server.send(connect_attribute)
|
1365
1157
|
end
|
1366
1158
|
|
1367
|
-
puts "\nSSH Target Address: #{@
|
1368
|
-
@
|
1159
|
+
puts "\nSSH Target Address: #{@connection_host}(#{connect_attribute})"
|
1160
|
+
@connection_host
|
1369
1161
|
end
|
1370
1162
|
|
1371
1163
|
def create_tags(hashed_tags)
|
1164
|
+
request_tags = []
|
1372
1165
|
hashed_tags.each_pair do |key, val|
|
1373
|
-
|
1166
|
+
request_tags << { key: key, value: val }
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
if request_tags.length > 0
|
1170
|
+
ec2_connection.create_tags(tags: request_tags, resources: [server.id])
|
1374
1171
|
end
|
1375
1172
|
end
|
1376
1173
|
|
1377
|
-
def
|
1378
|
-
|
1379
|
-
|
1174
|
+
def create_volume_tags(hashed_volume_tags)
|
1175
|
+
request_tags = []
|
1176
|
+
hashed_volume_tags.each_pair do |key, val|
|
1177
|
+
request_tags << { key: key, value: val }
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
if request_tags.length > 0
|
1181
|
+
ec2_connection.create_tags(tags: request_tags, resources: [server.volume_id])
|
1182
|
+
end
|
1183
|
+
end
|
1184
|
+
|
1185
|
+
def associate_address(elastic_ip)
|
1186
|
+
ec2_connection.associate_address({
|
1187
|
+
allocation_id: elastic_ip.allocation_id,
|
1188
|
+
instance_id: server.id,
|
1189
|
+
public_ip: elastic_ip.public_ip,
|
1190
|
+
})
|
1380
1191
|
end
|
1381
1192
|
|
1382
1193
|
def validate_nics!
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1194
|
+
params = {}
|
1195
|
+
if vpc_mode?
|
1196
|
+
network_attrs = { name: "vpc_id", value: [vpc_id] }
|
1197
|
+
params["filters"] = [network_attrs]
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
interfaces = ec2_connection.describe_network_interfaces(params)
|
1201
|
+
valid_nic_ids = interfaces.network_interfaces.map(&:network_interface_id)
|
1202
|
+
invalid_nic_ids = config_value(:network_interfaces) - valid_nic_ids
|
1203
|
+
|
1388
1204
|
return true if invalid_nic_ids.empty?
|
1205
|
+
|
1389
1206
|
ui.error "The following network interfaces are invalid: " \
|
1390
1207
|
"#{invalid_nic_ids.join(', ')}"
|
1391
1208
|
exit 1
|
1392
1209
|
end
|
1393
1210
|
|
1394
1211
|
def vpc_id
|
1395
|
-
@vpc_id ||=
|
1396
|
-
connection.subnets.get(locate_config_value(:subnet_id)).vpc_id
|
1397
|
-
end
|
1212
|
+
@vpc_id ||= fetch_subnet(locate_config_value(:subnet_id)).vpc_id
|
1398
1213
|
end
|
1399
1214
|
|
1400
1215
|
def wait_for_nic_attachment
|
1401
1216
|
attached_nics_count = 0
|
1402
|
-
until attached_nics_count ==
|
1403
|
-
locate_config_value(:network_interfaces).count
|
1217
|
+
until attached_nics_count == config_value(:network_interfaces).count
|
1404
1218
|
attachment_nics =
|
1405
1219
|
locate_config_value(:network_interfaces).map do |nic_id|
|
1406
|
-
|
1220
|
+
fetch_network_interfaces(nic_id).attachment.status
|
1407
1221
|
end
|
1408
1222
|
attached_nics_count = attachment_nics.grep("attached").count
|
1409
1223
|
end
|
@@ -1412,41 +1226,23 @@ EOH
|
|
1412
1226
|
def attach_nics
|
1413
1227
|
attachments = []
|
1414
1228
|
config[:network_interfaces].each_with_index do |nic_id, index|
|
1415
|
-
attachments <<
|
1416
|
-
|
1417
|
-
|
1229
|
+
attachments << ec2_connection.attach_network_interface({
|
1230
|
+
device_index: index + 1,
|
1231
|
+
instance_id: server.id,
|
1232
|
+
network_interface_id: nic_id,
|
1233
|
+
})
|
1418
1234
|
end
|
1419
1235
|
wait_for_nic_attachment
|
1420
|
-
# rubocop:disable Style/RedundantReturn
|
1421
|
-
return attachments
|
1422
|
-
# rubocop:enable Style/RedundantReturn
|
1423
|
-
end
|
1424
1236
|
|
1425
|
-
|
1426
|
-
connection.attach_classic_link_vpc(server.id, vpc_id, security_group_ids)
|
1237
|
+
attachments
|
1427
1238
|
end
|
1428
1239
|
|
1429
|
-
def
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
# unchanged ssh_port and changed winrm_port, override ssh_port
|
1436
|
-
if locate_config_value(:ssh_port).eql?(options[:ssh_port][:default]) &&
|
1437
|
-
!locate_config_value(:winrm_port).eql?(options[:winrm_port][:default])
|
1438
|
-
config[:ssh_port] = locate_config_value(:winrm_port)
|
1439
|
-
end
|
1440
|
-
# unset ssh_password and set winrm_password, override ssh_password
|
1441
|
-
if locate_config_value(:ssh_password).nil? &&
|
1442
|
-
!locate_config_value(:winrm_password).nil?
|
1443
|
-
config[:ssh_password] = locate_config_value(:winrm_password)
|
1444
|
-
end
|
1445
|
-
# unset identity_file and set kerberos_keytab_file, override identity_file
|
1446
|
-
if locate_config_value(:identity_file).nil? &&
|
1447
|
-
!locate_config_value(:kerberos_keytab_file).nil?
|
1448
|
-
config[:identity_file] = locate_config_value(:kerberos_keytab_file)
|
1449
|
-
end
|
1240
|
+
def enable_classic_link(vpc_id, security_group_ids)
|
1241
|
+
ec2_connection.attach_classic_link_vpc({
|
1242
|
+
instance_id: server.id,
|
1243
|
+
groups: security_group_ids,
|
1244
|
+
vpc_id: vpc_id,
|
1245
|
+
})
|
1450
1246
|
end
|
1451
1247
|
|
1452
1248
|
def tcp_test_winrm(ip_addr, port)
|
@@ -1515,22 +1311,20 @@ EOH
|
|
1515
1311
|
|
1516
1312
|
def check_windows_password_available(server_id)
|
1517
1313
|
sleep 10
|
1518
|
-
response =
|
1519
|
-
|
1520
|
-
|
1521
|
-
end
|
1522
|
-
response.body["passwordData"]
|
1314
|
+
response = fetch_password_data(server_id)
|
1315
|
+
return false unless response.password_data
|
1316
|
+
true
|
1523
1317
|
end
|
1524
1318
|
|
1525
1319
|
def windows_password
|
1526
|
-
if not
|
1527
|
-
if
|
1528
|
-
if
|
1320
|
+
if not config_value(:connection_password)
|
1321
|
+
if config_value(:ssh_identity_file)
|
1322
|
+
if server
|
1529
1323
|
print "\n#{ui.color("Waiting for Windows Admin password to be available: ", :magenta)}"
|
1530
|
-
print(".") until check_windows_password_available(
|
1531
|
-
response =
|
1532
|
-
data = File.read(locate_config_value(:
|
1533
|
-
config[:
|
1324
|
+
print(".") until check_windows_password_available(server.id) { puts("done") }
|
1325
|
+
response = fetch_password_data(server.id)
|
1326
|
+
data = File.read(locate_config_value(:ssh_identity_file))
|
1327
|
+
config[:connection_password] = decrypt_admin_password(response.password_data, data)
|
1534
1328
|
else
|
1535
1329
|
print "\n#{ui.color("Fetchig instance details: \n", :magenta)}"
|
1536
1330
|
end
|
@@ -1539,30 +1333,111 @@ EOH
|
|
1539
1333
|
exit 1
|
1540
1334
|
end
|
1541
1335
|
else
|
1542
|
-
|
1336
|
+
config_value(:connection_password)
|
1543
1337
|
end
|
1544
1338
|
end
|
1545
1339
|
|
1546
|
-
def load_winrm_deps
|
1547
|
-
require "winrm"
|
1548
|
-
require "chef/knife/winrm"
|
1549
|
-
require "chef/knife/bootstrap_windows_winrm"
|
1550
|
-
require "chef/knife/bootstrap_windows_ssh"
|
1551
|
-
require "chef/knife/core/windows_bootstrap_context"
|
1552
|
-
end
|
1553
|
-
|
1554
1340
|
# Returns the name of node after evaluation of server id if %s is present.
|
1555
1341
|
# Eg: "Test-%s" will return "Test-i-12345" in case the instance id is i-12345
|
1556
1342
|
def evaluate_node_name(node_name)
|
1557
1343
|
node_name % server.id
|
1558
1344
|
end
|
1559
1345
|
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1346
|
+
# TODO: connection_protocol and connection_port used to choose winrm/ssh or 5985/22 based on the image chosen
|
1347
|
+
def connection_port
|
1348
|
+
port = config_value(:connection_port,
|
1349
|
+
knife_key_for_protocol(connection_protocol, :port))
|
1350
|
+
return port if port
|
1351
|
+
|
1352
|
+
assign_default_port
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
# Set default port 5986 if winrm_ssl return true otherwise set it to 5985
|
1356
|
+
# Set default port 22 for ssh protocol
|
1357
|
+
# @return [Integer]
|
1358
|
+
def assign_default_port
|
1359
|
+
if winrm?
|
1360
|
+
config_value(:winrm_ssl) ? 5986 : 5985
|
1361
|
+
else
|
1362
|
+
22
|
1563
1363
|
end
|
1564
1364
|
end
|
1565
1365
|
|
1366
|
+
# url values override CLI flags, if you provide both
|
1367
|
+
# we'll use the one that you gave in the URL.
|
1368
|
+
def connection_protocol
|
1369
|
+
return @connection_protocol if @connection_protocol
|
1370
|
+
|
1371
|
+
default_protocol = is_image_windows? ? "winrm" : "ssh"
|
1372
|
+
|
1373
|
+
from_url = host_descriptor =~ /^(.*):\/\// ? $1 : nil
|
1374
|
+
from_cli = config[:connection_protocol]
|
1375
|
+
from_knife = Chef::Config[:knife][:connection_protocol]
|
1376
|
+
@connection_protocol = from_url || from_cli || from_knife || default_protocol
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
def connection_user
|
1380
|
+
@connection_user ||= config_value(:connection_user, knife_key_for_protocol(connection_protocol, :user))
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
def server_name
|
1384
|
+
return nil unless server
|
1385
|
+
server.public_dns_name || server.private_dns_name || server.private_ip_address
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
alias host_descriptor server_name
|
1389
|
+
|
1390
|
+
# If we don't specify a security group or security group id, Fog will
|
1391
|
+
# pick the appropriate default one. In case of a VPC we don't know the
|
1392
|
+
# default security group id at this point unless we look it up, hence
|
1393
|
+
# 'default' is printed if no id was specified.
|
1394
|
+
def printed_security_groups
|
1395
|
+
if server.groups
|
1396
|
+
server.groups.join(", ")
|
1397
|
+
else
|
1398
|
+
"default"
|
1399
|
+
end
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
def printed_security_group_ids
|
1403
|
+
if server.security_group_ids
|
1404
|
+
server.security_group_ids.join(", ")
|
1405
|
+
else
|
1406
|
+
"default"
|
1407
|
+
end
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def hashed_volume_tags
|
1411
|
+
hvt = {}
|
1412
|
+
volume_tags = config_value(:volume_tags)
|
1413
|
+
volume_tags.map { |t| key, val = t.split("="); hvt[key] = val } unless volume_tags.nil?
|
1414
|
+
|
1415
|
+
hvt
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
def printed_volume_tags
|
1419
|
+
hashed_volume_tags.map { |tag, val| "#{tag}: #{val}" }.join(", ")
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
def hashed_tags
|
1423
|
+
ht = {}
|
1424
|
+
tags.map { |t| key, val = t.split("="); ht[key] = val } unless tags.nil?
|
1425
|
+
|
1426
|
+
# Always set the Name tag
|
1427
|
+
unless ht.keys.include? "Name"
|
1428
|
+
if config_value(:chef_node_name)
|
1429
|
+
ht["Name"] = evaluate_node_name(config_value(:chef_node_name))
|
1430
|
+
else
|
1431
|
+
ht["Name"] = server.id
|
1432
|
+
end
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
ht
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
def printed_aws_tags
|
1439
|
+
hashed_tags.map { |tag, val| "#{tag}: #{val}" }.join(", ")
|
1440
|
+
end
|
1566
1441
|
end
|
1567
1442
|
end
|
1568
1443
|
end
|