knife-windows 0.5.15 → 0.6.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 +15 -0
- data/.gitignore +4 -4
- data/.rspec +3 -3
- data/.travis.yml +6 -6
- data/CHANGELOG.md +33 -0
- data/DOC_CHANGES.md +42 -0
- data/Gemfile +11 -11
- data/LICENSE +201 -201
- data/README.rdoc +134 -140
- data/RELEASE_NOTES.md +40 -0
- data/Rakefile +16 -16
- data/features/knife_help.feature +20 -20
- data/features/support/env.rb +5 -5
- data/knife-windows.gemspec +24 -24
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +222 -222
- data/lib/chef/knife/bootstrap_windows_base.rb +206 -196
- data/lib/chef/knife/bootstrap_windows_ssh.rb +93 -93
- data/lib/chef/knife/bootstrap_windows_winrm.rb +97 -62
- data/lib/chef/knife/core/windows_bootstrap_context.rb +177 -177
- data/lib/chef/knife/windows_helper.rb +34 -34
- data/lib/chef/knife/winrm.rb +296 -286
- data/lib/chef/knife/winrm_base.rb +99 -99
- data/lib/knife-windows/version.rb +6 -6
- data/spec/functional/bootstrap_download_spec.rb +122 -120
- data/spec/spec_helper.rb +63 -63
- data/spec/unit/knife/bootstrap_template_spec.rb +91 -91
- data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +85 -0
- data/spec/unit/knife/winrm_spec.rb +152 -82
- metadata +17 -12
- data/CHANGELOG +0 -14
- data/lib/chef/knife/bootstrap/windows-shell.erb +0 -68
@@ -1,222 +1,222 @@
|
|
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 Install Chef using chef-client MSI installer
|
109
|
-
|
110
|
-
<% url="https://www.opscode.com/chef/download?p=windows&pv=%MACHINE_OS%&m=%MACHINE_ARCH%" -%>
|
111
|
-
<% url += "&v=#{@config[:bootstrap_version]}" if @config.key? :bootstrap_version -%>
|
112
|
-
@set "REMOTE_SOURCE_MSI_URL=<%= url %>"
|
113
|
-
@set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
|
114
|
-
@set "CHEF_CLIENT_MSI_LOG_PATH=%TEMP%\chef-client-msi%RANDOM%.log"
|
115
|
-
@set "FALLBACK_QUERY_STRING=&DownloadContext=PowerShell"
|
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 cscript...
|
133
|
-
cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
|
134
|
-
|
135
|
-
@rem Work around issues found in Windows Server 2012 around job objects not respecting WSMAN memory quotas
|
136
|
-
@rem that cause the MSI download process to exceed the quota even when it is increased by administrators.
|
137
|
-
@rem Retry the download using a more memory-efficient mechanism that only works if PowerShell is available.
|
138
|
-
@set DOWNLOAD_ERROR_STATUS=!ERRORLEVEL!
|
139
|
-
@if ERRORLEVEL 1 (
|
140
|
-
@echo Failed cscript download with status code !DOWNLOAD_ERROR_STATUS! > "&2"
|
141
|
-
@if !DOWNLOAD_ERROR_STATUS!==0 set DOWNLOAD_ERROR_STATUS=2
|
142
|
-
) else (
|
143
|
-
@rem Sometimes the error level is not set even when the download failed,
|
144
|
-
@rem so check for the file to be sure it is there -- if it is not, we will retry
|
145
|
-
@if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
|
146
|
-
echo Failed download: download completed, but downloaded file not found > "&2"
|
147
|
-
set DOWNLOAD_ERROR_STATUS=2
|
148
|
-
) else (
|
149
|
-
echo Download via cscript succeeded.
|
150
|
-
)
|
151
|
-
)
|
152
|
-
|
153
|
-
@if NOT %DOWNLOAD_ERROR_STATUS%==0 (
|
154
|
-
@echo Warning: Failed to download "%REMOTE_SOURCE_MSI_URL%" to "%LOCAL_DESTINATION_MSI_PATH%"
|
155
|
-
@echo Warning: Retrying download with PowerShell if available...
|
156
|
-
|
157
|
-
@if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
|
158
|
-
|
159
|
-
@set powershell_download=powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File <%= bootstrap_directory %>\wget.ps1 "%REMOTE_SOURCE_MSI_URL%%FALLBACK_QUERY_STRING%" "%LOCAL_DESTINATION_MSI_PATH%"
|
160
|
-
@echo !powershell_download!
|
161
|
-
@call !powershell_download!
|
162
|
-
@if NOT ERRORLEVEL 1 (
|
163
|
-
echo Download via PowerShell succeeded.
|
164
|
-
) else (
|
165
|
-
echo Failed to download "%REMOTE_SOURCE_MSI_URL%" with status code !ERRORLEVEL!. > "&2"
|
166
|
-
echo Exiting without bootstrapping due to download failure. > "&2"
|
167
|
-
exit /b 1
|
168
|
-
)
|
169
|
-
)
|
170
|
-
|
171
|
-
@echo Installing downloaded client package...
|
172
|
-
|
173
|
-
<%= install_chef %>
|
174
|
-
|
175
|
-
@if ERRORLEVEL 1 (
|
176
|
-
echo Chef-client package failed to install with status code !ERRORLEVEL!. > "&2"
|
177
|
-
echo See installation log for additional detail: %CHEF_CLIENT_MSI_LOG_PATH%. > "&2"
|
178
|
-
) else (
|
179
|
-
@echo Installation completed successfully
|
180
|
-
del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
|
181
|
-
)
|
182
|
-
|
183
|
-
@endlocal
|
184
|
-
|
185
|
-
@echo off
|
186
|
-
echo Writing validation key...
|
187
|
-
|
188
|
-
> <%= bootstrap_directory %>\validation.pem (
|
189
|
-
<%= validation_key %>
|
190
|
-
)
|
191
|
-
|
192
|
-
echo Validation key written.
|
193
|
-
@echo on
|
194
|
-
|
195
|
-
<% if @config[:encrypted_data_bag_secret] -%>
|
196
|
-
> <%= bootstrap_directory %>\encrypted_data_bag_secret (
|
197
|
-
<%= encrypted_data_bag_secret %>
|
198
|
-
)
|
199
|
-
<% end -%>
|
200
|
-
|
201
|
-
<%# Generate Ohai Hints -%>
|
202
|
-
<% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
|
203
|
-
mkdir <%= bootstrap_directory %>\ohai\hints
|
204
|
-
|
205
|
-
<% @chef_config[:knife][:hints].each do |name, hash| -%>
|
206
|
-
> <%= bootstrap_directory %>\ohai\hints\<%= name %>.json (
|
207
|
-
<%= escape_and_echo(hash.to_json) %>
|
208
|
-
)
|
209
|
-
<% end -%>
|
210
|
-
<% end -%>
|
211
|
-
|
212
|
-
> <%= bootstrap_directory %>\client.rb (
|
213
|
-
<%= config_content %>
|
214
|
-
)
|
215
|
-
|
216
|
-
> <%= bootstrap_directory %>\first-boot.json (
|
217
|
-
<%= first_boot %>
|
218
|
-
)
|
219
|
-
|
220
|
-
@echo Starting chef to bootstrap the node...
|
221
|
-
<%= start_chef %>
|
222
|
-
|
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 Install Chef using chef-client MSI installer
|
109
|
+
|
110
|
+
<% url="https://www.opscode.com/chef/download?p=windows&pv=%MACHINE_OS%&m=%MACHINE_ARCH%" -%>
|
111
|
+
<% url += "&v=#{@config[:bootstrap_version]}" if @config.key? :bootstrap_version -%>
|
112
|
+
@set "REMOTE_SOURCE_MSI_URL=<%= url %>"
|
113
|
+
@set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
|
114
|
+
@set "CHEF_CLIENT_MSI_LOG_PATH=%TEMP%\chef-client-msi%RANDOM%.log"
|
115
|
+
@set "FALLBACK_QUERY_STRING=&DownloadContext=PowerShell"
|
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 cscript...
|
133
|
+
cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
|
134
|
+
|
135
|
+
@rem Work around issues found in Windows Server 2012 around job objects not respecting WSMAN memory quotas
|
136
|
+
@rem that cause the MSI download process to exceed the quota even when it is increased by administrators.
|
137
|
+
@rem Retry the download using a more memory-efficient mechanism that only works if PowerShell is available.
|
138
|
+
@set DOWNLOAD_ERROR_STATUS=!ERRORLEVEL!
|
139
|
+
@if ERRORLEVEL 1 (
|
140
|
+
@echo Failed cscript download with status code !DOWNLOAD_ERROR_STATUS! > "&2"
|
141
|
+
@if !DOWNLOAD_ERROR_STATUS!==0 set DOWNLOAD_ERROR_STATUS=2
|
142
|
+
) else (
|
143
|
+
@rem Sometimes the error level is not set even when the download failed,
|
144
|
+
@rem so check for the file to be sure it is there -- if it is not, we will retry
|
145
|
+
@if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
|
146
|
+
echo Failed download: download completed, but downloaded file not found > "&2"
|
147
|
+
set DOWNLOAD_ERROR_STATUS=2
|
148
|
+
) else (
|
149
|
+
echo Download via cscript succeeded.
|
150
|
+
)
|
151
|
+
)
|
152
|
+
|
153
|
+
@if NOT %DOWNLOAD_ERROR_STATUS%==0 (
|
154
|
+
@echo Warning: Failed to download "%REMOTE_SOURCE_MSI_URL%" to "%LOCAL_DESTINATION_MSI_PATH%"
|
155
|
+
@echo Warning: Retrying download with PowerShell if available...
|
156
|
+
|
157
|
+
@if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
|
158
|
+
|
159
|
+
@set powershell_download=powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File <%= bootstrap_directory %>\wget.ps1 "%REMOTE_SOURCE_MSI_URL%%FALLBACK_QUERY_STRING%" "%LOCAL_DESTINATION_MSI_PATH%"
|
160
|
+
@echo !powershell_download!
|
161
|
+
@call !powershell_download!
|
162
|
+
@if NOT ERRORLEVEL 1 (
|
163
|
+
echo Download via PowerShell succeeded.
|
164
|
+
) else (
|
165
|
+
echo Failed to download "%REMOTE_SOURCE_MSI_URL%" with status code !ERRORLEVEL!. > "&2"
|
166
|
+
echo Exiting without bootstrapping due to download failure. > "&2"
|
167
|
+
exit /b 1
|
168
|
+
)
|
169
|
+
)
|
170
|
+
|
171
|
+
@echo Installing downloaded client package...
|
172
|
+
|
173
|
+
<%= install_chef %>
|
174
|
+
|
175
|
+
@if ERRORLEVEL 1 (
|
176
|
+
echo Chef-client package failed to install with status code !ERRORLEVEL!. > "&2"
|
177
|
+
echo See installation log for additional detail: %CHEF_CLIENT_MSI_LOG_PATH%. > "&2"
|
178
|
+
) else (
|
179
|
+
@echo Installation completed successfully
|
180
|
+
del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
|
181
|
+
)
|
182
|
+
|
183
|
+
@endlocal
|
184
|
+
|
185
|
+
@echo off
|
186
|
+
echo Writing validation key...
|
187
|
+
|
188
|
+
> <%= bootstrap_directory %>\validation.pem (
|
189
|
+
<%= validation_key %>
|
190
|
+
)
|
191
|
+
|
192
|
+
echo Validation key written.
|
193
|
+
@echo on
|
194
|
+
|
195
|
+
<% if @config[:encrypted_data_bag_secret] -%>
|
196
|
+
> <%= bootstrap_directory %>\encrypted_data_bag_secret (
|
197
|
+
<%= encrypted_data_bag_secret %>
|
198
|
+
)
|
199
|
+
<% end -%>
|
200
|
+
|
201
|
+
<%# Generate Ohai Hints -%>
|
202
|
+
<% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
|
203
|
+
mkdir <%= bootstrap_directory %>\ohai\hints
|
204
|
+
|
205
|
+
<% @chef_config[:knife][:hints].each do |name, hash| -%>
|
206
|
+
> <%= bootstrap_directory %>\ohai\hints\<%= name %>.json (
|
207
|
+
<%= escape_and_echo(hash.to_json) %>
|
208
|
+
)
|
209
|
+
<% end -%>
|
210
|
+
<% end -%>
|
211
|
+
|
212
|
+
> <%= bootstrap_directory %>\client.rb (
|
213
|
+
<%= config_content %>
|
214
|
+
)
|
215
|
+
|
216
|
+
> <%= bootstrap_directory %>\first-boot.json (
|
217
|
+
<%= first_boot %>
|
218
|
+
)
|
219
|
+
|
220
|
+
@echo Starting chef to bootstrap the node...
|
221
|
+
<%= start_chef %>
|
222
|
+
|
@@ -1,196 +1,206 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
-
# Copyright:: Copyright (c) 2011 Opscode, 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'
|
20
|
-
require 'chef/encrypted_data_bag_item'
|
21
|
-
require 'chef/knife/core/windows_bootstrap_context'
|
22
|
-
|
23
|
-
class Chef
|
24
|
-
class Knife
|
25
|
-
module BootstrapWindowsBase
|
26
|
-
|
27
|
-
# :nodoc:
|
28
|
-
# Would prefer to do this in a rational way, but can't be done b/c of
|
29
|
-
# Mixlib::CLI's design :(
|
30
|
-
def self.included(includer)
|
31
|
-
includer.class_eval do
|
32
|
-
|
33
|
-
deps do
|
34
|
-
require 'readline'
|
35
|
-
require 'chef/json_compat'
|
36
|
-
end
|
37
|
-
|
38
|
-
option :chef_node_name,
|
39
|
-
:short => "-N NAME",
|
40
|
-
:long => "--node-name NAME",
|
41
|
-
:description => "The Chef node name for your new node"
|
42
|
-
|
43
|
-
option :prerelease,
|
44
|
-
:long => "--prerelease",
|
45
|
-
:description => "Install the pre-release chef gems"
|
46
|
-
|
47
|
-
option :bootstrap_version,
|
48
|
-
:long => "--bootstrap-version VERSION",
|
49
|
-
:description => "The version of Chef to install",
|
50
|
-
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
51
|
-
|
52
|
-
option :bootstrap_proxy,
|
53
|
-
:long => "--bootstrap-proxy PROXY_URL",
|
54
|
-
:description => "The proxy server for the node being bootstrapped",
|
55
|
-
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
56
|
-
|
57
|
-
option :bootstrap_no_proxy,
|
58
|
-
:long => "--bootstrap-no-proxy ",
|
59
|
-
:description => "Avoid a proxy server for the given addresses",
|
60
|
-
:proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
|
61
|
-
|
62
|
-
option :distro,
|
63
|
-
:short => "-d DISTRO",
|
64
|
-
:long => "--distro DISTRO",
|
65
|
-
:description => "Bootstrap a distro using a template",
|
66
|
-
:default => "windows-chef-client-msi"
|
67
|
-
|
68
|
-
option :template_file,
|
69
|
-
:long => "--template-file TEMPLATE",
|
70
|
-
:description => "Full path to location of template to use",
|
71
|
-
:default => false
|
72
|
-
|
73
|
-
option :run_list,
|
74
|
-
:short => "-r RUN_LIST",
|
75
|
-
:long => "--run-list RUN_LIST",
|
76
|
-
:description => "Comma separated list of roles/recipes to apply",
|
77
|
-
:proc => lambda { |o| o.split(",") },
|
78
|
-
:default => []
|
79
|
-
|
80
|
-
option :first_boot_attributes,
|
81
|
-
:short => "-j JSON_ATTRIBS",
|
82
|
-
:long => "--json-attributes",
|
83
|
-
:description => "A JSON string to be added to the first run of chef-client",
|
84
|
-
:proc => lambda { |o| JSON.parse(o) },
|
85
|
-
:default => {}
|
86
|
-
|
87
|
-
option :encrypted_data_bag_secret,
|
88
|
-
:short => "-s SECRET",
|
89
|
-
:long => "--secret ",
|
90
|
-
:description => "The secret key to use to decrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config.",
|
91
|
-
:default => false
|
92
|
-
|
93
|
-
option :encrypted_data_bag_secret_file,
|
94
|
-
:long => "--secret-file SECRET_FILE",
|
95
|
-
:description => "A file containing the secret key to use to encrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config."
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
bootstrap_files
|
109
|
-
|
110
|
-
bootstrap_files
|
111
|
-
bootstrap_files.
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
end
|
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
|
-
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, 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'
|
20
|
+
require 'chef/encrypted_data_bag_item'
|
21
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Knife
|
25
|
+
module BootstrapWindowsBase
|
26
|
+
|
27
|
+
# :nodoc:
|
28
|
+
# Would prefer to do this in a rational way, but can't be done b/c of
|
29
|
+
# Mixlib::CLI's design :(
|
30
|
+
def self.included(includer)
|
31
|
+
includer.class_eval do
|
32
|
+
|
33
|
+
deps do
|
34
|
+
require 'readline'
|
35
|
+
require 'chef/json_compat'
|
36
|
+
end
|
37
|
+
|
38
|
+
option :chef_node_name,
|
39
|
+
:short => "-N NAME",
|
40
|
+
:long => "--node-name NAME",
|
41
|
+
:description => "The Chef node name for your new node"
|
42
|
+
|
43
|
+
option :prerelease,
|
44
|
+
:long => "--prerelease",
|
45
|
+
:description => "Install the pre-release chef gems"
|
46
|
+
|
47
|
+
option :bootstrap_version,
|
48
|
+
:long => "--bootstrap-version VERSION",
|
49
|
+
:description => "The version of Chef to install",
|
50
|
+
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
51
|
+
|
52
|
+
option :bootstrap_proxy,
|
53
|
+
:long => "--bootstrap-proxy PROXY_URL",
|
54
|
+
:description => "The proxy server for the node being bootstrapped",
|
55
|
+
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
56
|
+
|
57
|
+
option :bootstrap_no_proxy,
|
58
|
+
:long => "--bootstrap-no-proxy ",
|
59
|
+
:description => "Avoid a proxy server for the given addresses",
|
60
|
+
:proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
|
61
|
+
|
62
|
+
option :distro,
|
63
|
+
:short => "-d DISTRO",
|
64
|
+
:long => "--distro DISTRO",
|
65
|
+
:description => "Bootstrap a distro using a template",
|
66
|
+
:default => "windows-chef-client-msi"
|
67
|
+
|
68
|
+
option :template_file,
|
69
|
+
:long => "--template-file TEMPLATE",
|
70
|
+
:description => "Full path to location of template to use",
|
71
|
+
:default => false
|
72
|
+
|
73
|
+
option :run_list,
|
74
|
+
:short => "-r RUN_LIST",
|
75
|
+
:long => "--run-list RUN_LIST",
|
76
|
+
:description => "Comma separated list of roles/recipes to apply",
|
77
|
+
:proc => lambda { |o| o.split(",") },
|
78
|
+
:default => []
|
79
|
+
|
80
|
+
option :first_boot_attributes,
|
81
|
+
:short => "-j JSON_ATTRIBS",
|
82
|
+
:long => "--json-attributes",
|
83
|
+
:description => "A JSON string to be added to the first run of chef-client",
|
84
|
+
:proc => lambda { |o| JSON.parse(o) },
|
85
|
+
:default => {}
|
86
|
+
|
87
|
+
option :encrypted_data_bag_secret,
|
88
|
+
:short => "-s SECRET",
|
89
|
+
:long => "--secret ",
|
90
|
+
:description => "The secret key to use to decrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config.",
|
91
|
+
:default => false
|
92
|
+
|
93
|
+
option :encrypted_data_bag_secret_file,
|
94
|
+
:long => "--secret-file SECRET_FILE",
|
95
|
+
:description => "A file containing the secret key to use to encrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config."
|
96
|
+
|
97
|
+
option :auth_timeout,
|
98
|
+
:long => "--auth-timeout MINUTES",
|
99
|
+
: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.",
|
100
|
+
:default => 25
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# TODO: This should go away when CHEF-2193 is fixed
|
105
|
+
def load_template(template=nil)
|
106
|
+
# Are we bootstrapping using an already shipped template?
|
107
|
+
if config[:template_file]
|
108
|
+
bootstrap_files = config[:template_file]
|
109
|
+
else
|
110
|
+
bootstrap_files = []
|
111
|
+
bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
|
112
|
+
bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
|
113
|
+
bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
|
114
|
+
bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
|
115
|
+
bootstrap_files.flatten!
|
116
|
+
end
|
117
|
+
|
118
|
+
template = Array(bootstrap_files).find do |bootstrap_template|
|
119
|
+
Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
|
120
|
+
::File.exists?(bootstrap_template)
|
121
|
+
end
|
122
|
+
|
123
|
+
unless template
|
124
|
+
ui.info("Can not find bootstrap definition for #{config[:distro]}")
|
125
|
+
raise Errno::ENOENT
|
126
|
+
end
|
127
|
+
|
128
|
+
Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
|
129
|
+
|
130
|
+
IO.read(template).chomp
|
131
|
+
end
|
132
|
+
|
133
|
+
def render_template(template=nil)
|
134
|
+
if config[:encrypted_data_bag_secret_file]
|
135
|
+
config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
|
136
|
+
end
|
137
|
+
context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
|
138
|
+
Erubis::Eruby.new(template).evaluate(context)
|
139
|
+
end
|
140
|
+
|
141
|
+
def bootstrap(proto=nil)
|
142
|
+
validate_name_args!
|
143
|
+
|
144
|
+
@node_name = Array(@name_args).first
|
145
|
+
# back compat--templates may use this setting:
|
146
|
+
config[:server_name] = @node_name
|
147
|
+
|
148
|
+
STDOUT.sync = STDERR.sync = true
|
149
|
+
|
150
|
+
wait_for_remote_response( config[:auth_timeout].to_i )
|
151
|
+
ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
|
152
|
+
# create a bootstrap.bat file on the node
|
153
|
+
# we have to run the remote commands in 2047 char chunks
|
154
|
+
create_bootstrap_bat_command do |command_chunk, chunk_num|
|
155
|
+
begin
|
156
|
+
render_command_result = run_command(%Q!cmd.exe /C echo "Rendering #{bootstrap_bat_file} chunk #{chunk_num}" && #{command_chunk}!)
|
157
|
+
ui.error("Batch render command returned #{render_command_result}") if render_command_result != 0
|
158
|
+
render_command_result
|
159
|
+
rescue SystemExit => e
|
160
|
+
raise unless e.success?
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# execute the bootstrap.bat file
|
165
|
+
bootstrap_command_result = run_command(bootstrap_command)
|
166
|
+
ui.error("Bootstrap command returned #{bootstrap_command_result}") if bootstrap_command_result != 0
|
167
|
+
bootstrap_command_result
|
168
|
+
end
|
169
|
+
|
170
|
+
protected
|
171
|
+
|
172
|
+
# Default implementation -- override only if required by the transport
|
173
|
+
def wait_for_remote_response(wait_max_minutes)
|
174
|
+
end
|
175
|
+
|
176
|
+
def bootstrap_command
|
177
|
+
@bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_bootstrap_bat_command(&block)
|
181
|
+
bootstrap_bat = []
|
182
|
+
chunk_num = 0
|
183
|
+
render_template(load_template(config[:bootstrap_template])).each_line do |line|
|
184
|
+
# escape WIN BATCH special chars
|
185
|
+
line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
|
186
|
+
# windows commands are limited to 2047 characters
|
187
|
+
if((bootstrap_bat + [line]).join(" && ").size > 2047 )
|
188
|
+
yield bootstrap_bat.join(" && "), chunk_num += 1
|
189
|
+
bootstrap_bat = []
|
190
|
+
end
|
191
|
+
bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
|
192
|
+
end
|
193
|
+
yield bootstrap_bat.join(" && "), chunk_num += 1
|
194
|
+
end
|
195
|
+
|
196
|
+
def bootstrap_bat_file
|
197
|
+
@bootstrap_bat_file ||= "\"%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat\""
|
198
|
+
end
|
199
|
+
|
200
|
+
def locate_config_value(key)
|
201
|
+
key = key.to_sym
|
202
|
+
Chef::Config[:knife][key] || config[key]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|