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.
@@ -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/winrm_base"
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
- include Knife::WinrmBase
31
- include Knife::BootstrapWindowsBase
29
+
32
30
  deps do
33
31
  require "tempfile"
34
32
  require "uri"
35
- require "chef/knife/bootstrap"
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 ENI1,ENI2",
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 run
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 = connection.addresses.detect { |addr| addr if addr.public_ip == requested_elastic_ip }
309
+ elastic_ip = ec2_connection.describe_addresses.addresses.detect { |addr| addr if addr.public_ip == requested_elastic_ip }
476
310
 
477
- if locate_config_value(:spot_price)
478
- server_def = create_server_def
479
- server_def[:groups] = server_def[:security_group_ids] if vpc_mode?
480
- spot_request = connection.spot_requests.create(server_def)
481
- msg_pair("Spot Request ID", spot_request.id)
482
- msg_pair("Spot Request Type", spot_request.request_type)
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.wait_for do
505
- @spinner ||= %w{| / - \\}
506
- print "\b" + @spinner.rotate!.first
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
- @server = connection.servers.create(create_server_def)
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
- hashed_tags = {}
523
- tags.map { |t| key, val = t.split("="); hashed_tags[key] = val } unless tags.nil?
524
-
525
- # Always set the Name tag
526
- unless hashed_tags.keys.include? "Name"
527
- if locate_config_value(:chef_node_name)
528
- hashed_tags["Name"] = evaluate_node_name(locate_config_value(:chef_node_name))
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
- printed_security_group_ids = "default"
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", @server.key_name)
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
- associate_eip(elastic_ip) if config[:associate_eip]
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 Fog::Compute::AWS::NotFound, Fog::Errors::Error
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", @server.subnet_id)
590
- msg_pair("Tenancy", @server.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", @server.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", @server.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", @server.dns_name)
599
- msg_pair("Public IP Address", @server.public_ip_address)
600
- msg_pair("Private DNS Name", @server.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", @server.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
- protocol = locate_config_value(:bootstrap_protocol)
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(ssh_connect_host, locate_config_value(:winrm_port)) do
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(ssh_connect_host, config[:ssh_port]) do
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(ssh_connect_host)
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", @server.id)
639
- msg_pair("Flavor", @server.flavor_id)
640
- msg_pair("Placement Group", @server.placement_group) unless @server.placement_group.nil?
641
- msg_pair("Image", @server.image_id)
642
- msg_pair("Region", connection.instance_variable_get(:@region))
643
- msg_pair("Availability Zone", @server.availability_zone)
644
- msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (@server.groups.nil? && @server.security_group_ids)
645
- msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || @server.security_group_ids
646
- msg_pair("IAM Profile", locate_config_value(:iam_instance_profile)) if locate_config_value(:iam_instance_profile)
647
- msg_pair("Primary ENI", locate_config_value(:primary_eni)) if locate_config_value(: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", locate_config_value(:chef_tag)) if locate_config_value(:chef_tag)
650
- msg_pair("SSH Key", @server.key_name)
651
- msg_pair("Root Device Type", @server.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 @server.root_device_type == "ebs"
654
- device_map = @server.block_device_mapping.first
655
- msg_pair("Root Volume ID", device_map["volumeId"])
656
- msg_pair("Root Device Name", device_map["deviceName"])
657
- msg_pair("Root Device Delete on Terminate", device_map["deleteOnTermination"])
658
- msg_pair("Standard or Provisioned IOPS", device_map["volumeType"])
659
- msg_pair("IOPS rate", device_map["iops"])
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
- @server.block_device_mapping.each do |device_map|
664
- msg_pair("Device Name", device_map["deviceName"])
665
- msg_pair("Volume ID", device_map["volumeId"])
666
- msg_pair("Delete on Terminate", device_map["deleteOnTermination"].to_s)
667
- msg_pair("Standard or Provisioned IOPS", device_map["volumeType"])
668
- msg_pair("IOPS rate", device_map["iops"])
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
- if ami.block_device_mapping.first["volumeSize"].to_i < config[:ebs_size].to_i
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
- "#{ami.block_device_mapping.first['volumeSize']}GB.\n" +
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", @server.ebs_optimized.to_s)
501
+ msg_pair("EBS is Optimized", server.ebs_optimized.to_s)
685
502
  end
686
503
  if vpc_mode?
687
- msg_pair("Subnet ID", @server.subnet_id)
688
- msg_pair("Tenancy", @server.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", @server.dns_name)
507
+ msg_pair("Public DNS Name", server.public_dns_name)
691
508
  end
692
509
  else
693
- msg_pair("Public DNS Name", @server.dns_name)
694
- msg_pair("Public IP Address", @server.public_ip_address)
695
- msg_pair("Private DNS Name", @server.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", @server.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 locate_config_value(:s3_secret)
746
- Chef::Knife::S3Source.fetch(locate_config_value(:s3_secret))
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(bootstrap)
751
- bootstrap.config[:run_list] = config[:run_list]
752
- bootstrap.config[:policy_group] = locate_config_value(:policy_group)
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 locate_config_value(:s3_secret)
765
- bootstrap.config[:secret] = s3_secret || locate_config_value(:secret)
766
- bootstrap.config[:secret_file] = locate_config_value(:secret_file)
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 locate_config_value(:chef_tag)
784
- bootstrap.config[:tags] = locate_config_value(:chef_tag)
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
- !!locate_config_value(:subnet_id)
596
+ !!config_value(:subnet_id)
866
597
  end
867
598
 
868
- def ami
869
- @ami ||= connection.images.get(locate_config_value(:image))
599
+ def validate_name_args!
600
+ # We don't know the name of our instance yet
870
601
  end
871
602
 
872
- def validate!
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
- super([:image, :ssh_key_name, :aws_access_key_id, :aws_secret_access_key])
610
+ validate_aws_config!([:image, :ssh_key_name, :aws_access_key_id, :aws_secret_access_key])
880
611
 
881
- validate_nics! if locate_config_value(:network_interfaces)
612
+ validate_nics! if config_value(:network_interfaces)
882
613
 
883
614
  if ami.nil?
884
- ui.error("The provided AMI value '#{locate_config_value(:image)}' could not be found. Is this AMI availble in the provided region #{locate_config_value(:region)}?")
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 = connection.addresses.collect { |addr| addr if addr.domain == eip_scope }.compact
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.server_id.nil? }
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 locate_config_value(:security_group_ids) && locate_config_value(:security_group_ids).class == String
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 locate_config_value(:ebs_encrypted)
685
+ if config_value(:ebs_encrypted)
955
686
  error_message = ""
956
687
  errors = []
957
688
  # validation for flavor and ebs_encrypted
958
- if !locate_config_value(:flavor)
689
+ if !config_value(:flavor)
959
690
  ui.error("--ebs-encrypted option requires valid flavor to be specified.")
960
691
  exit 1
961
- elsif locate_config_value(:ebs_encrypted) && ! %w{m3.medium m3.large m3.xlarge m3.2xlarge m4.large m4.xlarge
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?(locate_config_value(:flavor))
970
- ui.error("--ebs-encrypted option is not supported for #{locate_config_value(:flavor)} flavor.")
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 !locate_config_value(:ebs_size)
706
+ if !config_value(:ebs_size)
976
707
  errors << "--ebs-encrypted option requires valid --ebs-size to be specified."
977
- elsif (locate_config_value(:ebs_volume_type) == "gp2") && ! locate_config_value(:ebs_size).to_i.between?(1, 16384)
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 (locate_config_value(:ebs_volume_type) == "io1") && ! locate_config_value(:ebs_size).to_i.between?(4, 16384)
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 (locate_config_value(:ebs_volume_type) == "standard") && ! locate_config_value(:ebs_size).to_i.between?(1, 1024)
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 locate_config_value(:spot_price) && locate_config_value(:disable_api_termination)
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 locate_config_value(:spot_price).nil? && !locate_config_value(:spot_wait_mode).casecmp("prompt").zero?
997
- ui.error("spot-wait-mode option requires that a spot-price option is set.")
998
- exit 1
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 = locate_config_value(: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 locate_config_value(:winrm_password).to_s.length > 14
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 locate_config_value(:tag_node_in_chef)
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 locate_config_value(:tags)
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 = locate_config_value(:tags) || locate_config_value(:aws_tag)
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
- winrm_user = locate_config_value(:winrm_user).split("\\")
1048
- if (winrm_user[0] == ".") || (winrm_user[0] == "") || (winrm_user.length == 1)
780
+ user = connection_user.split("\\")
781
+ if (user[0] == ".") || (user[0] == "") || (user.length == 1)
1049
782
  user_related_commands = <<~EOH
1050
- net user /add #{locate_config_value(:winrm_user).delete('.\\')} #{windows_password} #{@allow_long_password};
1051
- net localgroup Administrators /add #{locate_config_value(:winrm_user).delete('.\\')};
1052
- EOH
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(locate_config_value(:aws_user_data)).gsub(/\\\\/, "\\").include? ssl_config_user_data.strip
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
- def create_server_def
1126
- server_def = {
1127
- image_id: locate_config_value(:image),
1128
- groups: config[:security_groups],
1129
- flavor_id: locate_config_value(:flavor),
1130
- key_name: locate_config_value(:ssh_key_name),
1131
- availability_zone: locate_config_value(:availability_zone),
1132
- price: locate_config_value(:spot_price),
1133
- request_type: locate_config_value(:spot_request_type),
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
- if primary_eni = locate_config_value(:primary_eni)
1137
- server_def[:network_interfaces] = [
1138
- {
1139
- NetworkInterfaceId: primary_eni,
1140
- DeviceIndex: "0",
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
- server_def[:security_group_ids] = locate_config_value(:security_group_ids)
1145
- server_def[:subnet_id] = locate_config_value(:subnet_id) if vpc_mode?
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
- server_def[:private_ip_address] = locate_config_value(:private_ip_address) if vpc_mode?
1149
- server_def[:placement_group] = locate_config_value(:placement_group)
1150
- server_def[:iam_instance_profile_name] = locate_config_value(:iam_instance_profile)
1151
- server_def[:tenancy] = "dedicated" if vpc_mode? && locate_config_value(:dedicated_instance)
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 locate_config_value(:winrm_transport) == "ssl"
1155
- if locate_config_value(:aws_user_data)
909
+ if config_value(:winrm_ssl)
910
+ if config_value(:aws_user_data)
1156
911
  begin
1157
- user_data = File.readlines(locate_config_value(:aws_user_data))
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
- server_def.merge!(user_data: user_data)
917
+ attributes.merge!(user_data: encode_data(user_data))
1163
918
  rescue
1164
- ui.warn("Cannot read #{locate_config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
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
- server_def[:user_data] = "<powershell>\n" + ssl_config_user_data + "</powershell>\n"
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 locate_config_value(:aws_user_data)
927
+ if config_value(:aws_user_data)
1173
928
  begin
1174
- server_def.merge!(user_data: File.read(locate_config_value(:aws_user_data)))
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 #{locate_config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
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
- if config[:ebs_optimized]
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 locate_config_value(:ebs_encrypted)
1189
- ami_map = ami.block_device_mapping[1]
940
+ if config_value(:ebs_encrypted)
941
+ ami_map = ami.block_device_mappings[1]
1190
942
  else
1191
- ami_map = ami.block_device_mapping.first
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["volumeSize"].to_s
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["deleteOnTermination"]
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["iops"].to_s
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
- server_def[:block_device_mapping] =
974
+ attributes[:block_device_mappings] =
1223
975
  [{
1224
- "DeviceName" => ami_map["deviceName"],
1225
- "Ebs.VolumeSize" => ebs_size,
1226
- "Ebs.DeleteOnTermination" => delete_term,
1227
- "Ebs.VolumeType" => config[:ebs_volume_type],
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
- server_def[:block_device_mapping].first["Ebs.Iops"] = iops_rate unless iops_rate.empty?
1230
- server_def[:block_device_mapping].first["Ebs.Encrypted"] = true if locate_config_value(:ebs_encrypted)
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
- (config[:ephemeral] || []).each_with_index do |device_name, i|
1234
- server_def[:block_device_mapping] = (server_def[:block_device_mapping] || []) << { "VirtualName" => "ephemeral#{i}", "DeviceName" => device_name }
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
- server_def[:disable_api_termination] = locate_config_value(:disable_api_termination) if locate_config_value(:spot_price).nil?
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
- server_def[:instance_initiated_shutdown_behavior] = locate_config_value(:instance_initiated_shutdown_behavior)
1241
- server_def[:chef_tag] = locate_config_value(:chef_tag)
1242
- server_def
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, config[:ssh_port])
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, config[:ssh_port]) do |local_tunnel_port|
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(locate_config_value(:ssh_gateway_identity))
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
- connection.subnets.get(server.subnet_id).map_public_ip_on_launch
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 ssh_connect_host
1353
- unless @ssh_connect_host
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.dns_name ? "dns_name" : "public_ip_address"
1153
+ connect_attribute = server.public_dns_name ? "public_dns_name" : "public_ip_address"
1362
1154
  server.send(connect_attribute)
1363
1155
  end
1364
- @ssh_connect_host = server.send(connect_attribute)
1156
+ @connection_host = server.send(connect_attribute)
1365
1157
  end
1366
1158
 
1367
- puts "\nSSH Target Address: #{@ssh_connect_host}(#{connect_attribute})"
1368
- @ssh_connect_host
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
- connection.tags.create key: key, value: val, resource_id: @server.id
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 associate_eip(elastic_ip)
1378
- connection.associate_address(server.id, elastic_ip.public_ip, nil, elastic_ip.allocation_id)
1379
- @server.wait_for(locate_config_value(:aws_connection_timeout)) { public_ip_address == elastic_ip.public_ip }
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
- valid_nic_ids = connection.network_interfaces.all(
1384
- vpc_mode? ? { "vpc-id" => vpc_id } : {}
1385
- ).map(&:network_interface_id)
1386
- invalid_nic_ids =
1387
- locate_config_value(:network_interfaces) - valid_nic_ids
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 ||= begin
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
- connection.network_interfaces.get(nic_id).attachment["status"]
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 << connection.attach_network_interface(nic_id,
1416
- server.id,
1417
- index + 1).body
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
- def enable_classic_link(vpc_id, security_group_ids)
1426
- connection.attach_classic_link_vpc(server.id, vpc_id, security_group_ids)
1237
+ attachments
1427
1238
  end
1428
1239
 
1429
- def ssh_override_winrm
1430
- # unchanged ssh_user and changed winrm_user, override ssh_user
1431
- if locate_config_value(:ssh_user).eql?(options[:ssh_user][:default]) &&
1432
- !locate_config_value(:winrm_user).eql?(options[:winrm_user][:default])
1433
- config[:ssh_user] = locate_config_value(:winrm_user)
1434
- end
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 = connection.get_password_data(server_id)
1519
- if not response.body["passwordData"]
1520
- return false
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 locate_config_value(:winrm_password)
1527
- if locate_config_value(:identity_file)
1528
- if @server
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(@server.id) { puts("done") }
1531
- response = connection.get_password_data(@server.id)
1532
- data = File.read(locate_config_value(:identity_file))
1533
- config[:winrm_password] = decrypt_admin_password(response.body["passwordData"], data)
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
- locate_config_value(:winrm_password)
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
- def create_volume_tags(hashed_volume_tags)
1561
- hashed_volume_tags.each_pair do |key, val|
1562
- connection.tags.create key: key, value: val, resource_id: @server.block_device_mapping.first["volumeId"]
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