knife-windows 0.5.12 → 0.5.14.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|