knife-windows 0.5.15 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +4 -4
- data/.rspec +3 -3
- data/.travis.yml +6 -6
- data/CHANGELOG.md +33 -0
- data/DOC_CHANGES.md +42 -0
- data/Gemfile +11 -11
- data/LICENSE +201 -201
- data/README.rdoc +134 -140
- data/RELEASE_NOTES.md +40 -0
- data/Rakefile +16 -16
- data/features/knife_help.feature +20 -20
- data/features/support/env.rb +5 -5
- data/knife-windows.gemspec +24 -24
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +222 -222
- data/lib/chef/knife/bootstrap_windows_base.rb +206 -196
- data/lib/chef/knife/bootstrap_windows_ssh.rb +93 -93
- data/lib/chef/knife/bootstrap_windows_winrm.rb +97 -62
- data/lib/chef/knife/core/windows_bootstrap_context.rb +177 -177
- data/lib/chef/knife/windows_helper.rb +34 -34
- data/lib/chef/knife/winrm.rb +296 -286
- data/lib/chef/knife/winrm_base.rb +99 -99
- data/lib/knife-windows/version.rb +6 -6
- data/spec/functional/bootstrap_download_spec.rb +122 -120
- data/spec/spec_helper.rb +63 -63
- data/spec/unit/knife/bootstrap_template_spec.rb +91 -91
- data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +85 -0
- data/spec/unit/knife/winrm_spec.rb +152 -82
- metadata +17 -12
- data/CHANGELOG +0 -14
- data/lib/chef/knife/bootstrap/windows-shell.erb +0 -68
data/spec/spec_helper.rb
CHANGED
@@ -1,63 +1,63 @@
|
|
1
|
-
|
2
|
-
# Author:: Adam Edwards (<adamed@opscode.com>)
|
3
|
-
# Copyright:: Copyright (c) 2012 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
|
15
|
-
# implied.
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
#
|
19
|
-
|
20
|
-
def windows?
|
21
|
-
!!(RUBY_PLATFORM =~ /mswin|mingw|windows/)
|
22
|
-
end
|
23
|
-
|
24
|
-
require_relative '../lib/chef/knife/core/windows_bootstrap_context'
|
25
|
-
require_relative '../lib/chef/knife/bootstrap_windows_winrm'
|
26
|
-
|
27
|
-
if windows?
|
28
|
-
require 'ruby-wmi'
|
29
|
-
end
|
30
|
-
|
31
|
-
def windows2012?
|
32
|
-
is_win2k12 = false
|
33
|
-
|
34
|
-
if windows?
|
35
|
-
this_operating_system = WMI::Win32_OperatingSystem.find(:first)
|
36
|
-
os_version = this_operating_system.send('Version')
|
37
|
-
|
38
|
-
# The operating system version is a string in the following form
|
39
|
-
# that can be split into components based on the '.' delimiter:
|
40
|
-
# MajorVersionNumber.MinorVersionNumber.BuildNumber
|
41
|
-
os_version_components = os_version.split('.')
|
42
|
-
|
43
|
-
if os_version_components.length < 2
|
44
|
-
raise 'WMI returned a Windows version from Win32_OperatingSystem.Version ' +
|
45
|
-
'with an unexpected format. The Windows version could not be determined.'
|
46
|
-
end
|
47
|
-
|
48
|
-
# Windows 6.2 is Windows Server 2012, so test the major and
|
49
|
-
# minor version components
|
50
|
-
is_win2k12 = os_version_components[0] == '6' && os_version_components[1] == '2'
|
51
|
-
end
|
52
|
-
|
53
|
-
is_win2k12
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
RSpec.configure do |config|
|
58
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
59
|
-
|
60
|
-
config.filter_run_excluding :windows_only => true unless windows?
|
61
|
-
config.filter_run_excluding :windows_2012_only => true unless windows2012?
|
62
|
-
end
|
63
|
-
|
1
|
+
|
2
|
+
# Author:: Adam Edwards (<adamed@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 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
|
15
|
+
# implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
def windows?
|
21
|
+
!!(RUBY_PLATFORM =~ /mswin|mingw|windows/)
|
22
|
+
end
|
23
|
+
|
24
|
+
require_relative '../lib/chef/knife/core/windows_bootstrap_context'
|
25
|
+
require_relative '../lib/chef/knife/bootstrap_windows_winrm'
|
26
|
+
|
27
|
+
if windows?
|
28
|
+
require 'ruby-wmi'
|
29
|
+
end
|
30
|
+
|
31
|
+
def windows2012?
|
32
|
+
is_win2k12 = false
|
33
|
+
|
34
|
+
if windows?
|
35
|
+
this_operating_system = WMI::Win32_OperatingSystem.find(:first)
|
36
|
+
os_version = this_operating_system.send('Version')
|
37
|
+
|
38
|
+
# The operating system version is a string in the following form
|
39
|
+
# that can be split into components based on the '.' delimiter:
|
40
|
+
# MajorVersionNumber.MinorVersionNumber.BuildNumber
|
41
|
+
os_version_components = os_version.split('.')
|
42
|
+
|
43
|
+
if os_version_components.length < 2
|
44
|
+
raise 'WMI returned a Windows version from Win32_OperatingSystem.Version ' +
|
45
|
+
'with an unexpected format. The Windows version could not be determined.'
|
46
|
+
end
|
47
|
+
|
48
|
+
# Windows 6.2 is Windows Server 2012, so test the major and
|
49
|
+
# minor version components
|
50
|
+
is_win2k12 = os_version_components[0] == '6' && os_version_components[1] == '2'
|
51
|
+
end
|
52
|
+
|
53
|
+
is_win2k12
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
RSpec.configure do |config|
|
58
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
59
|
+
|
60
|
+
config.filter_run_excluding :windows_only => true unless windows?
|
61
|
+
config.filter_run_excluding :windows_2012_only => true unless windows2012?
|
62
|
+
end
|
63
|
+
|
@@ -1,91 +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
|
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
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Edwards(<adamed@getchef.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Chef Software, 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 'spec_helper'
|
20
|
+
|
21
|
+
|
22
|
+
describe Chef::Knife::BootstrapWindowsWinrm do
|
23
|
+
before(:all) do
|
24
|
+
Chef::Config.reset
|
25
|
+
end
|
26
|
+
|
27
|
+
before do
|
28
|
+
# Kernel.stub(:sleep).and_return 10
|
29
|
+
bootstrap.stub(:sleep).and_return 10
|
30
|
+
end
|
31
|
+
|
32
|
+
after do
|
33
|
+
# Kernel.unstub(:sleep)
|
34
|
+
bootstrap.stub(:sleep).and_return 10
|
35
|
+
end
|
36
|
+
|
37
|
+
let (:bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new }
|
38
|
+
let(:initial_fail_count) { 4 }
|
39
|
+
it 'should retry if a 401 is received from WinRM' do
|
40
|
+
call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError, '401'}}
|
41
|
+
call_result_sequence.push(0)
|
42
|
+
bootstrap.stub(:run_command).and_return(*call_result_sequence)
|
43
|
+
|
44
|
+
bootstrap.should_receive(:run_command).exactly(call_result_sequence.length).times
|
45
|
+
bootstrap.send(:wait_for_remote_response, 2)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should retry if something other than a 401 is received from WinRM' do
|
49
|
+
call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError, '500'}}
|
50
|
+
call_result_sequence.push(0)
|
51
|
+
bootstrap.stub(:run_command).and_return(*call_result_sequence)
|
52
|
+
|
53
|
+
bootstrap.should_receive(:run_command).exactly(call_result_sequence.length).times
|
54
|
+
bootstrap.send(:wait_for_remote_response, 2)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should have a wait timeout of 25 minutes by default' do
|
58
|
+
bootstrap.stub(:run_command).and_raise WinRM::WinRMHTTPTransportError
|
59
|
+
bootstrap.stub(:create_bootstrap_bat_command).and_raise SystemExit
|
60
|
+
bootstrap.should_receive(:wait_for_remote_response).with(25)
|
61
|
+
bootstrap.stub(:validate_name_args!).and_return(nil)
|
62
|
+
bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
|
63
|
+
expect { bootstrap.bootstrap }.to raise_error SystemExit
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should keep retrying at 10s intervals if the timeout in minutes has not elapsed' do
|
67
|
+
call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError, '500'}}
|
68
|
+
call_result_sequence.push(0)
|
69
|
+
bootstrap.stub(:run_command).and_return(*call_result_sequence)
|
70
|
+
|
71
|
+
bootstrap.should_receive(:run_command).exactly(call_result_sequence.length).times
|
72
|
+
bootstrap.send(:wait_for_remote_response, 2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should stop retrying if more than 25 minutes has elapsed' do
|
76
|
+
times = [ Time.new(2014, 4, 1, 22, 25), Time.new(2014, 4, 1, 22, 51), Time.new(2014, 4, 1, 22, 52) ]
|
77
|
+
Time.stub(:now).and_return(*times)
|
78
|
+
run_command_result = lambda {raise WinRM::WinRMHTTPTransportError, '401'}
|
79
|
+
bootstrap.stub(:validate_name_args!).and_return(nil)
|
80
|
+
bootstrap.stub(:run_command).and_return(run_command_result)
|
81
|
+
bootstrap.should_receive(:run_command).exactly(1).times
|
82
|
+
bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
|
83
|
+
expect { bootstrap.bootstrap }.to raise_error RuntimeError
|
84
|
+
end
|
85
|
+
end
|
@@ -1,82 +1,152 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Bryan McLellan <btm@opscode.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 'spec_helper'
|
20
|
-
|
21
|
-
Chef::Knife::Winrm.load_deps
|
22
|
-
|
23
|
-
describe Chef::Knife::Winrm do
|
24
|
-
before(:all) do
|
25
|
-
@original_config = Chef::Config.hash_dup
|
26
|
-
@original_knife_config = Chef::Config[:knife].dup
|
27
|
-
end
|
28
|
-
|
29
|
-
after(:all) do
|
30
|
-
Chef::Config.configuration = @original_config
|
31
|
-
Chef::Config[:knife] = @original_knife_config
|
32
|
-
end
|
33
|
-
|
34
|
-
before do
|
35
|
-
@knife = Chef::Knife::Winrm.new
|
36
|
-
@knife.config[:attribute] = "fqdn"
|
37
|
-
@node_foo = Chef::Node.new
|
38
|
-
@node_foo.automatic_attrs[:fqdn] = "foo.example.org"
|
39
|
-
@node_foo.automatic_attrs[:ipaddress] = "10.0.0.1"
|
40
|
-
@node_bar = Chef::Node.new
|
41
|
-
@node_bar.automatic_attrs[:fqdn] = "bar.example.org"
|
42
|
-
@node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
|
43
|
-
@node_bar.automatic_attrs[:ec2][:public_hostname] = "somewhere.com"
|
44
|
-
end
|
45
|
-
|
46
|
-
describe "#configure_session" do
|
47
|
-
before do
|
48
|
-
@query = double("Chef::Search::Query")
|
49
|
-
end
|
50
|
-
|
51
|
-
context "when there are some hosts found but they do not have an attribute to connect with" do
|
52
|
-
before do
|
53
|
-
@knife.config[:manual] = false
|
54
|
-
@query.stub(:search).and_return([[@node_foo, @node_bar]])
|
55
|
-
@node_foo.automatic_attrs[:fqdn] = nil
|
56
|
-
@node_bar.automatic_attrs[:fqdn] = nil
|
57
|
-
Chef::Search::Query.stub(:new).and_return(@query)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should raise a specific error (KNIFE-222)" do
|
61
|
-
@knife.ui.should_receive(:fatal).with(/does not have the required attribute/)
|
62
|
-
@knife.should_receive(:exit).with(10)
|
63
|
-
@knife.configure_session
|
64
|
-
end
|
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
|
81
|
-
|
82
|
-
|
1
|
+
#
|
2
|
+
# Author:: Bryan McLellan <btm@opscode.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 'spec_helper'
|
20
|
+
|
21
|
+
Chef::Knife::Winrm.load_deps
|
22
|
+
|
23
|
+
describe Chef::Knife::Winrm do
|
24
|
+
before(:all) do
|
25
|
+
@original_config = Chef::Config.hash_dup
|
26
|
+
@original_knife_config = Chef::Config[:knife].nil? ? nil : Chef::Config[:knife].dup
|
27
|
+
end
|
28
|
+
|
29
|
+
after(:all) do
|
30
|
+
Chef::Config.configuration = @original_config
|
31
|
+
Chef::Config[:knife] = @original_knife_config if @original_knife_config
|
32
|
+
end
|
33
|
+
|
34
|
+
before do
|
35
|
+
@knife = Chef::Knife::Winrm.new
|
36
|
+
@knife.config[:attribute] = "fqdn"
|
37
|
+
@node_foo = Chef::Node.new
|
38
|
+
@node_foo.automatic_attrs[:fqdn] = "foo.example.org"
|
39
|
+
@node_foo.automatic_attrs[:ipaddress] = "10.0.0.1"
|
40
|
+
@node_bar = Chef::Node.new
|
41
|
+
@node_bar.automatic_attrs[:fqdn] = "bar.example.org"
|
42
|
+
@node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
|
43
|
+
@node_bar.automatic_attrs[:ec2][:public_hostname] = "somewhere.com"
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#configure_session" do
|
47
|
+
before do
|
48
|
+
@query = double("Chef::Search::Query")
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when there are some hosts found but they do not have an attribute to connect with" do
|
52
|
+
before do
|
53
|
+
@knife.config[:manual] = false
|
54
|
+
@query.stub(:search).and_return([[@node_foo, @node_bar]])
|
55
|
+
@node_foo.automatic_attrs[:fqdn] = nil
|
56
|
+
@node_bar.automatic_attrs[:fqdn] = nil
|
57
|
+
Chef::Search::Query.stub(:new).and_return(@query)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should raise a specific error (KNIFE-222)" do
|
61
|
+
@knife.ui.should_receive(:fatal).with(/does not have the required attribute/)
|
62
|
+
@knife.should_receive(:exit).with(10)
|
63
|
+
@knife.configure_session
|
64
|
+
end
|
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
|
81
|
+
|
82
|
+
describe Chef::Knife::Winrm do
|
83
|
+
context "when executing the run command which sets the process exit code" do
|
84
|
+
before(:each) do
|
85
|
+
Chef::Config[:knife] = {:winrm_transport => :http}
|
86
|
+
@winrm = Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', 'echo helloworld'])
|
87
|
+
end
|
88
|
+
|
89
|
+
after(:each) do
|
90
|
+
Chef::Config.configuration = @original_config
|
91
|
+
Chef::Config[:knife] = @original_knife_config if @original_knife_config
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should return with 0 if the command succeeds" do
|
95
|
+
@winrm.stub(:winrm_command).and_return(0)
|
96
|
+
exit_code = @winrm.run
|
97
|
+
exit_code.should == 0
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should exit the process with 0 if the command fails and returns config is not set" do
|
101
|
+
@winrm.stub(:winrm_command).and_return(1)
|
102
|
+
exit_code = @winrm.run
|
103
|
+
exit_code.should == 0
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should exit the process with non-zero status if the command fails and returns config is set to 0" do
|
107
|
+
command_status = 1
|
108
|
+
@winrm.config[:returns] = [0,53]
|
109
|
+
Chef::Config[:knife][:returns] = [0,53]
|
110
|
+
@winrm.stub(:winrm_command).and_return(command_status)
|
111
|
+
EventMachine::WinRM::Session.any_instance.stub(:exit_codes).and_return({"thishost" => command_status})
|
112
|
+
expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| e.status.should == command_status }
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should exit the process with a zero status if the command returns an expected non-zero status" do
|
116
|
+
command_status = 53
|
117
|
+
Chef::Config[:knife][:returns] = [0,53]
|
118
|
+
@winrm.stub(:winrm_command).and_return(command_status)
|
119
|
+
EventMachine::WinRM::Session.any_instance.stub(:exit_codes).and_return({"thishost" => command_status})
|
120
|
+
exit_code = @winrm.run
|
121
|
+
exit_code.should == 0
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should exit the process with a zero status if the command returns an expected non-zero status" do
|
125
|
+
command_status = 53
|
126
|
+
Chef::Config[:knife][:returns] = [0,53]
|
127
|
+
@winrm.stub(:winrm_command).and_return(command_status)
|
128
|
+
EventMachine::WinRM::Session.any_instance.stub(:exit_codes).and_return({"thishost" => command_status})
|
129
|
+
exit_code = @winrm.run
|
130
|
+
exit_code.should == 0
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should exit the process with 100 if command execution raises an exception other than 401" do
|
134
|
+
@winrm.stub(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError, '500')
|
135
|
+
expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| e.status.should == 100 }
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should exit the process with 100 if command execution raises a 401" do
|
139
|
+
@winrm.stub(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError, '401')
|
140
|
+
expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| e.status.should == 100 }
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should exit the process with 0 if command execution raises a 401 and suppress_auth_failure is set to true" do
|
144
|
+
@winrm.config[:suppress_auth_failure] = true
|
145
|
+
@winrm.stub(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError, '401')
|
146
|
+
exit_code = @winrm.run_with_pretty_exceptions
|
147
|
+
exit_code.should == 401
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|