chef 11.14.6-x86-mingw32 → 11.16.0-x86-mingw32
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 +4 -4
- data/lib/chef/exceptions.rb +4 -0
- data/lib/chef/mixin/windows_architecture_helper.rb +16 -0
- data/lib/chef/platform/query_helpers.rb +5 -1
- data/lib/chef/provider/dsc_script.rb +148 -0
- data/lib/chef/provider/user/dscl.rb +32 -28
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/resource/dsc_script.rb +140 -0
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/util/dsc/configuration_generator.rb +115 -0
- data/lib/chef/util/dsc/lcm_output_parser.rb +133 -0
- data/lib/chef/util/dsc/local_configuration_manager.rb +137 -0
- data/lib/chef/util/dsc/resource_info.rb +26 -0
- data/lib/chef/util/path_helper.rb +2 -2
- data/lib/chef/util/powershell/cmdlet.rb +136 -0
- data/lib/chef/util/powershell/cmdlet_result.rb +46 -0
- data/lib/chef/version.rb +1 -1
- data/spec/functional/resource/dsc_script_spec.rb +337 -0
- data/spec/functional/resource/group_spec.rb +5 -1
- data/spec/functional/util/powershell/cmdlet_spec.rb +114 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/platform_helpers.rb +24 -0
- data/spec/unit/platform/query_helpers_spec.rb +23 -0
- data/spec/unit/provider/dsc_script_spec.rb +145 -0
- data/spec/unit/provider/user/dscl_spec.rb +2 -1
- data/spec/unit/resource/dsc_script_spec.rb +127 -0
- data/spec/unit/util/dsc/configuration_generator_spec.rb +171 -0
- data/spec/unit/util/dsc/lcm_output_parser_spec.rb +169 -0
- data/spec/unit/util/dsc/local_configuration_manager_spec.rb +134 -0
- data/spec/unit/util/powershell/cmdlet_spec.rb +106 -0
- metadata +20 -4
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Edwards (<adamed@getchef.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2014 Chef Software, Inc.
|
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 'json'
|
20
|
+
|
21
|
+
class Chef::Util::Powershell
|
22
|
+
class CmdletResult
|
23
|
+
attr_reader :output_format
|
24
|
+
|
25
|
+
def initialize(status, output_format)
|
26
|
+
@status = status
|
27
|
+
@output_format = output_format
|
28
|
+
end
|
29
|
+
|
30
|
+
def stderr
|
31
|
+
@status.stderr
|
32
|
+
end
|
33
|
+
|
34
|
+
def return_value
|
35
|
+
if output_format == :object
|
36
|
+
JSON.parse(@status.stdout)
|
37
|
+
else
|
38
|
+
@status.stdout
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def succeeded?
|
43
|
+
@succeeded = @status.status.exitstatus == 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/chef/version.rb
CHANGED
@@ -0,0 +1,337 @@
|
|
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
|
+
require 'chef/mixin/shell_out'
|
21
|
+
require 'chef/mixin/windows_architecture_helper'
|
22
|
+
|
23
|
+
describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
|
24
|
+
include Chef::Mixin::WindowsArchitectureHelper
|
25
|
+
before(:all) do
|
26
|
+
@temp_dir = ::Dir.mktmpdir("dsc-functional-test")
|
27
|
+
end
|
28
|
+
|
29
|
+
after(:all) do
|
30
|
+
::FileUtils.rm_rf(@temp_dir) if ::Dir.exist?(@temp_dir)
|
31
|
+
end
|
32
|
+
|
33
|
+
include Chef::Mixin::ShellOut
|
34
|
+
|
35
|
+
def create_config_script_from_code(code, configuration_name, data = false)
|
36
|
+
script_code = data ? code : "Configuration '#{configuration_name}'\n{\n\t#{code}\n}\n"
|
37
|
+
data_suffix = data ? '_config_data' : ''
|
38
|
+
extension = data ? 'psd1' : 'ps1'
|
39
|
+
script_path = "#{@temp_dir}/dsc_functional_test#{data_suffix}.#{extension}"
|
40
|
+
::File.open(script_path, 'wt') do | script |
|
41
|
+
script.write(script_code)
|
42
|
+
end
|
43
|
+
script_path
|
44
|
+
end
|
45
|
+
|
46
|
+
def user_exists?(target_user)
|
47
|
+
result = false
|
48
|
+
begin
|
49
|
+
shell_out!("net user #{target_user}")
|
50
|
+
result = true
|
51
|
+
rescue Mixlib::ShellOut::ShellCommandFailed
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_user(target_user)
|
57
|
+
begin
|
58
|
+
shell_out!("net user #{target_user} /delete")
|
59
|
+
rescue Mixlib::ShellOut::ShellCommandFailed
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
let(:dsc_env_variable) { 'chefenvtest' }
|
64
|
+
let(:dsc_env_value1) { 'value1' }
|
65
|
+
let(:env_value2) { 'value2' }
|
66
|
+
let(:dsc_test_run_context) {
|
67
|
+
node = Chef::Node.new
|
68
|
+
node.automatic['platform'] = 'windows'
|
69
|
+
node.automatic['platform_version'] = '6.1'
|
70
|
+
node.automatic['kernel'][:machine] =
|
71
|
+
is_i386_process_on_x86_64_windows? ? :x86_64 : :i386
|
72
|
+
node.automatic[:languages][:powershell][:version] = '4.0'
|
73
|
+
empty_events = Chef::EventDispatch::Dispatcher.new
|
74
|
+
Chef::RunContext.new(node, {}, empty_events)
|
75
|
+
}
|
76
|
+
let(:dsc_test_resource_name) { 'DSCTest' }
|
77
|
+
let(:dsc_test_resource_base) {
|
78
|
+
Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
|
79
|
+
}
|
80
|
+
let(:test_registry_key) { 'HKEY_LOCAL_MACHINE\Software\Chef\Spec\Functional\Resource\dsc_script_spec' }
|
81
|
+
let(:test_registry_value) { 'Registration' }
|
82
|
+
let(:test_registry_data1) { 'LL927' }
|
83
|
+
let(:test_registry_data2) { 'LL928' }
|
84
|
+
let(:dsc_code) { <<-EOH
|
85
|
+
Registry "ChefRegKey"
|
86
|
+
{
|
87
|
+
Key = '#{test_registry_key}'
|
88
|
+
ValueName = '#{test_registry_value}'
|
89
|
+
ValueData = '#{test_registry_data}'
|
90
|
+
Ensure = 'Present'
|
91
|
+
}
|
92
|
+
EOH
|
93
|
+
}
|
94
|
+
|
95
|
+
let(:dsc_user_prefix) { 'dsc' }
|
96
|
+
let(:dsc_user_suffix) { 'chefx' }
|
97
|
+
let(:dsc_user) {"#{dsc_user_prefix}_usr_#{dsc_user_suffix}" }
|
98
|
+
let(:dsc_user_prefix_env_var_name) { 'dsc_user_env_prefix' }
|
99
|
+
let(:dsc_user_suffix_env_var_name) { 'dsc_user_env_suffix' }
|
100
|
+
let(:dsc_user_prefix_env_code) { "$env:#{dsc_user_prefix_env_var_name}"}
|
101
|
+
let(:dsc_user_suffix_env_code) { "$env:#{dsc_user_suffix_env_var_name}"}
|
102
|
+
let(:dsc_user_prefix_param_name) { 'dsc_user_prefix_param' }
|
103
|
+
let(:dsc_user_suffix_param_name) { 'dsc_user_suffix_param' }
|
104
|
+
let(:dsc_user_prefix_param_code) { "$#{dsc_user_prefix_param_name}"}
|
105
|
+
let(:dsc_user_suffix_param_code) { "$#{dsc_user_suffix_param_name}"}
|
106
|
+
let(:dsc_user_env_code) { "\"$(#{dsc_user_prefix_env_code})_usr_$(#{dsc_user_suffix_env_code})\""}
|
107
|
+
let(:dsc_user_param_code) { "\"$(#{dsc_user_prefix_param_code})_usr_$(#{dsc_user_suffix_param_code})\""}
|
108
|
+
|
109
|
+
let(:config_flags) { nil }
|
110
|
+
let(:config_params) { <<-EOH
|
111
|
+
|
112
|
+
[CmdletBinding()]
|
113
|
+
param
|
114
|
+
(
|
115
|
+
$#{dsc_user_prefix_param_name},
|
116
|
+
$#{dsc_user_suffix_param_name}
|
117
|
+
)
|
118
|
+
EOH
|
119
|
+
}
|
120
|
+
|
121
|
+
let(:config_param_section) { '' }
|
122
|
+
let(:dsc_user_code) { "'#{dsc_user}'" }
|
123
|
+
let(:dsc_user_prefix_code) { dsc_user_prefix }
|
124
|
+
let(:dsc_user_suffix_code) { dsc_user_suffix }
|
125
|
+
let(:dsc_script_environment_attribute) { nil }
|
126
|
+
let(:dsc_user_resources_code) { <<-EOH
|
127
|
+
#{config_param_section}
|
128
|
+
node localhost
|
129
|
+
{
|
130
|
+
$testuser = #{dsc_user_code}
|
131
|
+
$testpassword = ConvertTo-SecureString -String "jf9a8m49jrajf4#" -AsPlainText -Force
|
132
|
+
$testcred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $testuser, $testpassword
|
133
|
+
|
134
|
+
User dsctestusercreate
|
135
|
+
{
|
136
|
+
UserName = $testuser
|
137
|
+
Password = $testcred
|
138
|
+
Description = "DSC test user"
|
139
|
+
Ensure = "Present"
|
140
|
+
Disabled = $false
|
141
|
+
PasswordNeverExpires = $true
|
142
|
+
PasswordChangeRequired = $false
|
143
|
+
}
|
144
|
+
}
|
145
|
+
EOH
|
146
|
+
}
|
147
|
+
|
148
|
+
let(:dsc_user_config_data) {
|
149
|
+
<<-EOH
|
150
|
+
@{
|
151
|
+
AllNodes = @(
|
152
|
+
@{
|
153
|
+
NodeName = "localhost";
|
154
|
+
PSDscAllowPlainTextPassword = $true
|
155
|
+
}
|
156
|
+
)
|
157
|
+
}
|
158
|
+
|
159
|
+
EOH
|
160
|
+
}
|
161
|
+
|
162
|
+
let(:dsc_environment_env_var_name) { 'dsc_test_cwd' }
|
163
|
+
let(:dsc_environment_no_fail_not_etc_directory) { "#{ENV['systemroot']}\\system32" }
|
164
|
+
let(:dsc_environment_fail_etc_directory) { "#{ENV['systemroot']}\\system32\\drivers\\etc" }
|
165
|
+
let(:exception_message_signature) { 'LL927-LL928' }
|
166
|
+
let(:dsc_environment_config) {<<-EOH
|
167
|
+
if (($pwd.path -eq '#{dsc_environment_fail_etc_directory}') -and (test-path('#{dsc_environment_fail_etc_directory}')))
|
168
|
+
{
|
169
|
+
throw 'Signature #{exception_message_signature}: Purposefully failing because cwd == #{dsc_environment_fail_etc_directory}'
|
170
|
+
}
|
171
|
+
environment "whatsmydir"
|
172
|
+
{
|
173
|
+
Name = '#{dsc_environment_env_var_name}'
|
174
|
+
Value = $pwd.path
|
175
|
+
Ensure = 'Present'
|
176
|
+
}
|
177
|
+
EOH
|
178
|
+
}
|
179
|
+
|
180
|
+
let(:dsc_config_name) {
|
181
|
+
dsc_test_resource_base.name
|
182
|
+
}
|
183
|
+
let(:dsc_resource_from_code) {
|
184
|
+
dsc_test_resource_base.code(dsc_code)
|
185
|
+
dsc_test_resource_base
|
186
|
+
}
|
187
|
+
let(:config_name_value) { dsc_test_resource_base.name }
|
188
|
+
|
189
|
+
let(:dsc_resource_from_path) {
|
190
|
+
dsc_test_resource_base.command(create_config_script_from_code(dsc_code, config_name_value))
|
191
|
+
dsc_test_resource_base
|
192
|
+
}
|
193
|
+
|
194
|
+
before(:each) do
|
195
|
+
test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context)
|
196
|
+
test_key_resource.recursive(true)
|
197
|
+
test_key_resource.run_action(:delete_key)
|
198
|
+
end
|
199
|
+
|
200
|
+
after(:each) do
|
201
|
+
test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context)
|
202
|
+
test_key_resource.recursive(true)
|
203
|
+
test_key_resource.run_action(:delete_key)
|
204
|
+
end
|
205
|
+
|
206
|
+
shared_examples_for 'a dsc_script resource with specified PowerShell configuration code' do
|
207
|
+
let(:test_registry_data) { test_registry_data1 }
|
208
|
+
it 'should create a registry key with a specific registry value and data' do
|
209
|
+
expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(false)
|
210
|
+
dsc_test_resource.run_action(:run)
|
211
|
+
expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(true)
|
212
|
+
expect(dsc_test_resource.registry_value_exists?(test_registry_key, {:name => test_registry_value, :type => :string, :data => test_registry_data})).to eq(true)
|
213
|
+
end
|
214
|
+
|
215
|
+
it_should_behave_like 'a dsc_script resource with configuration affected by cwd'
|
216
|
+
end
|
217
|
+
|
218
|
+
shared_examples_for 'a dsc_script resource with configuration affected by cwd' do
|
219
|
+
after(:each) do
|
220
|
+
removal_resource = Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
|
221
|
+
removal_resource.code <<-EOH
|
222
|
+
environment 'removethis'
|
223
|
+
{
|
224
|
+
Name = '#{dsc_environment_env_var_name}'
|
225
|
+
Ensure = 'Absent'
|
226
|
+
}
|
227
|
+
EOH
|
228
|
+
removal_resource.run_action(:run)
|
229
|
+
end
|
230
|
+
let(:dsc_code) { dsc_environment_config }
|
231
|
+
it 'should not raise an exception if the cwd is not etc' do
|
232
|
+
dsc_test_resource.cwd(dsc_environment_no_fail_not_etc_directory)
|
233
|
+
expect {dsc_test_resource.run_action(:run)}.not_to raise_error
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should raise an exception if the cwd is etc' do
|
237
|
+
dsc_test_resource.cwd(dsc_environment_fail_etc_directory)
|
238
|
+
expect {dsc_test_resource.run_action(:run)}.to raise_error(Chef::Exceptions::PowershellCmdletException)
|
239
|
+
begin
|
240
|
+
dsc_test_resource.run_action(:run)
|
241
|
+
rescue Chef::Exceptions::PowershellCmdletException => e
|
242
|
+
expect(e.message).to match(exception_message_signature)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
shared_examples_for 'a parameterized DSC configuration script' do
|
248
|
+
context 'when specifying environment variables in the environment attribute' do
|
249
|
+
let(:dsc_user_prefix_code) { dsc_user_prefix_env_code }
|
250
|
+
let(:dsc_user_suffix_code) { dsc_user_suffix_env_code }
|
251
|
+
it_behaves_like 'a dsc_script with configuration that uses environment variables'
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
shared_examples_for 'a dsc_script with configuration data' do
|
256
|
+
context 'when using the configuration_data attribute' do
|
257
|
+
let(:configuration_data_attribute) { 'configuration_data' }
|
258
|
+
it_behaves_like 'a dsc_script with configuration data set via an attribute'
|
259
|
+
end
|
260
|
+
|
261
|
+
context 'when using the configuration_data_script attribute' do
|
262
|
+
let(:configuration_data_attribute) { 'configuration_data_script' }
|
263
|
+
it_behaves_like 'a dsc_script with configuration data set via an attribute'
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
shared_examples_for 'a dsc_script with configuration data set via an attribute' do
|
268
|
+
it 'should run a configuration script that creates a user' do
|
269
|
+
config_data_value = dsc_user_config_data
|
270
|
+
dsc_test_resource.configuration_name(config_name_value)
|
271
|
+
if configuration_data_attribute == 'configuration_data_script'
|
272
|
+
config_data_value = create_config_script_from_code(dsc_user_config_data, '', true)
|
273
|
+
end
|
274
|
+
dsc_test_resource.environment({dsc_user_prefix_env_var_name => dsc_user_prefix,
|
275
|
+
dsc_user_suffix_env_var_name => dsc_user_suffix})
|
276
|
+
dsc_test_resource.send(configuration_data_attribute, config_data_value)
|
277
|
+
dsc_test_resource.flags(config_flags)
|
278
|
+
expect(user_exists?(dsc_user)).to eq(false)
|
279
|
+
expect {dsc_test_resource.run_action(:run)}.not_to raise_error
|
280
|
+
expect(user_exists?(dsc_user)).to eq(true)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
shared_examples_for 'a dsc_script with configuration data that takes parameters' do
|
285
|
+
context 'when script code takes parameters for configuration' do
|
286
|
+
let(:dsc_user_code) { dsc_user_param_code }
|
287
|
+
let(:config_param_section) { config_params }
|
288
|
+
let(:config_flags) {{:"#{dsc_user_prefix_param_name}" => "#{dsc_user_prefix}", :"#{dsc_user_suffix_param_name}" => "#{dsc_user_suffix}"}}
|
289
|
+
it 'does not directly contain the user name' do
|
290
|
+
configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
|
291
|
+
file.read
|
292
|
+
end
|
293
|
+
expect(configuration_script_content.include?(dsc_user)).to be(false)
|
294
|
+
end
|
295
|
+
it_behaves_like 'a dsc_script with configuration data'
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
shared_examples_for 'a dsc_script with configuration data that uses environment variables' do
|
301
|
+
context 'when script code uses environment variables' do
|
302
|
+
let(:dsc_user_code) { dsc_user_env_code }
|
303
|
+
|
304
|
+
it 'does not directly contain the user name' do
|
305
|
+
configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
|
306
|
+
file.read
|
307
|
+
end
|
308
|
+
expect(configuration_script_content.include?(dsc_user)).to be(false)
|
309
|
+
end
|
310
|
+
it_behaves_like 'a dsc_script with configuration data'
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'when supplying configuration through the configuration attribute' do
|
315
|
+
let(:dsc_test_resource) { dsc_resource_from_code }
|
316
|
+
it_behaves_like 'a dsc_script resource with specified PowerShell configuration code'
|
317
|
+
end
|
318
|
+
|
319
|
+
context 'when supplying configuration using the path attribute' do
|
320
|
+
let(:dsc_test_resource) { dsc_resource_from_path }
|
321
|
+
it_behaves_like 'a dsc_script resource with specified PowerShell configuration code'
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'when running a configuration that manages users' do
|
325
|
+
before(:each) do
|
326
|
+
delete_user(dsc_user)
|
327
|
+
end
|
328
|
+
|
329
|
+
let(:dsc_code) { dsc_user_resources_code }
|
330
|
+
let(:config_name_value) { 'DSCTestConfig' }
|
331
|
+
let(:dsc_test_resource) { dsc_resource_from_path }
|
332
|
+
|
333
|
+
it_behaves_like 'a dsc_script with configuration data'
|
334
|
+
it_behaves_like 'a dsc_script with configuration data that uses environment variables'
|
335
|
+
it_behaves_like 'a dsc_script with configuration data that takes parameters'
|
336
|
+
end
|
337
|
+
end
|
@@ -40,6 +40,11 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
40
40
|
when "windows"
|
41
41
|
user_sid = sid_string_from_user(user)
|
42
42
|
user_sid.nil? ? false : Chef::Util::Windows::NetGroup.new(group_name).local_get_members.include?(user_sid)
|
43
|
+
when "mac_os_x"
|
44
|
+
membership_info = shell_out("dscl . -read /Groups/#{group_name}").stdout
|
45
|
+
members = membership_info.split(" ")
|
46
|
+
members.shift # Get rid of GroupMembership: string
|
47
|
+
members.include?(user)
|
43
48
|
else
|
44
49
|
Etc::getgrnam(group_name).mem.include?(user)
|
45
50
|
end
|
@@ -420,4 +425,3 @@ downthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreeQQQQQQ" }
|
|
420
425
|
end
|
421
426
|
end
|
422
427
|
end
|
423
|
-
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Edwards (<adamed@getchef.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: 2014, Chef Software, Inc.
|
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 'json'
|
20
|
+
require File.expand_path('../../../../spec_helper', __FILE__)
|
21
|
+
|
22
|
+
describe Chef::Util::Powershell::Cmdlet, :windows_only do
|
23
|
+
before(:all) do
|
24
|
+
ohai = Ohai::System.new
|
25
|
+
ohai.load_plugins
|
26
|
+
ohai.run_plugins(true, ['platform', 'kernel'])
|
27
|
+
@node = Chef::Node.new
|
28
|
+
@node.consume_external_attrs(ohai.data, {})
|
29
|
+
end
|
30
|
+
let(:cmd_output_format) { :text }
|
31
|
+
let(:simple_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-childitem', cmd_output_format, {:depth => 2}) }
|
32
|
+
let(:invalid_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-idontexist', cmd_output_format) }
|
33
|
+
let(:cmdlet_get_item_requires_switch_or_argument) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-item', cmd_output_format, {:depth => 2}) }
|
34
|
+
let(:cmdlet_alias_requires_switch_or_argument) { Chef::Util::Powershell::Cmdlet.new(@node, 'alias', cmd_output_format, {:depth => 2}) }
|
35
|
+
let(:etc_directory) { "#{ENV['systemroot']}\\system32\\drivers\\etc" }
|
36
|
+
let(:architecture_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, "$env:PROCESSOR_ARCHITECTURE")}
|
37
|
+
|
38
|
+
it "executes a simple process" do
|
39
|
+
result = simple_cmdlet.run
|
40
|
+
expect(result.succeeded?).to eq(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "#run does not raise a PowershellCmdletException exception if the command cannot be executed" do
|
44
|
+
expect {invalid_cmdlet.run}.not_to raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
it "#run! raises a PowershellCmdletException exception if the command cannot be executed" do
|
48
|
+
expect {invalid_cmdlet.run!}.to raise_error(Chef::Exceptions::PowershellCmdletException)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "executes a 64-bit command on a 64-bit OS, 32-bit otherwise" do
|
52
|
+
os_arch = ENV['PROCESSOR_ARCHITEW6432']
|
53
|
+
if os_arch.nil?
|
54
|
+
os_arch = ENV['PROCESSOR_ARCHITECTURE']
|
55
|
+
end
|
56
|
+
|
57
|
+
result = architecture_cmdlet.run
|
58
|
+
execution_arch = result.return_value
|
59
|
+
execution_arch.strip!
|
60
|
+
expect(execution_arch).to eq(os_arch)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "passes command line switches to the command" do
|
64
|
+
result = cmdlet_alias_requires_switch_or_argument.run({:name => 'ls'})
|
65
|
+
expect(result.succeeded?).to eq(true)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "passes command line arguments to the command" do
|
69
|
+
result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls')
|
70
|
+
expect(result.succeeded?).to eq(true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "passes command line arguments and switches to the command" do
|
74
|
+
result = cmdlet_get_item_requires_switch_or_argument.run({:path => etc_directory},{},' | select-object -property fullname | format-table -hidetableheaders')
|
75
|
+
expect(result.succeeded?).to eq(true)
|
76
|
+
returned_directory = result.return_value
|
77
|
+
returned_directory.strip!
|
78
|
+
expect(returned_directory).to eq(etc_directory)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "passes execution options to the command" do
|
82
|
+
result = cmdlet_get_item_requires_switch_or_argument.run({},{:cwd => etc_directory},'. | select-object -property fullname | format-table -hidetableheaders')
|
83
|
+
expect(result.succeeded?).to eq(true)
|
84
|
+
returned_directory = result.return_value
|
85
|
+
returned_directory.strip!
|
86
|
+
expect(returned_directory).to eq(etc_directory)
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when returning json" do
|
90
|
+
let(:cmd_output_format) { :json }
|
91
|
+
it "returns json format data", :windows_powershell_dsc_only do
|
92
|
+
result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls')
|
93
|
+
expect(result.succeeded?).to eq(true)
|
94
|
+
expect(lambda{JSON.parse(result.return_value)}).not_to raise_error
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when returning Ruby objects" do
|
99
|
+
let(:cmd_output_format) { :object }
|
100
|
+
it "returns object format data", :windows_powershell_dsc_only do
|
101
|
+
result = simple_cmdlet.run({},{:cwd => etc_directory}, 'hosts')
|
102
|
+
expect(result.succeeded?).to eq(true)
|
103
|
+
data = result.return_value
|
104
|
+
expect(data['Name']).to eq('hosts')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when constructor is given invalid arguments" do
|
109
|
+
let(:cmd_output_format) { :invalid }
|
110
|
+
it "throws an exception if an invalid format is passed to the constructor" do
|
111
|
+
expect(lambda{simple_cmdlet}).to raise_error
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|