knife-windows 1.8.0 → 1.9.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.
@@ -6,12 +6,12 @@ Example Note:
6
6
  ## Example Heading
7
7
  Details about the thing that changed that needs to get included in the Release Notes in markdown.
8
8
  -->
9
- # knife-windows 1.8.0 release notes:
9
+ # knife-windows 1.9.0 release notes:
10
10
 
11
- This release allows user to specify `config_log_location` and `config_log_level` options in config.rb/knife.rb. This sets the default `log_location` and `log_level` in the `client.rb` file of the node being bootstrapped.
11
+ This release re-introduces support for concurrent WinRM connections when
12
+ running `knife winrm`. Simply specify the number of concurrent connections
13
+ you would like using the `-C` (or `--concurrency`) flag.
12
14
 
13
- This is how you can pass the values in config.rb/knife.rb:
14
15
  ```
15
- chef_log_level :debug
16
- chef_log_location "C:/chef.log" #please make sure that the path exists
16
+ knife winrm "role:web" "net stats srv" -X Administrator -P 'super_secret_password' -C 4
17
17
  ```
data/Rakefile CHANGED
@@ -1,21 +1,21 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
3
-
4
- begin
5
- require 'rspec/core/rake_task'
6
-
7
- task :default => [:unit_spec, :functional_spec]
8
-
9
- desc "Run all functional specs in spec directory"
10
- RSpec::Core::RakeTask.new(:functional_spec) do |t|
11
- t.pattern = 'spec/functional/**/*_spec.rb'
12
- end
13
-
14
- desc "Run all unit specs in spec directory"
15
- RSpec::Core::RakeTask.new(:unit_spec) do |t|
16
- t.pattern = 'spec/unit/**/*_spec.rb'
17
- end
18
-
19
- rescue LoadError
20
- STDERR.puts "\n*** RSpec not available. (sudo) gem install rspec to run unit tests. ***\n\n"
21
- end
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+
7
+ task :default => [:unit_spec, :functional_spec]
8
+
9
+ desc "Run all functional specs in spec directory"
10
+ RSpec::Core::RakeTask.new(:functional_spec) do |t|
11
+ t.pattern = 'spec/functional/**/*_spec.rb'
12
+ end
13
+
14
+ desc "Run all unit specs in spec directory"
15
+ RSpec::Core::RakeTask.new(:unit_spec) do |t|
16
+ t.pattern = 'spec/unit/**/*_spec.rb'
17
+ end
18
+
19
+ rescue LoadError
20
+ STDERR.puts "\n*** RSpec not available. (sudo) gem install rspec to run unit tests. ***\n\n"
21
+ end
@@ -8,9 +8,6 @@ environment:
8
8
  bundle_gemfile: ci.gemfile
9
9
 
10
10
  matrix:
11
- - ruby_version: "20"
12
- chef_version: "< 12"
13
-
14
11
  - ruby_version: "23"
15
12
  chef_version: "~> 12.0"
16
13
 
@@ -1,20 +1,20 @@
1
- Feature: Ensure that the help works as designed
2
- In order to test the help via CLI
3
- As an Operator
4
- I want to run the CLI with different arguments
5
-
6
- Scenario: Running the windows sub-command shows available commands
7
- When I run `knife windows`
8
- And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
9
-
10
- Scenario: Running the windows sub-command shows available commands
11
- When I run `knife windows --help`
12
- And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
13
-
14
- Scenario: Running the windows sub-command shows available commands
15
- When I run `knife windows help`
16
- And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
17
-
18
- Scenario: Running the knife command shows available windows command"
19
- When I run `knife`
20
- And the output should contain "** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
1
+ Feature: Ensure that the help works as designed
2
+ In order to test the help via CLI
3
+ As an Operator
4
+ I want to run the CLI with different arguments
5
+
6
+ Scenario: Running the windows sub-command shows available commands
7
+ When I run `knife windows`
8
+ And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
9
+
10
+ Scenario: Running the windows sub-command shows available commands
11
+ When I run `knife windows --help`
12
+ And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
13
+
14
+ Scenario: Running the windows sub-command shows available commands
15
+ When I run `knife windows help`
16
+ And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
17
+
18
+ Scenario: Running the knife command shows available windows command"
19
+ When I run `knife`
20
+ And the output should contain "** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
@@ -1,5 +1,5 @@
1
- require 'aruba/cucumber'
2
-
3
- Before do
4
- @aruba_timeout_seconds = 5
5
- end
1
+ require 'aruba/cucumber'
2
+
3
+ Before do
4
+ @aruba_timeout_seconds = 5
5
+ end
@@ -330,20 +330,22 @@ class Chef
330
330
  # create a bootstrap.bat file on the node
