knife-windows 0.5.12 → 0.5.14.rc.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.
- data/.travis.yml +6 -0
- data/Gemfile +2 -1
- data/README.rdoc +1 -1
- data/features/knife_help.feature +20 -0
- data/features/support/env.rb +5 -0
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +92 -21
- data/lib/chef/knife/bootstrap_windows_base.rb +15 -2
- data/lib/chef/knife/core/windows_bootstrap_context.rb +7 -5
- data/lib/chef/knife/windows_helper.rb +34 -0
- data/lib/chef/knife/winrm.rb +21 -1
- data/lib/knife-windows/version.rb +1 -1
- data/spec/functional/bootstrap_download_spec.rb +11 -6
- data/spec/unit/knife/bootstrap_template_spec.rb +91 -0
- data/spec/unit/knife/winrm_spec.rb +17 -0
- metadata +18 -7
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -118,7 +118,7 @@ For development and testing purposes, unencrypted traffic with Basic authenticat
|
|
118
118
|
|
119
119
|
= CONTRIBUTING:
|
120
120
|
|
121
|
-
Please file bugs against the KNIFE_WINDOWS project at http://tickets.opscode.com/browse/
|
121
|
+
Please file bugs against the KNIFE_WINDOWS project at http://tickets.opscode.com/browse/knife
|
122
122
|
|
123
123
|
More information on the contribution process for Opscode projects can be found at: http://wiki.opscode.com/display/chef/How+to+Contribute
|
124
124
|
= LICENSE:
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Ensure that the help works as designed
|
2
|
+
In order to test the help via CLI
|
3
|
+
As an Operator
|
4
|
+
I want to run the CLI with different arguments
|
5
|
+
|
6
|
+
Scenario: Running the windows sub-command shows available commands
|
7
|
+
When I run `knife windows`
|
8
|
+
And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
|
9
|
+
|
10
|
+
Scenario: Running the windows sub-command shows available commands
|
11
|
+
When I run `knife windows --help`
|
12
|
+
And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
|
13
|
+
|
14
|
+
Scenario: Running the windows sub-command shows available commands
|
15
|
+
When I run `knife windows help`
|
16
|
+
And the output should contain "Available windows subcommands: (for details, knife SUB-COMMAND --help)\n\n** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
|
17
|
+
|
18
|
+
Scenario: Running the knife command shows available windows command"
|
19
|
+
When I run `knife`
|
20
|
+
And the output should contain "** WINDOWS COMMANDS **\nknife bootstrap windows winrm FQDN (options)\nknife bootstrap windows ssh FQDN (options)\nknife winrm QUERY COMMAND (options)"
|
@@ -16,10 +16,21 @@
|
|
16
16
|
@rem limitations under the License.
|
17
17
|
@rem
|
18
18
|
|
19
|
-
@
|
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
|
20
23
|
|
21
24
|
<%= "SETX HTTP_PROXY \"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] %>
|
22
|
-
|
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
|
+
)
|
23
34
|
|
24
35
|
> <%= bootstrap_directory %>\wget.vbs (
|
25
36
|
<%= win_wget %>
|
@@ -31,36 +42,54 @@ mkdir <%= bootstrap_directory %>
|
|
31
42
|
|
32
43
|
@rem Determine the version and the architecture
|
33
44
|
|
34
|
-
FOR /F "tokens=1-8 delims=.[] " %%A IN ('ver') DO (
|
45
|
+
@FOR /F "tokens=1-8 delims=.[] " %%A IN ('ver') DO (
|
35
46
|
@set WinMajor=%%D
|
36
47
|
@set WinMinor=%%E
|
37
48
|
@set WinBuild=%%F
|
38
49
|
)
|
39
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
|
+
|
40
61
|
goto Version%WinMajor%.%WinMinor%
|
41
62
|
|
63
|
+
:VersionUnknown
|
42
64
|
@rem If this is an unknown version of windows set the default
|
43
65
|
@set MACHINE_OS=2008r2
|
44
|
-
|
66
|
+
@echo Warning: Unknown version of Windows, assuming default of Windows %MACHINE_OS%
|
67
|
+
goto architecture_select
|
45
68
|
|
46
69
|
:Version6.0
|
47
70
|
@set MACHINE_OS=2008
|
48
|
-
goto
|
71
|
+
goto architecture_select
|
49
72
|
|
50
73
|
:Version5.2
|
51
74
|
@set MACHINE_OS=2003r2
|
52
|
-
goto
|
75
|
+
goto architecture_select
|
53
76
|
|
54
77
|
:Version6.1
|
55
78
|
@set MACHINE_OS=2008r2
|
56
|
-
goto
|
79
|
+
goto architecture_select
|
57
80
|
|
58
81
|
:Version6.2
|
59
82
|
@set MACHINE_OS=2012
|
60
|
-
goto
|
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
|
61
88
|
|
62
|
-
:
|
89
|
+
:architecture_select
|
90
|
+
goto Architecture%PROCESSOR_ARCHITEW6432%
|
63
91
|
|
92
|
+
:Architecture
|
64
93
|
goto Architecture%PROCESSOR_ARCHITECTURE%
|
65
94
|
|
66
95
|
@rem If this is an unknown architecture set the default
|
@@ -78,37 +107,79 @@ goto install
|
|
78
107
|
:install
|
79
108
|
@rem Install Chef using chef-client MSI installer
|
80
109
|
|
81
|
-
|
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 %>"
|
82
113
|
@set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
|
83
114
|
@set "FALLBACK_QUERY_STRING=&DownloadContext=PowerShell"
|
84
115
|
|
116
|
+
@rem Clear any pre-existing downloads
|
117
|
+
@echo Checking for existing downloaded package at "%LOCAL_DESTINATION_MSI_PATH%"
|
118
|
+
@if EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
|
119
|
+
@echo Found existing downloaded package, deleting.
|
120
|
+
@del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
|
121
|
+
@if ERRORLEVEL 1 (
|
122
|
+
echo Warning: Failed to delete pre-existing package with status code !ERRORLEVEL! > "&2"
|
123
|
+
)
|
124
|
+
) else (
|
125
|
+
echo No existing downloaded packages to delete.
|
126
|
+
)
|
127
|
+
|
128
|
+
@echo Attempting to download client package using cscript...
|
85
129
|
cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
|
86
130
|
|
87
131
|
@rem Work around issues found in Windows Server 2012 around job objects not respecting WSMAN memory quotas
|
88
132
|
@rem that cause the MSI download process to exceed the quota even when it is increased by administrators.
|
89
133
|
@rem Retry the download using a more memory-efficient mechanism that only works if PowerShell is available.
|
90
|
-
@
|
91
|
-
|
92
|
-
echo
|
93
|
-
if
|
94
|
-
|
95
|
-
|
96
|
-
if
|
97
|
-
|
134
|
+
@set DOWNLOAD_ERROR_STATUS=!ERRORLEVEL!
|
135
|
+
@if ERRORLEVEL 1 (
|
136
|
+
@echo Failed cscript download with status code !DOWNLOAD_ERROR_STATUS! > "&2"
|
137
|
+
@if !DOWNLOAD_ERROR_STATUS!==0 set DOWNLOAD_ERROR_STATUS=2
|
138
|
+
) else (
|
139
|
+
@rem Sometimes the error level is not set even when the download failed,
|
140
|
+
@rem so check for the file to be sure it is there -- if it's not, we'll retry
|
141
|
+
@if NOT EXIST "%LOCAL_DESTINATION_MSI_PATH%" (
|
142
|
+
echo Failed download: download completed, but downloaded file not found > "&2"
|
143
|
+
set DOWNLOAD_ERROR_STATUS=2
|
98
144
|
) else (
|
99
|
-
echo
|
100
|
-
echo Subsequent attempt to install the downloaded MSI is likely to fail
|
145
|
+
echo Download via cscript succeeded.
|
101
146
|
)
|
102
147
|
)
|
103
148
|
|
149
|
+
@if NOT %DOWNLOAD_ERROR_STATUS%==0 (
|
150
|
+
@echo Warning: Failed to download "%REMOTE_SOURCE_MSI_URL%" to "%LOCAL_DESTINATION_MSI_PATH%"
|
151
|
+
@echo Warning: Retrying download with PowerShell if available...
|
152
|
+
|
153
|
+
@if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
|
154
|
+
|
155
|
+
@set powershell_download=powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -command "& '<%= bootstrap_directory %>\wget.ps1' '%REMOTE_SOURCE_MSI_URL%%FALLBACK_QUERY_STRING%' '%LOCAL_DESTINATION_MSI_PATH%'"
|
156
|
+
@echo !powershell_download!
|
157
|
+
@call !powershell_download!
|
158
|
+
@if NOT ERRORLEVEL 1 (
|
159
|
+
echo Download via PowerShell succeeded.
|
160
|
+
) else (
|
161
|
+
echo Failed to download "%REMOTE_SOURCE_MSI_URL%" with status code !ERRORLEVEL!. > "&2"
|
162
|
+
echo Exiting without bootstrapping due to download failure. > "&2"
|
163
|
+
exit /b 1
|
164
|
+
)
|
165
|
+
)
|
166
|
+
|
167
|
+
@echo Starting bootstrap with downloaded client package
|
168
|
+
|
104
169
|
<%= install_chef %>
|
105
170
|
|
106
171
|
@endlocal
|
107
172
|
|
173
|
+
@echo off
|
174
|
+
echo Writing validation key...
|
175
|
+
|
108
176
|
> <%= bootstrap_directory %>\validation.pem (
|
109
177
|
<%= validation_key %>
|
110
178
|
)
|
111
179
|
|
180
|
+
echo Validation key written.
|
181
|
+
@echo on
|
182
|
+
|
112
183
|
<% if @config[:encrypted_data_bag_secret] -%>
|
113
184
|
> <%= bootstrap_directory %>\encrypted_data_bag_secret (
|
114
185
|
<%= encrypted_data_bag_secret %>
|
@@ -120,7 +191,7 @@ cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL
|
|
120
191
|
)
|
121
192
|
|
122
193
|
> <%= bootstrap_directory %>\first-boot.json (
|
123
|
-
<%=
|
194
|
+
<%= first_boot %>
|
124
195
|
)
|
125
196
|
|
126
197
|
<%= start_chef %>
|
@@ -18,6 +18,7 @@
|
|
18
18
|
|
19
19
|
require 'chef/knife'
|
20
20
|
require 'chef/encrypted_data_bag_item'
|
21
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
21
22
|
|
22
23
|
class Chef
|
23
24
|
class Knife
|
@@ -53,6 +54,11 @@ class Chef
|
|
53
54
|
:description => "The proxy server for the node being bootstrapped",
|
54
55
|
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
55
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
|
+
|
56
62
|
option :distro,
|
57
63
|
:short => "-d DISTRO",
|
58
64
|
:long => "--distro DISTRO",
|
@@ -71,6 +77,13 @@ class Chef
|
|
71
77
|
:proc => lambda { |o| o.split(",") },
|
72
78
|
:default => []
|
73
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
|
+
|
74
87
|
option :encrypted_data_bag_secret,
|
75
88
|
:short => "-s SECRET",
|
76
89
|
:long => "--secret ",
|
@@ -136,7 +149,7 @@ class Chef
|
|
136
149
|
# we have to run the remote commands in 2047 char chunks
|
137
150
|
create_bootstrap_bat_command do |command_chunk, chunk_num|
|
138
151
|
begin
|
139
|
-
run_command("cmd.exe /C echo \"Rendering
|
152
|
+
run_command("cmd.exe /C echo \"Rendering #{bootstrap_bat_file} chunk #{chunk_num}\" && #{command_chunk}")
|
140
153
|
rescue SystemExit => e
|
141
154
|
raise unless e.success?
|
142
155
|
end
|
@@ -167,7 +180,7 @@ class Chef
|
|
167
180
|
end
|
168
181
|
|
169
182
|
def bootstrap_bat_file
|
170
|
-
@bootstrap_bat_file ||= "%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat"
|
183
|
+
@bootstrap_bat_file ||= "\"%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat\""
|
171
184
|
end
|
172
185
|
|
173
186
|
def locate_config_value(key)
|
@@ -69,6 +69,7 @@ CONFIG
|
|
69
69
|
client_rb << "\n"
|
70
70
|
client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
71
71
|
client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
72
|
+
client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n} if knife_config[:bootstrap_no_proxy]
|
72
73
|
end
|
73
74
|
|
74
75
|
if @config[:encrypted_data_bag_secret]
|
@@ -83,10 +84,6 @@ CONFIG
|
|
83
84
|
start_chef << "chef-client -c c:/chef/client.rb -j c:/chef/first-boot.json -E #{bootstrap_environment}\n"
|
84
85
|
end
|
85
86
|
|
86
|
-
def run_list
|
87
|
-
escape_and_echo({ "run_list" => @run_list }.to_json)
|
88
|
-
end
|
89
|
-
|
90
87
|
def win_wget
|
91
88
|
win_wget = <<-WGET
|
92
89
|
url = WScript.Arguments.Named("url")
|
@@ -152,7 +149,7 @@ WGET_PS
|
|
152
149
|
end
|
153
150
|
|
154
151
|
def install_chef
|
155
|
-
install_chef = 'msiexec /
|
152
|
+
install_chef = 'msiexec /qn /i "%LOCAL_DESTINATION_MSI_PATH%"'
|
156
153
|
end
|
157
154
|
|
158
155
|
def bootstrap_directory
|
@@ -163,6 +160,11 @@ WGET_PS
|
|
163
160
|
local_download_path = "%TEMP%\\chef-client-latest.msi"
|
164
161
|
end
|
165
162
|
|
163
|
+
def first_boot
|
164
|
+
first_boot_attributes_and_run_list = (@config[:first_boot_attributes] || {}).merge(:run_list => @run_list)
|
165
|
+
escape_and_echo(first_boot_attributes_and_run_list.to_json)
|
166
|
+
end
|
167
|
+
|
166
168
|
# escape WIN BATCH special chars
|
167
169
|
# and prefixes each line with an
|
168
170
|
# echo
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chirag Jog (<chirag@clogeny.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 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/knife/winrm'
|
21
|
+
require 'chef/knife/bootstrap_windows_ssh'
|
22
|
+
require 'chef/knife/bootstrap_windows_winrm'
|
23
|
+
|
24
|
+
class Chef
|
25
|
+
class Knife
|
26
|
+
class WindowsHelper < Knife
|
27
|
+
|
28
|
+
banner "#{BootstrapWindowsWinrm.banner}\n" +
|
29
|
+
"#{BootstrapWindowsSsh.banner}\n" +
|
30
|
+
"#{Winrm.banner}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
data/lib/chef/knife/winrm.rb
CHANGED
@@ -75,6 +75,26 @@ class Chef
|
|
75
75
|
|
76
76
|
end
|
77
77
|
|
78
|
+
# TODO: Copied from Knife::Core:GenericPresenter. Should be extracted
|
79
|
+
def extract_nested_value(data, nested_value_spec)
|
80
|
+
nested_value_spec.split(".").each do |attr|
|
81
|
+
if data.nil?
|
82
|
+
nil # don't get no method error on nil
|
83
|
+
elsif data.respond_to?(attr.to_sym)
|
84
|
+
data = data.send(attr.to_sym)
|
85
|
+
elsif data.respond_to?(:[])
|
86
|
+
data = data[attr]
|
87
|
+
else
|
88
|
+
data = begin
|
89
|
+
data.send(attr.to_sym)
|
90
|
+
rescue NoMethodError
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
( !data.kind_of?(Array) && data.respond_to?(:to_hash) ) ? data.to_hash : data
|
96
|
+
end
|
97
|
+
|
78
98
|
def configure_session
|
79
99
|
list = case config[:manual]
|
80
100
|
when true
|
@@ -84,7 +104,7 @@ class Chef
|
|
84
104
|
q = Chef::Search::Query.new
|
85
105
|
@action_nodes = q.search(:node, @name_args[0])[0]
|
86
106
|
@action_nodes.each do |item|
|
87
|
-
i =
|
107
|
+
i = extract_nested_value(item, config[:attribute])
|
88
108
|
r.push(i) unless i.nil?
|
89
109
|
end
|
90
110
|
r
|
@@ -50,6 +50,9 @@ describe 'Knife::Windows::Core msi download functionality for knife Windows winr
|
|
50
50
|
# Location to which the download script will be modified to write
|
51
51
|
# the downloaded msi
|
52
52
|
@local_file_download_destination = "#{@temp_directory}/chef-client-latest.msi"
|
53
|
+
|
54
|
+
source_code_directory = File.dirname(__FILE__)
|
55
|
+
@template_file_path ="#{source_code_directory}/../../lib/chef/knife/bootstrap/windows-chef-client-msi.erb"
|
53
56
|
end
|
54
57
|
|
55
58
|
after(:all) do
|
@@ -64,7 +67,8 @@ describe 'Knife::Windows::Core msi download functionality for knife Windows winr
|
|
64
67
|
@mock_bootstrap_context = Chef::Knife::Core::WindowsBootstrapContext.new({ }, nil, { })
|
65
68
|
|
66
69
|
# Stub the bootstrap context and prevent config related sections
|
67
|
-
#
|
70
|
+
# from being populated, i.e. chef installation and first chef
|
71
|
+
# run sections
|
68
72
|
@mock_bootstrap_context.stub(:validation_key).and_return("echo.validation_key")
|
69
73
|
@mock_bootstrap_context.stub(:encrypted_data_bag_secret).and_return("echo.encrypted_data_bag_secret")
|
70
74
|
@mock_bootstrap_context.stub(:config_content).and_return("echo.config_content")
|
@@ -72,7 +76,7 @@ describe 'Knife::Windows::Core msi download functionality for knife Windows winr
|
|
72
76
|
@mock_bootstrap_context.stub(:run_list).and_return("echo.run_list")
|
73
77
|
@mock_bootstrap_context.stub(:install_chef).and_return("echo.echo install_chef_command")
|
74
78
|
|
75
|
-
# Change the
|
79
|
+
# Change the directories where bootstrap files will be created
|
76
80
|
@mock_bootstrap_context.stub(:bootstrap_directory).and_return(@temp_directory.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR))
|
77
81
|
@mock_bootstrap_context.stub(:local_download_path).and_return(@local_file_download_destination.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR))
|
78
82
|
|
@@ -87,14 +91,15 @@ describe 'Knife::Windows::Core msi download functionality for knife Windows winr
|
|
87
91
|
it "downloads the chef-client MSI during winrm bootstrap" do
|
88
92
|
clean_test_case
|
89
93
|
|
90
|
-
|
94
|
+
winrm_bootstrapper = Chef::Knife::BootstrapWindowsWinrm.new([ "127.0.0.1" ])
|
95
|
+
winrm_bootstrapper.config[:template_file] = @template_file_path
|
91
96
|
|
92
97
|
# Execute the commands locally that would normally be executed via WinRM
|
93
|
-
|
98
|
+
winrm_bootstrapper.stub(:run_command) do |command|
|
94
99
|
system(command)
|
95
100
|
end
|
96
101
|
|
97
|
-
|
102
|
+
winrm_bootstrapper.run
|
98
103
|
|
99
104
|
# Download should succeed
|
100
105
|
download_succeeded?.should == true
|
@@ -105,7 +110,7 @@ describe 'Knife::Windows::Core msi download functionality for knife Windows winr
|
|
105
110
|
File.exists?(@local_file_download_destination) && ! File.zero?(@local_file_download_destination)
|
106
111
|
end
|
107
112
|
|
108
|
-
# Remove file
|
113
|
+
# Remove file artifacts generated by individual test cases
|
109
114
|
def clean_test_case
|
110
115
|
if File.exists?(@local_file_download_destination)
|
111
116
|
File.delete(@local_file_download_destination)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chirag Jog (<chirag@clogeny.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Chirag Jog
|
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
|
+
TEMPLATE_FILE = File.expand_path(File.dirname(__FILE__)) + "/../../../lib/chef/knife/bootstrap/windows-chef-client-msi.erb"
|
20
|
+
|
21
|
+
require 'spec_helper'
|
22
|
+
|
23
|
+
describe "While Windows Bootstrapping" do
|
24
|
+
context "the default Windows bootstrapping template" do
|
25
|
+
bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
|
26
|
+
bootstrap.config[:template_file] = TEMPLATE_FILE
|
27
|
+
|
28
|
+
template = bootstrap.load_template
|
29
|
+
template_file_lines = template.split('\n')
|
30
|
+
it "should download Platform specific MSI" do
|
31
|
+
download_url=template_file_lines.find {|l| l.include?("url=")}
|
32
|
+
download_url.include?("%MACHINE_OS%") && download_url.include?("%MACHINE_ARCH%")
|
33
|
+
end
|
34
|
+
it "should download specific version of MSI if supplied" do
|
35
|
+
download_url_ext= template_file_lines.find {|l| l.include?("url +=")}
|
36
|
+
download_url_ext.include?("[:bootstrap_version]")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe Chef::Knife::BootstrapWindowsWinrm do
|
42
|
+
before(:all) do
|
43
|
+
@original_config = Chef::Config.hash_dup
|
44
|
+
@original_knife_config = Chef::Config[:knife].dup
|
45
|
+
end
|
46
|
+
|
47
|
+
after(:all) do
|
48
|
+
Chef::Config.configuration = @original_config
|
49
|
+
Chef::Config[:knife] = @original_knife_config
|
50
|
+
end
|
51
|
+
|
52
|
+
before(:each) do
|
53
|
+
Chef::Log.logger = Logger.new(StringIO.new)
|
54
|
+
@knife = Chef::Knife::BootstrapWindowsWinrm.new
|
55
|
+
# Merge default settings in.
|
56
|
+
@knife.merge_configs
|
57
|
+
@knife.config[:template_file] = TEMPLATE_FILE
|
58
|
+
@stdout = StringIO.new
|
59
|
+
@knife.ui.stub(:stdout).and_return(@stdout)
|
60
|
+
@stderr = StringIO.new
|
61
|
+
@knife.ui.stub(:stderr).and_return(@stderr)
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "specifying no_proxy with various entries" do
|
65
|
+
subject(:knife) { described_class.new }
|
66
|
+
let(:options){ ["--bootstrap-proxy", "", "--bootstrap-no-proxy", setting] }
|
67
|
+
let(:template_file) { TEMPLATE_FILE }
|
68
|
+
let(:rendered_template) do
|
69
|
+
knife.instance_variable_set("@template_file", template_file)
|
70
|
+
knife.parse_options(options)
|
71
|
+
# Avoid referencing a validation keyfile we won't find during #render_template
|
72
|
+
template_string = knife.read_template.gsub(/^.*[Vv]alidation_key.*$/, '')
|
73
|
+
knife.render_template(template_string)
|
74
|
+
end
|
75
|
+
|
76
|
+
context "via --bootstrap-no-proxy" do
|
77
|
+
let(:setting) { "api.opscode.com" }
|
78
|
+
|
79
|
+
it "renders the client.rb with a single FQDN no_proxy entry" do
|
80
|
+
rendered_template.should match(%r{.*no_proxy\s*\"api.opscode.com\".*})
|
81
|
+
end
|
82
|
+
end
|
83
|
+
context "via --bootstrap-no-proxy multiple" do
|
84
|
+
let(:setting) { "api.opscode.com,172.16.10.*" }
|
85
|
+
|
86
|
+
it "renders the client.rb with comma-separated FQDN and wildcard IP address no_proxy entries" do
|
87
|
+
rendered_template.should match(%r{.*no_proxy\s*"api.opscode.com,172.16.10.\*".*})
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -40,6 +40,7 @@ describe Chef::Knife::Winrm do
|
|
40
40
|
@node_bar = Chef::Node.new
|
41
41
|
@node_bar.automatic_attrs[:fqdn] = "bar.example.org"
|
42
42
|
@node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
|
43
|
+
@node_bar.automatic_attrs[:ec2][:public_hostname] = "somewhere.com"
|
43
44
|
end
|
44
45
|
|
45
46
|
describe "#configure_session" do
|
@@ -49,6 +50,7 @@ describe Chef::Knife::Winrm do
|
|
49
50
|
|
50
51
|
context "when there are some hosts found but they do not have an attribute to connect with" do
|
51
52
|
before do
|
53
|
+
@knife.config[:manual] = false
|
52
54
|
@query.stub!(:search).and_return([[@node_foo, @node_bar]])
|
53
55
|
@node_foo.automatic_attrs[:fqdn] = nil
|
54
56
|
@node_bar.automatic_attrs[:fqdn] = nil
|
@@ -61,5 +63,20 @@ describe Chef::Knife::Winrm do
|
|
61
63
|
@knife.configure_session
|
62
64
|
end
|
63
65
|
end
|
66
|
+
|
67
|
+
context "when there are nested attributes" do
|
68
|
+
before do
|
69
|
+
@knife.config[:manual] = false
|
70
|
+
@query.stub!(:search).and_return([[@node_foo, @node_bar]])
|
71
|
+
Chef::Search::Query.stub!(:new).and_return(@query)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should use nested attributes (KNIFE-276)" do
|
75
|
+
@knife.config[:attribute] = "ec2.public_hostname"
|
76
|
+
@knife.stub!(:session_from_list)
|
77
|
+
@knife.configure_session
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
64
81
|
end
|
65
82
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-windows
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.14.rc.0
|
5
|
+
prerelease: 7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Seth Chisamore
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-10-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: em-winrm
|
@@ -39,11 +39,14 @@ extra_rdoc_files:
|
|
39
39
|
files:
|
40
40
|
- .gitignore
|
41
41
|
- .rspec
|
42
|
+
- .travis.yml
|
42
43
|
- CHANGELOG
|
43
44
|
- Gemfile
|
44
45
|
- LICENSE
|
45
46
|
- README.rdoc
|
46
47
|
- Rakefile
|
48
|
+
- features/knife_help.feature
|
49
|
+
- features/support/env.rb
|
47
50
|
- knife-windows.gemspec
|
48
51
|
- lib/chef/knife/bootstrap/windows-chef-client-msi.erb
|
49
52
|
- lib/chef/knife/bootstrap/windows-shell.erb
|
@@ -51,11 +54,13 @@ files:
|
|
51
54
|
- lib/chef/knife/bootstrap_windows_ssh.rb
|
52
55
|
- lib/chef/knife/bootstrap_windows_winrm.rb
|
53
56
|
- lib/chef/knife/core/windows_bootstrap_context.rb
|
57
|
+
- lib/chef/knife/windows_helper.rb
|
54
58
|
- lib/chef/knife/winrm.rb
|
55
59
|
- lib/chef/knife/winrm_base.rb
|
56
60
|
- lib/knife-windows/version.rb
|
57
61
|
- spec/functional/bootstrap_download_spec.rb
|
58
62
|
- spec/spec_helper.rb
|
63
|
+
- spec/unit/knife/bootstrap_template_spec.rb
|
59
64
|
- spec/unit/knife/winrm_spec.rb
|
60
65
|
homepage: https://github.com/opscode/knife-windows
|
61
66
|
licenses: []
|
@@ -72,14 +77,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
78
|
none: false
|
74
79
|
requirements:
|
75
|
-
- - ! '
|
80
|
+
- - ! '>'
|
76
81
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
82
|
+
version: 1.3.1
|
78
83
|
requirements: []
|
79
84
|
rubyforge_project:
|
80
|
-
rubygems_version: 1.8.
|
85
|
+
rubygems_version: 1.8.23
|
81
86
|
signing_key:
|
82
87
|
specification_version: 3
|
83
88
|
summary: Plugin that adds functionality to Chef's Knife CLI for configuring/interacting
|
84
89
|
with nodes running Microsoft Windows
|
85
|
-
test_files:
|
90
|
+
test_files:
|
91
|
+
- features/knife_help.feature
|
92
|
+
- features/support/env.rb
|
93
|
+
- spec/functional/bootstrap_download_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
- spec/unit/knife/bootstrap_template_spec.rb
|
96
|
+
- spec/unit/knife/winrm_spec.rb
|