knife-windows 0.8.6.rc.0 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,106 +1,106 @@
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
- allow(bootstrap).to receive(:sleep).and_return(10)
30
- end
31
-
32
- after do
33
- # Kernel.unstub(:sleep)
34
- allow(bootstrap).to receive(:sleep).and_return(10)
35
- end
36
-
37
- let (:bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new(['winrm', '-d', 'windows-chef-client-msi', '-x', 'Administrator', 'localhost']) }
38
-
39
- let(:initial_fail_count) { 4 }
40
- it 'should retry if a 401 is received from WinRM' do
41
- call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('401', '401')}}
42
- call_result_sequence.push(0)
43
- allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
44
-
45
- expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
46
- bootstrap.send(:wait_for_remote_response, 2)
47
- end
48
-
49
- it 'should retry if something other than a 401 is received from WinRM' do
50
- call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('500', '500')}}
51
- call_result_sequence.push(0)
52
- allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
53
-
54
- expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
55
- bootstrap.send(:wait_for_remote_response, 2)
56
- end
57
-
58
- it 'should have a wait timeout of 2 minutes by default' do
59
- allow(bootstrap).to receive(:run_command).and_raise(WinRM::WinRMHTTPTransportError.new('',''))
60
- allow(bootstrap).to receive(:create_bootstrap_bat_command).and_raise(SystemExit)
61
- expect(bootstrap).to receive(:wait_for_remote_response).with(2)
62
- allow(bootstrap).to receive(:validate_name_args!).and_return(nil)
63
- bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
64
- expect { bootstrap.bootstrap }.to raise_error(SystemExit)
65
- end
66
-
67
- it 'should keep retrying at 10s intervals if the timeout in minutes has not elapsed' do
68
- call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('500', '500')}}
69
- call_result_sequence.push(0)
70
- allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
71
-
72
- expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
73
- bootstrap.send(:wait_for_remote_response, 2)
74
- end
75
-
76
- it "should exit bootstrap with non-zero status if the bootstrap fails" do
77
- command_status = 1
78
-
79
- #Stub out calls to create the session and just get the exit codes back
80
- winrm_mock = Chef::Knife::Winrm.new
81
- allow(Chef::Knife::Winrm).to receive(:new).and_return(winrm_mock)
82
- allow(winrm_mock).to receive(:configure_session)
83
- allow(winrm_mock).to receive(:winrm_command)
84
- session_mock = EventMachine::WinRM::Session.new
85
- allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
86
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
87
-
88
- #Skip over templating stuff and checking with the remote end
89
- allow(bootstrap).to receive(:create_bootstrap_bat_command)
90
- allow(bootstrap).to receive(:wait_for_remote_response)
91
-
92
- expect { bootstrap.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
93
- end
94
-
95
-
96
- it 'should stop retrying if more than 2 minutes has elapsed' do
97
- times = [ Time.new(2014, 4, 1, 22, 25), Time.new(2014, 4, 1, 22, 51), Time.new(2014, 4, 1, 22, 28) ]
98
- allow(Time).to receive(:now).and_return(*times)
99
- run_command_result = lambda {raise WinRM::WinRMHTTPTransportError.new('401', '401')}
100
- allow(bootstrap).to receive(:validate_name_args!).and_return(nil)
101
- allow(bootstrap).to receive(:run_command).and_return(run_command_result)
102
- expect(bootstrap).to receive(:run_command).exactly(1).times
103
- bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
104
- expect { bootstrap.bootstrap }.to raise_error RuntimeError
105
- end
106
- end
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
+ allow(bootstrap).to receive(:sleep).and_return(10)
30
+ end
31
+
32
+ after do
33
+ # Kernel.unstub(:sleep)
34
+ allow(bootstrap).to receive(:sleep).and_return(10)
35
+ end
36
+
37
+ let (:bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new(['winrm', '-d', 'windows-chef-client-msi', '-x', 'Administrator', 'localhost']) }
38
+
39
+ let(:initial_fail_count) { 4 }
40
+ it 'should retry if a 401 is received from WinRM' do
41
+ call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('401', '401')}}
42
+ call_result_sequence.push(0)
43
+ allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
44
+
45
+ expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
46
+ bootstrap.send(:wait_for_remote_response, 2)
47
+ end
48
+
49
+ it 'should retry if something other than a 401 is received from WinRM' do
50
+ call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('500', '500')}}
51
+ call_result_sequence.push(0)
52
+ allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
53
+
54
+ expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
55
+ bootstrap.send(:wait_for_remote_response, 2)
56
+ end
57
+
58
+ it 'should have a wait timeout of 2 minutes by default' do
59
+ allow(bootstrap).to receive(:run_command).and_raise(WinRM::WinRMHTTPTransportError.new('',''))
60
+ allow(bootstrap).to receive(:create_bootstrap_bat_command).and_raise(SystemExit)
61
+ expect(bootstrap).to receive(:wait_for_remote_response).with(2)
62
+ allow(bootstrap).to receive(:validate_name_args!).and_return(nil)
63
+ bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
64
+ expect { bootstrap.bootstrap }.to raise_error(SystemExit)
65
+ end
66
+
67
+ it 'should keep retrying at 10s intervals if the timeout in minutes has not elapsed' do
68
+ call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('500', '500')}}
69
+ call_result_sequence.push(0)
70
+ allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
71
+
72
+ expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
73
+ bootstrap.send(:wait_for_remote_response, 2)
74
+ end
75
+
76
+ it "should exit bootstrap with non-zero status if the bootstrap fails" do
77
+ command_status = 1
78
+
79
+ #Stub out calls to create the session and just get the exit codes back
80
+ winrm_mock = Chef::Knife::Winrm.new
81
+ allow(Chef::Knife::Winrm).to receive(:new).and_return(winrm_mock)
82
+ allow(winrm_mock).to receive(:configure_session)
83
+ allow(winrm_mock).to receive(:winrm_command)
84
+ session_mock = EventMachine::WinRM::Session.new
85
+ allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
86
+ allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
87
+
88
+ #Skip over templating stuff and checking with the remote end
89
+ allow(bootstrap).to receive(:create_bootstrap_bat_command)
90
+ allow(bootstrap).to receive(:wait_for_remote_response)
91
+
92
+ expect { bootstrap.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
93
+ end
94
+
95
+
96
+ it 'should stop retrying if more than 2 minutes has elapsed' do
97
+ times = [ Time.new(2014, 4, 1, 22, 25), Time.new(2014, 4, 1, 22, 51), Time.new(2014, 4, 1, 22, 28) ]
98
+ allow(Time).to receive(:now).and_return(*times)
99
+ run_command_result = lambda {raise WinRM::WinRMHTTPTransportError.new('401', '401')}
100
+ allow(bootstrap).to receive(:validate_name_args!).and_return(nil)
101
+ allow(bootstrap).to receive(:run_command).and_return(run_command_result)
102
+ expect(bootstrap).to receive(:run_command).exactly(1).times
103
+ bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
104
+ expect { bootstrap.bootstrap }.to raise_error RuntimeError
105
+ end
106
+ end
@@ -1,54 +1,54 @@
1
- #
2
- # Author:: Bryan McLellan <btm@loftninjas.org>
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
- describe Chef::Knife::Core::WindowsBootstrapContext do
22
- let(:mock_bootstrap_context) { Chef::Knife::Core::WindowsBootstrapContext.new({ }, nil, { :knife => {} }) }
23
-
24
- before do
25
- allow(Chef::Knife::Core::WindowsBootstrapContext).to receive(:new).and_return(mock_bootstrap_context)
26
- end
27
-
28
- describe "latest_current_windows_chef_version_query" do
29
- it "returns the major version of the current version of Chef" do
30
- stub_const("Chef::VERSION", '11.1.2')
31
- expect(mock_bootstrap_context.latest_current_windows_chef_version_query).to eq("&v=11")
32
- end
33
-
34
- it "does not add prerelease if the version of Chef installed is a prerelease" do
35
- stub_const("Chef::VERSION", '42.0.1.alpha.1')
36
- expect(mock_bootstrap_context.latest_current_windows_chef_version_query).not_to match(/&prerelease=true/)
37
- end
38
-
39
- it "does add prerelease if the version specified to be installed is a prerelease" do
40
- allow(mock_bootstrap_context).to receive(:knife_config).and_return(Mash.new(:bootstrap_version => "12.0.0.alpha.1"))
41
- expect(mock_bootstrap_context.latest_current_windows_chef_version_query).to eq("&v=12.0.0.alpha.1&prerelease=true")
42
- end
43
-
44
- context "when the prerelease config option is set" do
45
- before do
46
- mock_bootstrap_context.instance_variable_set(:@config, Mash.new(:prerelease => true))
47
- end
48
-
49
- it "sets prerelease to true in the returned string" do
50
- expect(mock_bootstrap_context.latest_current_windows_chef_version_query).to eq("&prerelease=true")
51
- end
52
- end
53
- end
54
- end
1
+ #
2
+ # Author:: Bryan McLellan <btm@loftninjas.org>
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
+ describe Chef::Knife::Core::WindowsBootstrapContext do
22
+ let(:mock_bootstrap_context) { Chef::Knife::Core::WindowsBootstrapContext.new({ }, nil, { :knife => {} }) }
23
+
24
+ before do
25
+ allow(Chef::Knife::Core::WindowsBootstrapContext).to receive(:new).and_return(mock_bootstrap_context)
26
+ end
27
+
28
+ describe "latest_current_windows_chef_version_query" do
29
+ it "returns the major version of the current version of Chef" do
30
+ stub_const("Chef::VERSION", '11.1.2')
31
+ expect(mock_bootstrap_context.latest_current_windows_chef_version_query).to eq("&v=11")
32
+ end
33
+
34
+ it "does not add prerelease if the version of Chef installed is a prerelease" do
35
+ stub_const("Chef::VERSION", '42.0.1.alpha.1')
36
+ expect(mock_bootstrap_context.latest_current_windows_chef_version_query).not_to match(/&prerelease=true/)
37
+ end
38
+
39
+ it "does add prerelease if the version specified to be installed is a prerelease" do
40
+ allow(mock_bootstrap_context).to receive(:knife_config).and_return(Mash.new(:bootstrap_version => "12.0.0.alpha.1"))
41
+ expect(mock_bootstrap_context.latest_current_windows_chef_version_query).to eq("&v=12.0.0.alpha.1&prerelease=true")
42
+ end
43
+
44
+ context "when the prerelease config option is set" do
45
+ before do
46
+ mock_bootstrap_context.instance_variable_set(:@config, Mash.new(:prerelease => true))
47
+ end
48
+
49
+ it "sets prerelease to true in the returned string" do
50
+ expect(mock_bootstrap_context.latest_current_windows_chef_version_query).to eq("&prerelease=true")
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,219 +1,219 @@
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
- allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
55
- @node_foo.automatic_attrs[:fqdn] = nil
56
- @node_bar.automatic_attrs[:fqdn] = nil
57
- allow(Chef::Search::Query).to receive(:new).and_return(@query)
58
- end
59
-
60
- it "should raise a specific error (KNIFE-222)" do
61
- expect(@knife.ui).to receive(:fatal).with(/does not have the required attribute/)
62
- expect(@knife).to 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
- allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
71
- allow(Chef::Search::Query).to receive(:new).and_return(@query)
72
- end
73
-
74
- it "should use nested attributes (KNIFE-276)" do
75
- @knife.config[:attribute] = "ec2.public_hostname"
76
- allow(@knife).to receive(: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
- allow(@winrm).to receive(:winrm_command).and_return(0)
96
- exit_code = @winrm.run
97
- expect(exit_code).to be_zero
98
- end
99
-
100
- it "should exit the process with exact exit status if the command fails and returns config is set to 0" do
101
- command_status = 510
102
- @winrm.config[:returns] = "0"
103
- Chef::Config[:knife][:returns] = [0]
104
- allow(@winrm).to receive(:winrm_command).and_return(command_status)
105
- session_mock = EventMachine::WinRM::Session.new
106
- allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
107
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
108
- begin
109
- @winrm.run
110
- expect(0).to eq(510)
111
- rescue Exception => e
112
- expect(e.status).to eq(command_status)
113
- end
114
- end
115
-
116
- it "should exit the process with non-zero status if the command fails and returns config is set to 0" do
117
- command_status = 1
118
- @winrm.config[:returns] = "0,53"
119
- Chef::Config[:knife][:returns] = [0,53]
120
- allow(@winrm).to receive(:winrm_command).and_return(command_status)
121
- session_mock = EventMachine::WinRM::Session.new
122
- allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
123
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
124
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
125
- end
126
-
127
- it "should exit the process with a zero status if the command returns an expected non-zero status" do
128
- command_status = 53
129
- Chef::Config[:knife][:returns] = [0,53]
130
- allow(@winrm).to receive(:winrm_command).and_return(command_status)
131
- session_mock = EventMachine::WinRM::Session.new
132
- allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
133
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
134
- exit_code = @winrm.run
135
- expect(exit_code).to be_zero
136
- end
137
-
138
- it "should exit the process with a zero status if the command returns an expected non-zero status" do
139
- command_status = 53
140
- Chef::Config[:knife][:returns] = [0,53]
141
- allow(@winrm).to receive(:winrm_command).and_return(command_status)
142
- session_mock = EventMachine::WinRM::Session.new
143
- allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
144
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
145
- exit_code = @winrm.run
146
- expect(exit_code).to be_zero
147
- end
148
-
149
- it "should exit the process with 100 if command execution raises an exception other than 401" do
150
- allow(@winrm).to receive(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('500', '500'))
151
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
152
- end
153
-
154
- it "should exit the process with 100 if command execution raises a 401" do
155
- allow(@winrm).to receive(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('401', '401'))
156
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
157
- end
158
-
159
- it "should exit the process with 0 if command execution raises a 401 and suppress_auth_failure is set to true" do
160
- @winrm.config[:suppress_auth_failure] = true
161
- allow(@winrm).to receive(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('401', '401'))
162
- exit_code = @winrm.run_with_pretty_exceptions
163
- expect(exit_code).to eq(401)
164
- end
165
-
166
- context "validate sspinegotiate transport option" do
167
- before do
168
- Chef::Config[:knife] = {:winrm_transport => :plaintext}
169
- allow(@winrm).to receive(:winrm_command).and_return(0)
170
- end
171
-
172
- it "should have winrm opts transport set to sspinegotiate for windows" do
173
- @winrm.config[:winrm_user] = "domain\\testuser"
174
- allow(Chef::Platform).to receive(:windows?).and_return(true)
175
- allow(@winrm).to receive(:require).with('winrm-s').and_return(true)
176
- expect(@winrm.session).to receive(:use).with("localhost", {:user=>"domain\\testuser", :password=>"testpassword", :port=>nil, :operation_timeout=>1800, :basic_auth_only=>false, :transport=>:sspinegotiate, :disable_sspi=>false})
177
- exit_code = @winrm.run
178
- end
179
-
180
- it "should use the winrm monkey patch for windows" do
181
- @winrm.config[:winrm_user] = "domain\\testuser"
182
- allow(Chef::Platform).to receive(:windows?).and_return(true)
183
- expect(@winrm).to receive(:require).with('winrm-s')
184
-
185
- exit_code = @winrm.run
186
- end
187
-
188
- context "when domain name not given" do
189
- it "should skip winrm monkey patch for windows" do
190
- @winrm.config[:winrm_user] = "testuser"
191
- allow(Chef::Platform).to receive(:windows?).and_return(true)
192
- expect(@winrm).to_not receive(:require).with('winrm-s')
193
-
194
- exit_code = @winrm.run
195
- end
196
- end
197
-
198
- context "when local domain name given" do
199
- it "should use the winrm monkey patch for windows" do
200
- @winrm.config[:winrm_user] = ".\\testuser"
201
- allow(Chef::Platform).to receive(:windows?).and_return(true)
202
- expect(@winrm).to receive(:require).with('winrm-s')
203
-
204
- exit_code = @winrm.run
205
- end
206
- end
207
-
208
- it "should not have winrm opts transport set to sspinegotiate for unix" do
209
- allow(Chef::Platform).to receive(:windows?).and_return(false)
210
-
211
- expect(@winrm.session).to receive(:use).with("localhost", {:user=>"testuser", :password=>"testpassword", :port=>nil, :operation_timeout=>1800, :basic_auth_only=>true, :transport=>:plaintext, :disable_sspi=>true})
212
- exit_code = @winrm.run
213
- end
214
- end
215
-
216
- end
217
- end
218
- end
219
- end
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
+ allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
55
+ @node_foo.automatic_attrs[:fqdn] = nil
56
+ @node_bar.automatic_attrs[:fqdn] = nil
57
+ allow(Chef::Search::Query).to receive(:new).and_return(@query)
58
+ end
59
+
60
+ it "should raise a specific error (KNIFE-222)" do
61
+ expect(@knife.ui).to receive(:fatal).with(/does not have the required attribute/)
62
+ expect(@knife).to 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
+ allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
71
+ allow(Chef::Search::Query).to receive(:new).and_return(@query)
72
+ end
73
+
74
+ it "should use nested attributes (KNIFE-276)" do
75
+ @knife.config[:attribute] = "ec2.public_hostname"
76
+ allow(@knife).to receive(: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
+ allow(@winrm).to receive(:winrm_command).and_return(0)
96
+ exit_code = @winrm.run
97
+ expect(exit_code).to be_zero
98
+ end
99
+
100
+ it "should exit the process with exact exit status if the command fails and returns config is set to 0" do
101
+ command_status = 510
102
+ @winrm.config[:returns] = "0"
103
+ Chef::Config[:knife][:returns] = [0]
104
+ allow(@winrm).to receive(:winrm_command).and_return(command_status)
105
+ session_mock = EventMachine::WinRM::Session.new
106
+ allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
107
+ allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
108
+ begin
109
+ @winrm.run
110
+ expect(0).to eq(510)
111
+ rescue Exception => e
112
+ expect(e.status).to eq(command_status)
113
+ end
114
+ end
115
+
116
+ it "should exit the process with non-zero status if the command fails and returns config is set to 0" do
117
+ command_status = 1
118
+ @winrm.config[:returns] = "0,53"
119
+ Chef::Config[:knife][:returns] = [0,53]
120
+ allow(@winrm).to receive(:winrm_command).and_return(command_status)
121
+ session_mock = EventMachine::WinRM::Session.new
122
+ allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
123
+ allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
124
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
125
+ end
126
+
127
+ it "should exit the process with a zero status if the command returns an expected non-zero status" do
128
+ command_status = 53
129
+ Chef::Config[:knife][:returns] = [0,53]
130
+ allow(@winrm).to receive(:winrm_command).and_return(command_status)
131
+ session_mock = EventMachine::WinRM::Session.new
132
+ allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
133
+ allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
134
+ exit_code = @winrm.run
135
+ expect(exit_code).to be_zero
136
+ end
137
+
138
+ it "should exit the process with a zero status if the command returns an expected non-zero status" do
139
+ command_status = 53
140
+ Chef::Config[:knife][:returns] = [0,53]
141
+ allow(@winrm).to receive(:winrm_command).and_return(command_status)
142
+ session_mock = EventMachine::WinRM::Session.new
143
+ allow(EventMachine::WinRM::Session).to receive(:new).and_return(session_mock)
144
+ allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
145
+ exit_code = @winrm.run
146
+ expect(exit_code).to be_zero
147
+ end
148
+
149
+ it "should exit the process with 100 if command execution raises an exception other than 401" do
150
+ allow(@winrm).to receive(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('500', '500'))
151
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
152
+ end
153
+
154
+ it "should exit the process with 100 if command execution raises a 401" do
155
+ allow(@winrm).to receive(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('401', '401'))
156
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
157
+ end
158
+
159
+ it "should exit the process with 0 if command execution raises a 401 and suppress_auth_failure is set to true" do
160
+ @winrm.config[:suppress_auth_failure] = true
161
+ allow(@winrm).to receive(:winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('401', '401'))
162
+ exit_code = @winrm.run_with_pretty_exceptions
163
+ expect(exit_code).to eq(401)
164
+ end
165
+
166
+ context "validate sspinegotiate transport option" do
167
+ before do
168
+ Chef::Config[:knife] = {:winrm_transport => :plaintext}
169
+ allow(@winrm).to receive(:winrm_command).and_return(0)
170
+ end
171
+
172
+ it "should have winrm opts transport set to sspinegotiate for windows" do
173
+ @winrm.config[:winrm_user] = "domain\\testuser"
174
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
175
+ allow(@winrm).to receive(:require).with('winrm-s').and_return(true)
176
+ expect(@winrm.session).to receive(:use).with("localhost", {:user=>"domain\\testuser", :password=>"testpassword", :port=>nil, :operation_timeout=>1800, :basic_auth_only=>false, :transport=>:sspinegotiate, :disable_sspi=>false})
177
+ exit_code = @winrm.run
178
+ end
179
+
180
+ it "should use the winrm monkey patch for windows" do
181
+ @winrm.config[:winrm_user] = "domain\\testuser"
182
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
183
+ expect(@winrm).to receive(:require).with('winrm-s')
184
+
185
+ exit_code = @winrm.run
186
+ end
187
+
188
+ context "when domain name not given" do
189
+ it "should skip winrm monkey patch for windows" do
190
+ @winrm.config[:winrm_user] = "testuser"
191
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
192
+ expect(@winrm).to_not receive(:require).with('winrm-s')
193
+
194
+ exit_code = @winrm.run
195
+ end
196
+ end
197
+
198
+ context "when local domain name given" do
199
+ it "should use the winrm monkey patch for windows" do
200
+ @winrm.config[:winrm_user] = ".\\testuser"
201
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
202
+ expect(@winrm).to receive(:require).with('winrm-s')
203
+
204
+ exit_code = @winrm.run
205
+ end
206
+ end
207
+
208
+ it "should not have winrm opts transport set to sspinegotiate for unix" do
209
+ allow(Chef::Platform).to receive(:windows?).and_return(false)
210
+
211
+ expect(@winrm.session).to receive(:use).with("localhost", {:user=>"testuser", :password=>"testpassword", :port=>nil, :operation_timeout=>1800, :basic_auth_only=>true, :transport=>:plaintext, :disable_sspi=>true})
212
+ exit_code = @winrm.run
213
+ end
214
+ end
215
+
216
+ end
217
+ end
218
+ end
219
+ end