331
331
  # we have to run the remote commands in 2047 char chunks
332
332
  create_bootstrap_bat_command do |command_chunk|
333
- begin
334
- render_command_result = run_command(command_chunk)
335
- ui.error("Batch render command returned #{render_command_result}") if render_command_result != 0
336
- render_command_result
337
- rescue SystemExit => e
338
- raise unless e.success?
333
+ render_command_result = run_command(command_chunk)
334
+ unless render_command_result == 0
335
+ ui.error("Batch render command returned #{render_command_result}")
336
+ exit render_command_result
339
337
  end
340
338
  end
341
339
 
342
340
  # execute the bootstrap.bat file
343
341
  bootstrap_command_result = run_command(bootstrap_command)
344
- ui.error("Bootstrap command returned #{bootstrap_command_result}") if bootstrap_command_result != 0
342
+ unless bootstrap_command_result == 0
343
+ ui.error("Bootstrap command returned #{bootstrap_command_result}")
344
+ exit bootstrap_command_result
345
+ end
345
346
 
346
- bootstrap_command_result
347
+ # exit 0
348
+ 0
347
349
  end
348
350
 
349
351
  protected
@@ -49,7 +49,12 @@ class Chef
49
49
  STDOUT.sync = STDERR.sync = true
50
50
 
51
51
  configure_session
52
- execute_remote_command
52
+ exit_status = execute_remote_command
53
+ if exit_status != 0
54
+ exit exit_status
55
+ else
56
+ exit_status
57
+ end
53
58
  end
54
59
 
55
60
  def execute_remote_command
@@ -112,42 +112,49 @@ class Chef
112
112
 
113
113
  def run_command(command = '')
114
114
  relay_winrm_command(command)
115
-
116
115
  check_for_errors!
117
-
118
- # Knife seems to ignore the return value of this method,
119
- # so we exit to force the process exit code for this
120
- # subcommand if returns is set
121
- exit @exit_code if @exit_code && @exit_code != 0
122
- 0
116
+ @exit_code
123
117
  end
124
118
 
125
119
  def relay_winrm_command(command)
126
120
  Chef::Log.debug(command)
127
- session_results = []
128
- @winrm_sessions.each do |s|
129
- begin
130
- session_results << s.relay_command(command)
131
- rescue WinRM::WinRMHTTPTransportError, WinRM::WinRMAuthorizationError => e
132
- if authorization_error?(e)
133
- if ! config[:suppress_auth_failure]
134
- # Display errors if the caller hasn't opted to retry
135
- ui.error "Failed to authenticate to #{s.host} as #{locate_config_value(:winrm_user)}"
136
- ui.info "Response: #{e.message}"
137
- ui.info get_failed_authentication_hint
138
- raise e
139
- end
140
- @exit_code = 401
141
- else
142
- raise e
121
+ @session_results = []
122
+
123
+ queue = Queue.new
124
+ @winrm_sessions.each { |s| queue << s }
125
+ # These nils will kill the Threads once no more sessions are left
126
+ locate_config_value(:concurrency).times { queue << nil }
127
+
128
+ threads = []
129
+ locate_config_value(:concurrency).times do
130
+ threads << Thread.new do
131
+ while session = queue.pop
132
+ run_command_in_thread(session, command)
143
133
  end
