knife-windows 1.9.6 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,172 +0,0 @@
1
- #
2
- # Author:: Kartik Null Cating-Subramanian(<ksubramanian@chef.io>)
3
- # Copyright:: Copyright (c) 2015-2016 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::Bootstrap, :chef_gte_12_7_only do
22
- before(:all) do
23
- Chef::Config.reset
24
- end
25
-
26
- let(:bootstrap) { Chef::Knife::Bootstrap.new }
27
- let(:win_bootstrap) { nil }
28
- let(:opt_map) { {} }
29
- let(:ref_ignore) { [] }
30
- let(:win_ignore) { [] }
31
-
32
- def compare_property(sym)
33
- win_bootstrap.options.each do |win_key, win_val|
34
- unless win_ignore.include?(win_key) || opt_map.include?(win_key) then
35
- actual = win_val[sym]
36
- expected = bootstrap.options[win_key][sym]
37
- expect(actual).to eq(expected),
38
- "#{win_key} flag's #{sym} property doesn't match
39
-
40
- expected: #{expected}
41
- got: #{actual}"
42
- end
43
- end
44
- end
45
-
46
- shared_examples 'compare_options' do
47
- it 'contains the option flags', :chef_lt_14_only do
48
- opt_map.default_proc = proc { |map, key| key }
49
- filtered_keys = (win_bootstrap.options.keys - win_ignore).map! { |key| opt_map[key] }
50
-
51
- expect(filtered_keys).to match_array(bootstrap.options.keys - ref_ignore)
52
- end
53
-
54
- it 'uses the same long-name' do
55
- compare_property(:long)
56
- end
57
-
58
- it 'uses the same short-name' do
59
- compare_property(:short)
60
- end
61
-
62
- it 'uses the same description' do
63
- compare_property(:description)
64
- end
65
-
66
- it 'uses the same default value' do
67
- compare_property(:default)
68
- end
69
- end
70
-
71
- context 'when compared to BootstrapWindowsWinrm' do
72
- let(:win_bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new }
73
-
74
- # opt_map: Hash of symbols in windows mapping to symbols in core. Name checks are
75
- # ignored for these.
76
- let(:opt_map) { {
77
- :msi_url => :bootstrap_url,
78
- :encrypted_data_bag_secret => :secret,
79
- :encrypted_data_bag_secret_file => :secret_file,
80
- :winrm_user => :ssh_user,
81
- :winrm_password => :ssh_password,
82
- :winrm_port => :ssh_port,
83
- :winrm_ssl_verify_mode => :host_key_verify,
84
- :bootstrap_install_command => :bootstrap_install_command,
85
- :hint => :hint
86
- }}
87
-
88
- # ref_ignore: Options in core that are not implemented here.
89
- let(:ref_ignore) { [
90
- # These are irrelevant to WinRM.
91
- :bootstrap_curl_options,
92
- :bootstrap_wget_options,
93
- :forward_agent,
94
- :preserve_home,
95
- :ssh_gateway,
96
- :use_sudo,
97
- :use_sudo_password,
98
- :encrypt, # irrelevant during bootstrap
99
- :identity_file,
100
- :ssh_identity_file,
101
- :ssh_gateway_identity,
102
- :bootstrap_proxy_user,
103
- :bootstrap_proxy_pass,
104
- :bootstrap_preinstall_command,
105
- :distro, # Deprecated - remove this when the flag is removed.
106
- :template_file, # Deprecated - remove this when the flag is removed.
107
- ]}
108
-
109
- # win_ignore: Options in windows that aren't relevant to core.
110
- let(:win_ignore) { [
111
- :attribute,
112
- :auth_timeout,
113
- :ca_trust_file,
114
- :install_as_service,
115
- :kerberos_keytab_file,
116
- :kerberos_realm,
117
- :kerberos_service,
118
- :manual,
119
- :session_timeout,
120
- :ssl_peer_fingerprint,
121
- :winrm_authentication_protocol,
122
- :winrm_transport,
123
- :winrm_codepage,
124
- :concurrency,
125
- :winrm_shell,
126
- :distro, # Deprecated - remove this when the flag is removed.
127
- :template_file, # Deprecated - remove this when the flag is removed.
128
- ] }
129
-
130
- include_examples 'compare_options'
131
- end
132
-
133
- context 'when compared to BootstrapWindowsSsh' do
134
- let(:win_bootstrap) { Chef::Knife::BootstrapWindowsSsh.new }
135
-
136
- # opt_map: Hash of symbols in windows mapping to symbols in core. Name checks are
137
- # ignored for these.
138
- let(:opt_map) { {
139
- :msi_url => :bootstrap_url,
140
- :encrypted_data_bag_secret => :secret,
141
- :encrypted_data_bag_secret_file => :secret_file,
142
- :bootstrap_install_command => :bootstrap_install_command,
143
- :hint => :hint
144
- }}
145
- # ref_ignore: Options in core that are not implemented here.
146
- let(:ref_ignore) { [
147
- :bootstrap_curl_options,
148
- :bootstrap_wget_options,
149
- :preserve_home,
150
- :use_sudo,
151
- :use_sudo_password,
152
- :encrypt, # irrelevant during bootstrap
153
- :ssh_gateway_identity,
154
- :bootstrap_proxy_user,
155
- :bootstrap_proxy_pass,
156
- :bootstrap_preinstall_command,
157
- :distro, # Deprecated - remove this when the flag is removed.
158
- :template_file, # Deprecated - remove this when the flag is removed.
159
- ]}
160
- # win_ignore: Options in windows that aren't relevant to core.
161
- let(:win_ignore) { [
162
- :auth_timeout,
163
- :install_as_service,
164
- :host_key_verification, # Deprecated - remove this when the flag is removed.
165
- :distro, # Deprecated - remove this when the flag is removed.
166
- :template_file, # Deprecated - remove this when the flag is removed.
167
- ] }
168
-
169
- include_examples 'compare_options'
170
- end
171
-
172
- end
@@ -1,139 +0,0 @@
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 Chef::Knife::BootstrapWindowsWinrm do
24
- let(:template_file) { TEMPLATE_FILE }
25
- let(:options) { [] }
26
- let(:rendered_template) do
27
- knife.instance_variable_set("@template_file", template_file)
28
- knife.parse_options(options)
29
- # Avoid referencing a validation keyfile we won't find during #render_template
30
- template = IO.read(template_file).chomp
31
- knife.render_template(template)
32
- end
33
- subject(:knife) { described_class.new }
34
-
35
- before(:all) do
36
- @original_config = Chef::Config.hash_dup
37
- @original_knife_config = Chef::Config[:knife].dup
38
- end
39
-
40
- after(:all) do
41
- Chef::Config.configuration = @original_config
42
- Chef::Config[:knife] = @original_knife_config
43
- end
44
-
45
- before(:each) do
46
- Chef::Log.logger = Logger.new(StringIO.new)
47
- @knife = Chef::Knife::BootstrapWindowsWinrm.new
48
- # Merge default settings in.
49
- @knife.merge_configs
50
- @knife.config[:template_file] = template_file
51
- @stdout = StringIO.new
52
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
53
- @stderr = StringIO.new
54
- allow(@knife.ui).to receive(:stderr).and_return(@stderr)
55
- end
56
-
57
- describe "specifying no_proxy with various entries" do
58
- let(:options){ ["--bootstrap-proxy", "", "--bootstrap-no-proxy", setting] }
59
-
60
- context "via --bootstrap-no-proxy" do
61
- let(:setting) { "api.chef.io" }
62
-
63
- it "renders the client.rb with a single FQDN no_proxy entry" do
64
- expect(rendered_template).to match(%r{.*no_proxy\s*\"api.chef.io\".*})
65
- end
66
- end
67
- context "via --bootstrap-no-proxy multiple" do
68
- let(:setting) { "api.chef.io,172.16.10.*" }
69
-
70
- it "renders the client.rb with comma-separated FQDN and wildcard IP address no_proxy entries" do
71
- expect(rendered_template).to match(%r{.*no_proxy\s*"api.chef.io,172.16.10.\*".*})
72
- end
73
- end
74
- end
75
-
76
- describe "specifying --msi-url" do
77
- context "with explicitly provided --msi-url" do
78
- let(:options) { ["--msi-url", "file:///something.msi"] }
79
-
80
- it "bootstrap batch file must fetch from provided url" do
81
- expect(rendered_template).to match(%r{.*REMOTE_SOURCE_MSI_URL=file:///something\.msi.*})
82
- end
83
- end
84
- context "with no provided --msi-url" do
85
- it "bootstrap batch file must fetch from provided url" do
86
- expect(rendered_template).to match(%r{.*REMOTE_SOURCE_MSI_URL=https://www\.chef\.io/.*})
87
- end
88
- end
89
- end
90
-
91
- describe "specifying knife_config[:architecture]" do
92
- it "puts the target architecture into the msi_url" do
93
- Chef::Config[:knife][:architecture] = :x86_64
94
- expect(rendered_template).to match(/MACHINE_ARCH=x86_64/)
95
- end
96
- end
97
-
98
- describe "when setting client_d_dir" do
99
- before do
100
- Chef::Config[:client_d_dir] = client_d_dir
101
- end
102
-
103
- context "client_d_dir is nil" do
104
- let(:client_d_dir) { nil }
105
-
106
- it "does not create c:/chef/client.d" do
107
- expect(rendered_template).not_to match(%r{mkdir c:\chef\client.d})
108
- end
109
- end
110
-
111
- context "client_d_dir is set" do
112
- let(:client_d_dir) do
113
- Chef::Util::PathHelper.cleanpath(
114
- File.join(File.dirname(__FILE__), "../../data/client.d_00")) end
115
-
116
- it "creates c:/chef/client.d" do
117
- expect(rendered_template).to match(/mkdir C:\\chef\\client.d/)
118
- end
119
-
120
- context "a flat directory structure" do
121
-
122
- it "creates a foo directory" do
123
- expect(rendered_template).to match(/C:\\chef\\client.d\\foo/)
124
- end
125
-
126
- it "creates a file 00-foo.rb" do
127
- expect(rendered_template).to match(/C:\\chef\\client.d\\00-foo.rb/)
128
- expect(rendered_template).to match("d6f9b976-289c-4149-baf7-81e6ffecf228")
129
- end
130
-
131
- it "creates a file bar" do
132
- expect(rendered_template).to match(/C:\\chef\\client.d\\foo\\bar.rb/)
133
- expect(rendered_template).to match("1 / 0")
134
- end
135
- end
136
- end
137
- end
138
-
139
- end
@@ -1,410 +0,0 @@
1
- #
2
- # Author:: Adam Edwards(<adamed@chef.io>)
3
- # Copyright:: Copyright (c) 2014-2016 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
- require 'winrm/output'
21
-
22
- Chef::Knife::Winrm.load_deps
23
-
24
- describe Chef::Knife::BootstrapWindowsWinrm do
25
- before do
26
- Chef::Config.reset
27
- bootstrap.config[:run_list] = []
28
- allow(bootstrap).to receive(:validate_options!).and_return(nil)
29
- allow(bootstrap).to receive(:sleep).and_return(10)
30
- allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session)
31
- allow(File).to receive(:exist?).with(anything).and_call_original
32
- allow(File).to receive(:exist?).with(File.expand_path(Chef::Config[:validation_key])).and_return(true)
33
- end
34
-
35
- after do
36
- allow(bootstrap).to receive(:sleep).and_return(10)
37
- end
38
-
39
- let(:session_opts) do
40
- {
41
- user: "Administrator",
42
- password: "testpassword",
43
- port: "5986",
44
- transport: :ssl,
45
- host: "localhost"
46
- }
47
- end
48
- let(:bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new(['winrm', '-d', 'windows-chef-client-msi', '-x', session_opts[:user], '-P', session_opts[:password], session_opts[:host]]) }
49
- let(:session) { Chef::Knife::WinrmSession.new(session_opts) }
50
- let(:arch_session_result) {
51
- o = WinRM::Output.new
52
- o << {stdout: "X86\r\n"}
53
- o
54
- }
55
- let(:arch_session_results) { [arch_session_result] }
56
- let(:initial_fail_count) { 4 }
57
-
58
- context "knife secret-file && knife secret options are passed" do
59
- before do
60
- Chef::Config.reset
61
- Chef::Config[:knife][:encrypted_data_bag_secret_file] = "/tmp/encrypted_data_bag_secret"
62
- Chef::Config[:knife][:encrypted_data_bag_secret] = "data_bag_secret_key_passed_under_knife_secret_option"
63
- end
64
- it "gives preference to secret key passed under knife's secret-file option" do
65
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
66
- Chef::Config[:knife][:encrypted_data_bag_secret_file]).
67
- and_return("data_bag_secret_key_passed_under_knife_secret_file_option")
68
- expect(bootstrap.load_correct_secret).to eq(
69
- "data_bag_secret_key_passed_under_knife_secret_file_option")
70
- end
71
- end
72
-
73
- context "cli secret-file && cli secret options are passed" do
74
- before do
75
- Chef::Config.reset
76
- bootstrap.config[:encrypted_data_bag_secret_file] = "/tmp/encrypted_data_bag_secret"
77
- bootstrap.config[:encrypted_data_bag_secret] = "data_bag_secret_key_passed_under_cli_secret_option"
78
- end
79
- it "gives preference to secret key passed under cli's secret-file option" do
80
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
81
- bootstrap.config[:encrypted_data_bag_secret_file]).
82
- and_return("data_bag_secret_key_passed_under_cli_secret_file_option")
83
- expect(bootstrap.load_correct_secret).to eq(
84
- "data_bag_secret_key_passed_under_cli_secret_file_option")
85
- end
86
- end
87
-
88
- context "knife secret-file, knife secret, cli secret-file && cli secret options are passed" do
89
- before do
90
- Chef::Config.reset
91
- Chef::Config[:knife][:encrypted_data_bag_secret_file] = "/tmp/knife_encrypted_data_bag_secret"
92
- Chef::Config[:knife][:encrypted_data_bag_secret] = "data_bag_secret_key_passed_under_knife_secret_option"
93
- bootstrap.config[:encrypted_data_bag_secret_file] = "/tmp/cli_encrypted_data_bag_secret"
94
- bootstrap.config[:encrypted_data_bag_secret] = "data_bag_secret_key_passed_under_cli_secret_option"
95
- end
96
- it "gives preference to secret key passed under cli's secret-file option" do
97
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
98
- Chef::Config[:knife][:encrypted_data_bag_secret_file]).
99
- and_return("data_bag_secret_key_passed_under_knife_secret_file_option")
100
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
101
- bootstrap.config[:encrypted_data_bag_secret_file]).
102
- and_return("data_bag_secret_key_passed_under_cli_secret_file_option")
103
- expect(bootstrap.load_correct_secret).to eq(
104
- "data_bag_secret_key_passed_under_cli_secret_file_option")
105
- end
106
- end
107
-
108
- context "knife secret-file && cli secret options are passed" do
109
- before do
110
- Chef::Config.reset
111
- Chef::Config[:knife][:encrypted_data_bag_secret_file] = "/tmp/encrypted_data_bag_secret"
112
- bootstrap.config[:encrypted_data_bag_secret] = "data_bag_secret_key_passed_under_cli_secret_option"
113
- end
114
- it "gives preference to secret key passed under cli's secret option" do
115
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
116
- Chef::Config[:knife][:encrypted_data_bag_secret_file]).
117
- and_return("data_bag_secret_key_passed_under_knife_secret_file_option")
118
- expect(bootstrap.load_correct_secret).to eq(
119
- "data_bag_secret_key_passed_under_cli_secret_option")
120
- end
121
- end
122
-
123
- context "knife secret && cli secret-file options are passed" do
124
- before do
125
- Chef::Config.reset
126
- Chef::Config[:knife][:encrypted_data_bag_secret] = "data_bag_secret_key_passed_under_knife_secret_option"
127
- bootstrap.config[:encrypted_data_bag_secret_file] = "/tmp/encrypted_data_bag_secret"
128
- end
129
- it "gives preference to secret key passed under cli's secret-file option" do
130
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
131
- bootstrap.config[:encrypted_data_bag_secret_file]).
132
- and_return("data_bag_secret_key_passed_under_cli_secret_file_option")
133
- expect(bootstrap.load_correct_secret).to eq(
134
- "data_bag_secret_key_passed_under_cli_secret_file_option")
135
- end
136
- end
137
-
138
- context "cli secret-file option is passed" do
139
- before do
140
- Chef::Config.reset
141
- bootstrap.config[:encrypted_data_bag_secret_file] = "/tmp/encrypted_data_bag_secret"
142
- end
143
- it "takes the secret key passed under cli's secret-file option" do
144
- allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
145
- bootstrap.config[:encrypted_data_bag_secret_file]).
146
- and_return("data_bag_secret_key_passed_under_cli_secret_file_option")
147
- expect(bootstrap.load_correct_secret).to eq(
148
- "data_bag_secret_key_passed_under_cli_secret_file_option")
149
- end
150
- end
151
-
152
- it 'should pass exit code from failed winrm call' do
153
- allow(session).to receive(:exit_code).and_return(500)
154
- allow(bootstrap).to receive(:wait_for_remote_response)
155
- allow(bootstrap).to receive(:create_bootstrap_bat_command)
156
- allow(session).to receive(:relay_command).and_return(arch_session_result)
157
- allow(bootstrap.ui).to receive(:info)
158
- expect {
159
- bootstrap.run_with_pretty_exceptions
160
- }.to raise_error(SystemExit) { |e|
161
- expect(e.status).to eq(500)
162
- }
163
- end
164
-
165
- it 'should retry if a 401 is received from WinRM' do
166
- call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('', '401')}}
167
- call_result_sequence.push(0)
168
- allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
169
- allow(bootstrap).to receive(:print)
170
- allow(bootstrap.ui).to receive(:info)
171
-
172
- expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
173
- bootstrap.send(:wait_for_remote_response, 2)
174
- end
175
-
176
- it 'should retry if something other than a 401 is received from WinRM' do
177
- call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('', '500')}}
178
- call_result_sequence.push(0)
179
- allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
180
- allow(bootstrap).to receive(:print)
181
- allow(bootstrap.ui).to receive(:info)
182
-
183
- expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
184
- bootstrap.send(:wait_for_remote_response, 2)
185
- end
186
-
187
- it 'should keep retrying at 10s intervals if the timeout in minutes has not elapsed' do
188
- call_result_sequence = Array.new(initial_fail_count) {lambda {raise WinRM::WinRMHTTPTransportError.new('', '500')}}
189
- call_result_sequence.push(0)
190
- allow(bootstrap).to receive(:run_command).and_return(*call_result_sequence)
191
- allow(bootstrap).to receive(:print)
192
- allow(bootstrap.ui).to receive(:info)
193
-
194
- expect(bootstrap).to receive(:run_command).exactly(call_result_sequence.length).times
195
- bootstrap.send(:wait_for_remote_response, 2)
196
- end
197
-
198
- it 'should have a wait timeout of 2 minutes by default' do
199
- allow(bootstrap).to receive(:run_command).and_raise(WinRM::WinRMHTTPTransportError.new('','500'))
200
- allow(bootstrap).to receive(:create_bootstrap_bat_command).and_raise(SystemExit)
201
- expect(bootstrap).to receive(:wait_for_remote_response).with(2)
202
-
203
- allow(bootstrap.ui).to receive(:info)
204
- bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
205
- expect { bootstrap.bootstrap }.to raise_error(SystemExit)
206
- end
207
-
208
- it 'should not a wait for timeout on Errno::ECONNREFUSED' do
209
- allow(bootstrap).to receive(:run_command).and_raise(Errno::ECONNREFUSED.new)
210
- allow(bootstrap.ui).to receive(:info)
211
- bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
212
- expect(bootstrap.ui).to receive(:error).with("Connection refused connecting to localhost:5985.")
213
-
214
- # wait_for_remote_response is protected method, So define singleton test method to call it.
215
- bootstrap.define_singleton_method(:test_wait_for_remote_response){wait_for_remote_response(bootstrap.options[:auth_timeout][:default])}
216
- expect { bootstrap.test_wait_for_remote_response }.to raise_error(Errno::ECONNREFUSED)
217
- end
218
-
219
- it 'should stop retrying if more than 2 minutes has elapsed' do
220
- times = [ Time.new(2014, 4, 1, 22, 25), Time.new(2014, 4, 1, 22, 51), Time.new(2014, 4, 1, 22, 28) ]
221
- allow(Time).to receive(:now).and_return(*times)
222
- run_command_result = lambda {raise WinRM::WinRMHTTPTransportError, '401'}
223
- allow(bootstrap).to receive(:run_command).and_return(run_command_result)
224
- allow(bootstrap).to receive(:print)
225
- allow(bootstrap.ui).to receive(:info)
226
- allow(bootstrap.ui).to receive(:error)
227
- expect(bootstrap).to receive(:run_command).exactly(1).times
228
- bootstrap.config[:auth_timeout] = bootstrap.options[:auth_timeout][:default]
229
- expect { bootstrap.bootstrap }.to raise_error /Command execution failed./
230
- end
231
-
232
- it 'successfully bootstraps' do
233
- Chef::Config[:knife][:bootstrap_architecture] = :i386
234
- allow(bootstrap).to receive(:wait_for_remote_response)
235
- allow(bootstrap).to receive(:create_bootstrap_bat_command)
236
- allow(bootstrap).to receive(:run_command).and_return(0)
237
- expect(bootstrap.bootstrap).to eq(0)
238
- expect(Chef::Config[:knife][:architecture]).to eq(:i686)
239
- end
240
-
241
- context "when the target node is 64 bit" do
242
- it 'successfully bootstraps' do
243
- Chef::Config[:knife][:bootstrap_architecture] = :x86_64
244
- allow(bootstrap).to receive(:wait_for_remote_response)
245
- allow(bootstrap).to receive(:create_bootstrap_bat_command)
246
- allow(bootstrap).to receive(:run_command).and_return(0)
247
- expect(bootstrap.bootstrap).to eq(0)
248
- expect(Chef::Config[:knife][:architecture]).to eq(:x86_64)
249
- end
250
- end
251
-
252
- context 'FQDN validation -' do
253
- it 'should raise an error if FQDN value is not passed' do
254
- bootstrap.instance_variable_set(:@name_args, [])
255
- allow(bootstrap.ui).to receive(:error)
256
- expect {
257
- bootstrap.run
258
- }.to raise_error(SystemExit)
259
- end
260
-
261
- it 'should not raise error if FQDN value is passed' do
262
- bootstrap.instance_variable_set(:@name_args, ["fqdn_name"])
263
- expect {
264
- bootstrap.run
265
- }.not_to raise_error(SystemExit)
266
- end
267
- end
268
-
269
- context "when validation_key is not present" do
270
- before do
271
- allow(File).to receive(:exist?).with(File.expand_path(Chef::Config[:validation_key])).and_return(false)
272
- bootstrap.client_builder = instance_double("Chef::Knife::Bootstrap::ClientBuilder", :run => nil, :client_path => nil)
273
- Chef::Config[:knife] = {:chef_node_name => 'foo.example.com'}
274
- end
275
-
276
- it 'raises an exception if winrm_authentication_protocol is basic and transport is plaintext' do
277
- Chef::Config[:knife] = {:winrm_authentication_protocol => 'basic', :winrm_transport => 'plaintext', :chef_node_name => 'foo.example.com'}
278
- expect(bootstrap.ui).to receive(:error)
279
- expect { bootstrap.run }.to raise_error(SystemExit)
280
- end
281
-
282
- it 'raises an exception if chef_node_name is not present ' do
283
- Chef::Config[:knife] = {:chef_node_name => nil}
284
- expect(bootstrap.client_builder).not_to receive(:run)
285
- expect(bootstrap.client_builder).not_to receive(:client_path)
286
- expect(bootstrap.ui).to receive(:error)
287
- expect { bootstrap.bootstrap }.to raise_error(SystemExit)
288
- end
289
- end
290
-
291
- context "when doing chef vault" do
292
- let(:vault_handler) { double('vault_handler', :doing_chef_vault? => true) }
293
- let(:node_name) { 'foo.example.com' }
294
- before do
295
- allow(bootstrap).to receive(:wait_for_remote_response)
296
- allow(bootstrap).to receive(:create_bootstrap_bat_command)
297
- allow(bootstrap).to receive(:run_command).and_return(0)
298
- bootstrap.config[:chef_node_name] = node_name
299
- bootstrap.chef_vault_handler = vault_handler
300
- end
301
-
302
- context "builder does not respond to client" do
303
- before do
304
- bootstrap.client_builder = instance_double("Chef::Knife::Bootstrap::ClientBuilder", :run => nil, :client_path => nil)
305
- end
306
-
307
- it "passes a node search query to the handler" do
308
- expect(vault_handler).to receive(:run).with(node_name: node_name)
309
- bootstrap.bootstrap
310
- end
311
- end
312
-
313
- context "builder responds to client" do
314
- let(:client) { Chef::ApiClient.new }
315
-
316
- before do
317
- bootstrap.client_builder = double("Chef::Knife::Bootstrap::ClientBuilder", :run => nil, :client_path => nil, :client => client)
318
- end
319
-
320
- it "passes a node search query to the handler" do
321
- expect(vault_handler).to receive(:run).with(client)
322
- bootstrap.bootstrap
323
- end
324
- end
325
- end
326
-
327
- describe 'first_boot_attributes' do
328
- let(:first_boot_attributes) { { 'a1' => 'b1', 'a2' => 'b2', 'source' => 'hash' } }
329
- let(:json_file) { 'my_json.json' }
330
- let(:first_boot_attributes_from_file) { read_json_file(json_file) }
331
-
332
- before do
333
- File.open(json_file,"w+") do |f|
334
- f.write <<-EOH
335
- {"b2" : "a3", "a4" : "b5", "source" : "file"}
336
- EOH
337
- end
338
- end
339
-
340
- context 'when none of the json-attributes options are passed' do
341
- it 'returns an empty hash' do
342
- response = bootstrap.first_boot_attributes
343
- expect(response).to be == {}
344
- end
345
- end
346
-
347
- context 'when only --json-attributes option is passed' do
348
- before do
349
- bootstrap.config[:first_boot_attributes] = first_boot_attributes
350
- end
351
-
352
- it 'returns the hash passed by the user in --json-attributes option' do
353
- response = bootstrap.first_boot_attributes
354
- expect(response).to be == first_boot_attributes
355
- end
356
- end
357
-
358
- context 'when only --json-attribute-file option is passed' do
359
- before do
360
- bootstrap.config[:first_boot_attributes_from_file] = first_boot_attributes_from_file
361
- end
362
-
363
- it 'returns the hash passed by the user in --json-attribute-file option' do
364
- response = bootstrap.first_boot_attributes
365
- expect(response).to be == { 'b2' => 'a3', 'a4' => 'b5', 'source' => 'file' }
366
- end
367
- end
368
-
369
- context 'when both the --json-attributes option and --json-attribute-file options are passed' do
370
- before do
371
- bootstrap.config[:first_boot_attributes] = first_boot_attributes
372
- bootstrap.config[:first_boot_attributes_from_file] = first_boot_attributes_from_file
373
- end
374
-
375
- it 'returns the hash passed by the user in --json-attributes option' do
376
- response = bootstrap.first_boot_attributes
377
- expect(response).to be == first_boot_attributes
378
- end
379
- end
380
-
381
- after do
382
- FileUtils.rm_rf json_file
383
- end
384
- end
385
-
386
- describe 'render_template' do
387
- before do
388
- allow(bootstrap).to receive(:first_boot_attributes).and_return(
389
- { 'a1' => 'b3', 'a2' => 'b1' }
390
- )
391
- allow(bootstrap).to receive(:load_correct_secret).and_return(
392
- 'my_secret'
393
- )
394
- allow(Erubis::Eruby).to receive_message_chain(:new, :evaluate).and_return(
395
- 'my_template'
396
- )
397
- end
398
-
399
- it 'sets correct values into config and returns the correct response' do
400
- response = bootstrap.render_template
401
- expect(bootstrap.config[:first_boot_attributes]).to be == { 'a1' => 'b3', 'a2' => 'b1' }
402
- expect(bootstrap.config[:secret]).to be == 'my_secret'
403
- expect(response).to be == 'my_template'
404
- end
405
- end
406
- end
407
-
408
- def read_json_file(file)
409
- Chef::JSONCompat.parse(File.read(file))
410
- end