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.
@@ -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
- end
98
- end
99
-
100
- # TODO: This should go away when CHEF-2193 is fixed
101
- def load_template(template=nil)
102
- # Are we bootstrapping using an already shipped template?
103
- if config[:template_file]
104
- bootstrap_files = config[:template_file]
105
- else
106
- bootstrap_files = []
107
- bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
108
- bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
109
- bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
110
- bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
111
- bootstrap_files.flatten!
112
- end
113
-
114
- template = Array(bootstrap_files).find do |bootstrap_template|
115
- Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
116
- ::File.exists?(bootstrap_template)
117
- end
118
-
119
- unless template
120
- ui.info("Can not find bootstrap definition for #{config[:distro]}")
121
- raise Errno::ENOENT
122
- end
123
-
124
- Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
125
-
126
- IO.read(template).chomp
127
- end
128
-
129
- def render_template(template=nil)
130
- if config[:encrypted_data_bag_secret_file]
131
- config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
132
- end
133
- context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
134
- Erubis::Eruby.new(template).evaluate(context)
135
- end
136
-
137
- def bootstrap(proto=nil)
138
-
139
- validate_name_args!
140
-
141
- @node_name = Array(@name_args).first
142
- # back compat--templates may use this setting:
143
- config[:server_name] = @node_name
144
-
145
- STDOUT.sync = STDERR.sync = true
146
-
147
- ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
148
- # create a bootstrap.bat file on the node
149
- # we have to run the remote commands in 2047 char chunks
150
- create_bootstrap_bat_command do |command_chunk, chunk_num|
151
- begin
152
- render_command_result = run_command(%Q!cmd.exe /C echo "Rendering #{bootstrap_bat_file} chunk #{chunk_num}" && #{command_chunk}!)
153
- ui.error("Batch render command returned #{render_command_result}") if render_command_result != 0
154
- render_command_result
155
- rescue SystemExit => e
156
- raise unless e.success?
157
- end
158
- end
159
-
160
- # execute the bootstrap.bat file
161
- bootstrap_command_result = run_command(bootstrap_command)
162
- ui.error("Bootstrap command returned #{bootstrap_command_result}") if bootstrap_command_result != 0
163
- bootstrap_command_result
164
- end
165
-
166
- def bootstrap_command
167
- @bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
168
- end
169
-
170
- def create_bootstrap_bat_command(&block)
171
- bootstrap_bat = []
172
- chunk_num = 0
173
- render_template(load_template(config[:bootstrap_template])).each_line do |line|
174
- # escape WIN BATCH special chars
175
- line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
176
- # windows commands are limited to 2047 characters
177
- if((bootstrap_bat + [line]).join(" && ").size > 2047 )
178
- yield bootstrap_bat.join(" && "), chunk_num += 1
179
- bootstrap_bat = []
180
- end
181
- bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
182
- end
183
- yield bootstrap_bat.join(" && "), chunk_num += 1
184
- end
185
-
186
- def bootstrap_bat_file
187
- @bootstrap_bat_file ||= "\"%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat\""
188
- end
189
-
190
- def locate_config_value(key)
191
- key = key.to_sym
192
- Chef::Config[:knife][key] || config[key]
193
- end
194
- end
195
- end
196
- end
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