knife-ec2 1.0.32 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/knife/ec2_ami_list.rb +8 -8
- data/lib/chef/knife/ec2_flavor_list.rb +1 -1
- data/lib/chef/knife/ec2_server_create.rb +148 -159
- data/lib/chef/knife/ec2_server_list.rb +2 -2
- data/lib/chef/knife/helpers/ec2_base.rb +34 -45
- data/lib/chef/knife/helpers/s3_source.rb +5 -5
- data/lib/knife-ec2/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16530eadac768b8b35d935346fe20b291ff40623b302b2c050c5b63e8c38879f
|
4
|
+
data.tar.gz: 49d24390d1c3e6ba4bcfe330628bf1b1debd8bf4bd38725b1892eb8c066a624d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26a987b8e84c65929f8ad6bdaab50258320a7b58747a689c61e4d294f156ad612338cf57a1fd34a6a33cd1c510d3812faa061a1ae978315c258343093c6ea08d
|
7
|
+
data.tar.gz: 8e7e4e7e3cc6c7181555ab0b412f7560b6f976554c8671c9586daf7832d6937a9af51b42997a8f6844fb7b05d21ae2b36c831bbabb5d1f078c8d152763d3f63e
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Piyush Awasthi (<piyush.awasthi@msystechnologies.com>)
|
3
|
-
# Copyright:: Copyright (c)
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -27,7 +27,7 @@ class Chef
|
|
27
27
|
# By default owner is aws-marketplace but you can specify following owner with the help of -o or --owner
|
28
28
|
# * self => Displays the list of AMIs created by the user
|
29
29
|
# * aws-marketplace => Displays all AMIs form trusted vendors like Ubuntu, Microsoft, SAP, Zend as well as many open source offering
|
30
|
-
# *
|
30
|
+
# * microsoft => Displays only Microsoft vendor AMIs
|
31
31
|
#
|
32
32
|
# == Platform
|
33
33
|
# By default all platform AMI's will display but you can filter your response
|
@@ -95,8 +95,8 @@ class Chef
|
|
95
95
|
all_data = {}
|
96
96
|
ec2_connection.describe_images(image_params).images.each do |v|
|
97
97
|
v_data = {}
|
98
|
-
if
|
99
|
-
next unless v.description.downcase.include?(
|
98
|
+
if config[:search]
|
99
|
+
next unless v.description.downcase.include?(config[:search].downcase)
|
100
100
|
end
|
101
101
|
|
102
102
|
%w{image_id platform description architecture}.each do |id|
|
@@ -112,16 +112,16 @@ class Chef
|
|
112
112
|
|
113
113
|
def image_params
|
114
114
|
params = {}
|
115
|
-
params["owners"] = [
|
115
|
+
params["owners"] = [config[:owner].to_s]
|
116
116
|
|
117
117
|
filters = []
|
118
|
-
if
|
118
|
+
if config[:platform]
|
119
119
|
filters << { name: "platform",
|
120
|
-
values: [
|
120
|
+
values: [config[:platform]] }
|
121
121
|
end
|
122
122
|
|
123
123
|
# TODO: Need to find substring to match in the description
|
124
|
-
# filters << { description:
|
124
|
+
# filters << { description: config[:search] } if config[:search]
|
125
125
|
|
126
126
|
if filters.length > 0
|
127
127
|
params["filters"] = filters
|
@@ -27,7 +27,7 @@ class Chef
|
|
27
27
|
banner "knife ec2 flavor list (options) [DEPRECATED]"
|
28
28
|
|
29
29
|
def run
|
30
|
-
ui.error("knife ec2 flavor list has been deprecated as this functionality is not provided by the AWS API the previous
|
30
|
+
ui.error("knife ec2 flavor list has been deprecated as this functionality is not provided by the AWS API the previous implementation relied upon hardcoded values that were often incorrect. For an up to date list of instance types see https://www.ec2instances.info/")
|
31
31
|
exit 1
|
32
32
|
end
|
33
33
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Adam Jacob (<adam@chef.io>)
|
3
3
|
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
4
|
-
# Copyright:: Copyright (c)
|
4
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -28,9 +28,9 @@ class Chef
|
|
28
28
|
include Knife::Ec2Base
|
29
29
|
|
30
30
|
deps do
|
31
|
-
require "tempfile"
|
32
|
-
require "uri"
|
33
|
-
require "net/ssh"
|
31
|
+
require "tempfile" unless defined?(Tempfile)
|
32
|
+
require "uri" unless defined?(URI)
|
33
|
+
require "net/ssh" unless defined?(Net::SSH)
|
34
34
|
require "net/ssh/gateway"
|
35
35
|
Chef::Knife::Bootstrap.load_deps
|
36
36
|
end
|
@@ -43,14 +43,12 @@ class Chef
|
|
43
43
|
option :flavor,
|
44
44
|
short: "-f FLAVOR",
|
45
45
|
long: "--flavor FLAVOR",
|
46
|
-
description: "The flavor of server (m1.small, m1.medium, etc)"
|
47
|
-
proc: Proc.new { |f| Chef::Config[:knife][:flavor] = f }
|
46
|
+
description: "The flavor of server (m1.small, m1.medium, etc)"
|
48
47
|
|
49
48
|
option :image,
|
50
49
|
short: "-I IMAGE",
|
51
50
|
long: "--image IMAGE",
|
52
|
-
description: "The AMI for the server"
|
53
|
-
proc: Proc.new { |i| Chef::Config[:knife][:image] = i }
|
51
|
+
description: "The AMI for the server"
|
54
52
|
|
55
53
|
option :iam_instance_profile,
|
56
54
|
long: "--iam-profile NAME",
|
@@ -62,14 +60,14 @@ class Chef
|
|
62
60
|
description: "The security groups for this server; not allowed when using VPC",
|
63
61
|
proc: Proc.new { |groups| groups.split(",") }
|
64
62
|
|
65
|
-
option :
|
63
|
+
option :security_group_ids,
|
66
64
|
short: "-g SECURITY_GROUP_ID",
|
67
65
|
long: "--security-group-id ID",
|
68
66
|
description: "The security group id for this server; required when using VPC. Use the --security-group-id option multiple times when specifying multiple groups for e.g. -g sg-e985168d -g sg-e7f06383 -g sg-ec1b7e88.",
|
69
|
-
proc: Proc.new { |security_group_id|
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
proc: Proc.new { |security_group_id, accumulator|
|
68
|
+
accumulator ||= []
|
69
|
+
accumulator.push(security_group_id)
|
70
|
+
accumulator
|
73
71
|
}
|
74
72
|
|
75
73
|
option :associate_eip,
|
@@ -82,8 +80,7 @@ class Chef
|
|
82
80
|
|
83
81
|
option :placement_group,
|
84
82
|
long: "--placement-group PLACEMENT_GROUP",
|
85
|
-
description: "The placement group to place a cluster compute instance"
|
86
|
-
proc: Proc.new { |pg| Chef::Config[:knife][:placement_group] = pg }
|
83
|
+
description: "The placement group to place a cluster compute instance"
|
87
84
|
|
88
85
|
option :primary_eni,
|
89
86
|
long: "--primary-eni ENI_ID",
|
@@ -92,14 +89,12 @@ class Chef
|
|
92
89
|
option :availability_zone,
|
93
90
|
short: "-Z ZONE",
|
94
91
|
long: "--availability-zone ZONE",
|
95
|
-
description: "The Availability Zone"
|
96
|
-
proc: Proc.new { |key| Chef::Config[:knife][:availability_zone] = key }
|
92
|
+
description: "The Availability Zone"
|
97
93
|
|
98
94
|
option :ssh_key_name,
|
99
95
|
short: "-S KEY",
|
100
96
|
long: "--ssh-key KEY",
|
101
|
-
description: "The AWS SSH key id"
|
102
|
-
proc: Proc.new { |key| Chef::Config[:knife][:ssh_key_name] = key }
|
97
|
+
description: "The AWS SSH key id"
|
103
98
|
|
104
99
|
option :ebs_size,
|
105
100
|
long: "--ebs-size SIZE",
|
@@ -115,40 +110,33 @@ class Chef
|
|
115
110
|
|
116
111
|
option :secret,
|
117
112
|
long: "--secret ",
|
118
|
-
description: "The secret key to use to encrypt data bag item values"
|
119
|
-
proc: lambda { |s| Chef::Config[:knife][:secret] = s }
|
113
|
+
description: "The secret key to use to encrypt data bag item values"
|
120
114
|
|
121
115
|
option :secret_file,
|
122
116
|
long: "--secret-file SECRET_FILE",
|
123
|
-
description: "A file containing the secret key to use to encrypt data bag item values"
|
124
|
-
proc: lambda { |sf| Chef::Config[:knife][:secret_file] = sf }
|
117
|
+
description: "A file containing the secret key to use to encrypt data bag item values"
|
125
118
|
|
126
119
|
option :s3_secret,
|
127
120
|
long: "--s3-secret S3_SECRET_URL",
|
128
|
-
description: "S3 URL (e.g. s3://bucket/file) for the encrypted_data_bag_secret_file"
|
129
|
-
proc: lambda { |url| Chef::Config[:knife][:s3_secret] = url }
|
121
|
+
description: "S3 URL (e.g. s3://bucket/file) for the encrypted_data_bag_secret_file"
|
130
122
|
|
131
123
|
option :subnet_id,
|
132
124
|
long: "--subnet SUBNET-ID",
|
133
|
-
description: "create node in this Virtual Private Cloud Subnet ID (implies VPC mode)"
|
134
|
-
proc: Proc.new { |key| Chef::Config[:knife][:subnet_id] = key }
|
125
|
+
description: "create node in this Virtual Private Cloud Subnet ID (implies VPC mode)"
|
135
126
|
|
136
127
|
option :private_ip_address,
|
137
128
|
long: "--private-ip-address IP-ADDRESS",
|
138
|
-
description: "allows to specify the private IP address of the instance in VPC mode"
|
139
|
-
proc: Proc.new { |ip| Chef::Config[:knife][:private_ip_address] = ip }
|
129
|
+
description: "allows to specify the private IP address of the instance in VPC mode"
|
140
130
|
|
141
131
|
option :fqdn,
|
142
132
|
long: "--fqdn FQDN",
|
143
133
|
description: "Pre-defined FQDN. This is used for Kerberos Authentication purpose only",
|
144
|
-
proc: Proc.new { |key| Chef::Config[:knife][:fqdn] = key },
|
145
134
|
default: nil
|
146
135
|
|
147
136
|
option :aws_user_data,
|
148
137
|
long: "--user-data USER_DATA_FILE",
|
149
138
|
short: "-u USER_DATA_FILE",
|
150
139
|
description: "The EC2 User Data file to provision the instance with",
|
151
|
-
proc: Proc.new { |m| Chef::Config[:knife][:aws_user_data] = m },
|
152
140
|
default: nil
|
153
141
|
|
154
142
|
option :ephemeral,
|
@@ -172,19 +160,16 @@ class Chef
|
|
172
160
|
option :ebs_volume_type,
|
173
161
|
long: "--ebs-volume-type TYPE",
|
174
162
|
description: "Possible values are standard (magnetic) | io1 | gp2 | sc1 | st1. Default is gp2",
|
175
|
-
proc: Proc.new { |key| Chef::Config[:knife][:ebs_volume_type] = key },
|
176
163
|
default: "gp2"
|
177
164
|
|
178
165
|
option :ebs_provisioned_iops,
|
179
166
|
long: "--provisioned-iops IOPS",
|
180
167
|
description: "IOPS rate, only used when ebs volume type is 'io1'",
|
181
|
-
proc: Proc.new { |key| Chef::Config[:knife][:provisioned_iops] = key },
|
182
168
|
default: nil
|
183
169
|
|
184
170
|
option :validation_key_url,
|
185
171
|
long: "--validation-key-url URL",
|
186
|
-
description: "Path to the validation key"
|
187
|
-
proc: proc { |m| Chef::Config[:validation_key_url] = m }
|
172
|
+
description: "Path to the validation key"
|
188
173
|
|
189
174
|
option :ebs_encrypted,
|
190
175
|
long: "--ebs-encrypted",
|
@@ -213,7 +198,7 @@ class Chef
|
|
213
198
|
option :aws_connection_timeout,
|
214
199
|
long: "--aws-connection-timeout MINUTES",
|
215
200
|
description: "The maximum time in minutes to wait to for aws connection. Default is 10 min",
|
216
|
-
proc: proc { |t| t = t.to_i * 60
|
201
|
+
proc: proc { |t| t = t.to_i * 60 },
|
217
202
|
default: 600
|
218
203
|
|
219
204
|
option :create_ssl_listener,
|
@@ -261,19 +246,19 @@ class Chef
|
|
261
246
|
option :chef_tag,
|
262
247
|
long: "--chef-tag CHEF_TAG",
|
263
248
|
description: "Use to tag the node in chef server; Provide --chef-tag option multiple times when specifying multiple tags e.g. --chef-tag tag1 --chef-tag tag2.",
|
264
|
-
proc: Proc.new { |chef_tag|
|
265
|
-
|
266
|
-
|
267
|
-
|
249
|
+
proc: Proc.new { |chef_tag, accumulator|
|
250
|
+
accumulator ||= []
|
251
|
+
accumulator.push(chef_tag)
|
252
|
+
accumulator
|
268
253
|
}
|
269
254
|
|
270
255
|
option :aws_tag,
|
271
256
|
long: "--aws-tag AWS_TAG",
|
272
257
|
description: "AWS tag for this server; Use the --aws-tag option multiple times when specifying multiple tags e.g. --aws-tag key1=value1 --aws-tag key2=value2.",
|
273
|
-
proc: Proc.new { |aws_tag|
|
274
|
-
|
275
|
-
|
276
|
-
|
258
|
+
proc: Proc.new { |aws_tag, accumulator|
|
259
|
+
accumulator ||= []
|
260
|
+
accumulator.push(aws_tag)
|
261
|
+
accumulator
|
277
262
|
}
|
278
263
|
|
279
264
|
option :cpu_credits,
|
@@ -287,7 +272,7 @@ class Chef
|
|
287
272
|
# For VPC EIP assignment we need the allocation ID so fetch full EIP details
|
288
273
|
elastic_ip = ec2_connection.describe_addresses.addresses.detect { |addr| addr if addr.public_ip == requested_elastic_ip }
|
289
274
|
|
290
|
-
if
|
275
|
+
if config[:spot_price]
|
291
276
|
server_def = spot_instances_attributes
|
292
277
|
spot_request = ec2_connection.request_spot_instances(server_def)
|
293
278
|
msg_pair("Spot Request ID", spot_request.spot_instance_request_id)
|
@@ -340,7 +325,7 @@ class Chef
|
|
340
325
|
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (server.groups && server.security_groups_ids)
|
341
326
|
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || server.security_groups_ids
|
342
327
|
|
343
|
-
msg_pair("IAM Profile",
|
328
|
+
msg_pair("IAM Profile", config[:iam_instance_profile])
|
344
329
|
|
345
330
|
msg_pair("AWS Tags", printed_aws_tags)
|
346
331
|
msg_pair("Volume Tags", printed_volume_tags)
|
@@ -352,7 +337,7 @@ class Chef
|
|
352
337
|
# occasionally 'ready?' isn't, so retry a couple times if needed.
|
353
338
|
tries = 6
|
354
339
|
begin
|
355
|
-
disable_source_dest_check if vpc_mode? &&
|
340
|
+
disable_source_dest_check if vpc_mode? && config[:disable_source_dest_check]
|
356
341
|
|
357
342
|
create_tags(hashed_tags) unless hashed_tags.empty?
|
358
343
|
create_volume_tags(hashed_volume_tags) unless hashed_volume_tags.empty?
|
@@ -387,7 +372,7 @@ class Chef
|
|
387
372
|
end
|
388
373
|
msg_pair("Private IP Address", server.private_ip_address)
|
389
374
|
|
390
|
-
if
|
375
|
+
if config[:validation_key_url]
|
391
376
|
download_validation_key(validation_key_path)
|
392
377
|
Chef::Config[:validation_key] = validation_key_path
|
393
378
|
end
|
@@ -415,16 +400,16 @@ class Chef
|
|
415
400
|
|
416
401
|
fqdn = connection_host
|
417
402
|
if winrm?
|
418
|
-
if
|
403
|
+
if config[:kerberos_realm]
|
419
404
|
# Fetch AD/WINS based fqdn if any for Kerberos-based Auth
|
420
|
-
fqdn =
|
405
|
+
fqdn = config[:fqdn] || fetch_server_fqdn(server.private_ip_address)
|
421
406
|
end
|
422
407
|
config[:connection_password] = windows_password
|
423
408
|
end
|
424
409
|
@name_args = [fqdn]
|
425
410
|
|
426
|
-
if
|
427
|
-
config[:chef_node_name] = evaluate_node_name(
|
411
|
+
if config[:chef_node_name]
|
412
|
+
config[:chef_node_name] = evaluate_node_name(config[:chef_node_name])
|
428
413
|
else
|
429
414
|
config[:chef_node_name] = server.id
|
430
415
|
end
|
@@ -441,10 +426,10 @@ class Chef
|
|
441
426
|
msg_pair("Availability Zone", server.availability_zone)
|
442
427
|
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (server.groups.nil? && server.security_group_ids)
|
443
428
|
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || server.security_group_ids
|
444
|
-
msg_pair("IAM Profile",
|
445
|
-
msg_pair("Primary ENI",
|
429
|
+
msg_pair("IAM Profile", config[:iam_instance_profile]) if config[:iam_instance_profile]
|
430
|
+
msg_pair("Primary ENI", config[:primary_eni]) if config[:primary_eni]
|
446
431
|
msg_pair("AWS Tags", printed_aws_tags)
|
447
|
-
msg_pair("Chef Tags",
|
432
|
+
msg_pair("Chef Tags", config[:tags]) if config[:tags].any?
|
448
433
|
msg_pair("SSH Key", server.key_name)
|
449
434
|
msg_pair("Root Device Type", server.root_device_type)
|
450
435
|
msg_pair("Root Volume Tags", printed_volume_tags)
|
@@ -509,8 +494,8 @@ class Chef
|
|
509
494
|
|
510
495
|
def validation_key_path
|
511
496
|
@validation_key_path ||= begin
|
512
|
-
if URI(
|
513
|
-
URI(
|
497
|
+
if URI(config[:validation_key_url]).scheme == "file"
|
498
|
+
URI(config[:validation_key_url]).path
|
514
499
|
else
|
515
500
|
validation_key_tmpfile.path
|
516
501
|
end
|
@@ -524,10 +509,10 @@ class Chef
|
|
524
509
|
|
525
510
|
def download_validation_key(tempfile)
|
526
511
|
Chef::Log.debug "Downloading validation key " \
|
527
|
-
"<#{
|
512
|
+
"<#{config[:validation_key_url]}> to file " \
|
528
513
|
"<#{tempfile}>"
|
529
514
|
|
530
|
-
case URI(
|
515
|
+
case URI(config[:validation_key_url]).scheme
|
531
516
|
when "s3"
|
532
517
|
File.open(tempfile, "w") { |f| f.write(s3_validation_key) }
|
533
518
|
end
|
@@ -535,31 +520,31 @@ class Chef
|
|
535
520
|
|
536
521
|
def s3_validation_key
|
537
522
|
@s3_validation_key ||= begin
|
538
|
-
Chef::Knife::S3Source.fetch(
|
523
|
+
Chef::Knife::S3Source.fetch(config[:validation_key_url])
|
539
524
|
end
|
540
525
|
end
|
541
526
|
|
542
527
|
def s3_secret
|
543
528
|
@s3_secret ||= begin
|
544
|
-
return false unless
|
529
|
+
return false unless config[:s3_secret]
|
545
530
|
|
546
|
-
Chef::Knife::S3Source.fetch(
|
531
|
+
Chef::Knife::S3Source.fetch(config[:s3_secret])
|
547
532
|
end
|
548
533
|
end
|
549
534
|
|
550
535
|
def bootstrap_common_params
|
551
|
-
config[:encrypted_data_bag_secret] = s3_secret ||
|
552
|
-
config[:encrypted_data_bag_secret_file] =
|
536
|
+
config[:encrypted_data_bag_secret] = s3_secret || config[:secret]
|
537
|
+
config[:encrypted_data_bag_secret_file] = config[:secret_file]
|
553
538
|
# retrieving the secret from S3 is unique to knife-ec2, so we need to set "command line secret" to the value fetched from S3
|
554
539
|
# When linux vm is spawned, the chef's secret option proc function sets the value "command line secret" and this value is used by
|
555
540
|
# chef's code to check if secret option is passed through command line or not
|
556
|
-
|
557
|
-
config[:secret] = s3_secret ||
|
541
|
+
config[:cl_secret] = s3_secret if config[:s3_secret]
|
542
|
+
config[:secret] = s3_secret || config[:secret]
|
558
543
|
|
559
544
|
# Modify global configuration state to ensure hint gets set by
|
560
545
|
# knife-bootstrap
|
561
|
-
|
562
|
-
|
546
|
+
config[:hints] ||= {}
|
547
|
+
config[:hints]["ec2"] ||= {}
|
563
548
|
end
|
564
549
|
|
565
550
|
def fetch_server_fqdn(ip_addr)
|
@@ -570,7 +555,7 @@ class Chef
|
|
570
555
|
def vpc_mode?
|
571
556
|
# Amazon Virtual Private Cloud requires a subnet_id. If
|
572
557
|
# present, do a few things differently
|
573
|
-
!!
|
558
|
+
!!config[:subnet_id]
|
574
559
|
end
|
575
560
|
|
576
561
|
# When options connection_protocol and connection_port are not provided
|
@@ -586,17 +571,17 @@ class Chef
|
|
586
571
|
end
|
587
572
|
|
588
573
|
def plugin_validate_options!
|
589
|
-
if
|
590
|
-
|
591
|
-
|
574
|
+
if config.key?(:aws_ssh_key_id)
|
575
|
+
config[:ssh_key_name] = config[:aws_ssh_key_id] unless config[:ssh_key_name]
|
576
|
+
config.delete(:aws_ssh_key_id)
|
592
577
|
ui.warn("Use of aws_ssh_key_id option in knife.rb/config.rb config is deprecated, use ssh_key_name option instead.")
|
593
578
|
end
|
594
|
-
create_key_pair unless
|
579
|
+
create_key_pair unless config[:ssh_key_name]
|
595
580
|
|
596
|
-
validate_nics! if
|
581
|
+
validate_nics! if config[:network_interfaces]
|
597
582
|
|
598
583
|
if ami.nil?
|
599
|
-
ui.error("The provided AMI value '#{
|
584
|
+
ui.error("The provided AMI value '#{config[:image]}' could not be found. Is this AMI availble in the provided region #{config[:region]}?")
|
600
585
|
exit 1
|
601
586
|
end
|
602
587
|
|
@@ -623,7 +608,7 @@ class Chef
|
|
623
608
|
if config[:associate_eip]
|
624
609
|
eips = ec2_connection.describe_addresses.addresses.collect { |addr| addr if addr.domain == eip_scope }.compact
|
625
610
|
|
626
|
-
unless eips.detect { |addr| addr.public_ip == config[:associate_eip] && addr.instance_id.nil? }
|
611
|
+
unless eips.detect { |addr| addr.public_ip == config[:associate_eip] && (addr.instance_id.nil? || addr.instance_id.empty?) }
|
627
612
|
ui.error("Elastic IP requested is not available.")
|
628
613
|
exit 1
|
629
614
|
end
|
@@ -651,7 +636,7 @@ class Chef
|
|
651
636
|
end
|
652
637
|
|
653
638
|
# Validation for security_group_ids passed through knife.rb/config.rb. It will raise error if values are not provided in Array.
|
654
|
-
if
|
639
|
+
if config[:security_group_ids] && config[:security_group_ids].class == String
|
655
640
|
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']")
|
656
641
|
exit 1
|
657
642
|
end
|
@@ -666,14 +651,14 @@ class Chef
|
|
666
651
|
exit 1
|
667
652
|
end
|
668
653
|
|
669
|
-
if
|
654
|
+
if config[:ebs_encrypted]
|
670
655
|
error_message = ""
|
671
656
|
errors = []
|
672
657
|
# validation for flavor and ebs_encrypted
|
673
|
-
if !
|
658
|
+
if !config[:flavor]
|
674
659
|
ui.error("--ebs-encrypted option requires valid flavor to be specified.")
|
675
660
|
exit 1
|
676
|
-
elsif
|
661
|
+
elsif config[:ebs_encrypted] && ! %w{m3.medium m3.large m3.xlarge m3.2xlarge m4.large m4.xlarge
|
677
662
|
m4.2xlarge m4.4xlarge m4.10xlarge m4.16xlarge t2.nano t2.micro t2.small
|
678
663
|
t2.medium t2.large t2.xlarge t2.2xlarge d2.xlarge d2.2xlarge d2.4xlarge
|
679
664
|
d2.8xlarge c4.large c4.xlarge c4.2xlarge c4.4xlarge c4.8xlarge c3.large
|
@@ -681,19 +666,19 @@ class Chef
|
|
681
666
|
r3.2xlarge r3.4xlarge r3.8xlarge r4.large r4.xlarge r4.2xlarge r4.4xlarge
|
682
667
|
r4.8xlarge r4.16xlarge x1.16xlarge x1.32xlarge i2.xlarge i2.2xlarge i2.4xlarge
|
683
668
|
i2.8xlarge i3.large i3.xlarge i3.2xlarge i3.4xlarge i3.8xlarge i3.16xlarge
|
684
|
-
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge}.include?(
|
685
|
-
ui.error("--ebs-encrypted option is not supported for #{
|
669
|
+
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge}.include?(config[:flavor])
|
670
|
+
ui.error("--ebs-encrypted option is not supported for #{config[:flavor]} flavor.")
|
686
671
|
exit 1
|
687
672
|
end
|
688
673
|
|
689
674
|
# validation for ebs_size and ebs_volume_type and ebs_encrypted
|
690
|
-
if !
|
675
|
+
if !config[:ebs_size]
|
691
676
|
errors << "--ebs-encrypted option requires valid --ebs-size to be specified."
|
692
|
-
elsif (
|
677
|
+
elsif (config[:ebs_volume_type] == "gp2") && ! config[:ebs_size].to_i.between?(1, 16384)
|
693
678
|
errors << "--ebs-size should be in between 1-16384 for 'gp2' ebs volume type."
|
694
|
-
elsif (
|
679
|
+
elsif (config[:ebs_volume_type] == "io1") && ! config[:ebs_size].to_i.between?(4, 16384)
|
695
680
|
errors << "--ebs-size should be in between 4-16384 for 'io1' ebs volume type."
|
696
|
-
elsif (
|
681
|
+
elsif (config[:ebs_volume_type] == "standard") && ! config[:ebs_size].to_i.between?(1, 1024)
|
697
682
|
errors << "--ebs-size should be in between 1-1024 for 'standard' ebs volume type."
|
698
683
|
end
|
699
684
|
|
@@ -703,19 +688,19 @@ class Chef
|
|
703
688
|
end
|
704
689
|
end
|
705
690
|
|
706
|
-
if
|
691
|
+
if config[:spot_price] && config[:disable_api_termination]
|
707
692
|
ui.error("spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances.")
|
708
693
|
exit 1
|
709
694
|
end
|
710
695
|
|
711
|
-
if
|
712
|
-
unless
|
696
|
+
if config[:spot_price].nil? && config[:spot_wait_mode]
|
697
|
+
unless config[:spot_wait_mode].casecmp("prompt") == 0
|
713
698
|
ui.error("spot-wait-mode option requires that a spot-price option is set.")
|
714
699
|
exit 1
|
715
700
|
end
|
716
701
|
end
|
717
702
|
|
718
|
-
volume_tags =
|
703
|
+
volume_tags = config[:volume_tags]
|
719
704
|
if !volume_tags.nil? && (volume_tags.length != volume_tags.to_s.count("="))
|
720
705
|
ui.error("Volume Tags should be entered in a key = value pair")
|
721
706
|
exit 1
|
@@ -723,27 +708,27 @@ class Chef
|
|
723
708
|
|
724
709
|
if winrm?
|
725
710
|
reg = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,40}$/
|
726
|
-
unless
|
711
|
+
unless config[:connection_password]&.match?(reg)
|
727
712
|
ui.error("Complexity requirements are not met. Password length should be 8-40 characters and include: 1 uppercase, 1 lowercase, 1 digit, and 1 special character")
|
728
713
|
exit 1
|
729
714
|
end
|
730
715
|
end
|
731
716
|
|
732
|
-
if
|
717
|
+
if config[:chef_tag]
|
733
718
|
# If --chef-tag is provided then it will be set in chef as single value e.g. --chef-tag "myTag"
|
734
719
|
# --tags has been removed from knife-ec2, now it's available in core
|
735
|
-
config[:tags] +=
|
720
|
+
config[:tags] += config[:chef_tag]
|
736
721
|
ui.warn("[DEPRECATED] --chef-tag option is deprecated and will be removed in future release. Use --tags TAGS option instead.")
|
737
722
|
end
|
738
723
|
|
739
|
-
if
|
724
|
+
if config[:cpu_credits] && !config[:flavor]
|
740
725
|
ui.error("Instance type should be specified and should be any of T2/T3 type.")
|
741
726
|
exit 1
|
742
727
|
end
|
743
728
|
end
|
744
729
|
|
745
730
|
def parse_aws_tags
|
746
|
-
tags =
|
731
|
+
tags = config[:aws_tag]
|
747
732
|
if !tags.nil? && (tags.length != tags.to_s.count("="))
|
748
733
|
ui.error("AWS Tags should be entered in a key = value pair")
|
749
734
|
exit 1
|
@@ -817,7 +802,7 @@ class Chef
|
|
817
802
|
end
|
818
803
|
|
819
804
|
def ssl_config_data_already_exist?
|
820
|
-
File.read(
|
805
|
+
File.read(config[:aws_user_data]).gsub(/\\\\/, "\\").include? ssl_config_user_data.strip
|
821
806
|
end
|
822
807
|
|
823
808
|
def process_user_data(script_lines)
|
@@ -841,7 +826,7 @@ class Chef
|
|
841
826
|
|
842
827
|
# base64-encoded text
|
843
828
|
def encode_data(text)
|
844
|
-
require "base64"
|
829
|
+
require "base64" unless defined?(Base64)
|
845
830
|
Base64.encode64(text)
|
846
831
|
end
|
847
832
|
|
@@ -849,59 +834,60 @@ class Chef
|
|
849
834
|
attributes = {
|
850
835
|
instance_count: 1,
|
851
836
|
launch_specification: server_attributes,
|
852
|
-
spot_price:
|
853
|
-
type:
|
837
|
+
spot_price: config[:spot_price],
|
838
|
+
type: config[:spot_request_type],
|
854
839
|
}
|
855
840
|
end
|
856
841
|
|
857
842
|
def server_attributes
|
858
843
|
attributes = {
|
859
|
-
image_id:
|
860
|
-
instance_type:
|
861
|
-
|
862
|
-
key_name: config_value(:ssh_key_name),
|
844
|
+
image_id: config[:image],
|
845
|
+
instance_type: config[:flavor],
|
846
|
+
key_name: config[:ssh_key_name],
|
863
847
|
max_count: 1,
|
864
848
|
min_count: 1,
|
865
849
|
placement: {
|
866
|
-
availability_zone:
|
850
|
+
availability_zone: config[:availability_zone],
|
867
851
|
},
|
868
852
|
}
|
869
853
|
|
870
854
|
network_attrs = {}
|
871
|
-
if !!
|
872
|
-
network_attrs[:network_interface_id] =
|
855
|
+
if !!config[:primary_eni]
|
856
|
+
network_attrs[:network_interface_id] = config[:primary_eni]
|
873
857
|
elsif vpc_mode?
|
874
|
-
network_attrs[:subnet_id] =
|
858
|
+
network_attrs[:subnet_id] = config[:subnet_id]
|
875
859
|
end
|
876
860
|
|
877
861
|
if vpc_mode?
|
878
|
-
network_attrs[:groups] =
|
879
|
-
network_attrs[:private_ip_address] =
|
880
|
-
network_attrs[:associate_public_ip_address] =
|
862
|
+
network_attrs[:groups] = config[:security_group_ids] if !!config[:security_group_ids]
|
863
|
+
network_attrs[:private_ip_address] = config[:private_ip_address]
|
864
|
+
network_attrs[:associate_public_ip_address] = config[:associate_public_ip]
|
865
|
+
else
|
866
|
+
attributes[:security_groups] = config[:security_groups]
|
881
867
|
end
|
882
868
|
|
883
869
|
if network_attrs.length > 0
|
884
870
|
network_attrs[:device_index] = 0
|
885
871
|
attributes[:network_interfaces] = [network_attrs]
|
886
872
|
else
|
887
|
-
attributes[:security_group_ids] =
|
873
|
+
attributes[:security_group_ids] = config[:security_group_ids]
|
888
874
|
end
|
889
875
|
|
890
|
-
attributes[:placement][:group_name] =
|
891
|
-
attributes[:placement][:tenancy] = "dedicated" if vpc_mode? &&
|
876
|
+
attributes[:placement][:group_name] = config[:placement_group]
|
877
|
+
attributes[:placement][:tenancy] = "dedicated" if vpc_mode? && config[:dedicated_instance]
|
892
878
|
attributes[:iam_instance_profile] = {}
|
893
|
-
attributes[:iam_instance_profile][:name] =
|
894
|
-
if
|
895
|
-
if
|
879
|
+
attributes[:iam_instance_profile][:name] = config[:iam_instance_profile]
|
880
|
+
if config[:winrm_ssl]
|
881
|
+
if config[:aws_user_data]
|
896
882
|
begin
|
897
|
-
user_data = File.readlines(
|
883
|
+
user_data = File.readlines(config[:aws_user_data])
|
898
884
|
if config[:create_ssl_listener]
|
899
885
|
user_data = process_user_data(user_data)
|
900
886
|
end
|
901
887
|
user_data = user_data.join
|
902
888
|
attributes.merge!(user_data: encode_data(user_data))
|
903
889
|
rescue
|
904
|
-
ui.warn("Cannot read #{
|
890
|
+
ui.warn("Cannot read #{config[:aws_user_data]}: #{$!.inspect}. Ignoring option.")
|
905
891
|
end
|
906
892
|
else
|
907
893
|
if config[:create_ssl_listener]
|
@@ -909,19 +895,19 @@ class Chef
|
|
909
895
|
end
|
910
896
|
end
|
911
897
|
else
|
912
|
-
if
|
898
|
+
if config[:aws_user_data]
|
913
899
|
begin
|
914
|
-
user_data = File.read(
|
900
|
+
user_data = File.read(config[:aws_user_data])
|
915
901
|
attributes.merge!(user_data: encode_data(user_data))
|
916
902
|
rescue
|
917
|
-
ui.warn("Cannot read #{
|
903
|
+
ui.warn("Cannot read #{config[:aws_user_data]}: #{$!.inspect}. Ignoring option.")
|
918
904
|
end
|
919
905
|
end
|
920
906
|
end
|
921
|
-
attributes[:ebs_optimized] = !!
|
907
|
+
attributes[:ebs_optimized] = !!config[:ebs_optimized]
|
922
908
|
|
923
909
|
if ami.root_device_type == "ebs"
|
924
|
-
if
|
910
|
+
if config[:ebs_encrypted]
|
925
911
|
ami_map = ami.block_device_mappings[1]
|
926
912
|
else
|
927
913
|
ami_map = ami.block_device_mappings.first
|
@@ -965,7 +951,7 @@ class Chef
|
|
965
951
|
},
|
966
952
|
}]
|
967
953
|
attributes[:block_device_mappings][0][:ebs][:iops] = iops_rate unless iops_rate.nil? || iops_rate.empty?
|
968
|
-
attributes[:block_device_mappings][0][:ebs][:encrypted] = true if
|
954
|
+
attributes[:block_device_mappings][0][:ebs][:encrypted] = true if config[:ebs_encrypted]
|
969
955
|
end
|
970
956
|
|
971
957
|
if config[:ephemeral] && config[:ephemeral].length > 0
|
@@ -977,9 +963,9 @@ class Chef
|
|
977
963
|
end
|
978
964
|
|
979
965
|
## cannot pass disable_api_termination option to the API when using spot instances ##
|
980
|
-
attributes[:disable_api_termination] =
|
966
|
+
attributes[:disable_api_termination] = config[:disable_api_termination] if config[:spot_price].nil?
|
981
967
|
|
982
|
-
attributes[:instance_initiated_shutdown_behavior] =
|
968
|
+
attributes[:instance_initiated_shutdown_behavior] = config[:instance_initiated_shutdown_behavior]
|
983
969
|
|
984
970
|
if config[:cpu_credits]
|
985
971
|
attributes[:credit_specification] =
|
@@ -1015,8 +1001,8 @@ class Chef
|
|
1015
1001
|
delay = 15 # Default Delay for waiter
|
1016
1002
|
attempts = 40 # Default max attempts for waiter
|
1017
1003
|
|
1018
|
-
if
|
1019
|
-
attempts = (
|
1004
|
+
if config[:aws_connection_timeout]
|
1005
|
+
attempts = (config[:aws_connection_timeout].to_f / delay).to_i
|
1020
1006
|
end
|
1021
1007
|
attempts
|
1022
1008
|
end
|
@@ -1101,7 +1087,7 @@ class Chef
|
|
1101
1087
|
|
1102
1088
|
# Use the keys specificed on the command line if available (overrides SSH Config)
|
1103
1089
|
if config[:ssh_gateway_identity]
|
1104
|
-
gateway_keys = Array(
|
1090
|
+
gateway_keys = Array(config[:ssh_gateway_identity])
|
1105
1091
|
end
|
1106
1092
|
|
1107
1093
|
unless gateway_keys.nil?
|
@@ -1193,16 +1179,23 @@ class Chef
|
|
1193
1179
|
file_path = File.join(Config.config_dir, "#{key_pair.key_name}.pem")
|
1194
1180
|
file = File.open(file_path, "w+") { |f| f << key_pair.key_material }
|
1195
1181
|
|
1196
|
-
|
1197
|
-
|
1182
|
+
config[:ssh_key_name] = key_pair.key_name
|
1183
|
+
config[:ssh_identity_file] = file.path
|
1198
1184
|
puts "\nGenerated keypair file: #{file.path}"
|
1199
1185
|
end
|
1200
1186
|
|
1201
1187
|
def associate_address(elastic_ip)
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1188
|
+
if vpc_mode?
|
1189
|
+
ec2_connection.associate_address({
|
1190
|
+
allocation_id: elastic_ip.allocation_id,
|
1191
|
+
instance_id: server.id,
|
1192
|
+
})
|
1193
|
+
else
|
1194
|
+
ec2_connection.associate_address({
|
1195
|
+
public_ip: elastic_ip.public_ip,
|
1196
|
+
instance_id: server.id,
|
1197
|
+
})
|
1198
|
+
end
|
1206
1199
|
end
|
1207
1200
|
|
1208
1201
|
def validate_nics!
|
@@ -1214,7 +1207,7 @@ class Chef
|
|
1214
1207
|
|
1215
1208
|
interfaces = ec2_connection.describe_network_interfaces(params)
|
1216
1209
|
valid_nic_ids = interfaces.network_interfaces.map(&:network_interface_id)
|
1217
|
-
invalid_nic_ids =
|
1210
|
+
invalid_nic_ids = config[:network_interfaces] - valid_nic_ids
|
1218
1211
|
|
1219
1212
|
return true if invalid_nic_ids.empty?
|
1220
1213
|
|
@@ -1224,14 +1217,14 @@ class Chef
|
|
1224
1217
|
end
|
1225
1218
|
|
1226
1219
|
def vpc_id
|
1227
|
-
@vpc_id ||= fetch_subnet(
|
1220
|
+
@vpc_id ||= fetch_subnet(config[:subnet_id]).vpc_id
|
1228
1221
|
end
|
1229
1222
|
|
1230
1223
|
def wait_for_nic_attachment
|
1231
1224
|
attached_nics_count = 0
|
1232
|
-
until attached_nics_count ==
|
1225
|
+
until attached_nics_count == config[:network_interfaces].count
|
1233
1226
|
attachment_nics =
|
1234
|
-
|
1227
|
+
config[:network_interfaces].map do |nic_id|
|
1235
1228
|
fetch_network_interfaces(nic_id).attachment.status
|
1236
1229
|
end
|
1237
1230
|
attached_nics_count = attachment_nics.grep("attached").count
|
@@ -1328,12 +1321,11 @@ class Chef
|
|
1328
1321
|
end
|
1329
1322
|
|
1330
1323
|
def decrypt_admin_password(encoded_password, key)
|
1331
|
-
require "base64"
|
1332
|
-
require "openssl"
|
1324
|
+
require "base64" unless defined?(Base64)
|
1325
|
+
require "openssl" unless defined?(OpenSSL)
|
1333
1326
|
private_key = OpenSSL::PKey::RSA.new(key)
|
1334
1327
|
encrypted_password = Base64.decode64(encoded_password)
|
1335
|
-
|
1336
|
-
password
|
1328
|
+
private_key.private_decrypt(encrypted_password)
|
1337
1329
|
end
|
1338
1330
|
|
1339
1331
|
def check_windows_password_available(server_id)
|
@@ -1345,23 +1337,23 @@ class Chef
|
|
1345
1337
|
end
|
1346
1338
|
|
1347
1339
|
def windows_password
|
1348
|
-
if not
|
1349
|
-
if
|
1340
|
+
if not config[:connection_password]
|
1341
|
+
if config[:ssh_identity_file]
|
1350
1342
|
if server
|
1351
1343
|
print "\n#{ui.color("Waiting for Windows Admin password to be available: ", :magenta)}"
|
1352
1344
|
print(".") until check_windows_password_available(server.id) { puts("done") }
|
1353
1345
|
response = fetch_password_data(server.id)
|
1354
|
-
data = File.read(
|
1346
|
+
data = File.read(config[:ssh_identity_file])
|
1355
1347
|
config[:connection_password] = decrypt_admin_password(response.password_data, data)
|
1356
1348
|
else
|
1357
|
-
print "\n#{ui.color("
|
1349
|
+
print "\n#{ui.color("Fetching instance details: \n", :magenta)}"
|
1358
1350
|
end
|
1359
1351
|
else
|
1360
1352
|
ui.error("Cannot find SSH Identity file, required to fetch dynamically generated password")
|
1361
1353
|
exit 1
|
1362
1354
|
end
|
1363
1355
|
else
|
1364
|
-
|
1356
|
+
config[:connection_password]
|
1365
1357
|
end
|
1366
1358
|
end
|
1367
1359
|
|
@@ -1373,7 +1365,7 @@ class Chef
|
|
1373
1365
|
|
1374
1366
|
# TODO: connection_protocol and connection_port used to choose winrm/ssh or 5985/22 based on the image chosen
|
1375
1367
|
def connection_port
|
1376
|
-
port =
|
1368
|
+
port = config[:connection_port] || config[knife_key_for_protocol(:port)]
|
1377
1369
|
return port if port
|
1378
1370
|
|
1379
1371
|
assign_default_port
|
@@ -1384,7 +1376,7 @@ class Chef
|
|
1384
1376
|
# @return [Integer]
|
1385
1377
|
def assign_default_port
|
1386
1378
|
if winrm?
|
1387
|
-
|
1379
|
+
config[:winrm_ssl] ? 5986 : 5985
|
1388
1380
|
else
|
1389
1381
|
22
|
1390
1382
|
end
|
@@ -1397,13 +1389,12 @@ class Chef
|
|
1397
1389
|
|
1398
1390
|
default_protocol = is_image_windows? ? "winrm" : "ssh"
|
1399
1391
|
from_url = host_descriptor =~ %r{^(.*)://} ? $1 : nil
|
1400
|
-
|
1401
|
-
|
1402
|
-
@connection_protocol_ec2 = from_url || from_cli || from_knife || default_protocol
|
1392
|
+
from_config = config[:connection_protocol]
|
1393
|
+
@connection_protocol_ec2 = from_url || from_config || default_protocol
|
1403
1394
|
end
|
1404
1395
|
|
1405
1396
|
def connection_user
|
1406
|
-
@connection_user ||=
|
1397
|
+
@connection_user ||= config[:connection_user] || config[knife_key_for_protocol(:user)]
|
1407
1398
|
end
|
1408
1399
|
|
1409
1400
|
def server_name
|
@@ -1411,8 +1402,6 @@ class Chef
|
|
1411
1402
|
|
1412
1403
|
if !server.public_dns_name.empty?
|
1413
1404
|
server.public_dns_name
|
1414
|
-
elsif !server.private_dns_name.empty?
|
1415
|
-
server.private_dns_name
|
1416
1405
|
else
|
1417
1406
|
server.private_ip_address
|
1418
1407
|
end
|
@@ -1442,7 +1431,7 @@ class Chef
|
|
1442
1431
|
|
1443
1432
|
def hashed_volume_tags
|
1444
1433
|
hvt = {}
|
1445
|
-
volume_tags =
|
1434
|
+
volume_tags = config[:volume_tags]
|
1446
1435
|
volume_tags.map { |t| key, val = t.split("="); hvt[key] = val } unless volume_tags.nil?
|
1447
1436
|
|
1448
1437
|
hvt
|
@@ -1458,8 +1447,8 @@ class Chef
|
|
1458
1447
|
|
1459
1448
|
# Always set the Name tag
|
1460
1449
|
unless ht.key?("Name")
|
1461
|
-
if
|
1462
|
-
ht["Name"] = evaluate_node_name(
|
1450
|
+
if config[:chef_node_name]
|
1451
|
+
ht["Name"] = evaluate_node_name(config[:chef_node_name])
|
1463
1452
|
else
|
1464
1453
|
ht["Name"] = server.id
|
1465
1454
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Adam Jacob (<adam@chef.io>)
|
3
3
|
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
4
|
-
# Copyright:: Copyright (c)
|
4
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -122,7 +122,7 @@ class Chef
|
|
122
122
|
|
123
123
|
output_column_count = servers_list.length
|
124
124
|
|
125
|
-
|
125
|
+
unless config[:region]
|
126
126
|
ui.warn "No region was specified in knife.rb/config.rb or as an argument. The default region, us-east-1, will be used:"
|
127
127
|
end
|
128
128
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
#
|
3
3
|
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
4
|
-
# Copyright:: Copyright (c)
|
4
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -51,46 +51,41 @@ class Chef
|
|
51
51
|
option :aws_access_key_id,
|
52
52
|
short: "-A ID",
|
53
53
|
long: "--aws-access-key-id KEY",
|
54
|
-
description: "Your AWS Access Key ID"
|
55
|
-
proc: Proc.new { |key| Chef::Config[:knife][:aws_access_key_id] = key }
|
54
|
+
description: "Your AWS Access Key ID"
|
56
55
|
|
57
56
|
option :aws_secret_access_key,
|
58
57
|
short: "-K SECRET",
|
59
58
|
long: "--aws-secret-access-key SECRET",
|
60
|
-
description: "Your AWS API Secret Access Key"
|
61
|
-
proc: Proc.new { |key| Chef::Config[:knife][:aws_secret_access_key] = key }
|
59
|
+
description: "Your AWS API Secret Access Key"
|
62
60
|
|
63
61
|
option :aws_session_token,
|
64
62
|
long: "--aws-session-token TOKEN",
|
65
|
-
description: "Your AWS Session Token, for use with AWS STS Federation or Session Tokens"
|
66
|
-
proc: Proc.new { |key| Chef::Config[:knife][:aws_session_token] = key }
|
63
|
+
description: "Your AWS Session Token, for use with AWS STS Federation or Session Tokens"
|
67
64
|
|
68
65
|
option :region,
|
69
66
|
long: "--region REGION",
|
70
|
-
description: "Your AWS region"
|
71
|
-
proc: Proc.new { |key| Chef::Config[:knife][:region] = key }
|
67
|
+
description: "Your AWS region"
|
72
68
|
|
73
69
|
option :use_iam_profile,
|
74
70
|
long: "--use-iam-profile",
|
75
71
|
description: "Use IAM profile assigned to current machine",
|
76
72
|
boolean: true,
|
77
|
-
default: false
|
78
|
-
proc: Proc.new { |key| Chef::Config[:knife][:use_iam_profile] = key }
|
73
|
+
default: false
|
79
74
|
end
|
80
75
|
end
|
81
76
|
|
82
77
|
def connection_string
|
83
78
|
conn = {}
|
84
|
-
conn[:region] =
|
79
|
+
conn[:region] = config[:region] || "us-east-1"
|
85
80
|
Chef::Log.debug "Using AWS region #{conn[:region]}"
|
86
81
|
conn[:credentials] =
|
87
|
-
if
|
82
|
+
if config[:use_iam_profile]
|
88
83
|
Chef::Log.debug "Using iam profile for authentication as use_iam_profile set"
|
89
84
|
Aws::InstanceProfileCredentials.new
|
90
85
|
else
|
91
|
-
Chef::Log.debug "Setting up AWS connection using aws_access_key_id: #{mask(
|
86
|
+
Chef::Log.debug "Setting up AWS connection using aws_access_key_id: #{mask(config[:aws_access_key_id])} aws_secret_access_key: #{mask(config[:aws_secret_access_key])} aws_session_token: #{mask(config[:aws_session_token])}"
|
92
87
|
|
93
|
-
Aws::Credentials.new(
|
88
|
+
Aws::Credentials.new(config[:aws_access_key_id], config[:aws_secret_access_key], config[:aws_session_token])
|
94
89
|
end
|
95
90
|
conn
|
96
91
|
end
|
@@ -100,6 +95,10 @@ class Chef
|
|
100
95
|
@ec2_connection ||= Aws::EC2::Client.new(connection_string)
|
101
96
|
end
|
102
97
|
|
98
|
+
def vpc_mode?
|
99
|
+
!!config[:subnet_id]
|
100
|
+
end
|
101
|
+
|
103
102
|
def fetch_ami(image_id)
|
104
103
|
return nil unless image_id
|
105
104
|
|
@@ -147,7 +146,7 @@ class Chef
|
|
147
146
|
server_data[id] = server_obj.instances[0].send(id)
|
148
147
|
end
|
149
148
|
server_data["availability_zone"] = server_obj.instances[0].placement.availability_zone
|
150
|
-
server_data["groups"] = server_obj.groups.map(&:
|
149
|
+
server_data["groups"] = server_obj.groups.map(&:group_name) unless vpc_mode?
|
151
150
|
server_data["iam_instance_profile"] = ( server_obj.instances[0].iam_instance_profile.nil? ? nil : server_obj.instances[0].iam_instance_profile.arn[%r{instance-profile/(.*)}] )
|
152
151
|
server_data["id"] = server_data["instance_id"]
|
153
152
|
|
@@ -157,8 +156,8 @@ class Chef
|
|
157
156
|
server_data["security_groups"] = server_obj.instances[0].security_groups.map(&:group_name)
|
158
157
|
server_data["security_group_ids"] = server_obj.instances[0].security_groups.map(&:group_id)
|
159
158
|
server_data["state"] = server_obj.instances[0].state.name
|
160
|
-
server_data["subnet_id"] = server_obj.instances[0].network_interfaces[0].subnet_id
|
161
|
-
server_data["source_dest_check"] = server_obj.instances[0].network_interfaces[0].source_dest_check
|
159
|
+
server_data["subnet_id"] = server_obj.instances[0].network_interfaces[0].subnet_id if vpc_mode?
|
160
|
+
server_data["source_dest_check"] = server_obj.instances[0].network_interfaces[0].source_dest_check if vpc_mode?
|
162
161
|
server_data["tags"] = tags
|
163
162
|
server_data["tenancy"] = server_obj.instances[0].placement.tenancy
|
164
163
|
server_data["volume_id"] = server_obj.instances[0].block_device_mappings[0]&.ebs&.volume_id
|
@@ -172,16 +171,6 @@ class Chef
|
|
172
171
|
OpenStruct.new(server_hashes)
|
173
172
|
end
|
174
173
|
|
175
|
-
# @return [String]
|
176
|
-
def locate_config_value(key)
|
177
|
-
key = key.to_sym
|
178
|
-
if defined?(config_value) # Inherited by bootstrap
|
179
|
-
config_value(key) || default_config[key]
|
180
|
-
else
|
181
|
-
config[key] || Chef::Config[:knife][key] || default_config[key]
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
174
|
def msg_pair(label, value, color = :cyan)
|
186
175
|
if value && !value.to_s.empty?
|
187
176
|
ui.info("#{ui.color(label, color)}: #{value}")
|
@@ -189,7 +178,7 @@ class Chef
|
|
189
178
|
end
|
190
179
|
|
191
180
|
def ami
|
192
|
-
@ami ||= fetch_ami(
|
181
|
+
@ami ||= fetch_ami(config[:image])
|
193
182
|
end
|
194
183
|
|
195
184
|
# Platform value return for Windows AMIs; otherwise, it is blank.
|
@@ -203,16 +192,16 @@ class Chef
|
|
203
192
|
def validate_aws_config!(keys = %i{aws_access_key_id aws_secret_access_key})
|
204
193
|
errors = [] # track all errors so we report on all of them
|
205
194
|
|
206
|
-
validate_aws_config_file! if
|
207
|
-
unless
|
195
|
+
validate_aws_config_file! if config[:aws_config_file]
|
196
|
+
unless config[:use_iam_profile] # skip config file / key validation if we're using iam profile
|
208
197
|
# validate the creds file if:
|
209
198
|
# aws keys have not been passed in config / CLI and the default cred file location does exist
|
210
199
|
# OR
|
211
200
|
# the user passed aws_credential_file
|
212
|
-
if (
|
213
|
-
|
201
|
+
if (config.keys & %i{aws_access_key_id aws_secret_access_key}).empty? && aws_cred_file_location ||
|
202
|
+
config[:aws_credential_file]
|
214
203
|
|
215
|
-
unless (
|
204
|
+
unless (config.keys & %i{aws_access_key_id aws_secret_access_key}).empty?
|
216
205
|
errors << "Either provide a credentials file or the access key and secret keys but not both."
|
217
206
|
end
|
218
207
|
|
@@ -221,7 +210,7 @@ class Chef
|
|
221
210
|
|
222
211
|
keys.each do |k|
|
223
212
|
pretty_key = k.to_s.tr("_", " ").gsub(/\w+/) { |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
|
224
|
-
if
|
213
|
+
if config[k].nil?
|
225
214
|
errors << "You did not provide a valid '#{pretty_key}' value."
|
226
215
|
end
|
227
216
|
end
|
@@ -239,8 +228,8 @@ class Chef
|
|
239
228
|
# @return [String, nil] location to aws credentials file or nil if none exists
|
240
229
|
def aws_cred_file_location
|
241
230
|
@cred_file ||= begin
|
242
|
-
if !
|
243
|
-
|
231
|
+
if !config[:aws_credential_file].nil?
|
232
|
+
config[:aws_credential_file]
|
244
233
|
else
|
245
234
|
Chef::Util::PathHelper.home(".aws", "credentials") if ::File.exist?(Chef::Util::PathHelper.home(".aws", "credentials"))
|
246
235
|
end
|
@@ -284,7 +273,7 @@ class Chef
|
|
284
273
|
|
285
274
|
# Custom Warning
|
286
275
|
def custom_warnings!
|
287
|
-
|
276
|
+
unless config[:region]
|
288
277
|
ui.warn "No region was specified in knife.rb/config.rb or as an argument. The default region, us-east-1, will be used:"
|
289
278
|
end
|
290
279
|
end
|
@@ -294,18 +283,18 @@ class Chef
|
|
294
283
|
# validate the contents of the aws configuration file
|
295
284
|
# @return [void]
|
296
285
|
def validate_aws_config_file!
|
297
|
-
config_file =
|
286
|
+
config_file = config[:aws_config_file]
|
298
287
|
Chef::Log.debug "Using AWS config file at #{config_file}"
|
299
288
|
|
300
289
|
raise ArgumentError, "The provided --aws_config_file (#{config_file}) cannot be found on disk." unless File.exist?(config_file)
|
301
290
|
|
302
291
|
aws_config = ini_parse(File.read(config_file))
|
303
|
-
profile_key =
|
292
|
+
profile_key = config[:aws_profile]
|
304
293
|
profile_key = "profile #{profile_key}" if profile_key != "default"
|
305
294
|
|
306
295
|
unless aws_config.values.empty?
|
307
296
|
if aws_config[profile_key]
|
308
|
-
|
297
|
+
config[:region] = aws_config[profile_key]["region"]
|
309
298
|
else
|
310
299
|
raise ArgumentError, "The provided --aws-profile '#{profile_key}' is invalid."
|
311
300
|
end
|
@@ -326,7 +315,7 @@ class Chef
|
|
326
315
|
# aws_access_key_id = somethingsomethingdarkside
|
327
316
|
# aws_secret_access_key = somethingsomethingdarkside
|
328
317
|
aws_creds = ini_parse(File.read(aws_cred_file_location))
|
329
|
-
profile =
|
318
|
+
profile = config[:aws_profile]
|
330
319
|
Chef::Log.debug "Using AWS profile #{profile}"
|
331
320
|
entries = if aws_creds.values.first.key?("AWSAccessKeyId")
|
332
321
|
aws_creds.values.first
|
@@ -335,9 +324,9 @@ class Chef
|
|
335
324
|
end
|
336
325
|
|
337
326
|
if entries
|
338
|
-
|
339
|
-
|
340
|
-
|
327
|
+
config[:aws_access_key_id] = entries["AWSAccessKeyId"] || entries["aws_access_key_id"]
|
328
|
+
config[:aws_secret_access_key] = entries["AWSSecretKey"] || entries["aws_secret_access_key"]
|
329
|
+
config[:aws_session_token] = entries["AWSSessionToken"] || entries["aws_session_token"]
|
341
330
|
else
|
342
331
|
raise ArgumentError, "The provided --aws-profile '#{profile}' is invalid. Does the credential file at '#{aws_cred_file_location}' contain this profile?"
|
343
332
|
end
|
@@ -60,15 +60,15 @@ class Chef
|
|
60
60
|
|
61
61
|
def connection_string
|
62
62
|
conn = {}
|
63
|
-
conn[:region] =
|
63
|
+
conn[:region] = config[:region]
|
64
64
|
conn[:credentials] =
|
65
|
-
if
|
65
|
+
if config[:use_iam_profile]
|
66
66
|
Aws::InstanceProfileCredentials.new
|
67
67
|
else
|
68
68
|
Aws::Credentials.new(
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
config[:aws_access_key_id],
|
70
|
+
config[:aws_secret_access_key],
|
71
|
+
config[:aws_session_token]
|
72
72
|
)
|
73
73
|
end
|
74
74
|
conn
|
data/lib/knife-ec2/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-ec2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '15.
|
19
|
+
version: '15.11'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '15.
|
26
|
+
version: '15.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: aws-sdk-s3
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
84
|
requirements:
|
85
85
|
- - ">="
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
version: '2.
|
87
|
+
version: '2.6'
|
88
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
89
|
requirements:
|
90
90
|
- - ">="
|