knife-ec2 0.18.2 → 0.19.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.expeditor/config.yml +13 -16
- data/.github/CODEOWNERS +4 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- data/.gitignore +0 -1
- data/.rspec +2 -0
- data/.rubocop.yml +30 -0
- data/.travis.yml +10 -17
- data/CHANGELOG.md +29 -7
- data/DOC_CHANGES.md +2 -12
- data/Gemfile +26 -2
- data/README.md +72 -75
- data/RELEASE_NOTES.md +10 -0
- data/Rakefile +25 -26
- data/VERSION +1 -1
- data/knife-ec2.gemspec +13 -20
- data/lib/chef/knife/ec2_ami_list.rb +31 -34
- data/lib/chef/knife/ec2_base.rb +137 -94
- data/lib/chef/knife/ec2_flavor_list.rb +12 -13
- data/lib/chef/knife/ec2_server_create.rb +440 -461
- data/lib/chef/knife/ec2_server_delete.rb +43 -41
- data/lib/chef/knife/ec2_server_list.rb +31 -28
- data/lib/chef/knife/s3_source.rb +22 -3
- data/lib/knife-ec2/version.rb +2 -2
- data/spec/spec_helper.rb +10 -11
- data/spec/unit/ec2_ami_list_spec.rb +297 -297
- data/spec/unit/ec2_flavor_list_spec.rb +18 -18
- data/spec/unit/ec2_server_create_spec.rb +952 -951
- data/spec/unit/ec2_server_delete_spec.rb +60 -61
- data/spec/unit/ec2_server_list_spec.rb +28 -28
- data/spec/unit/s3_source_deps_spec.rb +7 -7
- data/spec/unit/s3_source_spec.rb +17 -17
- metadata +26 -79
- data/CONTRIBUTING.md +0 -245
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
3
|
-
# Copyright:: Copyright (c) 2012-
|
3
|
+
# Copyright:: Copyright (c) 2012-2018 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");
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
19
|
+
require "chef/knife/ec2_base"
|
20
20
|
|
21
21
|
class Chef
|
22
22
|
class Knife
|
@@ -27,17 +27,16 @@ class Chef
|
|
27
27
|
banner "knife ec2 flavor list (options)"
|
28
28
|
|
29
29
|
def run
|
30
|
-
|
31
30
|
validate!
|
32
31
|
custom_warnings!
|
33
32
|
|
34
33
|
flavor_list = [
|
35
|
-
ui.color(
|
36
|
-
ui.color(
|
37
|
-
ui.color(
|
38
|
-
ui.color(
|
39
|
-
ui.color(
|
40
|
-
ui.color(
|
34
|
+
ui.color("ID", :bold),
|
35
|
+
ui.color("Name", :bold),
|
36
|
+
ui.color("Architecture", :bold),
|
37
|
+
ui.color("RAM", :bold),
|
38
|
+
ui.color("Disk", :bold),
|
39
|
+
ui.color("Cores", :bold)
|
41
40
|
].flatten.compact
|
42
41
|
|
43
42
|
output_column_count = flavor_list.length
|
@@ -48,13 +47,13 @@ class Chef
|
|
48
47
|
raise api_error
|
49
48
|
end
|
50
49
|
|
51
|
-
if
|
50
|
+
if config[:format] == "summary"
|
52
51
|
flavors.each do |flavor|
|
53
52
|
flavor_list << flavor.id.to_s
|
54
53
|
flavor_list << flavor.name
|
55
|
-
flavor_list << "#{flavor.bits
|
56
|
-
flavor_list << "#{flavor.ram
|
57
|
-
flavor_list << "#{flavor.disk
|
54
|
+
flavor_list << "#{flavor.bits}-bit"
|
55
|
+
flavor_list << "#{flavor.ram}"
|
56
|
+
flavor_list << "#{flavor.disk} GB"
|
58
57
|
flavor_list << flavor.cores.to_s
|
59
58
|
end
|
60
59
|
puts ui.list(flavor_list, :uneven_columns_across, output_column_count)
|
@@ -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) 2010-
|
4
|
+
# Copyright:: Copyright (c) 2010-2018 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");
|
@@ -17,10 +17,10 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
20
|
+
require "chef/knife/ec2_base"
|
21
|
+
require "chef/knife/s3_source"
|
22
|
+
require "chef/knife/winrm_base"
|
23
|
+
require "chef/knife/bootstrap_windows_base"
|
24
24
|
|
25
25
|
class Chef
|
26
26
|
class Knife
|
@@ -30,12 +30,9 @@ class Chef
|
|
30
30
|
include Knife::WinrmBase
|
31
31
|
include Knife::BootstrapWindowsBase
|
32
32
|
deps do
|
33
|
-
require
|
34
|
-
require
|
35
|
-
require
|
36
|
-
require 'readline'
|
37
|
-
require 'chef/json_compat'
|
38
|
-
require 'chef/knife/bootstrap'
|
33
|
+
require "tempfile"
|
34
|
+
require "uri"
|
35
|
+
require "chef/knife/bootstrap"
|
39
36
|
Chef::Knife::Bootstrap.load_deps
|
40
37
|
end
|
41
38
|
|
@@ -45,34 +42,34 @@ class Chef
|
|
45
42
|
attr_reader :server
|
46
43
|
|
47
44
|
option :flavor,
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
45
|
+
short: "-f FLAVOR",
|
46
|
+
long: "--flavor FLAVOR",
|
47
|
+
description: "The flavor of server (m1.small, m1.medium, etc)",
|
48
|
+
proc: Proc.new { |f| Chef::Config[:knife][:flavor] = f }
|
52
49
|
|
53
50
|
option :image,
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
51
|
+
short: "-I IMAGE",
|
52
|
+
long: "--image IMAGE",
|
53
|
+
description: "The AMI for the server",
|
54
|
+
proc: Proc.new { |i| Chef::Config[:knife][:image] = i }
|
58
55
|
|
59
56
|
option :iam_instance_profile,
|
60
|
-
:
|
61
|
-
:
|
57
|
+
long: "--iam-profile NAME",
|
58
|
+
description: "The IAM instance profile to apply to this instance."
|
62
59
|
|
63
60
|
option :security_groups,
|
64
|
-
:
|
65
|
-
:
|
66
|
-
:
|
67
|
-
:
|
61
|
+
short: "-G X,Y,Z",
|
62
|
+
long: "--groups X,Y,Z",
|
63
|
+
description: "The security groups for this server; not allowed when using VPC",
|
64
|
+
proc: Proc.new { |groups| groups.split(",") }
|
68
65
|
|
69
66
|
option :security_group_ids,
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
73
|
-
ui.warn(
|
74
|
-
if security_group_ids.
|
75
|
-
Chef::Config[:knife][:security_group_ids] = security_group_ids.
|
67
|
+
long: "--security-group-ids 'X,Y,Z'",
|
68
|
+
description: "The security group ids for this server; required when using VPC. Provide values in format --security-group-ids 'X,Y,Z'. [DEPRECATED] This option will be removed in future release. Use the new --security-group-id option. ",
|
69
|
+
proc: Proc.new { |security_group_ids|
|
70
|
+
ui.warn("[DEPRECATED] This option will be removed in future release. Use the new --security-group-id option multiple times when specifying multiple groups for e.g. -g sg-e985168d -g sg-e7f06383 -g sg-ec1b7e88.")
|
71
|
+
if security_group_ids.delete(" ").split(",").size > 1
|
72
|
+
Chef::Config[:knife][:security_group_ids] = security_group_ids.delete(" ").split(",")
|
76
73
|
else
|
77
74
|
Chef::Config[:knife][:security_group_ids] ||= []
|
78
75
|
Chef::Config[:knife][:security_group_ids].push(security_group_ids)
|
@@ -81,329 +78,311 @@ class Chef
|
|
81
78
|
}
|
82
79
|
|
83
80
|
option :security_group_id,
|
84
|
-
:
|
85
|
-
:
|
86
|
-
:
|
87
|
-
:
|
81
|
+
short: "-g SECURITY_GROUP_ID",
|
82
|
+
long: "--security-group-id ID",
|
83
|
+
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.",
|
84
|
+
proc: Proc.new { |security_group_id|
|
88
85
|
Chef::Config[:knife][:security_group_ids] ||= []
|
89
86
|
Chef::Config[:knife][:security_group_ids].push(security_group_id)
|
90
87
|
Chef::Config[:knife][:security_group_ids]
|
91
88
|
}
|
92
89
|
|
93
90
|
option :associate_eip,
|
94
|
-
:
|
95
|
-
:
|
91
|
+
long: "--associate-eip IP_ADDRESS",
|
92
|
+
description: "Associate existing elastic IP address with instance after launch"
|
96
93
|
|
97
94
|
option :dedicated_instance,
|
98
|
-
:
|
99
|
-
:
|
95
|
+
long: "--dedicated_instance",
|
96
|
+
description: "Launch as a Dedicated instance (VPC ONLY)"
|
100
97
|
|
101
98
|
option :placement_group,
|
102
|
-
:
|
103
|
-
:
|
104
|
-
:
|
99
|
+
long: "--placement-group PLACEMENT_GROUP",
|
100
|
+
description: "The placement group to place a cluster compute instance",
|
101
|
+
proc: Proc.new { |pg| Chef::Config[:knife][:placement_group] = pg }
|
105
102
|
|
106
103
|
option :primary_eni,
|
107
|
-
:
|
108
|
-
:
|
104
|
+
long: "--primary-eni ENI_ID",
|
105
|
+
description: "Specify a pre-existing eni to use when building the instance."
|
109
106
|
|
110
107
|
option :tags,
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
108
|
+
short: "-T T=V[,T=V,...]",
|
109
|
+
long: "--tags Tag=Value[,Tag=Value...]",
|
110
|
+
description: "The tags for this server. [DEPRECATED] Use --aws-tag instead.",
|
111
|
+
proc: Proc.new { |tags|
|
115
112
|
Chef::Log.warn("[DEPRECATED] --tags option is deprecated. Use --aws-tag option instead.")
|
116
|
-
tags.split(
|
113
|
+
tags.split(",")
|
117
114
|
}
|
118
115
|
|
119
116
|
option :availability_zone,
|
120
|
-
:
|
121
|
-
:
|
122
|
-
:
|
123
|
-
:
|
117
|
+
short: "-Z ZONE",
|
118
|
+
long: "--availability-zone ZONE",
|
119
|
+
description: "The Availability Zone",
|
120
|
+
proc: Proc.new { |key| Chef::Config[:knife][:availability_zone] = key }
|
124
121
|
|
125
122
|
option :chef_node_name,
|
126
|
-
:
|
127
|
-
:
|
128
|
-
:
|
129
|
-
:
|
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 }
|
130
127
|
|
131
128
|
option :ssh_key_name,
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
129
|
+
short: "-S KEY",
|
130
|
+
long: "--ssh-key KEY",
|
131
|
+
description: "The AWS SSH key id",
|
132
|
+
proc: Proc.new { |key| Chef::Config[:knife][:ssh_key_name] = key }
|
136
133
|
|
137
134
|
option :ssh_user,
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
135
|
+
short: "-x USERNAME",
|
136
|
+
long: "--ssh-user USERNAME",
|
137
|
+
description: "The ssh username",
|
138
|
+
default: "root"
|
142
139
|
|
143
140
|
option :ssh_password,
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
141
|
+
short: "-P PASSWORD",
|
142
|
+
long: "--ssh-password PASSWORD",
|
143
|
+
description: "The ssh password"
|
147
144
|
|
148
145
|
option :ssh_port,
|
149
|
-
:
|
150
|
-
:
|
151
|
-
:
|
152
|
-
:
|
153
|
-
:
|
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 }
|
154
151
|
|
155
152
|
option :ssh_gateway,
|
156
|
-
:
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:
|
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 }
|
160
157
|
|
161
158
|
option :ssh_gateway_identity,
|
162
|
-
:
|
163
|
-
:
|
164
|
-
:
|
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 }
|
165
162
|
|
166
163
|
option :identity_file,
|
167
|
-
:
|
168
|
-
:
|
169
|
-
:
|
164
|
+
short: "-i IDENTITY_FILE",
|
165
|
+
long: "--identity-file IDENTITY_FILE",
|
166
|
+
description: "The SSH identity file used for authentication"
|
170
167
|
|
171
168
|
option :prerelease,
|
172
|
-
:
|
173
|
-
:
|
169
|
+
long: "--prerelease",
|
170
|
+
description: "Install the pre-release chef gems"
|
174
171
|
|
175
172
|
option :bootstrap_version,
|
176
|
-
:
|
177
|
-
:
|
178
|
-
:
|
173
|
+
long: "--bootstrap-version VERSION",
|
174
|
+
description: "The version of Chef to install",
|
175
|
+
proc: Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
179
176
|
|
180
177
|
option :bootstrap_proxy,
|
181
|
-
:
|
182
|
-
:
|
183
|
-
:
|
184
|
-
|
185
|
-
option :distro,
|
186
|
-
:short => "-d DISTRO",
|
187
|
-
:long => "--distro DISTRO",
|
188
|
-
:description => "Bootstrap a distro using a template. [DEPRECATED] Use --bootstrap-template option instead.",
|
189
|
-
:proc => Proc.new { |v|
|
190
|
-
Chef::Log.warn("[DEPRECATED] -d / --distro option is deprecated. Use --bootstrap-template option instead.")
|
191
|
-
v
|
192
|
-
}
|
193
|
-
|
194
|
-
option :template_file,
|
195
|
-
:long => "--template-file TEMPLATE",
|
196
|
-
:description => "Full path to location of template to use. [DEPRECATED] Use -t / --bootstrap-template option instead.",
|
197
|
-
:proc => Proc.new { |v|
|
198
|
-
Chef::Log.warn("[DEPRECATED] --template-file option is deprecated. Use -t / --bootstrap-template option instead.")
|
199
|
-
v
|
200
|
-
}
|
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 }
|
201
181
|
|
202
182
|
option :bootstrap_template,
|
203
|
-
:
|
204
|
-
:
|
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."
|
205
185
|
|
206
186
|
option :ebs_size,
|
207
|
-
:
|
208
|
-
:
|
187
|
+
long: "--ebs-size SIZE",
|
188
|
+
description: "The size of the EBS volume in GB, for EBS-backed instances"
|
209
189
|
|
210
190
|
option :ebs_optimized,
|
211
|
-
:
|
212
|
-
:
|
191
|
+
long: "--ebs-optimized",
|
192
|
+
description: "Enabled optimized EBS I/O"
|
213
193
|
|
214
194
|
option :ebs_no_delete_on_term,
|
215
|
-
:
|
216
|
-
:
|
195
|
+
long: "--ebs-no-delete-on-term",
|
196
|
+
description: "Do not delete EBS volume on instance termination"
|
217
197
|
|
218
198
|
option :run_list,
|
219
|
-
:
|
220
|
-
:
|
221
|
-
:
|
222
|
-
:
|
223
|
-
:
|
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: []
|
224
204
|
|
225
205
|
option :secret,
|
226
|
-
:
|
227
|
-
:
|
228
|
-
:
|
206
|
+
long: "--secret ",
|
207
|
+
description: "The secret key to use to encrypt data bag item values",
|
208
|
+
proc: lambda { |s| Chef::Config[:knife][:secret] = s }
|
229
209
|
|
230
210
|
option :secret_file,
|
231
|
-
:
|
232
|
-
:
|
233
|
-
:
|
211
|
+
long: "--secret-file SECRET_FILE",
|
212
|
+
description: "A file containing the secret key to use to encrypt data bag item values",
|
213
|
+
proc: lambda { |sf| Chef::Config[:knife][:secret_file] = sf }
|
234
214
|
|
235
215
|
option :s3_secret,
|
236
|
-
:
|
237
|
-
:
|
238
|
-
:
|
216
|
+
long: "--s3-secret S3_SECRET_URL",
|
217
|
+
description: "S3 URL (e.g. s3://bucket/file) for the encrypted_data_bag_secret_file",
|
218
|
+
proc: lambda { |url| Chef::Config[:knife][:s3_secret] = url }
|
239
219
|
|
240
220
|
option :subnet_id,
|
241
|
-
:
|
242
|
-
:
|
243
|
-
:
|
221
|
+
long: "--subnet SUBNET-ID",
|
222
|
+
description: "create node in this Virtual Private Cloud Subnet ID (implies VPC mode)",
|
223
|
+
proc: Proc.new { |key| Chef::Config[:knife][:subnet_id] = key }
|
244
224
|
|
245
225
|
option :private_ip_address,
|
246
|
-
:
|
247
|
-
:
|
248
|
-
:
|
226
|
+
long: "--private-ip-address IP-ADDRESS",
|
227
|
+
description: "allows to specify the private IP address of the instance in VPC mode",
|
228
|
+
proc: Proc.new { |ip| Chef::Config[:knife][:private_ip_address] = ip }
|
249
229
|
|
250
230
|
option :host_key_verify,
|
251
|
-
:
|
252
|
-
:
|
253
|
-
:
|
254
|
-
:
|
231
|
+
long: "--[no-]host-key-verify",
|
232
|
+
description: "Verify host key, enabled by default.",
|
233
|
+
boolean: true,
|
234
|
+
default: true
|
255
235
|
|
256
236
|
option :bootstrap_protocol,
|
257
|
-
:
|
258
|
-
:
|
259
|
-
:
|
260
|
-
:
|
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
|
261
241
|
|
262
242
|
option :fqdn,
|
263
|
-
:
|
264
|
-
:
|
265
|
-
:
|
266
|
-
:
|
243
|
+
long: "--fqdn FQDN",
|
244
|
+
description: "Pre-defined FQDN. This is used for Kerberos Authentication purpose only",
|
245
|
+
proc: Proc.new { |key| Chef::Config[:knife][:fqdn] = key },
|
246
|
+
default: nil
|
267
247
|
|
268
248
|
option :aws_user_data,
|
269
|
-
:
|
270
|
-
:
|
271
|
-
:
|
272
|
-
:
|
273
|
-
:
|
249
|
+
long: "--user-data USER_DATA_FILE",
|
250
|
+
short: "-u USER_DATA_FILE",
|
251
|
+
description: "The EC2 User Data file to provision the instance with",
|
252
|
+
proc: Proc.new { |m| Chef::Config[:knife][:aws_user_data] = m },
|
253
|
+
default: nil
|
274
254
|
|
275
255
|
option :hint,
|
276
|
-
:
|
277
|
-
:
|
278
|
-
:
|
279
|
-
|
280
|
-
|
281
|
-
|
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
|
282
262
|
}
|
283
263
|
|
284
264
|
option :ephemeral,
|
285
|
-
:
|
286
|
-
:
|
287
|
-
:
|
288
|
-
:
|
265
|
+
long: "--ephemeral EPHEMERAL_DEVICES",
|
266
|
+
description: "Comma separated list of device locations (eg - /dev/sdb) to map ephemeral devices",
|
267
|
+
proc: lambda { |o| o.split(/[\s,]+/) },
|
268
|
+
default: []
|
289
269
|
|
290
270
|
option :server_connect_attribute,
|
291
|
-
:
|
292
|
-
:
|
293
|
-
:
|
294
|
-
:
|
271
|
+
long: "--server-connect-attribute ATTRIBUTE",
|
272
|
+
short: "-a ATTRIBUTE",
|
273
|
+
description: "The EC2 server attribute to use for the SSH connection if necessary, e.g. public_ip_address or private_ip_address.",
|
274
|
+
default: nil
|
295
275
|
|
296
276
|
option :associate_public_ip,
|
297
|
-
:
|
298
|
-
:
|
299
|
-
:
|
300
|
-
:
|
277
|
+
long: "--associate-public-ip",
|
278
|
+
description: "Associate public ip to VPC instance.",
|
279
|
+
boolean: true,
|
280
|
+
default: false
|
301
281
|
|
302
282
|
option :ebs_volume_type,
|
303
|
-
:
|
304
|
-
:
|
305
|
-
:
|
306
|
-
:
|
283
|
+
long: "--ebs-volume-type TYPE",
|
284
|
+
description: "Possible values are standard (magnetic) | io1 | gp2 | sc1 | st1. Default is gp2",
|
285
|
+
proc: Proc.new { |key| Chef::Config[:knife][:ebs_volume_type] = key },
|
286
|
+
default: "gp2"
|
307
287
|
|
308
288
|
option :ebs_provisioned_iops,
|
309
|
-
:
|
310
|
-
:
|
311
|
-
:
|
312
|
-
:
|
289
|
+
long: "--provisioned-iops IOPS",
|
290
|
+
description: "IOPS rate, only used when ebs volume type is 'io1'",
|
291
|
+
proc: Proc.new { |key| Chef::Config[:knife][:provisioned_iops] = key },
|
292
|
+
default: nil
|
313
293
|
|
314
294
|
option :auth_timeout,
|
315
|
-
:
|
316
|
-
:
|
317
|
-
:
|
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
|
318
298
|
|
319
299
|
option :validation_key_url,
|
320
|
-
:
|
321
|
-
:
|
322
|
-
:
|
300
|
+
long: "--validation-key-url URL",
|
301
|
+
description: "Path to the validation key",
|
302
|
+
proc: proc { |m| Chef::Config[:validation_key_url] = m }
|
323
303
|
|
324
304
|
option :ebs_encrypted,
|
325
|
-
:
|
326
|
-
:
|
327
|
-
:
|
328
|
-
:
|
305
|
+
long: "--ebs-encrypted",
|
306
|
+
description: "Enables EBS volume encryption",
|
307
|
+
boolean: true,
|
308
|
+
default: false
|
329
309
|
|
330
310
|
option :spot_price,
|
331
|
-
:
|
332
|
-
:
|
333
|
-
:
|
311
|
+
long: "--spot-price PRICE",
|
312
|
+
description: "The maximum hourly USD price for the instance",
|
313
|
+
default: nil
|
334
314
|
|
335
315
|
option :spot_request_type,
|
336
|
-
:
|
337
|
-
:
|
338
|
-
:
|
316
|
+
long: "--spot-request-type TYPE",
|
317
|
+
description: "The Spot Instance request type. Possible values are 'one-time' and 'persistent', default value is 'one-time'",
|
318
|
+
default: "one-time"
|
339
319
|
|
340
320
|
option :spot_wait_mode,
|
341
|
-
:
|
342
|
-
:
|
343
|
-
"Whether we should wait for spot request fulfillment. Could be 'wait', 'exit', or " \
|
321
|
+
long: "--spot-wait-mode MODE",
|
322
|
+
description: "Whether we should wait for spot request fulfillment. Could be 'wait', 'exit', or " \
|
344
323
|
"'prompt' (default). For any of the above mentioned choices, ('wait') - if the " \
|
345
324
|
"instance does not get allocated before the command itself times-out or ('exit') the " \
|
346
325
|
"user needs to manually bootstrap the instance in the future after it gets allocated.",
|
347
|
-
:
|
326
|
+
default: "prompt"
|
348
327
|
|
349
328
|
option :aws_connection_timeout,
|
350
|
-
:
|
351
|
-
:
|
352
|
-
:
|
353
|
-
:
|
329
|
+
long: "--aws-connection-timeout MINUTES",
|
330
|
+
description: "The maximum time in minutes to wait to for aws connection. Default is 10 min",
|
331
|
+
proc: proc { |t| t = t.to_i * 60; Chef::Config[:aws_connection_timeout] = t },
|
332
|
+
default: 600
|
354
333
|
|
355
334
|
option :node_ssl_verify_mode,
|
356
|
-
:
|
357
|
-
:
|
358
|
-
:
|
359
|
-
valid_values =
|
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}
|
360
339
|
unless valid_values.include?(v)
|
361
340
|
raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}"
|
362
341
|
end
|
363
342
|
}
|
364
343
|
|
365
344
|
option :node_verify_api_cert,
|
366
|
-
:
|
367
|
-
:
|
368
|
-
:
|
345
|
+
long: "--[no-]node-verify-api-cert",
|
346
|
+
description: "Verify the SSL cert for HTTPS requests to the Chef server API.",
|
347
|
+
boolean: true
|
369
348
|
|
370
349
|
option :bootstrap_no_proxy,
|
371
|
-
:
|
372
|
-
:
|
373
|
-
:
|
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 }
|
374
353
|
|
375
354
|
option :bootstrap_url,
|
376
|
-
:
|
377
|
-
:
|
378
|
-
:
|
355
|
+
long: "--bootstrap-url URL",
|
356
|
+
description: "URL to a custom installation script",
|
357
|
+
proc: Proc.new { |u| Chef::Config[:knife][:bootstrap_url] = u }
|
379
358
|
|
380
359
|
option :bootstrap_install_command,
|
381
|
-
:
|
382
|
-
:
|
383
|
-
:
|
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 }
|
384
363
|
|
385
364
|
option :bootstrap_wget_options,
|
386
|
-
:
|
387
|
-
:
|
388
|
-
:
|
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 }
|
389
368
|
|
390
369
|
option :bootstrap_curl_options,
|
391
|
-
:
|
392
|
-
:
|
393
|
-
:
|
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 }
|
394
373
|
|
395
374
|
option :bootstrap_vault_file,
|
396
|
-
:
|
397
|
-
:
|
375
|
+
long: "--bootstrap-vault-file VAULT_FILE",
|
376
|
+
description: "A JSON file with a list of vault(s) and item(s) to be updated"
|
398
377
|
|
399
378
|
option :bootstrap_vault_json,
|
400
|
-
:
|
401
|
-
:
|
379
|
+
long: "--bootstrap-vault-json VAULT_JSON",
|
380
|
+
description: "A JSON string with the vault(s) and item(s) to be updated"
|
402
381
|
|
403
382
|
option :bootstrap_vault_item,
|
404
|
-
:
|
405
|
-
:
|
406
|
-
:
|
383
|
+
long: "--bootstrap-vault-item VAULT_ITEM",
|
384
|
+
description: 'A single vault and item to update as "vault:item"',
|
385
|
+
proc: Proc.new { |i|
|
407
386
|
(vault, item) = i.split(/:/)
|
408
387
|
Chef::Config[:knife][:bootstrap_vault_item] ||= {}
|
409
388
|
Chef::Config[:knife][:bootstrap_vault_item][vault] ||= []
|
@@ -412,75 +391,75 @@ class Chef
|
|
412
391
|
}
|
413
392
|
|
414
393
|
option :use_sudo_password,
|
415
|
-
:
|
416
|
-
:
|
417
|
-
:
|
394
|
+
long: "--use-sudo-password",
|
395
|
+
description: "Execute the bootstrap via sudo with password",
|
396
|
+
boolean: false
|
418
397
|
|
419
398
|
option :forward_agent,
|
420
|
-
:
|
421
|
-
:
|
422
|
-
:
|
423
|
-
:
|
399
|
+
short: "-A",
|
400
|
+
long: "--forward-agent",
|
401
|
+
description: "Enable SSH agent forwarding",
|
402
|
+
boolean: true
|
424
403
|
|
425
404
|
option :create_ssl_listener,
|
426
|
-
:
|
427
|
-
:
|
428
|
-
:
|
429
|
-
:
|
405
|
+
long: "--[no-]create-ssl-listener",
|
406
|
+
description: "Create ssl listener, enabled by default.",
|
407
|
+
boolean: true,
|
408
|
+
default: true
|
430
409
|
|
431
410
|
option :network_interfaces,
|
432
|
-
:
|
433
|
-
:
|
434
|
-
:
|
435
|
-
:
|
411
|
+
short: "-n",
|
412
|
+
long: "--attach-network-interface ENI1,ENI2",
|
413
|
+
description: "Attach additional network interfaces during bootstrap",
|
414
|
+
proc: proc { |nics| nics.split(",") }
|
436
415
|
|
437
416
|
option :classic_link_vpc_id,
|
438
|
-
:
|
439
|
-
:
|
417
|
+
long: "--classic-link-vpc-id VPC_ID",
|
418
|
+
description: "Enable ClassicLink connection with a VPC"
|
440
419
|
|
441
420
|
option :classic_link_vpc_security_group_ids,
|
442
|
-
:
|
443
|
-
:
|
444
|
-
:
|
421
|
+
long: "--classic-link-vpc-security-groups-ids X,Y,Z",
|
422
|
+
description: "Comma-separated list of security group ids for ClassicLink",
|
423
|
+
proc: Proc.new { |groups| groups.split(",") }
|
445
424
|
|
446
425
|
option :disable_api_termination,
|
447
|
-
:
|
448
|
-
:
|
449
|
-
:
|
450
|
-
:
|
426
|
+
long: "--disable-api-termination",
|
427
|
+
description: "Disable termination of the instance using the Amazon EC2 console, CLI and API.",
|
428
|
+
boolean: true,
|
429
|
+
default: false
|
451
430
|
|
452
431
|
option :volume_tags,
|
453
|
-
:
|
454
|
-
:
|
455
|
-
:
|
432
|
+
long: "--volume-tags Tag=Value[,Tag=Value...]",
|
433
|
+
description: "Tag the Root volume",
|
434
|
+
proc: Proc.new { |volume_tags| volume_tags.split(",") }
|
456
435
|
|
457
436
|
option :tag_node_in_chef,
|
458
|
-
:
|
459
|
-
:
|
460
|
-
:
|
437
|
+
long: "--tag-node-in-chef",
|
438
|
+
description: "Flag for tagging node in ec2 and chef both. [DEPRECATED] Use --chef-tag instead.",
|
439
|
+
proc: Proc.new { |v|
|
461
440
|
Chef::Log.warn("[DEPRECATED] --tag-node-in-chef option is deprecated. Use --chef-tag option instead.")
|
462
441
|
v
|
463
442
|
},
|
464
|
-
:
|
465
|
-
:
|
443
|
+
boolean: true,
|
444
|
+
default: false
|
466
445
|
|
467
446
|
option :instance_initiated_shutdown_behavior,
|
468
|
-
:
|
469
|
-
:
|
447
|
+
long: "--instance-initiated-shutdown-behavior SHUTDOWN_BEHAVIOR",
|
448
|
+
description: "Indicates whether an instance stops or terminates when you initiate shutdown from the instance. Possible values are 'stop' and 'terminate', default is 'stop'."
|
470
449
|
|
471
450
|
option :chef_tag,
|
472
|
-
:
|
473
|
-
:
|
474
|
-
:
|
451
|
+
long: "--chef-tag CHEF_TAG",
|
452
|
+
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.",
|
453
|
+
proc: Proc.new { |chef_tag|
|
475
454
|
Chef::Config[:knife][:chef_tag] ||= []
|
476
455
|
Chef::Config[:knife][:chef_tag].push(chef_tag)
|
477
456
|
Chef::Config[:knife][:chef_tag]
|
478
457
|
}
|
479
458
|
|
480
459
|
option :aws_tag,
|
481
|
-
:
|
482
|
-
:
|
483
|
-
:
|
460
|
+
long: "--aws-tag AWS_TAG",
|
461
|
+
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.",
|
462
|
+
proc: Proc.new { |aws_tag|
|
484
463
|
Chef::Config[:knife][:aws_tag] ||= []
|
485
464
|
Chef::Config[:knife][:aws_tag].push(aws_tag)
|
486
465
|
Chef::Config[:knife][:aws_tag]
|
@@ -493,7 +472,7 @@ class Chef
|
|
493
472
|
requested_elastic_ip = config[:associate_eip] if config[:associate_eip]
|
494
473
|
|
495
474
|
# For VPC EIP assignment we need the allocation ID so fetch full EIP details
|
496
|
-
elastic_ip = connection.addresses.detect{|addr| addr if addr.public_ip == requested_elastic_ip}
|
475
|
+
elastic_ip = connection.addresses.detect { |addr| addr if addr.public_ip == requested_elastic_ip }
|
497
476
|
|
498
477
|
if locate_config_value(:spot_price)
|
499
478
|
server_def = create_server_def
|
@@ -504,16 +483,16 @@ class Chef
|
|
504
483
|
msg_pair("Spot Price", spot_request.price)
|
505
484
|
|
506
485
|
case config[:spot_wait_mode]
|
507
|
-
when
|
486
|
+
when "prompt", "", nil
|
508
487
|
wait_msg = "Do you want to wait for Spot Instance Request fulfillment? (Y/N) \n"
|
509
488
|
wait_msg += "Y - Wait for Spot Instance request fulfillment\n"
|
510
489
|
wait_msg += "N - Do not wait for Spot Instance request fulfillment. "
|
511
490
|
wait_msg += ui.color("[WARN :: Request would be alive on AWS ec2 side but execution of Chef Bootstrap on the target instance will get skipped.]\n", :red, :bold)
|
512
491
|
wait_msg += ui.color("\n[WARN :: For any of the above mentioned choices, (Y) - if the instance does not get allocated before the command itself times-out or (N) - user decides to exit, then in both cases user needs to manually bootstrap the instance in the future after it gets allocated.]\n\n", :cyan, :bold)
|
513
492
|
confirm(wait_msg)
|
514
|
-
when
|
493
|
+
when "wait"
|
515
494
|
# wait for the node and run Chef bootstrap
|
516
|
-
when
|
495
|
+
when "exit"
|
517
496
|
ui.color("The 'exit' option was specified for --spot-wait-mode, exiting.", :cyan)
|
518
497
|
exit
|
519
498
|
else
|
@@ -540,8 +519,8 @@ class Chef
|
|
540
519
|
end
|
541
520
|
end
|
542
521
|
|
543
|
-
hashed_tags={}
|
544
|
-
tags.map{ |t| key,val=t.split(
|
522
|
+
hashed_tags = {}
|
523
|
+
tags.map { |t| key, val = t.split("="); hashed_tags[key] = val } unless tags.nil?
|
545
524
|
|
546
525
|
# Always set the Name tag
|
547
526
|
unless hashed_tags.keys.include? "Name"
|
@@ -552,12 +531,12 @@ class Chef
|
|
552
531
|
end
|
553
532
|
end
|
554
533
|
|
555
|
-
printed_aws_tags = hashed_tags.map{ |tag, val| "#{tag}: #{val}" }.join(", ")
|
534
|
+
printed_aws_tags = hashed_tags.map { |tag, val| "#{tag}: #{val}" }.join(", ")
|
556
535
|
|
557
|
-
hashed_volume_tags={}
|
536
|
+
hashed_volume_tags = {}
|
558
537
|
volume_tags = locate_config_value(:volume_tags)
|
559
|
-
volume_tags.map{ |t| key,val=t.split(
|
560
|
-
printed_volume_tags = hashed_volume_tags.map{ |tag, val| "#{tag}: #{val}" }.join(", ")
|
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(", ")
|
561
540
|
|
562
541
|
msg_pair("Instance ID", @server.id)
|
563
542
|
msg_pair("Flavor", @server.flavor_id)
|
@@ -571,11 +550,11 @@ class Chef
|
|
571
550
|
# 'default' is printed if no id was specified.
|
572
551
|
printed_security_groups = "default"
|
573
552
|
printed_security_groups = @server.groups.join(", ") if @server.groups
|
574
|
-
msg_pair("Security Groups", printed_security_groups) unless vpc_mode?
|
553
|
+
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? || (@server.groups.nil? && @server.security_group_ids)
|
575
554
|
|
576
555
|
printed_security_group_ids = "default"
|
577
556
|
printed_security_group_ids = @server.security_group_ids.join(", ") if @server.security_group_ids
|
578
|
-
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode?
|
557
|
+
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? || @server.security_group_ids
|
579
558
|
|
580
559
|
msg_pair("IAM Profile", locate_config_value(:iam_instance_profile))
|
581
560
|
|
@@ -627,24 +606,24 @@ class Chef
|
|
627
606
|
Chef::Config[:validation_key] = validation_key_path
|
628
607
|
end
|
629
608
|
|
630
|
-
#Check if Server is Windows or Linux
|
609
|
+
# Check if Server is Windows or Linux
|
631
610
|
if is_image_windows?
|
632
611
|
protocol = locate_config_value(:bootstrap_protocol)
|
633
|
-
protocol ||=
|
634
|
-
if protocol ==
|
612
|
+
protocol ||= "winrm"
|
613
|
+
if protocol == "winrm"
|
635
614
|
load_winrm_deps
|
636
615
|
print "\n#{ui.color("Waiting for winrm access to become available", :magenta)}"
|
637
|
-
print(".") until tcp_test_winrm(ssh_connect_host, locate_config_value(:winrm_port))
|
616
|
+
print(".") until tcp_test_winrm(ssh_connect_host, locate_config_value(:winrm_port)) do
|
638
617
|
sleep 10
|
639
618
|
puts("done")
|
640
|
-
|
619
|
+
end
|
641
620
|
else
|
642
621
|
print "\n#{ui.color("Waiting for sshd access to become available", :magenta)}"
|
643
|
-
#If FreeSSHd, winsshd etc are available
|
644
|
-
print(".") until tcp_test_ssh(ssh_connect_host, config[:ssh_port])
|
622
|
+
# If FreeSSHd, winsshd etc are available
|
623
|
+
print(".") until tcp_test_ssh(ssh_connect_host, config[:ssh_port]) do
|
645
624
|
sleep @initial_sleep_delay ||= (vpc_mode? ? 40 : 10)
|
646
625
|
puts("done")
|
647
|
-
|
626
|
+
end
|
648
627
|
ssh_override_winrm
|
649
628
|
end
|
650
629
|
bootstrap_for_windows_node(@server, ssh_connect_host).run
|
@@ -662,8 +641,8 @@ class Chef
|
|
662
641
|
msg_pair("Image", @server.image_id)
|
663
642
|
msg_pair("Region", connection.instance_variable_get(:@region))
|
664
643
|
msg_pair("Availability Zone", @server.availability_zone)
|
665
|
-
msg_pair("Security Groups", printed_security_groups) unless vpc_mode?
|
666
|
-
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode?
|
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
|
667
646
|
msg_pair("IAM Profile", locate_config_value(:iam_instance_profile)) if locate_config_value(:iam_instance_profile)
|
668
647
|
msg_pair("Primary ENI", locate_config_value(:primary_eni)) if locate_config_value(:primary_eni)
|
669
648
|
msg_pair("AWS Tags", printed_aws_tags)
|
@@ -673,30 +652,30 @@ class Chef
|
|
673
652
|
msg_pair("Root Volume Tags", printed_volume_tags)
|
674
653
|
if @server.root_device_type == "ebs"
|
675
654
|
device_map = @server.block_device_mapping.first
|
676
|
-
msg_pair("Root Volume ID", device_map[
|
677
|
-
msg_pair("Root Device Name", device_map[
|
678
|
-
msg_pair("Root Device Delete on Terminate", device_map[
|
679
|
-
msg_pair("Standard or Provisioned IOPS", device_map[
|
680
|
-
msg_pair("IOPS rate", device_map[
|
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"])
|
681
660
|
|
682
661
|
print "\n#{ui.color("Block devices", :magenta)}\n"
|
683
662
|
print "#{ui.color("===========================", :magenta)}\n"
|
684
663
|
@server.block_device_mapping.each do |device_map|
|
685
|
-
msg_pair("Device Name", device_map[
|
686
|
-
msg_pair("Volume ID", device_map[
|
687
|
-
msg_pair("Delete on Terminate", device_map[
|
688
|
-
msg_pair("Standard or Provisioned IOPS", device_map[
|
689
|
-
msg_pair("IOPS rate", 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"])
|
690
669
|
print "\n"
|
691
670
|
end
|
692
671
|
print "#{ui.color("===========================", :magenta)}\n"
|
693
672
|
|
694
673
|
if config[:ebs_size]
|
695
|
-
if ami.block_device_mapping.first[
|
674
|
+
if ami.block_device_mapping.first["volumeSize"].to_i < config[:ebs_size].to_i
|
696
675
|
volume_too_large_warning = "#{config[:ebs_size]}GB " +
|
697
|
-
|
698
|
-
|
699
|
-
|
676
|
+
"EBS volume size is larger than size set in AMI of " +
|
677
|
+
"#{ami.block_device_mapping.first['volumeSize']}GB.\n" +
|
678
|
+
"Use file system tools to make use of the increased volume size."
|
700
679
|
msg_pair("Warning", volume_too_large_warning, :yellow)
|
701
680
|
end
|
702
681
|
end
|
@@ -716,20 +695,22 @@ class Chef
|
|
716
695
|
msg_pair("Private DNS Name", @server.private_dns_name)
|
717
696
|
end
|
718
697
|
msg_pair("Private IP Address", @server.private_ip_address)
|
719
|
-
msg_pair("Environment", config[:environment] ||
|
720
|
-
msg_pair("Run List", (config[:run_list] || []).join(
|
698
|
+
msg_pair("Environment", config[:environment] || "_default")
|
699
|
+
msg_pair("Run List", (config[:run_list] || []).join(", "))
|
721
700
|
if config[:first_boot_attributes] || config[:first_boot_attributes_from_file]
|
722
|
-
msg_pair("JSON Attributes",config[:first_boot_attributes] || config[:first_boot_attributes_from_file])
|
701
|
+
msg_pair("JSON Attributes", config[:first_boot_attributes] || config[:first_boot_attributes_from_file])
|
723
702
|
end
|
724
703
|
end
|
725
704
|
|
705
|
+
# return the default bootstrap template based on platform
|
706
|
+
# @return [String]
|
726
707
|
def default_bootstrap_template
|
727
|
-
is_image_windows? ?
|
708
|
+
is_image_windows? ? "windows-chef-client-msi" : "chef-full"
|
728
709
|
end
|
729
710
|
|
730
711
|
def validation_key_path
|
731
712
|
@validation_key_path ||= begin
|
732
|
-
if URI(Chef::Config[:knife][:validation_key_url]).scheme ==
|
713
|
+
if URI(Chef::Config[:knife][:validation_key_url]).scheme == "file"
|
733
714
|
URI(Chef::Config[:knife][:validation_key_url]).path
|
734
715
|
else
|
735
716
|
validation_key_tmpfile.path
|
@@ -737,18 +718,19 @@ class Chef
|
|
737
718
|
end
|
738
719
|
end
|
739
720
|
|
721
|
+
# @return [Tempfile]
|
740
722
|
def validation_key_tmpfile
|
741
|
-
@validation_key_tmpfile ||= Tempfile.new(
|
723
|
+
@validation_key_tmpfile ||= Tempfile.new("validation_key")
|
742
724
|
end
|
743
725
|
|
744
726
|
def download_validation_key(tempfile)
|
745
|
-
Chef::Log.debug
|
727
|
+
Chef::Log.debug "Downloading validation key " \
|
746
728
|
"<#{Chef::Config[:knife][:validation_key_url]}> to file " \
|
747
729
|
"<#{tempfile}>"
|
748
730
|
|
749
731
|
case URI(Chef::Config[:knife][:validation_key_url]).scheme
|
750
|
-
when
|
751
|
-
File.open(tempfile,
|
732
|
+
when "s3"
|
733
|
+
File.open(tempfile, "w") { |f| f.write(s3_validation_key) }
|
752
734
|
end
|
753
735
|
end
|
754
736
|
|
@@ -770,9 +752,6 @@ class Chef
|
|
770
752
|
bootstrap.config[:policy_group] = locate_config_value(:policy_group)
|
771
753
|
bootstrap.config[:policy_name] = locate_config_value(:policy_name)
|
772
754
|
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
773
|
-
bootstrap.config[:distro] = locate_config_value(:distro) || default_bootstrap_template
|
774
|
-
# setting bootstrap_template value to template_file for backward compatibility
|
775
|
-
bootstrap.config[:template_file] = locate_config_value(:template_file) || locate_config_value(:bootstrap_template)
|
776
755
|
bootstrap.config[:environment] = locate_config_value(:environment)
|
777
756
|
bootstrap.config[:prerelease] = config[:prerelease]
|
778
757
|
bootstrap.config[:first_boot_attributes] = locate_config_value(:first_boot_attributes)
|
@@ -813,14 +792,14 @@ class Chef
|
|
813
792
|
end
|
814
793
|
|
815
794
|
def fetch_server_fqdn(ip_addr)
|
816
|
-
require
|
795
|
+
require "resolv"
|
817
796
|
Resolv.getname(ip_addr)
|
818
797
|
end
|
819
798
|
|
820
799
|
def bootstrap_for_windows_node(server, fqdn)
|
821
|
-
if locate_config_value(:bootstrap_protocol) ==
|
800
|
+
if locate_config_value(:bootstrap_protocol) == "winrm" || locate_config_value(:bootstrap_protocol).nil?
|
822
801
|
if locate_config_value(:kerberos_realm)
|
823
|
-
#Fetch AD/WINS based fqdn if any for Kerberos-based Auth
|
802
|
+
# Fetch AD/WINS based fqdn if any for Kerberos-based Auth
|
824
803
|
fqdn = locate_config_value(:fqdn) || fetch_server_fqdn(server.private_ip_address)
|
825
804
|
end
|
826
805
|
bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
|
@@ -834,7 +813,7 @@ class Chef
|
|
834
813
|
bootstrap.config[:winrm_port] = locate_config_value(:winrm_port)
|
835
814
|
bootstrap.config[:auth_timeout] = locate_config_value(:auth_timeout)
|
836
815
|
bootstrap.config[:winrm_ssl_verify_mode] = locate_config_value(:winrm_ssl_verify_mode)
|
837
|
-
elsif locate_config_value(:bootstrap_protocol) ==
|
816
|
+
elsif locate_config_value(:bootstrap_protocol) == "ssh"
|
838
817
|
bootstrap = Chef::Knife::BootstrapWindowsSsh.new
|
839
818
|
bootstrap.config[:ssh_user] = locate_config_value(:ssh_user)
|
840
819
|
bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
|
@@ -859,7 +838,7 @@ class Chef
|
|
859
838
|
bootstrap_common_params(bootstrap)
|
860
839
|
end
|
861
840
|
|
862
|
-
def bootstrap_for_linux_node(server,ssh_host)
|
841
|
+
def bootstrap_for_linux_node(server, ssh_host)
|
863
842
|
bootstrap = Chef::Knife::Bootstrap.new
|
864
843
|
bootstrap.name_args = [ssh_host]
|
865
844
|
bootstrap.config[:ssh_user] = config[:ssh_user]
|
@@ -873,7 +852,7 @@ class Chef
|
|
873
852
|
else
|
874
853
|
bootstrap.config[:chef_node_name] = server.id
|
875
854
|
end
|
876
|
-
bootstrap.config[:use_sudo] = true unless config[:ssh_user] ==
|
855
|
+
bootstrap.config[:use_sudo] = true unless config[:ssh_user] == "root"
|
877
856
|
# may be needed for vpc_mode
|
878
857
|
bootstrap.config[:host_key_verify] = config[:host_key_verify]
|
879
858
|
bootstrap_common_params(bootstrap)
|
@@ -901,50 +880,50 @@ class Chef
|
|
901
880
|
validate_nics! if locate_config_value(:network_interfaces)
|
902
881
|
|
903
882
|
if ami.nil?
|
904
|
-
ui.error("
|
883
|
+
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)}?")
|
905
884
|
exit 1
|
906
885
|
end
|
907
886
|
|
908
|
-
if vpc_mode?
|
887
|
+
if vpc_mode? && !!config[:security_groups]
|
909
888
|
ui.error("You are using a VPC, security groups specified with '-G' are not allowed, specify one or more security group ids with '-g' instead.")
|
910
889
|
exit 1
|
911
890
|
end
|
912
891
|
|
913
|
-
if !vpc_mode?
|
892
|
+
if !vpc_mode? && !!config[:private_ip_address]
|
914
893
|
ui.error("You can only specify a private IP address if you are using VPC.")
|
915
894
|
exit 1
|
916
895
|
end
|
917
896
|
|
918
|
-
if config[:dedicated_instance]
|
897
|
+
if config[:dedicated_instance] && !vpc_mode?
|
919
898
|
ui.error("You can only specify a Dedicated Instance if you are using VPC.")
|
920
899
|
exit 1
|
921
900
|
end
|
922
901
|
|
923
|
-
if !vpc_mode?
|
902
|
+
if !vpc_mode? && config[:associate_public_ip]
|
924
903
|
ui.error("--associate-public-ip option only applies to VPC instances, and you have not specified a subnet id.")
|
925
904
|
exit 1
|
926
905
|
end
|
927
906
|
|
928
907
|
if config[:associate_eip]
|
929
|
-
eips = connection.addresses.collect{|addr| addr if addr.domain == eip_scope}.compact
|
908
|
+
eips = connection.addresses.collect { |addr| addr if addr.domain == eip_scope }.compact
|
930
909
|
|
931
|
-
unless eips.detect{|addr| addr.public_ip == config[:associate_eip] && addr.server_id
|
910
|
+
unless eips.detect { |addr| addr.public_ip == config[:associate_eip] && addr.server_id.nil? }
|
932
911
|
ui.error("Elastic IP requested is not available.")
|
933
912
|
exit 1
|
934
913
|
end
|
935
914
|
end
|
936
915
|
|
937
|
-
if config[:ebs_provisioned_iops]
|
916
|
+
if config[:ebs_provisioned_iops] && (config[:ebs_volume_type] != "io1")
|
938
917
|
ui.error("--provisioned-iops option is only supported for volume type of 'io1'")
|
939
918
|
exit 1
|
940
919
|
end
|
941
920
|
|
942
|
-
if config[:ebs_volume_type] ==
|
921
|
+
if (config[:ebs_volume_type] == "io1") && config[:ebs_provisioned_iops].nil?
|
943
922
|
ui.error("--provisioned-iops option is required when using volume type of 'io1'")
|
944
923
|
exit 1
|
945
924
|
end
|
946
925
|
|
947
|
-
if config[:ebs_volume_type]
|
926
|
+
if config[:ebs_volume_type] && ! %w{gp2 io1 standard}.include?(config[:ebs_volume_type])
|
948
927
|
ui.error("--ebs-volume-type must be 'standard' or 'io1' or 'gp2'")
|
949
928
|
msg opt_parser
|
950
929
|
exit 1
|
@@ -966,7 +945,7 @@ class Chef
|
|
966
945
|
exit 1
|
967
946
|
end
|
968
947
|
|
969
|
-
if vpc_mode?
|
948
|
+
if vpc_mode? && config[:classic_link_vpc_id]
|
970
949
|
ui.error("You can only use ClassicLink if you are not using a VPC")
|
971
950
|
exit 1
|
972
951
|
end
|
@@ -978,15 +957,15 @@ class Chef
|
|
978
957
|
if !locate_config_value(:flavor)
|
979
958
|
ui.error("--ebs-encrypted option requires valid flavor to be specified.")
|
980
959
|
exit 1
|
981
|
-
elsif
|
960
|
+
elsif locate_config_value(:ebs_encrypted) && ! %w{m3.medium m3.large m3.xlarge m3.2xlarge m4.large m4.xlarge
|
982
961
|
m4.2xlarge m4.4xlarge m4.10xlarge m4.16xlarge t2.nano t2.micro t2.small
|
983
|
-
t2.medium t2.large t2.xlarge t2.2xlarge d2.xlarge
|
962
|
+
t2.medium t2.large t2.xlarge t2.2xlarge d2.xlarge d2.2xlarge d2.4xlarge
|
984
963
|
d2.8xlarge c4.large c4.xlarge c4.2xlarge c4.4xlarge c4.8xlarge c3.large
|
985
964
|
c3.xlarge c3.2xlarge c3.4xlarge c3.8xlarge cr1.8xlarge r3.large r3.xlarge
|
986
965
|
r3.2xlarge r3.4xlarge r3.8xlarge r4.large r4.xlarge r4.2xlarge r4.4xlarge
|
987
966
|
r4.8xlarge r4.16xlarge x1.16xlarge x1.32xlarge i2.xlarge i2.2xlarge i2.4xlarge
|
988
967
|
i2.8xlarge i3.large i3.xlarge i3.2xlarge i3.4xlarge i3.8xlarge i3.16xlarge
|
989
|
-
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge
|
968
|
+
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge}.include?(locate_config_value(:flavor))
|
990
969
|
ui.error("--ebs-encrypted option is not supported for #{locate_config_value(:flavor)} flavor.")
|
991
970
|
exit 1
|
992
971
|
end
|
@@ -994,15 +973,15 @@ class Chef
|
|
994
973
|
# validation for ebs_size and ebs_volume_type and ebs_encrypted
|
995
974
|
if !locate_config_value(:ebs_size)
|
996
975
|
errors << "--ebs-encrypted option requires valid --ebs-size to be specified."
|
997
|
-
elsif locate_config_value(:ebs_volume_type) == "gp2"
|
976
|
+
elsif (locate_config_value(:ebs_volume_type) == "gp2") && ! locate_config_value(:ebs_size).to_i.between?(1, 16384)
|
998
977
|
errors << "--ebs-size should be in between 1-16384 for 'gp2' ebs volume type."
|
999
|
-
elsif locate_config_value(:ebs_volume_type) == "io1"
|
978
|
+
elsif (locate_config_value(:ebs_volume_type) == "io1") && ! locate_config_value(:ebs_size).to_i.between?(4, 16384)
|
1000
979
|
errors << "--ebs-size should be in between 4-16384 for 'io1' ebs volume type."
|
1001
|
-
elsif locate_config_value(:ebs_volume_type) == "standard"
|
980
|
+
elsif (locate_config_value(:ebs_volume_type) == "standard") && ! locate_config_value(:ebs_size).to_i.between?(1, 1024)
|
1002
981
|
errors << "--ebs-size should be in between 1-1024 for 'standard' ebs volume type."
|
1003
982
|
end
|
1004
983
|
|
1005
|
-
if errors.each{|e| error_message = "#{error_message} #{e}"}.any?
|
984
|
+
if errors.each { |e| error_message = "#{error_message} #{e}" }.any?
|
1006
985
|
ui.error(error_message)
|
1007
986
|
exit 1
|
1008
987
|
end
|
@@ -1013,26 +992,26 @@ class Chef
|
|
1013
992
|
exit 1
|
1014
993
|
end
|
1015
994
|
|
1016
|
-
if locate_config_value(:spot_price).nil? && locate_config_value(:spot_wait_mode).
|
1017
|
-
ui.error(
|
995
|
+
if locate_config_value(:spot_price).nil? && !locate_config_value(:spot_wait_mode).casecmp("prompt").zero?
|
996
|
+
ui.error("spot-wait-mode option requires that a spot-price option is set.")
|
1018
997
|
exit 1
|
1019
998
|
end
|
1020
999
|
|
1021
1000
|
volume_tags = locate_config_value(:volume_tags)
|
1022
|
-
if !volume_tags.nil?
|
1001
|
+
if !volume_tags.nil? && (volume_tags.length != volume_tags.to_s.count("="))
|
1023
1002
|
ui.error("Volume Tags should be entered in a key = value pair")
|
1024
1003
|
exit 1
|
1025
1004
|
end
|
1026
1005
|
|
1027
|
-
if
|
1006
|
+
if locate_config_value(:winrm_password).to_s.length > 14
|
1028
1007
|
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):")
|
1029
1008
|
password_promt = STDIN.gets.chomp.upcase
|
1030
|
-
if
|
1031
|
-
|
1032
|
-
elsif
|
1033
|
-
|
1009
|
+
if password_promt == "N"
|
1010
|
+
raise "Exiting as operation with password greater than 14 characters not accepted"
|
1011
|
+
elsif password_promt == "Y"
|
1012
|
+
@allow_long_password = "/yes"
|
1034
1013
|
else
|
1035
|
-
|
1014
|
+
raise "The input provided is incorrect."
|
1036
1015
|
end
|
1037
1016
|
end
|
1038
1017
|
|
@@ -1046,12 +1025,12 @@ class Chef
|
|
1046
1025
|
end
|
1047
1026
|
|
1048
1027
|
def tags
|
1049
|
-
|
1050
|
-
if !tags.nil?
|
1028
|
+
tags = locate_config_value(:tags) || locate_config_value(:aws_tag)
|
1029
|
+
if !tags.nil? && (tags.length != tags.to_s.count("="))
|
1051
1030
|
ui.error("AWS Tags should be entered in a key = value pair")
|
1052
1031
|
exit 1
|
1053
1032
|
end
|
1054
|
-
|
1033
|
+
tags
|
1055
1034
|
end
|
1056
1035
|
|
1057
1036
|
def eip_scope
|
@@ -1063,64 +1042,64 @@ class Chef
|
|
1063
1042
|
end
|
1064
1043
|
|
1065
1044
|
def ssl_config_user_data
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
net user /add #{locate_config_value(:winrm_user).delete('.\\')} #{windows_password} #{@allow_long_password};
|
1071
|
-
net localgroup Administrators /add #{locate_config_value(:winrm_user).delete('.\\')};
|
1045
|
+
user_related_commands = ""
|
1046
|
+
winrm_user = locate_config_value(:winrm_user).split("\\")
|
1047
|
+
if (winrm_user[0] == ".") || (winrm_user[0] == "") || (winrm_user.length == 1)
|
1048
|
+
user_related_commands = <<~EOH
|
1049
|
+
net user /add #{locate_config_value(:winrm_user).delete('.\\')} #{windows_password} #{@allow_long_password};
|
1050
|
+
net localgroup Administrators /add #{locate_config_value(:winrm_user).delete('.\\')};
|
1072
1051
|
EOH
|
1073
|
-
|
1074
|
-
|
1075
|
-
#{user_related_commands}
|
1076
|
-
If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
|
1077
|
-
|
1078
|
-
}
|
1079
|
-
If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
|
1080
|
-
|
1081
|
-
}
|
1082
|
-
$vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
|
1083
|
-
If (-Not $vm_name) {
|
1084
|
-
|
1085
|
-
}
|
1086
|
-
|
1087
|
-
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
|
1088
|
-
$name.Encode("CN=$vm_name", 0)
|
1089
|
-
$key = new-object -com "X509Enrollment.CX509PrivateKey.1"
|
1090
|
-
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
|
1091
|
-
$key.KeySpec = 1
|
1092
|
-
$key.Length = 2048
|
1093
|
-
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
|
1094
|
-
$key.MachineContext = 1
|
1095
|
-
$key.Create()
|
1096
|
-
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
|
1097
|
-
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
|
1098
|
-
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
|
1099
|
-
$ekuoids.add($serverauthoid)
|
1100
|
-
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
|
1101
|
-
$ekuext.InitializeEncode($ekuoids)
|
1102
|
-
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
|
1103
|
-
$cert.InitializeFromPrivateKey(2, $key, "")
|
1104
|
-
$cert.Subject = $name
|
1105
|
-
$cert.Issuer = $cert.Subject
|
1106
|
-
$cert.NotBefore = get-date
|
1107
|
-
$cert.NotAfter = $cert.NotBefore.AddYears(10)
|
1108
|
-
$cert.X509Extensions.Add($ekuext)
|
1109
|
-
$cert.Encode()
|
1110
|
-
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
|
1111
|
-
$enrollment.InitializeFromRequest($cert)
|
1112
|
-
$certdata = $enrollment.CreateRequest(0)
|
1113
|
-
$enrollment.InstallResponse(2, $certdata, 0, "")
|
1114
|
-
|
1115
|
-
$thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
|
1116
|
-
$create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
|
1117
|
-
iex $create_listener_cmd
|
1118
|
-
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
|
1052
|
+
end
|
1053
|
+
<<~EOH
|
1054
|
+
#{user_related_commands}
|
1055
|
+
If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
|
1056
|
+
winrm quickconfig -q
|
1057
|
+
}
|
1058
|
+
If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
|
1059
|
+
winrm delete winrm/config/listener?Address=*+Transport=HTTP
|
1060
|
+
}
|
1061
|
+
$vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
|
1062
|
+
If (-Not $vm_name) {
|
1063
|
+
$vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/local-ipv4
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
|
1067
|
+
$name.Encode("CN=$vm_name", 0)
|
1068
|
+
$key = new-object -com "X509Enrollment.CX509PrivateKey.1"
|
1069
|
+
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
|
1070
|
+
$key.KeySpec = 1
|
1071
|
+
$key.Length = 2048
|
1072
|
+
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
|
1073
|
+
$key.MachineContext = 1
|
1074
|
+
$key.Create()
|
1075
|
+
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
|
1076
|
+
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
|
1077
|
+
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
|
1078
|
+
$ekuoids.add($serverauthoid)
|
1079
|
+
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
|
1080
|
+
$ekuext.InitializeEncode($ekuoids)
|
1081
|
+
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
|
1082
|
+
$cert.InitializeFromPrivateKey(2, $key, "")
|
1083
|
+
$cert.Subject = $name
|
1084
|
+
$cert.Issuer = $cert.Subject
|
1085
|
+
$cert.NotBefore = get-date
|
1086
|
+
$cert.NotAfter = $cert.NotBefore.AddYears(10)
|
1087
|
+
$cert.X509Extensions.Add($ekuext)
|
1088
|
+
$cert.Encode()
|
1089
|
+
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
|
1090
|
+
$enrollment.InitializeFromRequest($cert)
|
1091
|
+
$certdata = $enrollment.CreateRequest(0)
|
1092
|
+
$enrollment.InstallResponse(2, $certdata, 0, "")
|
1093
|
+
|
1094
|
+
$thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
|
1095
|
+
$create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
|
1096
|
+
iex $create_listener_cmd
|
1097
|
+
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
|
1119
1098
|
EOH
|
1120
1099
|
end
|
1121
1100
|
|
1122
1101
|
def ssl_config_data_already_exist?
|
1123
|
-
File.read(locate_config_value(:aws_user_data)).gsub(/\\\\/,"\\").include? ssl_config_user_data.strip
|
1102
|
+
File.read(locate_config_value(:aws_user_data)).gsub(/\\\\/, "\\").include? ssl_config_user_data.strip
|
1124
1103
|
end
|
1125
1104
|
|
1126
1105
|
def process_user_data(script_lines)
|
@@ -1136,7 +1115,7 @@ EOH
|
|
1136
1115
|
when ps_start_tag_index && ps_end_tag_index
|
1137
1116
|
script_lines[ps_end_tag_index] = ssl_config_user_data + ps_end_tag
|
1138
1117
|
when !ps_start_tag_index && !ps_end_tag_index
|
1139
|
-
script_lines.insert(-1,"\n\n" + ps_start_tag + ssl_config_user_data + ps_end_tag)
|
1118
|
+
script_lines.insert(-1, "\n\n" + ps_start_tag + ssl_config_user_data + ps_end_tag)
|
1140
1119
|
end
|
1141
1120
|
end
|
1142
1121
|
script_lines
|
@@ -1144,20 +1123,20 @@ EOH
|
|
1144
1123
|
|
1145
1124
|
def create_server_def
|
1146
1125
|
server_def = {
|
1147
|
-
:
|
1148
|
-
:
|
1149
|
-
:
|
1150
|
-
:
|
1151
|
-
:
|
1152
|
-
:
|
1153
|
-
:
|
1126
|
+
image_id: locate_config_value(:image),
|
1127
|
+
groups: config[:security_groups],
|
1128
|
+
flavor_id: locate_config_value(:flavor),
|
1129
|
+
key_name: locate_config_value(:ssh_key_name),
|
1130
|
+
availability_zone: locate_config_value(:availability_zone),
|
1131
|
+
price: locate_config_value(:spot_price),
|
1132
|
+
request_type: locate_config_value(:spot_request_type),
|
1154
1133
|
}
|
1155
1134
|
|
1156
1135
|
if primary_eni = locate_config_value(:primary_eni)
|
1157
1136
|
server_def[:network_interfaces] = [
|
1158
1137
|
{
|
1159
|
-
:
|
1160
|
-
:
|
1138
|
+
NetworkInterfaceId: primary_eni,
|
1139
|
+
DeviceIndex: "0",
|
1161
1140
|
}
|
1162
1141
|
]
|
1163
1142
|
else
|
@@ -1168,10 +1147,10 @@ EOH
|
|
1168
1147
|
server_def[:private_ip_address] = locate_config_value(:private_ip_address) if vpc_mode?
|
1169
1148
|
server_def[:placement_group] = locate_config_value(:placement_group)
|
1170
1149
|
server_def[:iam_instance_profile_name] = locate_config_value(:iam_instance_profile)
|
1171
|
-
server_def[:tenancy] = "dedicated" if vpc_mode?
|
1172
|
-
server_def[:associate_public_ip] = locate_config_value(:associate_public_ip) if vpc_mode?
|
1150
|
+
server_def[:tenancy] = "dedicated" if vpc_mode? && locate_config_value(:dedicated_instance)
|
1151
|
+
server_def[:associate_public_ip] = locate_config_value(:associate_public_ip) if vpc_mode? && config[:associate_public_ip]
|
1173
1152
|
|
1174
|
-
if locate_config_value(:winrm_transport) ==
|
1153
|
+
if locate_config_value(:winrm_transport) == "ssl"
|
1175
1154
|
if locate_config_value(:aws_user_data)
|
1176
1155
|
begin
|
1177
1156
|
user_data = File.readlines(locate_config_value(:aws_user_data))
|
@@ -1179,19 +1158,19 @@ EOH
|
|
1179
1158
|
user_data = process_user_data(user_data)
|
1180
1159
|
end
|
1181
1160
|
user_data = user_data.join
|
1182
|
-
server_def.merge!(:
|
1161
|
+
server_def.merge!(user_data: user_data)
|
1183
1162
|
rescue
|
1184
1163
|
ui.warn("Cannot read #{locate_config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
|
1185
1164
|
end
|
1186
1165
|
else
|
1187
1166
|
if config[:create_ssl_listener]
|
1188
|
-
server_def
|
1167
|
+
server_def[:user_data] = "<powershell>\n" + ssl_config_user_data + "</powershell>\n"
|
1189
1168
|
end
|
1190
1169
|
end
|
1191
1170
|
else
|
1192
1171
|
if locate_config_value(:aws_user_data)
|
1193
1172
|
begin
|
1194
|
-
server_def.merge!(:
|
1173
|
+
server_def.merge!(user_data: File.read(locate_config_value(:aws_user_data)))
|
1195
1174
|
rescue
|
1196
1175
|
ui.warn("Cannot read #{locate_config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
|
1197
1176
|
end
|
@@ -1241,17 +1220,17 @@ EOH
|
|
1241
1220
|
|
1242
1221
|
server_def[:block_device_mapping] =
|
1243
1222
|
[{
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1223
|
+
"DeviceName" => ami_map["deviceName"],
|
1224
|
+
"Ebs.VolumeSize" => ebs_size,
|
1225
|
+
"Ebs.DeleteOnTermination" => delete_term,
|
1226
|
+
"Ebs.VolumeType" => config[:ebs_volume_type],
|
1248
1227
|
}]
|
1249
|
-
server_def[:block_device_mapping].first[
|
1250
|
-
server_def[:block_device_mapping].first[
|
1228
|
+
server_def[:block_device_mapping].first["Ebs.Iops"] = iops_rate unless iops_rate.empty?
|
1229
|
+
server_def[:block_device_mapping].first["Ebs.Encrypted"] = true if locate_config_value(:ebs_encrypted)
|
1251
1230
|
end
|
1252
1231
|
|
1253
1232
|
(config[:ephemeral] || []).each_with_index do |device_name, i|
|
1254
|
-
server_def[:block_device_mapping] = (server_def[:block_device_mapping] || []) << {
|
1233
|
+
server_def[:block_device_mapping] = (server_def[:block_device_mapping] || []) << { "VirtualName" => "ephemeral#{i}", "DeviceName" => device_name }
|
1255
1234
|
end
|
1256
1235
|
|
1257
1236
|
## cannot pass disable_api_termination option to the API when using spot instances ##
|
@@ -1300,7 +1279,7 @@ EOH
|
|
1300
1279
|
|
1301
1280
|
def wait_for_tunnelled_sshd(ssh_gateway, hostname)
|
1302
1281
|
initial = true
|
1303
|
-
print(".") until tunnel_test_ssh(ssh_gateway, hostname)
|
1282
|
+
print(".") until tunnel_test_ssh(ssh_gateway, hostname) do
|
1304
1283
|
if initial
|
1305
1284
|
initial = false
|
1306
1285
|
sleep (vpc_mode? ? 40 : 10)
|
@@ -1308,14 +1287,14 @@ EOH
|
|
1308
1287
|
sleep 10
|
1309
1288
|
end
|
1310
1289
|
puts("done")
|
1311
|
-
|
1290
|
+
end
|
1312
1291
|
end
|
1313
1292
|
|
1314
1293
|
def tunnel_test_ssh(ssh_gateway, hostname, &block)
|
1315
1294
|
status = false
|
1316
1295
|
gateway = configure_ssh_gateway(ssh_gateway)
|
1317
1296
|
gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port|
|
1318
|
-
status = tcp_test_ssh(
|
1297
|
+
status = tcp_test_ssh("localhost", local_tunnel_port, &block)
|
1319
1298
|
end
|
1320
1299
|
status
|
1321
1300
|
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
@@ -1326,9 +1305,9 @@ EOH
|
|
1326
1305
|
end
|
1327
1306
|
|
1328
1307
|
def configure_ssh_gateway(ssh_gateway)
|
1329
|
-
gw_host, gw_user = ssh_gateway.split(
|
1330
|
-
gw_host, gw_port = gw_host.split(
|
1331
|
-
gateway_options = { :
|
1308
|
+
gw_host, gw_user = ssh_gateway.split("@").reverse
|
1309
|
+
gw_host, gw_port = gw_host.split(":")
|
1310
|
+
gateway_options = { port: gw_port || 22 }
|
1332
1311
|
|
1333
1312
|
# Load the SSH config for the SSH gateway host.
|
1334
1313
|
# Set the gateway user if it was not part of the
|
@@ -1354,7 +1333,7 @@ EOH
|
|
1354
1333
|
|
1355
1334
|
def wait_for_direct_sshd(hostname, ssh_port)
|
1356
1335
|
initial = true
|
1357
|
-
print(".") until tcp_test_ssh(hostname, ssh_port)
|
1336
|
+
print(".") until tcp_test_ssh(hostname, ssh_port) do
|
1358
1337
|
if initial
|
1359
1338
|
initial = false
|
1360
1339
|
sleep (vpc_mode? ? 40 : 10)
|
@@ -1362,7 +1341,7 @@ EOH
|
|
1362
1341
|
sleep 10
|
1363
1342
|
end
|
1364
1343
|
puts("done")
|
1365
|
-
|
1344
|
+
end
|
1366
1345
|
end
|
1367
1346
|
|
1368
1347
|
def subnet_public_ip_on_launch?
|
@@ -1389,8 +1368,8 @@ EOH
|
|
1389
1368
|
end
|
1390
1369
|
|
1391
1370
|
def create_tags(hashed_tags)
|
1392
|
-
hashed_tags.each_pair do |key,val|
|
1393
|
-
connection.tags.create :
|
1371
|
+
hashed_tags.each_pair do |key, val|
|
1372
|
+
connection.tags.create key: key, value: val, resource_id: @server.id
|
1394
1373
|
end
|
1395
1374
|
end
|
1396
1375
|
|
@@ -1401,12 +1380,12 @@ EOH
|
|
1401
1380
|
|
1402
1381
|
def validate_nics!
|
1403
1382
|
valid_nic_ids = connection.network_interfaces.all(
|
1404
|
-
vpc_mode? ? {
|
1383
|
+
vpc_mode? ? { "vpc-id" => vpc_id } : {}
|
1405
1384
|
).map(&:network_interface_id)
|
1406
1385
|
invalid_nic_ids =
|
1407
1386
|
locate_config_value(:network_interfaces) - valid_nic_ids
|
1408
1387
|
return true if invalid_nic_ids.empty?
|
1409
|
-
ui.error
|
1388
|
+
ui.error "The following network interfaces are invalid: " \
|
1410
1389
|
"#{invalid_nic_ids.join(', ')}"
|
1411
1390
|
exit 1
|
1412
1391
|
end
|
@@ -1420,12 +1399,12 @@ EOH
|
|
1420
1399
|
def wait_for_nic_attachment
|
1421
1400
|
attached_nics_count = 0
|
1422
1401
|
until attached_nics_count ==
|
1423
|
-
|
1402
|
+
locate_config_value(:network_interfaces).count
|
1424
1403
|
attachment_nics =
|
1425
1404
|
locate_config_value(:network_interfaces).map do |nic_id|
|
1426
|
-
connection.network_interfaces.get(nic_id).attachment[
|
1405
|
+
connection.network_interfaces.get(nic_id).attachment["status"]
|
1427
1406
|
end
|
1428
|
-
attached_nics_count = attachment_nics.grep(
|
1407
|
+
attached_nics_count = attachment_nics.grep("attached").count
|
1429
1408
|
end
|
1430
1409
|
end
|
1431
1410
|
|
@@ -1489,7 +1468,7 @@ EOH
|
|
1489
1468
|
rescue Errno::ENETUNREACH
|
1490
1469
|
sleep 2
|
1491
1470
|
false
|
1492
|
-
|
1471
|
+
ensure
|
1493
1472
|
tcp_socket && tcp_socket.close
|
1494
1473
|
end
|
1495
1474
|
|
@@ -1498,7 +1477,7 @@ EOH
|
|
1498
1477
|
readable = IO.select([tcp_socket], nil, nil, 5)
|
1499
1478
|
if readable
|
1500
1479
|
ssh_banner = tcp_socket.gets
|
1501
|
-
if ssh_banner.nil?
|
1480
|
+
if ssh_banner.nil? || ssh_banner.empty?
|
1502
1481
|
false
|
1503
1482
|
else
|
1504
1483
|
Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{ssh_banner}")
|
@@ -1525,8 +1504,8 @@ EOH
|
|
1525
1504
|
end
|
1526
1505
|
|
1527
1506
|
def decrypt_admin_password(encoded_password, key)
|
1528
|
-
require
|
1529
|
-
require
|
1507
|
+
require "base64"
|
1508
|
+
require "openssl"
|
1530
1509
|
private_key = OpenSSL::PKey::RSA.new(key)
|
1531
1510
|
encrypted_password = Base64.decode64(encoded_password)
|
1532
1511
|
password = private_key.private_decrypt(encrypted_password)
|
@@ -1564,22 +1543,22 @@ EOH
|
|
1564
1543
|
end
|
1565
1544
|
|
1566
1545
|
def load_winrm_deps
|
1567
|
-
require
|
1568
|
-
require
|
1569
|
-
require
|
1570
|
-
require
|
1571
|
-
require
|
1546
|
+
require "winrm"
|
1547
|
+
require "chef/knife/winrm"
|
1548
|
+
require "chef/knife/bootstrap_windows_winrm"
|
1549
|
+
require "chef/knife/bootstrap_windows_ssh"
|
1550
|
+
require "chef/knife/core/windows_bootstrap_context"
|
1572
1551
|
end
|
1573
1552
|
|
1574
|
-
#Returns the name of node after evaluation of server id if %s is present.
|
1575
|
-
#Eg: "Test-%s" will return "Test-i-12345" in case the instance id is i-12345
|
1553
|
+
# Returns the name of node after evaluation of server id if %s is present.
|
1554
|
+
# Eg: "Test-%s" will return "Test-i-12345" in case the instance id is i-12345
|
1576
1555
|
def evaluate_node_name(node_name)
|
1577
|
-
|
1556
|
+
node_name % server.id
|
1578
1557
|
end
|
1579
1558
|
|
1580
1559
|
def create_volume_tags(hashed_volume_tags)
|
1581
|
-
hashed_volume_tags.each_pair do |key,val|
|
1582
|
-
connection.tags.create :
|
1560
|
+
hashed_volume_tags.each_pair do |key, val|
|
1561
|
+
connection.tags.create key: key, value: val, resource_id: @server.block_device_mapping.first["volumeId"]
|
1583
1562
|
end
|
1584
1563
|
end
|
1585
1564
|
|