knife-windows 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +5 -5
- data/.travis.yml +26 -26
- data/CHANGELOG.md +112 -108
- data/DOC_CHANGES.md +14 -14
- data/Gemfile +12 -12
- data/LICENSE +201 -201
- data/README.md +391 -385
- data/RELEASE_NOTES.md +34 -34
- data/Rakefile +21 -21
- data/appveyor.yml +42 -42
- data/ci.gemfile +15 -15
- data/features/knife_help.feature +20 -20
- data/features/support/env.rb +5 -5
- data/knife-windows.gemspec +25 -25
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +233 -247
- data/lib/chef/knife/bootstrap_windows_base.rb +449 -415
- data/lib/chef/knife/bootstrap_windows_ssh.rb +115 -115
- data/lib/chef/knife/bootstrap_windows_winrm.rb +95 -95
- data/lib/chef/knife/core/windows_bootstrap_context.rb +372 -366
- data/lib/chef/knife/knife_windows_base.rb +33 -33
- data/lib/chef/knife/windows_cert_generate.rb +155 -155
- data/lib/chef/knife/windows_cert_install.rb +68 -68
- data/lib/chef/knife/windows_helper.rb +36 -36
- data/lib/chef/knife/windows_listener_create.rb +107 -107
- data/lib/chef/knife/winrm.rb +122 -122
- data/lib/chef/knife/winrm_base.rb +117 -117
- data/lib/chef/knife/winrm_knife_base.rb +305 -303
- data/lib/chef/knife/winrm_session.rb +88 -87
- data/lib/chef/knife/winrm_shared_options.rb +47 -47
- data/lib/chef/knife/wsman_endpoint.rb +44 -44
- data/lib/chef/knife/wsman_test.rb +117 -117
- data/lib/knife-windows/path_helper.rb +234 -234
- data/lib/knife-windows/version.rb +6 -6
- data/spec/assets/win_template_rendered_with_bootstrap_install_command.txt +217 -217
- data/spec/assets/win_template_rendered_with_bootstrap_install_command_on_12_5_client.txt +217 -217
- data/spec/assets/win_template_rendered_without_bootstrap_install_command.txt +329 -329
- data/spec/assets/win_template_rendered_without_bootstrap_install_command_on_12_5_client.txt +329 -329
- data/spec/assets/win_template_unrendered.txt +246 -246
- data/spec/functional/bootstrap_download_spec.rb +241 -234
- data/spec/spec_helper.rb +94 -93
- data/spec/unit/knife/bootstrap_options_spec.rb +155 -155
- data/spec/unit/knife/bootstrap_template_spec.rb +98 -92
- data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +341 -295
- data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +177 -177
- data/spec/unit/knife/windows_cert_generate_spec.rb +90 -90
- data/spec/unit/knife/windows_cert_install_spec.rb +51 -51
- data/spec/unit/knife/windows_listener_create_spec.rb +76 -76
- data/spec/unit/knife/winrm_session_spec.rb +65 -65
- data/spec/unit/knife/winrm_spec.rb +516 -516
- data/spec/unit/knife/wsman_test_spec.rb +202 -202
- metadata +23 -4
@@ -1,366 +1,372 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Seth Chisamore (<schisamo@
|
3
|
-
# Copyright:: Copyright (c) 2011
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
require 'chef/knife/core/bootstrap_context'
|
20
|
-
|
21
|
-
# Chef::Util::PathHelper in Chef 11 is a bit juvenile still
|
22
|
-
require 'knife-windows/path_helper'
|
23
|
-
# require 'chef/util/path_helper'
|
24
|
-
|
25
|
-
|
26
|
-
class Chef
|
27
|
-
class Knife
|
28
|
-
module Core
|
29
|
-
# Instances of BootstrapContext are the context objects (i.e., +self+) for
|
30
|
-
# bootstrap templates. For backwards compatability, they +must+ set the
|
31
|
-
# following instance variables:
|
32
|
-
# * @config - a hash of knife's config values
|
33
|
-
# * @run_list - the run list for the node to boostrap
|
34
|
-
#
|
35
|
-
class WindowsBootstrapContext < BootstrapContext
|
36
|
-
PathHelper = ::Knife::Windows::PathHelper
|
37
|
-
|
38
|
-
attr_accessor :client_pem
|
39
|
-
|
40
|
-
def initialize(config, run_list, chef_config, secret=nil)
|
41
|
-
@config = config
|
42
|
-
@run_list = run_list
|
43
|
-
@chef_config = chef_config
|
44
|
-
@secret = secret
|
45
|
-
# Compatibility with Chef 12 and Chef 11 versions
|
46
|
-
begin
|
47
|
-
# Pass along the secret parameter for Chef 12
|
48
|
-
super(config, run_list, chef_config, secret)
|
49
|
-
rescue ArgumentError
|
50
|
-
# The Chef 11 base class only has parameters for initialize
|
51
|
-
super(config, run_list, chef_config)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def validation_key
|
56
|
-
if File.exist?(File.expand_path(@chef_config[:validation_key]))
|
57
|
-
IO.read(File.expand_path(@chef_config[:validation_key]))
|
58
|
-
else
|
59
|
-
false
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def secret
|
64
|
-
escape_and_echo(@config[:secret])
|
65
|
-
end
|
66
|
-
|
67
|
-
def trusted_certs_script
|
68
|
-
@trusted_certs_script ||= trusted_certs_content
|
69
|
-
end
|
70
|
-
|
71
|
-
def config_content
|
72
|
-
client_rb = <<-CONFIG
|
73
|
-
log_level :info
|
74
|
-
log_location STDOUT
|
75
|
-
|
76
|
-
chef_server_url "#{@chef_config[:chef_server_url]}"
|
77
|
-
validation_client_name "#{@chef_config[:validation_client_name]}"
|
78
|
-
|
79
|
-
file_cache_path "c:/chef/cache"
|
80
|
-
file_backup_path "c:/chef/backup"
|
81
|
-
cache_options ({:path => "c:/chef/cache/checksums", :skip_expires => true})
|
82
|
-
|
83
|
-
CONFIG
|
84
|
-
if @config[:chef_node_name]
|
85
|
-
client_rb << %Q{node_name "#{@config[:chef_node_name]}"\n}
|
86
|
-
else
|
87
|
-
client_rb << "# Using default node name (fqdn)\n"
|
88
|
-
end
|
89
|
-
|
90
|
-
# We configure :verify_api_cert only when it's overridden on the CLI
|
91
|
-
# or when specified in the knife config.
|
92
|
-
if !@config[:node_verify_api_cert].nil? || knife_config.has_key?(:verify_api_cert)
|
93
|
-
value = @config[:node_verify_api_cert].nil? ? knife_config[:verify_api_cert] : @config[:node_verify_api_cert]
|
94
|
-
client_rb << %Q{verify_api_cert #{value}\n}
|
95
|
-
end
|
96
|
-
|
97
|
-
# We configure :ssl_verify_mode only when it's overridden on the CLI
|
98
|
-
# or when specified in the knife config.
|
99
|
-
if @config[:node_ssl_verify_mode] || knife_config.has_key?(:ssl_verify_mode)
|
100
|
-
value = case @config[:node_ssl_verify_mode]
|
101
|
-
when "peer"
|
102
|
-
:verify_peer
|
103
|
-
when "none"
|
104
|
-
:verify_none
|
105
|
-
when nil
|
106
|
-
knife_config[:ssl_verify_mode]
|
107
|
-
else
|
108
|
-
nil
|
109
|
-
end
|
110
|
-
|
111
|
-
if value
|
112
|
-
client_rb << %Q{ssl_verify_mode :#{value}\n}
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
if @config[:ssl_verify_mode]
|
117
|
-
client_rb << %Q{ssl_verify_mode :#{knife_config[:ssl_verify_mode]}\n}
|
118
|
-
end
|
119
|
-
|
120
|
-
if knife_config[:bootstrap_proxy]
|
121
|
-
client_rb << "\n"
|
122
|
-
client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
123
|
-
client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
124
|
-
client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n} if knife_config[:bootstrap_no_proxy]
|
125
|
-
end
|
126
|
-
|
127
|
-
if knife_config[:bootstrap_no_proxy]
|
128
|
-
client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n}
|
129
|
-
end
|
130
|
-
|
131
|
-
if @config[:secret]
|
132
|
-
client_rb << %Q{encrypted_data_bag_secret "c:/chef/encrypted_data_bag_secret"\n}
|
133
|
-
end
|
134
|
-
|
135
|
-
unless trusted_certs_script.empty?
|
136
|
-
client_rb << %Q{trusted_certs_dir "c:/chef/trusted_certs"\n}
|
137
|
-
end
|
138
|
-
|
139
|
-
if Chef::Config[:fips]
|
140
|
-
client_rb <<
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
Set
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
rem
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
rem
|
217
|
-
|
218
|
-
|
219
|
-
End If
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
objXMLHTTP
|
224
|
-
objXMLHTTP.
|
225
|
-
If
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
objADOStream.
|
235
|
-
objADOStream.
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
$
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
end
|
264
|
-
|
265
|
-
def
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
def
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
@
|
338
|
-
|
339
|
-
@
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2011-2016 Chef Software, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/core/bootstrap_context'
|
20
|
+
|
21
|
+
# Chef::Util::PathHelper in Chef 11 is a bit juvenile still
|
22
|
+
require 'knife-windows/path_helper'
|
23
|
+
# require 'chef/util/path_helper'
|
24
|
+
|
25
|
+
|
26
|
+
class Chef
|
27
|
+
class Knife
|
28
|
+
module Core
|
29
|
+
# Instances of BootstrapContext are the context objects (i.e., +self+) for
|
30
|
+
# bootstrap templates. For backwards compatability, they +must+ set the
|
31
|
+
# following instance variables:
|
32
|
+
# * @config - a hash of knife's config values
|
33
|
+
# * @run_list - the run list for the node to boostrap
|
34
|
+
#
|
35
|
+
class WindowsBootstrapContext < BootstrapContext
|
36
|
+
PathHelper = ::Knife::Windows::PathHelper
|
37
|
+
|
38
|
+
attr_accessor :client_pem
|
39
|
+
|
40
|
+
def initialize(config, run_list, chef_config, secret=nil)
|
41
|
+
@config = config
|
42
|
+
@run_list = run_list
|
43
|
+
@chef_config = chef_config
|
44
|
+
@secret = secret
|
45
|
+
# Compatibility with Chef 12 and Chef 11 versions
|
46
|
+
begin
|
47
|
+
# Pass along the secret parameter for Chef 12
|
48
|
+
super(config, run_list, chef_config, secret)
|
49
|
+
rescue ArgumentError
|
50
|
+
# The Chef 11 base class only has parameters for initialize
|
51
|
+
super(config, run_list, chef_config)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def validation_key
|
56
|
+
if File.exist?(File.expand_path(@chef_config[:validation_key]))
|
57
|
+
IO.read(File.expand_path(@chef_config[:validation_key]))
|
58
|
+
else
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def secret
|
64
|
+
escape_and_echo(@config[:secret])
|
65
|
+
end
|
66
|
+
|
67
|
+
def trusted_certs_script
|
68
|
+
@trusted_certs_script ||= trusted_certs_content
|
69
|
+
end
|
70
|
+
|
71
|
+
def config_content
|
72
|
+
client_rb = <<-CONFIG
|
73
|
+
log_level :info
|
74
|
+
log_location STDOUT
|
75
|
+
|
76
|
+
chef_server_url "#{@chef_config[:chef_server_url]}"
|
77
|
+
validation_client_name "#{@chef_config[:validation_client_name]}"
|
78
|
+
|
79
|
+
file_cache_path "c:/chef/cache"
|
80
|
+
file_backup_path "c:/chef/backup"
|
81
|
+
cache_options ({:path => "c:/chef/cache/checksums", :skip_expires => true})
|
82
|
+
|
83
|
+
CONFIG
|
84
|
+
if @config[:chef_node_name]
|
85
|
+
client_rb << %Q{node_name "#{@config[:chef_node_name]}"\n}
|
86
|
+
else
|
87
|
+
client_rb << "# Using default node name (fqdn)\n"
|
88
|
+
end
|
89
|
+
|
90
|
+
# We configure :verify_api_cert only when it's overridden on the CLI
|
91
|
+
# or when specified in the knife config.
|
92
|
+
if !@config[:node_verify_api_cert].nil? || knife_config.has_key?(:verify_api_cert)
|
93
|
+
value = @config[:node_verify_api_cert].nil? ? knife_config[:verify_api_cert] : @config[:node_verify_api_cert]
|
94
|
+
client_rb << %Q{verify_api_cert #{value}\n}
|
95
|
+
end
|
96
|
+
|
97
|
+
# We configure :ssl_verify_mode only when it's overridden on the CLI
|
98
|
+
# or when specified in the knife config.
|
99
|
+
if @config[:node_ssl_verify_mode] || knife_config.has_key?(:ssl_verify_mode)
|
100
|
+
value = case @config[:node_ssl_verify_mode]
|
101
|
+
when "peer"
|
102
|
+
:verify_peer
|
103
|
+
when "none"
|
104
|
+
:verify_none
|
105
|
+
when nil
|
106
|
+
knife_config[:ssl_verify_mode]
|
107
|
+
else
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
if value
|
112
|
+
client_rb << %Q{ssl_verify_mode :#{value}\n}
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
if @config[:ssl_verify_mode]
|
117
|
+
client_rb << %Q{ssl_verify_mode :#{knife_config[:ssl_verify_mode]}\n}
|
118
|
+
end
|
119
|
+
|
120
|
+
if knife_config[:bootstrap_proxy]
|
121
|
+
client_rb << "\n"
|
122
|
+
client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
123
|
+
client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
124
|
+
client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n} if knife_config[:bootstrap_no_proxy]
|
125
|
+
end
|
126
|
+
|
127
|
+
if knife_config[:bootstrap_no_proxy]
|
128
|
+
client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n}
|
129
|
+
end
|
130
|
+
|
131
|
+
if @config[:secret]
|
132
|
+
client_rb << %Q{encrypted_data_bag_secret "c:/chef/encrypted_data_bag_secret"\n}
|
133
|
+
end
|
134
|
+
|
135
|
+
unless trusted_certs_script.empty?
|
136
|
+
client_rb << %Q{trusted_certs_dir "c:/chef/trusted_certs"\n}
|
137
|
+
end
|
138
|
+
|
139
|
+
if Chef::Config[:fips]
|
140
|
+
client_rb << <<-CONFIG
|
141
|
+
fips true
|
142
|
+
chef_version = ::Chef::VERSION.split(".")
|
143
|
+
unless chef_version[0].to_i > 12 || (chef_version[0].to_i == 12 && chef_version[1].to_i >= 8)
|
144
|
+
raise "FIPS Mode requested but not supported by this client"
|
145
|
+
end
|
146
|
+
CONFIG
|
147
|
+
end
|
148
|
+
|
149
|
+
escape_and_echo(client_rb)
|
150
|
+
end
|
151
|
+
|
152
|
+
def start_chef
|
153
|
+
bootstrap_environment_option = bootstrap_environment.nil? ? '' : " -E #{bootstrap_environment}"
|
154
|
+
start_chef = "SET \"PATH=%PATH%;C:\\ruby\\bin;C:\\opscode\\chef\\bin;C:\\opscode\\chef\\embedded\\bin\"\n"
|
155
|
+
start_chef << "chef-client -c c:/chef/client.rb -j c:/chef/first-boot.json#{bootstrap_environment_option}\n"
|
156
|
+
end
|
157
|
+
|
158
|
+
def latest_current_windows_chef_version_query
|
159
|
+
installer_version_string = nil
|
160
|
+
if @config[:prerelease]
|
161
|
+
installer_version_string = "&prerelease=true"
|
162
|
+
else
|
163
|
+
chef_version_string = if knife_config[:bootstrap_version]
|
164
|
+
knife_config[:bootstrap_version]
|
165
|
+
else
|
166
|
+
Chef::VERSION.split(".").first
|
167
|
+
end
|
168
|
+
|
169
|
+
installer_version_string = "&v=#{chef_version_string}"
|
170
|
+
|
171
|
+
# If bootstrapping a pre-release version add the prerelease query string
|
172
|
+
if chef_version_string.split(".").length > 3
|
173
|
+
installer_version_string << "&prerelease=true"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
installer_version_string
|
178
|
+
end
|
179
|
+
|
180
|
+
def win_wget
|
181
|
+
# I tried my best to figure out how to properly url decode and switch / to \
|
182
|
+
# but this is VBScript - so I don't really care that badly.
|
183
|
+
win_wget = <<-WGET
|
184
|
+
url = WScript.Arguments.Named("url")
|
185
|
+
path = WScript.Arguments.Named("path")
|
186
|
+
proxy = null
|
187
|
+
'* Vaguely attempt to handle file:// scheme urls by url unescaping and switching all
|
188
|
+
'* / into \. Also assume that file:/// is a local absolute path and that file://<foo>
|
189
|
+
'* is possibly a network file path.
|
190
|
+
If InStr(url, "file://") = 1 Then
|
191
|
+
url = Unescape(url)
|
192
|
+
If InStr(url, "file:///") = 1 Then
|
193
|
+
sourcePath = Mid(url, Len("file:///") + 1)
|
194
|
+
Else
|
195
|
+
sourcePath = Mid(url, Len("file:") + 1)
|
196
|
+
End If
|
197
|
+
sourcePath = Replace(sourcePath, "/", "\\")
|
198
|
+
|
199
|
+
Set objFSO = CreateObject("Scripting.FileSystemObject")
|
200
|
+
If objFSO.Fileexists(path) Then objFSO.DeleteFile path
|
201
|
+
objFSO.CopyFile sourcePath, path, true
|
202
|
+
Set objFSO = Nothing
|
203
|
+
|
204
|
+
Else
|
205
|
+
Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP")
|
206
|
+
Set wshShell = CreateObject( "WScript.Shell" )
|
207
|
+
Set objUserVariables = wshShell.Environment("USER")
|
208
|
+
|
209
|
+
rem http proxy is optional
|
210
|
+
rem attempt to read from HTTP_PROXY env var first
|
211
|
+
On Error Resume Next
|
212
|
+
|
213
|
+
If NOT (objUserVariables("HTTP_PROXY") = "") Then
|
214
|
+
proxy = objUserVariables("HTTP_PROXY")
|
215
|
+
|
216
|
+
rem fall back to named arg
|
217
|
+
ElseIf NOT (WScript.Arguments.Named("proxy") = "") Then
|
218
|
+
proxy = WScript.Arguments.Named("proxy")
|
219
|
+
End If
|
220
|
+
|
221
|
+
If NOT isNull(proxy) Then
|
222
|
+
rem setProxy method is only available on ServerXMLHTTP 6.0+
|
223
|
+
Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
|
224
|
+
objXMLHTTP.setProxy 2, proxy
|
225
|
+
End If
|
226
|
+
|
227
|
+
On Error Goto 0
|
228
|
+
|
229
|
+
objXMLHTTP.open "GET", url, false
|
230
|
+
objXMLHTTP.send()
|
231
|
+
If objXMLHTTP.Status = 200 Then
|
232
|
+
Set objADOStream = CreateObject("ADODB.Stream")
|
233
|
+
objADOStream.Open
|
234
|
+
objADOStream.Type = 1
|
235
|
+
objADOStream.Write objXMLHTTP.ResponseBody
|
236
|
+
objADOStream.Position = 0
|
237
|
+
Set objFSO = Createobject("Scripting.FileSystemObject")
|
238
|
+
If objFSO.Fileexists(path) Then objFSO.DeleteFile path
|
239
|
+
Set objFSO = Nothing
|
240
|
+
objADOStream.SaveToFile path
|
241
|
+
objADOStream.Close
|
242
|
+
Set objADOStream = Nothing
|
243
|
+
End If
|
244
|
+
Set objXMLHTTP = Nothing
|
245
|
+
End If
|
246
|
+
WGET
|
247
|
+
escape_and_echo(win_wget)
|
248
|
+
end
|
249
|
+
|
250
|
+
def win_wget_ps
|
251
|
+
win_wget_ps = <<-WGET_PS
|
252
|
+
param(
|
253
|
+
[String] $remoteUrl,
|
254
|
+
[String] $localPath
|
255
|
+
)
|
256
|
+
|
257
|
+
$webClient = new-object System.Net.WebClient;
|
258
|
+
|
259
|
+
$webClient.DownloadFile($remoteUrl, $localPath);
|
260
|
+
WGET_PS
|
261
|
+
|
262
|
+
escape_and_echo(win_wget_ps)
|
263
|
+
end
|
264
|
+
|
265
|
+
def install_chef
|
266
|
+
# The normal install command uses regular double quotes in
|
267
|
+
# the install command, so request such a string from install_command
|
268
|
+
install_chef = install_command('"') + "\n" + fallback_install_task_command
|
269
|
+
end
|
270
|
+
|
271
|
+
def bootstrap_directory
|
272
|
+
bootstrap_directory = "C:\\chef"
|
273
|
+
end
|
274
|
+
|
275
|
+
def local_download_path
|
276
|
+
local_download_path = "%TEMP%\\chef-client-latest.msi"
|
277
|
+
end
|
278
|
+
|
279
|
+
def msi_url(machine_os=nil, machine_arch=nil, download_context=nil)
|
280
|
+
# The default msi path has a number of url query parameters - we attempt to substitute
|
281
|
+
# such parameters in as long as they are provided by the template.
|
282
|
+
|
283
|
+
if @config[:msi_url].nil? || @config[:msi_url].empty?
|
284
|
+
url = "https://www.chef.io/chef/download?p=windows"
|
285
|
+
url += "&pv=#{machine_os}" unless machine_os.nil?
|
286
|
+
url += "&m=#{machine_arch}" unless machine_arch.nil?
|
287
|
+
url += "&DownloadContext=#{download_context}" unless download_context.nil?
|
288
|
+
url += latest_current_windows_chef_version_query
|
289
|
+
else
|
290
|
+
@config[:msi_url]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def first_boot
|
295
|
+
escape_and_echo(super.to_json)
|
296
|
+
end
|
297
|
+
|
298
|
+
# escape WIN BATCH special chars
|
299
|
+
# and prefixes each line with an
|
300
|
+
# echo
|
301
|
+
def escape_and_echo(file_contents)
|
302
|
+
file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1')
|
303
|
+
end
|
304
|
+
|
305
|
+
private
|
306
|
+
|
307
|
+
def install_command(executor_quote)
|
308
|
+
if @config[:install_as_service]
|
309
|
+
"msiexec /qn /log #{executor_quote}%CHEF_CLIENT_MSI_LOG_PATH%#{executor_quote} /i #{executor_quote}%LOCAL_DESTINATION_MSI_PATH%#{executor_quote} ADDLOCAL=#{executor_quote}ChefClientFeature,ChefServiceFeature#{executor_quote}"
|
310
|
+
else
|
311
|
+
"msiexec /qn /log #{executor_quote}%CHEF_CLIENT_MSI_LOG_PATH%#{executor_quote} /i #{executor_quote}%LOCAL_DESTINATION_MSI_PATH%#{executor_quote}"
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# Returns a string for copying the trusted certificates on the workstation to the system being bootstrapped
|
316
|
+
# This string should contain both the commands necessary to both create the files, as well as their content
|
317
|
+
def trusted_certs_content
|
318
|
+
content = ""
|
319
|
+
if @chef_config[:trusted_certs_dir]
|
320
|
+
Dir.glob(File.join(PathHelper.escape_glob(@chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
|
321
|
+
content << "> #{bootstrap_directory}/trusted_certs/#{File.basename(cert)} (\n" +
|
322
|
+
escape_and_echo(IO.read(File.expand_path(cert))) + "\n)\n"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
content
|
326
|
+
end
|
327
|
+
|
328
|
+
def fallback_install_task_command
|
329
|
+
# This command will be executed by schtasks.exe in the batch
|
330
|
+
# code below. To handle tasks that contain arguments that
|
331
|
+
# need to be double quoted, schtasks allows the use of single
|
332
|
+
# quotes that will later be converted to double quotes
|
333
|
+
command = install_command('\'')
|
334
|
+
<<-EOH
|
335
|
+
@set MSIERRORCODE=!ERRORLEVEL!
|
336
|
+
@if ERRORLEVEL 1 (
|
337
|
+
@echo WARNING: Failed to install Chef Client MSI package in remote context with status code !MSIERRORCODE!.
|
338
|
+
@echo WARNING: This may be due to a defect in operating system update KB2918614: http://support.microsoft.com/kb/2918614
|
339
|
+
@set OLDLOGLOCATION="%CHEF_CLIENT_MSI_LOG_PATH%-fail.log"
|
340
|
+
@move "%CHEF_CLIENT_MSI_LOG_PATH%" "!OLDLOGLOCATION!" > NUL
|
341
|
+
@echo WARNING: Saving installation log of failure at !OLDLOGLOCATION!
|
342
|
+
@echo WARNING: Retrying installation with local context...
|
343
|
+
@schtasks /create /f /sc once /st 00:00:00 /tn chefclientbootstraptask /ru SYSTEM /rl HIGHEST /tr \"cmd /c #{command} & sleep 2 & waitfor /s %computername% /si chefclientinstalldone\"
|
344
|
+
|
345
|
+
@if ERRORLEVEL 1 (
|
346
|
+
@echo ERROR: Failed to create Chef Client installation scheduled task with status code !ERRORLEVEL! > "&2"
|
347
|
+
) else (
|
348
|
+
@echo Successfully created scheduled task to install Chef Client.
|
349
|
+
@schtasks /run /tn chefclientbootstraptask
|
350
|
+
@if ERRORLEVEL 1 (
|
351
|
+
@echo ERROR: Failed to execut Chef Client installation scheduled task with status code !ERRORLEVEL!. > "&2"
|
352
|
+
) else (
|
353
|
+
@echo Successfully started Chef Client installation scheduled task.
|
354
|
+
@echo Waiting for installation to complete -- this may take a few minutes...
|
355
|
+
waitfor chefclientinstalldone /t 600
|
356
|
+
if ERRORLEVEL 1 (
|
357
|
+
@echo ERROR: Timed out waiting for Chef Client package to install
|
358
|
+
) else (
|
359
|
+
@echo Finished waiting for Chef Client package to install.
|
360
|
+
)
|
361
|
+
@schtasks /delete /f /tn chefclientbootstraptask > NUL
|
362
|
+
)
|
363
|
+
)
|
364
|
+
) else (
|
365
|
+
@echo Successfully installed Chef Client package.
|
366
|
+
)
|
367
|
+
EOH
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|