144
134
  end
145
135
  end
146
- session_results
136
+ threads.map(&:join)
137
+ @session_results
147
138
  end
148
139
 
149
140
  private
150
141
 
142
+ def run_command_in_thread(s, command)
143
+ @session_results << s.relay_command(command)
144
+ rescue WinRM::WinRMHTTPTransportError, WinRM::WinRMAuthorizationError => e
145
+ if authorization_error?(e)
146
+ if ! config[:suppress_auth_failure]
147
+ # Display errors if the caller hasn't opted to retry
148
+ ui.error "Failed to authenticate to #{s.host} as #{locate_config_value(:winrm_user)}"
149
+ ui.info "Response: #{e.message}"
150
+ ui.info get_failed_authentication_hint
151
+ raise e
152
+ end
153
+ else
154
+ raise e
155
+ end
156
+ end
157
+
151
158
  def get_failed_authentication_hint
152
159
  if @session_opts[:basic_auth_only]
153
160
  FAILED_BASIC_HINT
@@ -162,10 +169,11 @@ class Chef
162
169
  end
163
170
 
164
171
  def check_for_errors!
172
+ @exit_code ||= 0
165
173
  @winrm_sessions.each do |session|
166
174
  session_exit_code = session.exit_code
167
175
  unless success_return_codes.include? session_exit_code.to_i
168
- @exit_code = session_exit_code.to_i
176
+ @exit_code = [@exit_code, session_exit_code.to_i].max
169
177
  ui.error "Failed to execute command on #{session.host} return code #{session_exit_code}"
170
178
  end
171
179
  end
@@ -73,6 +73,9 @@ class Chef
73
73
  end
74
74
  @exit_code = session_result.exitcode
75
75
  session_result
76
+ rescue WinRM::WinRMHTTPTransportError, WinRM::WinRMAuthorizationError => e
77
+ @exit_code = 401
78
+ raise e
76
79
  end
77
80
 
78
81
  private
@@ -39,6 +39,13 @@ class Chef
39
39
  :long => "--attribute ATTR",
40
40
  :description => "The attribute to use for opening the connection - default is fqdn",
41
41
  :default => "fqdn"
42
+
43
+ option :concurrency,
44
+ :short => "-C NUM",
45
+ :long => "--concurrency NUM",
46
+ :description => "The number of allowed concurrent connections",
47
+ :default => 1,
48
+ :proc => lambda { |o| o.to_i }
42
49
  end
43
50
  end
44
51
 
@@ -1,6 +1,6 @@
1
1
  module Knife
2
2
  module Windows
3
- VERSION = "1.8.0"
3
+ VERSION = "1.9.0"
4
4
  MAJOR, MINOR, TINY = VERSION.split('.')
5
5
  end
6
6
  end
