knife-windows 0.5.15 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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