@@ -1,246 +1,246 @@
1
- @rem
2
- @rem Author:: Seth Chisamore (<schisamo@opscode.com>)
3
- @rem Copyright:: Copyright (c) 2011 Opscode, Inc.
4
- @rem License:: Apache License, Version 2.0
5
- @rem
6
- @rem Licensed under the Apache License, Version 2.0 (the "License");
7
- @rem you may not use this file except in compliance with the License.
8
- @rem You may obtain a copy of the License at
9
- @rem
10
- @rem http://www.apache.org/licenses/LICENSE-2.0
11
- @rem
12
- @rem Unless required by applicable law or agreed to in writing, software
13
- @rem distributed under the License is distributed on an "AS IS" BASIS,
14
- @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- @rem See the License for the specific language governing permissions and
16
- @rem limitations under the License.
17
- @rem
18
-
19
- @rem Use delayed environment expansion so that ERRORLEVEL can be evaluated with the
20
- @rem !ERRORLEVEL! syntax which evaluates at execution of the line of script, not when
21
- @rem the line is read. See help for the /E switch from cmd.exe /? .
22
- @setlocal ENABLEDELAYEDEXPANSION
23
-
24
- <%= "SETX HTTP_PROXY \"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] %>
25
-
26
- @set BOOTSTRAP_DIRECTORY=<%= bootstrap_directory %>
27
- @echo Checking for existing directory "%BOOTSTRAP_DIRECTORY%"...
28
- @if NOT EXIST %BOOTSTRAP_DIRECTORY% (
29
- @echo Existing directory not found, creating.
30
- @mkdir %BOOTSTRAP_DIRECTORY%
31
- ) else (
32
- @echo Existing directory found, skipping creation.
33
- )
34
-
35
- > <%= bootstrap_directory %>\wget.vbs (
36
- <%= win_wget %>
37
- )
38
-
39
- > <%= bootstrap_directory %>\wget.ps1 (
40
- <%= win_wget_ps %>
41
- )
42
-
43
- @rem Determine the version and the architecture
44
-
45
- @FOR /F "usebackq tokens=1-8 delims=.[] " %%A IN (`ver`) DO (
46
- @set WinMajor=%%D
47
- @set WinMinor=%%E
48
- @set WinBuild=%%F
49
- )
50
-
51
- @echo Detected Windows Version %WinMajor%.%WinMinor% Build %WinBuild%
52
-
53
- @set LATEST_OS_VERSION_MAJOR=6
54
- @set LATEST_OS_VERSION_MINOR=3
55
-
56
- @if /i %WinMajor% GTR %LATEST_OS_VERSION_MAJOR% goto VersionUnknown
57
- @if /i %WinMajor% EQU %LATEST_OS_VERSION_MAJOR% (
58
- @if /i %WinMinor% GTR %LATEST_OS_VERSION_MINOR% goto VersionUnknown
59
- )
60
-
61
- goto Version%WinMajor%.%WinMinor%
62
-
63
- :VersionUnknown
64
- @rem If this is an unknown version of windows set the default
65
- @set MACHINE_OS=2008r2
66
- @echo Warning: Unknown version of Windows, assuming default of Windows %MACHINE_OS%
67
- goto architecture_select
68
-
69
- :Version6.0
70
- @set MACHINE_OS=2008
71
- goto architecture_select
72
-
73
- :Version5.2
74
- @set MACHINE_OS=2003r2
75
- goto architecture_select
76
-
77
- :Version6.1
78
- @set MACHINE_OS=2008r2
79
- goto architecture_select
80
-
81
- :Version6.2
82
- @set MACHINE_OS=2012
83
- goto architecture_select
84
-
85
- @rem Currently Windows Server 2012 R2 is treated as equivalent to Windows Server 2012
86
- :Version6.3
87
- goto Version6.2
88
-
89
- :architecture_select
90
- goto Architecture%PROCESSOR_ARCHITEW6432%
91
-
92
- :Architecture
93
- goto Architecture%PROCESSOR_ARCHITECTURE%
94
-
95
- @rem If this is an unknown architecture set the default
96
- @set MACHINE_ARCH=i686
97
- goto install
98
-
99
- :Architecturex86
100
- @set MACHINE_ARCH=i686
101
- goto install
102
-
103
- :Architectureamd64
104
- @set MACHINE_ARCH=x86_64
105
- goto install
106
-
107
- :install
108
- @rem If user has provided the custom installation command for chef-client then execute it
109
- <% if @chef_config[:knife][:bootstrap_install_command] %>
110
- <%= @chef_config[:knife][:bootstrap_install_command] %>
111
- <% else %>
112
- @rem Install Chef using chef-client MSI installer
113
-
114
- @set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
115
- @set "CHEF_CLIENT_MSI_LOG_PATH=%TEMP%\chef-client-msi%RANDOM%.log"
116
-
117
- @rem Clear any pre-existing downloads
118
- @echo Checking for existing downloaded package at "%LOCAL_DESTINATION_MSI_PATH%"
119
- @if EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
120
- @echo Found existing downloaded package, deleting.
121
- @del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
122
- @if ERRORLEVEL 1 (
123
- echo Warning: Failed to delete pre-existing package with status code !ERRORLEVEL! > "&2"
124
- )
125
- ) else (
126
- echo No existing downloaded packages to delete.
127
- )
128
-
129
- @rem If there is somehow a name collision, remove pre-existing log
130
- @if EXIST "%CHEF_CLIENT_MSI_LOG_PATH%" del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
131
-
132
- @echo Attempting to download client package using PowerShell if available...
133
- @set "REMOTE_SOURCE_MSI_URL=<%= msi_url('%MACHINE_OS%', '%MACHINE_ARCH%', 'PowerShell') %>"
134
- @set powershell_download=powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File <%= bootstrap_directory %>\wget.ps1 "%REMOTE_SOURCE_MSI_URL%" "%LOCAL_DESTINATION_MSI_PATH%"
135
- @echo !powershell_download!
136
- @call !powershell_download!
137
-
138
- @set DOWNLOAD_ERROR_STATUS=!ERRORLEVEL!
139
-
140
- @if ERRORLEVEL 1 (
141
- @echo Failed PowerShell download with status code !DOWNLOAD_ERROR_STATUS! > "&2"
142
- @if !DOWNLOAD_ERROR_STATUS!==0 set DOWNLOAD_ERROR_STATUS=2
143
- ) else (
144
- @rem Sometimes the error level is not set even when the download failed,
145
- @rem so check for the file to be sure it is there -- if it is not, we will retry
146
- @if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
147
- echo Failed download: download completed, but downloaded file not found > "&2"
148
- set DOWNLOAD_ERROR_STATUS=2
149
- ) else (
150
- echo Download via PowerShell succeeded.
151
- )
152
- )
153
-
154
- @if NOT %DOWNLOAD_ERROR_STATUS%==0 (
155
- @echo Warning: Failed to download "%REMOTE_SOURCE_MSI_URL%" to "%LOCAL_DESTINATION_MSI_PATH%"
156
- @echo Warning: Retrying download with cscript ...
157
-
158
- @if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
159
-
160
- @set "REMOTE_SOURCE_MSI_URL=<%= msi_url('%MACHINE_OS%', '%MACHINE_ARCH%') %>"
161
- cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
162
-
163
- @if NOT ERRORLEVEL 1 (
164
- @rem Sometimes the error level is not set even when the download failed,
165
- @rem so check for the file to be sure it is there.
166
- @if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
167
- echo Failed download: download completed, but downloaded file not found > "&2"
168
- echo Exiting without bootstrapping due to download failure. > "&2"
169
- exit /b 1
170
- ) else (
171
- echo Download via cscript succeeded.
172
- )
173
- ) else (
174
- echo Failed to download "%REMOTE_SOURCE_MSI_URL%" with status code !ERRORLEVEL!. > "&2"
175
- echo Exiting without bootstrapping due to download failure. > "&2"
176
- exit /b 1
177
- )
178
- )
179
-
180
- @echo Installing downloaded client package...
181
-
182
- <%= install_chef %>
183
-
184
- @if ERRORLEVEL 1 (
185
- echo Chef-client package failed to install with status code !ERRORLEVEL!. > "&2"
186
- echo See installation log for additional detail: %CHEF_CLIENT_MSI_LOG_PATH%. > "&2"
187
- ) else (
188
- @echo Installation completed successfully
189
- del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
190
- )
191
-
192
- <% end %>
193
-
194
- @endlocal
195
-
196
- @echo off
197
-
198
- <% if client_pem -%>
199
- > <%= bootstrap_directory %>\client.pem (
200
- <%= escape_and_echo(::File.read(::File.expand_path(client_pem))) %>
201
- )
202
- <% end -%>
203
-
204
- echo Writing validation key...
205
-
206
- <% if validation_key -%>
207
- > <%= bootstrap_directory %>\validation.pem (
208
- <%= escape_and_echo(validation_key) %>
209
- )
210
- <% end -%>
211
-
212
- echo Validation key written.
213
- @echo on
214
-
215
- <% if @config[:secret] -%>
216
- > <%= bootstrap_directory %>\encrypted_data_bag_secret (
217
- <%= secret %>
218
- )
219
- <% end -%>
220
-
221
- <% unless trusted_certs_script.empty? -%>
222
- mkdir <%= bootstrap_directory %>\trusted_certs
223
- <%= trusted_certs_script %>
224
- <% end -%>
225
-
226
- <%# Generate Ohai Hints -%>
227
- <% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
228
- mkdir <%= bootstrap_directory %>\ohai\hints
229
-
230
- <% @chef_config[:knife][:hints].each do |name, hash| -%>
231
- > <%= bootstrap_directory %>\ohai\hints\<%= name %>.json (
232
- <%= escape_and_echo(hash.to_json) %>
233
- )
234
- <% end -%>
235
- <% end -%>
236
-
237
- > <%= bootstrap_directory %>\client.rb (
238
- <%= config_content %>
239
- )
240
-
241
- > <%= bootstrap_directory %>\first-boot.json (
242
- <%= first_boot %>
243
- )
244
-
245
- @echo Starting chef to bootstrap the node...
246
- <%= start_chef %>
1
+ @rem
2
+ @rem Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ @rem Copyright:: Copyright (c) 2011 Opscode, Inc.
4
+ @rem License:: Apache License, Version 2.0
5
+ @rem
6
+ @rem Licensed under the Apache License, Version 2.0 (the "License");
7
+ @rem you may not use this file except in compliance with the License.
8
+ @rem You may obtain a copy of the License at
9
+ @rem
10
+ @rem http://www.apache.org/licenses/LICENSE-2.0
11
+ @rem
12
+ @rem Unless required by applicable law or agreed to in writing, software
13
+ @rem distributed under the License is distributed on an "AS IS" BASIS,
14
+ @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ @rem See the License for the specific language governing permissions and
16
+ @rem limitations under the License.
17
+ @rem
18
+
19
+ @rem Use delayed environment expansion so that ERRORLEVEL can be evaluated with the
20
+ @rem !ERRORLEVEL! syntax which evaluates at execution of the line of script, not when
21
+ @rem the line is read. See help for the /E switch from cmd.exe /? .
22
+ @setlocal ENABLEDELAYEDEXPANSION
23
+
24
+ <%= "SETX HTTP_PROXY \"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] %>
25
+
26
+ @set BOOTSTRAP_DIRECTORY=<%= bootstrap_directory %>
27
+ @echo Checking for existing directory "%BOOTSTRAP_DIRECTORY%"...
28
+ @if NOT EXIST %BOOTSTRAP_DIRECTORY% (
29
+ @echo Existing directory not found, creating.
30
+ @mkdir %BOOTSTRAP_DIRECTORY%
31
+ ) else (
32
+ @echo Existing directory found, skipping creation.
33
+ )
34
+
35
+ > <%= bootstrap_directory %>\wget.vbs (
36
+ <%= win_wget %>
37
+ )
38
+
39
+ > <%= bootstrap_directory %>\wget.ps1 (
40
+ <%= win_wget_ps %>
41
+ )
42
+
43
+ @rem Determine the version and the architecture
44
+
45
+ @FOR /F "usebackq tokens=1-8 delims=.[] " %%A IN (`ver`) DO (
46
+ @set WinMajor=%%D
47
+ @set WinMinor=%%E
48
+ @set WinBuild=%%F
49
+ )
50
+
51
+ @echo Detected Windows Version %WinMajor%.%WinMinor% Build %WinBuild%
52
+
53
+ @set LATEST_OS_VERSION_MAJOR=6
54
+ @set LATEST_OS_VERSION_MINOR=3
55
+
56
+ @if /i %WinMajor% GTR %LATEST_OS_VERSION_MAJOR% goto VersionUnknown
57
+ @if /i %WinMajor% EQU %LATEST_OS_VERSION_MAJOR% (
58
+ @if /i %WinMinor% GTR %LATEST_OS_VERSION_MINOR% goto VersionUnknown
59
+ )
60
+
61
+ goto Version%WinMajor%.%WinMinor%
62
+
63
+ :VersionUnknown
64
+ @rem If this is an unknown version of windows set the default
65
+ @set MACHINE_OS=2008r2
66
+ @echo Warning: Unknown version of Windows, assuming default of Windows %MACHINE_OS%
67
+ goto architecture_select
68
+
69
+ :Version6.0
70
+ @set MACHINE_OS=2008
71
+ goto architecture_select
72
+
73
+ :Version5.2
74
+ @set MACHINE_OS=2003r2
75
+ goto architecture_select
76
+
77
+ :Version6.1
78
+ @set MACHINE_OS=2008r2
79
+ goto architecture_select
80
+
81
+ :Version6.2
82
+ @set MACHINE_OS=2012
83
+ goto architecture_select
84
+
85
+ @rem Currently Windows Server 2012 R2 is treated as equivalent to Windows Server 2012
86
+ :Version6.3
87
+ goto Version6.2
88
+
89
+ :architecture_select
90
+ goto Architecture%PROCESSOR_ARCHITEW6432%
91
+
92
+ :Architecture
93
+ goto Architecture%PROCESSOR_ARCHITECTURE%
94
+
95
+ @rem If this is an unknown architecture set the default
96
+ @set MACHINE_ARCH=i686
97
+ goto install
98
+
99
+ :Architecturex86
100
+ @set MACHINE_ARCH=i686
101
+ goto install
102
+
103
+ :Architectureamd64
104
+ @set MACHINE_ARCH=x86_64
105
+ goto install
106
+
107
+ :install
108
+ @rem If user has provided the custom installation command for chef-client then execute it
109
+ <% if @chef_config[:knife][:bootstrap_install_command] %>
110
+ <%= @chef_config[:knife][:bootstrap_install_command] %>
111
+ <% else %>
112
+ @rem Install Chef using chef-client MSI installer
113
+
114
+ @set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
115
+ @set "CHEF_CLIENT_MSI_LOG_PATH=%TEMP%\chef-client-msi%RANDOM%.log"
116
+
117
+ @rem Clear any pre-existing downloads
118
+ @echo Checking for existing downloaded package at "%LOCAL_DESTINATION_MSI_PATH%"
119
+ @if EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
120
+ @echo Found existing downloaded package, deleting.
121
+ @del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
122
+ @if ERRORLEVEL 1 (
123
+ echo Warning: Failed to delete pre-existing package with status code !ERRORLEVEL! > "&2"
124
+ )
125
+ ) else (
126
+ echo No existing downloaded packages to delete.
127
+ )
128
+
129
+ @rem If there is somehow a name collision, remove pre-existing log
130
+ @if EXIST "%CHEF_CLIENT_MSI_LOG_PATH%" del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
131
+
132
+ @echo Attempting to download client package using PowerShell if available...
133
+ @set "REMOTE_SOURCE_MSI_URL=<%= msi_url('%MACHINE_OS%', '%MACHINE_ARCH%', 'PowerShell') %>"
134
+ @set powershell_download=powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File <%= bootstrap_directory %>\wget.ps1 "%REMOTE_SOURCE_MSI_URL%" "%LOCAL_DESTINATION_MSI_PATH%"
135
+ @echo !powershell_download!
136
+ @call !powershell_download!
137
+
138
+ @set DOWNLOAD_ERROR_STATUS=!ERRORLEVEL!
139
+
140
+ @if ERRORLEVEL 1 (
141
+ @echo Failed PowerShell download with status code !DOWNLOAD_ERROR_STATUS! > "&2"
142
+ @if !DOWNLOAD_ERROR_STATUS!==0 set DOWNLOAD_ERROR_STATUS=2
143
+ ) else (
144
+ @rem Sometimes the error level is not set even when the download failed,
145
+ @rem so check for the file to be sure it is there -- if it is not, we will retry
146
+ @if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
147
+ echo Failed download: download completed, but downloaded file not found > "&2"
148
+ set DOWNLOAD_ERROR_STATUS=2
149
+ ) else (
150
+ echo Download via PowerShell succeeded.
151
+ )
152
+ )
153
+
154
+ @if NOT %DOWNLOAD_ERROR_STATUS%==0 (
155
+ @echo Warning: Failed to download "%REMOTE_SOURCE_MSI_URL%" to "%LOCAL_DESTINATION_MSI_PATH%"
156
+ @echo Warning: Retrying download with cscript ...
157
+
158
+ @if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
159
+
160
+ @set "REMOTE_SOURCE_MSI_URL=<%= msi_url('%MACHINE_OS%', '%MACHINE_ARCH%') %>"
161
+ cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
162
+
163
+ @if NOT ERRORLEVEL 1 (
164
+ @rem Sometimes the error level is not set even when the download failed,
165
+ @rem so check for the file to be sure it is there.
166
+ @if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
167
+ echo Failed download: download completed, but downloaded file not found > "&2"
168
+ echo Exiting without bootstrapping due to download failure. > "&2"
169
+ exit /b 1
170
+ ) else (
171
+ echo Download via cscript succeeded.
172
+ )
173
+ ) else (
174
+ echo Failed to download "%REMOTE_SOURCE_MSI_URL%" with status code !ERRORLEVEL!. > "&2"
175
+ echo Exiting without bootstrapping due to download failure. > "&2"
176
+ exit /b 1
177
+ )
178
+ )
179
+
180
+ @echo Installing downloaded client package...
181
+
182
+ <%= install_chef %>
183
+
184
+ @if ERRORLEVEL 1 (
185
+ echo Chef-client package failed to install with status code !ERRORLEVEL!. > "&2"
186
+ echo See installation log for additional detail: %CHEF_CLIENT_MSI_LOG_PATH%. > "&2"
187
+ ) else (
188
+ @echo Installation completed successfully
189
+ del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
190
+ )
191
+
192
+ <% end %>
193
+
194
+ @endlocal
195
+
196
+ @echo off
197
+
198
+ <% if client_pem -%>
199
+ > <%= bootstrap_directory %>\client.pem (
200
+ <%= escape_and_echo(::File.read(::File.expand_path(client_pem))) %>
201
+ )
202
+ <% end -%>
203
+
204
+ echo Writing validation key...
205
+
206
+ <% if validation_key -%>
207
+ > <%= bootstrap_directory %>\validation.pem (
208
+ <%= escape_and_echo(validation_key) %>
209
+ )
210
+ <% end -%>
211
+
212
+ echo Validation key written.
213
+ @echo on
214
+
215
+ <% if @config[:secret] -%>
216
+ > <%= bootstrap_directory %>\encrypted_data_bag_secret (
217
+ <%= secret %>
218
+ )
219
+ <% end -%>
220
+
221
+ <% unless trusted_certs_script.empty? -%>
222
+ mkdir <%= bootstrap_directory %>\trusted_certs
223
+ <%= trusted_certs_script %>
224
+ <% end -%>
225
+
226
+ <%# Generate Ohai Hints -%>
227
+ <% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
228
+ mkdir <%= bootstrap_directory %>\ohai\hints
229
+
230
+ <% @chef_config[:knife][:hints].each do |name, hash| -%>
231
+ > <%= bootstrap_directory %>\ohai\hints\<%= name %>.json (
232
+ <%= escape_and_echo(hash.to_json) %>
233
+ )
234
+ <% end -%>
235
+ <% end -%>
236
+
237
+ > <%= bootstrap_directory %>\client.rb (
238
+ <%= config_content %>
239
+ )
240
+
241
+ > <%= bootstrap_directory %>\first-boot.json (
242
+ <%= first_boot %>
243
+ )
244
+
245
+ @echo Starting chef to bootstrap the node...
246
+ <%= start_chef %>