diff options
author | Bryan McLellan <btm@loftninjas.org> | 2014-09-03 14:13:46 -0400 |
---|---|---|
committer | adamedx <adamed@getchef.com> | 2014-09-03 11:55:49 -0700 |
commit | 3166bd959316c6fdb54455607332bf80e8eed147 (patch) | |
tree | 3d229db48d3e1d9c36340d7c564194d1abf07d58 | |
parent | a3dbf43c4dfb756c5ac1b016dd65598ee69868a8 (diff) | |
download | chef-3166bd959316c6fdb54455607332bf80e8eed147.tar.gz |
Switch fileformat to unix, clean up whitespace.
Converts a few files from CRLF->LF.
Removes some trailing whitespace as well.
-rw-r--r-- | lib/chef/provider/dsc_script.rb | 6 | ||||
-rw-r--r-- | lib/chef/util/dsc/configuration_generator.rb | 2 | ||||
-rw-r--r-- | lib/chef/util/dsc/lcm_output_parser.rb | 10 | ||||
-rw-r--r-- | lib/chef/util/path_helper.rb | 4 | ||||
-rw-r--r-- | lib/chef/util/powershell/cmdlet.rb | 2 | ||||
-rw-r--r-- | lib/chef/util/powershell/cmdlet_result.rb | 4 | ||||
-rw-r--r-- | spec/functional/resource/dsc_script_spec.rb | 672 | ||||
-rw-r--r-- | spec/functional/util/powershell/cmdlet_spec.rb | 228 | ||||
-rw-r--r-- | spec/unit/provider/dsc_script_spec.rb | 6 | ||||
-rw-r--r-- | spec/unit/util/dsc/configuration_generator_spec.rb | 2 | ||||
-rw-r--r-- | spec/unit/util/dsc/local_configuration_manager_spec.rb | 268 |
11 files changed, 602 insertions, 602 deletions
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb index d296e09c23..5d7322842c 100644 --- a/lib/chef/provider/dsc_script.rb +++ b/lib/chef/provider/dsc_script.rb @@ -28,10 +28,10 @@ class Chef @dsc_resource = dsc_resource @resource_converged = false @operations = { - :set => Proc.new { |config_manager, document| + :set => Proc.new { |config_manager, document| config_manager.set_configuration(document) }, - :test => Proc.new { |config_manager, document| + :test => Proc.new { |config_manager, document| config_manager.test_configuration(document) }} end @@ -131,7 +131,7 @@ class Chef private def generate_description - ["converge DSC configuration '#{configuration_friendly_name}'"] + + ["converge DSC configuration '#{configuration_friendly_name}'"] + @dsc_resources_info.map do |resource| if resource.changes_state? # We ignore the last log message because it only contains the time it took, which looks weird diff --git a/lib/chef/util/dsc/configuration_generator.rb b/lib/chef/util/dsc/configuration_generator.rb index 9f8c0e7309..12cd5dc3a2 100644 --- a/lib/chef/util/dsc/configuration_generator.rb +++ b/lib/chef/util/dsc/configuration_generator.rb @@ -37,7 +37,7 @@ class Chef::Util::DSC def configuration_document_from_script_path(script_path, configuration_name, configuration_flags, shellout_flags) validate_configuration_name!(configuration_name) - + document_generation_cmdlet = Chef::Util::Powershell::Cmdlet.new( @node, configuration_document_generation_code(script_path, configuration_name)) diff --git a/lib/chef/util/dsc/lcm_output_parser.rb b/lib/chef/util/dsc/lcm_output_parser.rb index 6532d79d6f..91181b3089 100644 --- a/lib/chef/util/dsc/lcm_output_parser.rb +++ b/lib/chef/util/dsc/lcm_output_parser.rb @@ -64,7 +64,7 @@ class Chef # Parses the output from LCM and returns a list of Chef::Util::DSC::ResourceInfo objects # that describe how the resources affected the system - # + # # Example: # parse <<-EOF # What if: [Machine]: LCM: [Start Set ] @@ -80,11 +80,11 @@ class Chef # # [ # Chef::Util::DSC::ResourceInfo.new( - # '[[File]FileToNotBeThere]', - # true, + # '[[File]FileToNotBeThere]', + # true, # [ - # '[[File]FileToNotBeThere]', - # '[C:\Shouldnotexist.txt]', + # '[[File]FileToNotBeThere]', + # '[C:\Shouldnotexist.txt]', # '[[File]FileToNotBeThere] in 0.1 seconds' # ] # ) diff --git a/lib/chef/util/path_helper.rb b/lib/chef/util/path_helper.rb index 534a9087ae..1c8f6f5d08 100644 --- a/lib/chef/util/path_helper.rb +++ b/lib/chef/util/path_helper.rb @@ -32,7 +32,7 @@ class Chef Chef::Log.error(msg) raise Chef::Exceptions::ValidationFailed, msg end - + if windows_max_length_exceeded?(path) Chef::Log.debug("Path '#{path}' is longer than #{WIN_MAX_PATH}, prefixing with'\\\\?\\'") path.insert(0, "\\\\?\\") @@ -50,7 +50,7 @@ class Chef return true end end - + false end diff --git a/lib/chef/util/powershell/cmdlet.rb b/lib/chef/util/powershell/cmdlet.rb index f99812dc24..40edbb13c6 100644 --- a/lib/chef/util/powershell/cmdlet.rb +++ b/lib/chef/util/powershell/cmdlet.rb @@ -131,6 +131,6 @@ class Chef::Util::Powershell command_switches.join(' ') end - end + end end diff --git a/lib/chef/util/powershell/cmdlet_result.rb b/lib/chef/util/powershell/cmdlet_result.rb index 696013e684..af7b3607cd 100644 --- a/lib/chef/util/powershell/cmdlet_result.rb +++ b/lib/chef/util/powershell/cmdlet_result.rb @@ -20,13 +20,13 @@ require 'json' class Chef::Util::Powershell class CmdletResult - attr_reader :output_format + attr_reader :output_format def initialize(status, output_format) @status = status @output_format = output_format end - + def stderr @status.stderr end diff --git a/spec/functional/resource/dsc_script_spec.rb b/spec/functional/resource/dsc_script_spec.rb index 79917c01df..2aa1f35772 100644 --- a/spec/functional/resource/dsc_script_spec.rb +++ b/spec/functional/resource/dsc_script_spec.rb @@ -1,336 +1,336 @@ -#
-# Author:: Adam Edwards (<adamed@getchef.com>)
-# Copyright:: Copyright (c) 2014 Chef Software, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-require 'chef/mixin/shell_out'
-require 'chef/mixin/windows_architecture_helper'
-
-describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
- include Chef::Mixin::WindowsArchitectureHelper
- before(:all) do
- @temp_dir = ::Dir.mktmpdir("dsc-functional-test")
- end
-
- after(:all) do
- ::FileUtils.rm_rf(@temp_dir) if ::Dir.exist?(@temp_dir)
- end
-
- include Chef::Mixin::ShellOut
-
- def create_config_script_from_code(code, configuration_name, data = false)
- script_code = data ? code : "Configuration '#{configuration_name}'\n{\n\t#{code}\n}\n"
- data_suffix = data ? '_config_data' : ''
- extension = data ? 'psd1' : 'ps1'
- script_path = "#{@temp_dir}/dsc_functional_test#{data_suffix}.#{extension}"
- ::File.open(script_path, 'wt') do | script |
- script.write(script_code)
- end
- script_path
- end
-
- def user_exists?(target_user)
- result = false
- begin
- shell_out!("net user #{target_user}")
- result = true
- rescue Mixlib::ShellOut::ShellCommandFailed
- end
- result
- end
-
- def delete_user(target_user)
- begin
- shell_out!("net user #{target_user} /delete")
- rescue Mixlib::ShellOut::ShellCommandFailed
- end
- end
-
- let(:dsc_env_variable) { 'chefenvtest' }
- let(:dsc_env_value1) { 'value1' }
- let(:env_value2) { 'value2' }
- let(:dsc_test_run_context) {
- node = Chef::Node.new
- node.default['platform'] = 'windows'
- node.default['platform_version'] = '6.1'
- node.default['kernel'][:machine] =
- is_i386_process_on_x86_64_windows? ? :x86_64 : :i386
- empty_events = Chef::EventDispatch::Dispatcher.new
- Chef::RunContext.new(node, {}, empty_events)
- }
- let(:dsc_test_resource_name) { 'DSCTest' }
- let(:dsc_test_resource_base) {
- Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
- }
- let(:test_registry_key) { 'HKEY_LOCAL_MACHINE\Software\Chef\Spec\Functional\Resource\dsc_script_spec' }
- let(:test_registry_value) { 'Registration' }
- let(:test_registry_data1) { 'LL927' }
- let(:test_registry_data2) { 'LL928' }
- let(:dsc_code) { <<-EOH
- Registry "ChefRegKey"
- {
- Key = '#{test_registry_key}'
- ValueName = '#{test_registry_value}'
- ValueData = '#{test_registry_data}'
- Ensure = 'Present'
- }
-EOH
- }
-
- let(:dsc_user_prefix) { 'dsc' }
- let(:dsc_user_suffix) { 'chefx' }
- let(:dsc_user) {"#{dsc_user_prefix}_usr_#{dsc_user_suffix}" }
- let(:dsc_user_prefix_env_var_name) { 'dsc_user_env_prefix' }
- let(:dsc_user_suffix_env_var_name) { 'dsc_user_env_suffix' }
- let(:dsc_user_prefix_env_code) { "$env:#{dsc_user_prefix_env_var_name}"}
- let(:dsc_user_suffix_env_code) { "$env:#{dsc_user_suffix_env_var_name}"}
- let(:dsc_user_prefix_param_name) { 'dsc_user_prefix_param' }
- let(:dsc_user_suffix_param_name) { 'dsc_user_suffix_param' }
- let(:dsc_user_prefix_param_code) { "$#{dsc_user_prefix_param_name}"}
- let(:dsc_user_suffix_param_code) { "$#{dsc_user_suffix_param_name}"}
- let(:dsc_user_env_code) { "\"$(#{dsc_user_prefix_env_code})_usr_$(#{dsc_user_suffix_env_code})\""}
- let(:dsc_user_param_code) { "\"$(#{dsc_user_prefix_param_code})_usr_$(#{dsc_user_suffix_param_code})\""}
-
- let(:config_flags) { nil }
- let(:config_params) { <<-EOH
-
- [CmdletBinding()]
- param
- (
- $#{dsc_user_prefix_param_name},
- $#{dsc_user_suffix_param_name}
- )
-EOH
- }
-
- let(:config_param_section) { '' }
- let(:dsc_user_code) { "'#{dsc_user}'" }
- let(:dsc_user_prefix_code) { dsc_user_prefix }
- let(:dsc_user_suffix_code) { dsc_user_suffix }
- let(:dsc_script_environment_attribute) { nil }
- let(:dsc_user_resources_code) { <<-EOH
- #{config_param_section}
-node localhost
-{
-$testuser = #{dsc_user_code}
-$testpassword = ConvertTo-SecureString -String "jf9a8m49jrajf4#" -AsPlainText -Force
-$testcred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $testuser, $testpassword
-
-User dsctestusercreate
-{
- UserName = $testuser
- Password = $testcred
- Description = "DSC test user"
- Ensure = "Present"
- Disabled = $false
- PasswordNeverExpires = $true
- PasswordChangeRequired = $false
-}
-}
-EOH
- }
-
- let(:dsc_user_config_data) {
-<<-EOH
-@{
- AllNodes = @(
- @{
- NodeName = "localhost";
- PSDscAllowPlainTextPassword = $true
- }
- )
-}
-
-EOH
- }
-
- let(:dsc_environment_env_var_name) { 'dsc_test_cwd' }
- let(:dsc_environment_no_fail_not_etc_directory) { "#{ENV['systemroot']}\\system32" }
- let(:dsc_environment_fail_etc_directory) { "#{ENV['systemroot']}\\system32\\drivers\\etc" }
- let(:exception_message_signature) { 'LL927-LL928' }
- let(:dsc_environment_config) {<<-EOH
-if (($pwd.path -eq '#{dsc_environment_fail_etc_directory}') -and (test-path('#{dsc_environment_fail_etc_directory}')))
-{
- throw 'Signature #{exception_message_signature}: Purposefully failing because cwd == #{dsc_environment_fail_etc_directory}'
-}
-environment "whatsmydir"
-{
- Name = '#{dsc_environment_env_var_name}'
- Value = $pwd.path
- Ensure = 'Present'
-}
-EOH
- }
-
- let(:dsc_config_name) {
- dsc_test_resource_base.name
- }
- let(:dsc_resource_from_code) {
- dsc_test_resource_base.code(dsc_code)
- dsc_test_resource_base
- }
- let(:config_name_value) { dsc_test_resource_base.name }
-
- let(:dsc_resource_from_path) {
- dsc_test_resource_base.command(create_config_script_from_code(dsc_code, config_name_value))
- dsc_test_resource_base
- }
-
- before(:each) do
- test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context)
- test_key_resource.recursive(true)
- test_key_resource.run_action(:delete_key)
- end
-
- after(:each) do
- test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context)
- test_key_resource.recursive(true)
- test_key_resource.run_action(:delete_key)
- end
-
- shared_examples_for 'a dsc_script resource with specified PowerShell configuration code' do
- let(:test_registry_data) { test_registry_data1 }
- it 'should create a registry key with a specific registry value and data' do
- expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(false)
- dsc_test_resource.run_action(:run)
- expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(true)
- expect(dsc_test_resource.registry_value_exists?(test_registry_key, {:name => test_registry_value, :type => :string, :data => test_registry_data})).to eq(true)
- end
-
- it_should_behave_like 'a dsc_script resource with configuration affected by cwd'
- end
-
- shared_examples_for 'a dsc_script resource with configuration affected by cwd' do
- after(:each) do
- removal_resource = Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
- removal_resource.code <<-EOH
-environment 'removethis'
-{
- Name = '#{dsc_environment_env_var_name}'
- Ensure = 'Absent'
-}
-EOH
- removal_resource.run_action(:run)
- end
- let(:dsc_code) { dsc_environment_config }
- it 'should not raise an exception if the cwd is not etc' do
- dsc_test_resource.cwd(dsc_environment_no_fail_not_etc_directory)
- expect {dsc_test_resource.run_action(:run)}.not_to raise_error
- end
-
- it 'should raise an exception if the cwd is etc' do
- dsc_test_resource.cwd(dsc_environment_fail_etc_directory)
- expect {dsc_test_resource.run_action(:run)}.to raise_error(Chef::Exceptions::PowershellCmdletException)
- begin
- dsc_test_resource.run_action(:run)
- rescue Chef::Exceptions::PowershellCmdletException => e
- expect(e.message).to match(exception_message_signature)
- end
- end
- end
-
- shared_examples_for 'a parameterized DSC configuration script' do
- context 'when specifying environment variables in the environment attribute' do
- let(:dsc_user_prefix_code) { dsc_user_prefix_env_code }
- let(:dsc_user_suffix_code) { dsc_user_suffix_env_code }
- it_behaves_like 'a dsc_script with configuration that uses environment variables'
- end
- end
-
- shared_examples_for 'a dsc_script with configuration data' do
- context 'when using the configuration_data attribute' do
- let(:configuration_data_attribute) { 'configuration_data' }
- it_behaves_like 'a dsc_script with configuration data set via an attribute'
- end
-
- context 'when using the configuration_data_script attribute' do
- let(:configuration_data_attribute) { 'configuration_data_script' }
- it_behaves_like 'a dsc_script with configuration data set via an attribute'
- end
- end
-
- shared_examples_for 'a dsc_script with configuration data set via an attribute' do
- it 'should run a configuration script that creates a user' do
- config_data_value = dsc_user_config_data
- dsc_test_resource.configuration_name(config_name_value)
- if configuration_data_attribute == 'configuration_data_script'
- config_data_value = create_config_script_from_code(dsc_user_config_data, '', true)
- end
- dsc_test_resource.environment({dsc_user_prefix_env_var_name => dsc_user_prefix,
- dsc_user_suffix_env_var_name => dsc_user_suffix})
- dsc_test_resource.send(configuration_data_attribute, config_data_value)
- dsc_test_resource.flags(config_flags)
- expect(user_exists?(dsc_user)).to eq(false)
- expect {dsc_test_resource.run_action(:run)}.not_to raise_error
- expect(user_exists?(dsc_user)).to eq(true)
- end
- end
-
- shared_examples_for 'a dsc_script with configuration data that takes parameters' do
- context 'when script code takes parameters for configuration' do
- let(:dsc_user_code) { dsc_user_param_code }
- let(:config_param_section) { config_params }
- let(:config_flags) {{:"#{dsc_user_prefix_param_name}" => "#{dsc_user_prefix}", :"#{dsc_user_suffix_param_name}" => "#{dsc_user_suffix}"}}
- it 'does not directly contain the user name' do
- configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
- file.read
- end
- expect(configuration_script_content.include?(dsc_user)).to be(false)
- end
- it_behaves_like 'a dsc_script with configuration data'
- end
-
- end
-
- shared_examples_for 'a dsc_script with configuration data that uses environment variables' do
- context 'when script code uses environment variables' do
- let(:dsc_user_code) { dsc_user_env_code }
-
- it 'does not directly contain the user name' do
- configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
- file.read
- end
- expect(configuration_script_content.include?(dsc_user)).to be(false)
- end
- it_behaves_like 'a dsc_script with configuration data'
- end
- end
-
- context 'when supplying configuration through the configuration attribute' do
- let(:dsc_test_resource) { dsc_resource_from_code }
- it_behaves_like 'a dsc_script resource with specified PowerShell configuration code'
- end
-
- context 'when supplying configuration using the path attribute' do
- let(:dsc_test_resource) { dsc_resource_from_path }
- it_behaves_like 'a dsc_script resource with specified PowerShell configuration code'
- end
-
- context 'when running a configuration that manages users' do
- before(:each) do
- delete_user(dsc_user)
- end
-
- let(:dsc_code) { dsc_user_resources_code }
- let(:config_name_value) { 'DSCTestConfig' }
- let(:dsc_test_resource) { dsc_resource_from_path }
-
- it_behaves_like 'a dsc_script with configuration data'
- it_behaves_like 'a dsc_script with configuration data that uses environment variables'
- it_behaves_like 'a dsc_script with configuration data that takes parameters'
- end
-end
+# +# Author:: Adam Edwards (<adamed@getchef.com>) +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'spec_helper' +require 'chef/mixin/shell_out' +require 'chef/mixin/windows_architecture_helper' + +describe Chef::Resource::DscScript, :windows_powershell_dsc_only do + include Chef::Mixin::WindowsArchitectureHelper + before(:all) do + @temp_dir = ::Dir.mktmpdir("dsc-functional-test") + end + + after(:all) do + ::FileUtils.rm_rf(@temp_dir) if ::Dir.exist?(@temp_dir) + end + + include Chef::Mixin::ShellOut + + def create_config_script_from_code(code, configuration_name, data = false) + script_code = data ? code : "Configuration '#{configuration_name}'\n{\n\t#{code}\n}\n" + data_suffix = data ? '_config_data' : '' + extension = data ? 'psd1' : 'ps1' + script_path = "#{@temp_dir}/dsc_functional_test#{data_suffix}.#{extension}" + ::File.open(script_path, 'wt') do | script | + script.write(script_code) + end + script_path + end + + def user_exists?(target_user) + result = false + begin + shell_out!("net user #{target_user}") + result = true + rescue Mixlib::ShellOut::ShellCommandFailed + end + result + end + + def delete_user(target_user) + begin + shell_out!("net user #{target_user} /delete") + rescue Mixlib::ShellOut::ShellCommandFailed + end + end + + let(:dsc_env_variable) { 'chefenvtest' } + let(:dsc_env_value1) { 'value1' } + let(:env_value2) { 'value2' } + let(:dsc_test_run_context) { + node = Chef::Node.new + node.default['platform'] = 'windows' + node.default['platform_version'] = '6.1' + node.default['kernel'][:machine] = + is_i386_process_on_x86_64_windows? ? :x86_64 : :i386 + empty_events = Chef::EventDispatch::Dispatcher.new + Chef::RunContext.new(node, {}, empty_events) + } + let(:dsc_test_resource_name) { 'DSCTest' } + let(:dsc_test_resource_base) { + Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context) + } + let(:test_registry_key) { 'HKEY_LOCAL_MACHINE\Software\Chef\Spec\Functional\Resource\dsc_script_spec' } + let(:test_registry_value) { 'Registration' } + let(:test_registry_data1) { 'LL927' } + let(:test_registry_data2) { 'LL928' } + let(:dsc_code) { <<-EOH + Registry "ChefRegKey" + { + Key = '#{test_registry_key}' + ValueName = '#{test_registry_value}' + ValueData = '#{test_registry_data}' + Ensure = 'Present' + } +EOH + } + + let(:dsc_user_prefix) { 'dsc' } + let(:dsc_user_suffix) { 'chefx' } + let(:dsc_user) {"#{dsc_user_prefix}_usr_#{dsc_user_suffix}" } + let(:dsc_user_prefix_env_var_name) { 'dsc_user_env_prefix' } + let(:dsc_user_suffix_env_var_name) { 'dsc_user_env_suffix' } + let(:dsc_user_prefix_env_code) { "$env:#{dsc_user_prefix_env_var_name}"} + let(:dsc_user_suffix_env_code) { "$env:#{dsc_user_suffix_env_var_name}"} + let(:dsc_user_prefix_param_name) { 'dsc_user_prefix_param' } + let(:dsc_user_suffix_param_name) { 'dsc_user_suffix_param' } + let(:dsc_user_prefix_param_code) { "$#{dsc_user_prefix_param_name}"} + let(:dsc_user_suffix_param_code) { "$#{dsc_user_suffix_param_name}"} + let(:dsc_user_env_code) { "\"$(#{dsc_user_prefix_env_code})_usr_$(#{dsc_user_suffix_env_code})\""} + let(:dsc_user_param_code) { "\"$(#{dsc_user_prefix_param_code})_usr_$(#{dsc_user_suffix_param_code})\""} + + let(:config_flags) { nil } + let(:config_params) { <<-EOH + + [CmdletBinding()] + param + ( + $#{dsc_user_prefix_param_name}, + $#{dsc_user_suffix_param_name} + ) +EOH + } + + let(:config_param_section) { '' } + let(:dsc_user_code) { "'#{dsc_user}'" } + let(:dsc_user_prefix_code) { dsc_user_prefix } + let(:dsc_user_suffix_code) { dsc_user_suffix } + let(:dsc_script_environment_attribute) { nil } + let(:dsc_user_resources_code) { <<-EOH + #{config_param_section} +node localhost +{ +$testuser = #{dsc_user_code} +$testpassword = ConvertTo-SecureString -String "jf9a8m49jrajf4#" -AsPlainText -Force +$testcred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $testuser, $testpassword + +User dsctestusercreate +{ + UserName = $testuser + Password = $testcred + Description = "DSC test user" + Ensure = "Present" + Disabled = $false + PasswordNeverExpires = $true + PasswordChangeRequired = $false +} +} +EOH + } + + let(:dsc_user_config_data) { +<<-EOH +@{ + AllNodes = @( + @{ + NodeName = "localhost"; + PSDscAllowPlainTextPassword = $true + } + ) +} + +EOH + } + + let(:dsc_environment_env_var_name) { 'dsc_test_cwd' } + let(:dsc_environment_no_fail_not_etc_directory) { "#{ENV['systemroot']}\\system32" } + let(:dsc_environment_fail_etc_directory) { "#{ENV['systemroot']}\\system32\\drivers\\etc" } + let(:exception_message_signature) { 'LL927-LL928' } + let(:dsc_environment_config) {<<-EOH +if (($pwd.path -eq '#{dsc_environment_fail_etc_directory}') -and (test-path('#{dsc_environment_fail_etc_directory}'))) +{ + throw 'Signature #{exception_message_signature}: Purposefully failing because cwd == #{dsc_environment_fail_etc_directory}' +} +environment "whatsmydir" +{ + Name = '#{dsc_environment_env_var_name}' + Value = $pwd.path + Ensure = 'Present' +} +EOH + } + + let(:dsc_config_name) { + dsc_test_resource_base.name + } + let(:dsc_resource_from_code) { + dsc_test_resource_base.code(dsc_code) + dsc_test_resource_base + } + let(:config_name_value) { dsc_test_resource_base.name } + + let(:dsc_resource_from_path) { + dsc_test_resource_base.command(create_config_script_from_code(dsc_code, config_name_value)) + dsc_test_resource_base + } + + before(:each) do + test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context) + test_key_resource.recursive(true) + test_key_resource.run_action(:delete_key) + end + + after(:each) do + test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context) + test_key_resource.recursive(true) + test_key_resource.run_action(:delete_key) + end + + shared_examples_for 'a dsc_script resource with specified PowerShell configuration code' do + let(:test_registry_data) { test_registry_data1 } + it 'should create a registry key with a specific registry value and data' do + expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(false) + dsc_test_resource.run_action(:run) + expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(true) + expect(dsc_test_resource.registry_value_exists?(test_registry_key, {:name => test_registry_value, :type => :string, :data => test_registry_data})).to eq(true) + end + + it_should_behave_like 'a dsc_script resource with configuration affected by cwd' + end + + shared_examples_for 'a dsc_script resource with configuration affected by cwd' do + after(:each) do + removal_resource = Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context) + removal_resource.code <<-EOH +environment 'removethis' +{ + Name = '#{dsc_environment_env_var_name}' + Ensure = 'Absent' +} +EOH + removal_resource.run_action(:run) + end + let(:dsc_code) { dsc_environment_config } + it 'should not raise an exception if the cwd is not etc' do + dsc_test_resource.cwd(dsc_environment_no_fail_not_etc_directory) + expect {dsc_test_resource.run_action(:run)}.not_to raise_error + end + + it 'should raise an exception if the cwd is etc' do + dsc_test_resource.cwd(dsc_environment_fail_etc_directory) + expect {dsc_test_resource.run_action(:run)}.to raise_error(Chef::Exceptions::PowershellCmdletException) + begin + dsc_test_resource.run_action(:run) + rescue Chef::Exceptions::PowershellCmdletException => e + expect(e.message).to match(exception_message_signature) + end + end + end + + shared_examples_for 'a parameterized DSC configuration script' do + context 'when specifying environment variables in the environment attribute' do + let(:dsc_user_prefix_code) { dsc_user_prefix_env_code } + let(:dsc_user_suffix_code) { dsc_user_suffix_env_code } + it_behaves_like 'a dsc_script with configuration that uses environment variables' + end + end + + shared_examples_for 'a dsc_script with configuration data' do + context 'when using the configuration_data attribute' do + let(:configuration_data_attribute) { 'configuration_data' } + it_behaves_like 'a dsc_script with configuration data set via an attribute' + end + + context 'when using the configuration_data_script attribute' do + let(:configuration_data_attribute) { 'configuration_data_script' } + it_behaves_like 'a dsc_script with configuration data set via an attribute' + end + end + + shared_examples_for 'a dsc_script with configuration data set via an attribute' do + it 'should run a configuration script that creates a user' do + config_data_value = dsc_user_config_data + dsc_test_resource.configuration_name(config_name_value) + if configuration_data_attribute == 'configuration_data_script' + config_data_value = create_config_script_from_code(dsc_user_config_data, '', true) + end + dsc_test_resource.environment({dsc_user_prefix_env_var_name => dsc_user_prefix, + dsc_user_suffix_env_var_name => dsc_user_suffix}) + dsc_test_resource.send(configuration_data_attribute, config_data_value) + dsc_test_resource.flags(config_flags) + expect(user_exists?(dsc_user)).to eq(false) + expect {dsc_test_resource.run_action(:run)}.not_to raise_error + expect(user_exists?(dsc_user)).to eq(true) + end + end + + shared_examples_for 'a dsc_script with configuration data that takes parameters' do + context 'when script code takes parameters for configuration' do + let(:dsc_user_code) { dsc_user_param_code } + let(:config_param_section) { config_params } + let(:config_flags) {{:"#{dsc_user_prefix_param_name}" => "#{dsc_user_prefix}", :"#{dsc_user_suffix_param_name}" => "#{dsc_user_suffix}"}} + it 'does not directly contain the user name' do + configuration_script_content = ::File.open(dsc_test_resource.command) do | file | + file.read + end + expect(configuration_script_content.include?(dsc_user)).to be(false) + end + it_behaves_like 'a dsc_script with configuration data' + end + + end + + shared_examples_for 'a dsc_script with configuration data that uses environment variables' do + context 'when script code uses environment variables' do + let(:dsc_user_code) { dsc_user_env_code } + + it 'does not directly contain the user name' do + configuration_script_content = ::File.open(dsc_test_resource.command) do | file | + file.read + end + expect(configuration_script_content.include?(dsc_user)).to be(false) + end + it_behaves_like 'a dsc_script with configuration data' + end + end + + context 'when supplying configuration through the configuration attribute' do + let(:dsc_test_resource) { dsc_resource_from_code } + it_behaves_like 'a dsc_script resource with specified PowerShell configuration code' + end + + context 'when supplying configuration using the path attribute' do + let(:dsc_test_resource) { dsc_resource_from_path } + it_behaves_like 'a dsc_script resource with specified PowerShell configuration code' + end + + context 'when running a configuration that manages users' do + before(:each) do + delete_user(dsc_user) + end + + let(:dsc_code) { dsc_user_resources_code } + let(:config_name_value) { 'DSCTestConfig' } + let(:dsc_test_resource) { dsc_resource_from_path } + + it_behaves_like 'a dsc_script with configuration data' + it_behaves_like 'a dsc_script with configuration data that uses environment variables' + it_behaves_like 'a dsc_script with configuration data that takes parameters' + end +end diff --git a/spec/functional/util/powershell/cmdlet_spec.rb b/spec/functional/util/powershell/cmdlet_spec.rb index 71ad49d5f1..63d1ac09b5 100644 --- a/spec/functional/util/powershell/cmdlet_spec.rb +++ b/spec/functional/util/powershell/cmdlet_spec.rb @@ -1,114 +1,114 @@ -#
-# Author:: Adam Edwards (<adamed@getchef.com>)
-#
-# Copyright:: 2014, Chef Software, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'json'
-require File.expand_path('../../../../spec_helper', __FILE__)
-
-describe Chef::Util::Powershell::Cmdlet, :windows_only do
- before(:all) do
- ohai = Ohai::System.new
- ohai.load_plugins
- ohai.run_plugins(true, ['platform', 'kernel'])
- @node = Chef::Node.new
- @node.consume_external_attrs(ohai.data, {})
- end
- let(:cmd_output_format) { :text }
- let(:simple_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-childitem', cmd_output_format, {:depth => 2}) }
- let(:invalid_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-idontexist', cmd_output_format) }
- let(:cmdlet_get_item_requires_switch_or_argument) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-item', cmd_output_format, {:depth => 2}) }
- let(:cmdlet_alias_requires_switch_or_argument) { Chef::Util::Powershell::Cmdlet.new(@node, 'alias', cmd_output_format, {:depth => 2}) }
- let(:etc_directory) { "#{ENV['systemroot']}\\system32\\drivers\\etc" }
- let(:architecture_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, "$env:PROCESSOR_ARCHITECTURE")}
-
- it "executes a simple process" do
- result = simple_cmdlet.run
- expect(result.succeeded?).to eq(true)
- end
-
- it "#run does not raise a PowershellCmdletException exception if the command cannot be executed" do
- expect {invalid_cmdlet.run}.not_to raise_error
- end
-
- it "#run! raises a PowershellCmdletException exception if the command cannot be executed" do
- expect {invalid_cmdlet.run!}.to raise_error(Chef::Exceptions::PowershellCmdletException)
- end
-
- it "executes a 64-bit command on a 64-bit OS, 32-bit otherwise" do
- os_arch = ENV['PROCESSOR_ARCHITEW6432']
- if os_arch.nil?
- os_arch = ENV['PROCESSOR_ARCHITECTURE']
- end
-
- result = architecture_cmdlet.run
- execution_arch = result.return_value
- execution_arch.strip!
- expect(execution_arch).to eq(os_arch)
- end
-
- it "passes command line switches to the command" do
- result = cmdlet_alias_requires_switch_or_argument.run({:name => 'ls'})
- expect(result.succeeded?).to eq(true)
- end
-
- it "passes command line arguments to the command" do
- result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls')
- expect(result.succeeded?).to eq(true)
- end
-
- it "passes command line arguments and switches to the command" do
- result = cmdlet_get_item_requires_switch_or_argument.run({:path => etc_directory},{},' | select-object -property fullname | format-table -hidetableheaders')
- expect(result.succeeded?).to eq(true)
- returned_directory = result.return_value
- returned_directory.strip!
- expect(returned_directory).to eq(etc_directory)
- end
-
- it "passes execution options to the command" do
- result = cmdlet_get_item_requires_switch_or_argument.run({},{:cwd => etc_directory},'. | select-object -property fullname | format-table -hidetableheaders')
- expect(result.succeeded?).to eq(true)
- returned_directory = result.return_value
- returned_directory.strip!
- expect(returned_directory).to eq(etc_directory)
- end
-
- context "when returning json" do
- let(:cmd_output_format) { :json }
- it "returns json format data", :windows_powershell_dsc_only do
- result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls')
- expect(result.succeeded?).to eq(true)
- expect(lambda{JSON.parse(result.return_value)}).not_to raise_error
- end
- end
-
- context "when returning Ruby objects" do
- let(:cmd_output_format) { :object }
- it "returns object format data", :windows_powershell_dsc_only do
- result = simple_cmdlet.run({},{:cwd => etc_directory}, 'hosts')
- expect(result.succeeded?).to eq(true)
- data = result.return_value
- expect(data['Name']).to eq('hosts')
- end
- end
-
- context "when constructor is given invalid arguments" do
- let(:cmd_output_format) { :invalid }
- it "throws an exception if an invalid format is passed to the constructor" do
- expect(lambda{simple_cmdlet}).to raise_error
- end
- end
-end
+# +# Author:: Adam Edwards (<adamed@getchef.com>) +# +# Copyright:: 2014, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'json' +require File.expand_path('../../../../spec_helper', __FILE__) + +describe Chef::Util::Powershell::Cmdlet, :windows_only do + before(:all) do + ohai = Ohai::System.new + ohai.load_plugins + ohai.run_plugins(true, ['platform', 'kernel']) + @node = Chef::Node.new + @node.consume_external_attrs(ohai.data, {}) + end + let(:cmd_output_format) { :text } + let(:simple_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-childitem', cmd_output_format, {:depth => 2}) } + let(:invalid_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-idontexist', cmd_output_format) } + let(:cmdlet_get_item_requires_switch_or_argument) { Chef::Util::Powershell::Cmdlet.new(@node, 'get-item', cmd_output_format, {:depth => 2}) } + let(:cmdlet_alias_requires_switch_or_argument) { Chef::Util::Powershell::Cmdlet.new(@node, 'alias', cmd_output_format, {:depth => 2}) } + let(:etc_directory) { "#{ENV['systemroot']}\\system32\\drivers\\etc" } + let(:architecture_cmdlet) { Chef::Util::Powershell::Cmdlet.new(@node, "$env:PROCESSOR_ARCHITECTURE")} + + it "executes a simple process" do + result = simple_cmdlet.run + expect(result.succeeded?).to eq(true) + end + + it "#run does not raise a PowershellCmdletException exception if the command cannot be executed" do + expect {invalid_cmdlet.run}.not_to raise_error + end + + it "#run! raises a PowershellCmdletException exception if the command cannot be executed" do + expect {invalid_cmdlet.run!}.to raise_error(Chef::Exceptions::PowershellCmdletException) + end + + it "executes a 64-bit command on a 64-bit OS, 32-bit otherwise" do + os_arch = ENV['PROCESSOR_ARCHITEW6432'] + if os_arch.nil? + os_arch = ENV['PROCESSOR_ARCHITECTURE'] + end + + result = architecture_cmdlet.run + execution_arch = result.return_value + execution_arch.strip! + expect(execution_arch).to eq(os_arch) + end + + it "passes command line switches to the command" do + result = cmdlet_alias_requires_switch_or_argument.run({:name => 'ls'}) + expect(result.succeeded?).to eq(true) + end + + it "passes command line arguments to the command" do + result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls') + expect(result.succeeded?).to eq(true) + end + + it "passes command line arguments and switches to the command" do + result = cmdlet_get_item_requires_switch_or_argument.run({:path => etc_directory},{},' | select-object -property fullname | format-table -hidetableheaders') + expect(result.succeeded?).to eq(true) + returned_directory = result.return_value + returned_directory.strip! + expect(returned_directory).to eq(etc_directory) + end + + it "passes execution options to the command" do + result = cmdlet_get_item_requires_switch_or_argument.run({},{:cwd => etc_directory},'. | select-object -property fullname | format-table -hidetableheaders') + expect(result.succeeded?).to eq(true) + returned_directory = result.return_value + returned_directory.strip! + expect(returned_directory).to eq(etc_directory) + end + + context "when returning json" do + let(:cmd_output_format) { :json } + it "returns json format data", :windows_powershell_dsc_only do + result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls') + expect(result.succeeded?).to eq(true) + expect(lambda{JSON.parse(result.return_value)}).not_to raise_error + end + end + + context "when returning Ruby objects" do + let(:cmd_output_format) { :object } + it "returns object format data", :windows_powershell_dsc_only do + result = simple_cmdlet.run({},{:cwd => etc_directory}, 'hosts') + expect(result.succeeded?).to eq(true) + data = result.return_value + expect(data['Name']).to eq('hosts') + end + end + + context "when constructor is given invalid arguments" do + let(:cmd_output_format) { :invalid } + it "throws an exception if an invalid format is passed to the constructor" do + expect(lambda{simple_cmdlet}).to raise_error + end + end +end diff --git a/spec/unit/provider/dsc_script_spec.rb b/spec/unit/provider/dsc_script_spec.rb index 8c9064a6c1..b0b4416a66 100644 --- a/spec/unit/provider/dsc_script_spec.rb +++ b/spec/unit/provider/dsc_script_spec.rb @@ -74,7 +74,7 @@ describe Chef::Provider::DscScript do describe '#generate_configuration_document' do # I think integration tests should cover these cases - + it 'uses configuration_document_from_script_path when a dsc script file is given' do @provider.stub(:load_current_resource) @resource.command("path_to_script") @@ -107,7 +107,7 @@ describe Chef::Provider::DscScript do dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something']) @provider.stub(:run_configuration).with(:test).and_return([dsc_resource_info]) @provider.stub(:run_configuration).with(:set) - + @provider.run_action(:run) @resource.should be_updated @@ -115,7 +115,7 @@ describe Chef::Provider::DscScript do it 'should not converge if the script is already converged' do @provider.stub(:run_configuration).with(:test).and_return([]) - + @provider.run_action(:run) @resource.should_not be_updated end diff --git a/spec/unit/util/dsc/configuration_generator_spec.rb b/spec/unit/util/dsc/configuration_generator_spec.rb index 1c6c57ac57..8fcc85a71c 100644 --- a/spec/unit/util/dsc/configuration_generator_spec.rb +++ b/spec/unit/util/dsc/configuration_generator_spec.rb @@ -141,7 +141,7 @@ describe Chef::Util::DSC::ConfigurationGenerator do it "should find the mof file" do # These tests seem way too implementation specific. Unfortunatly, File and Dir # need to be mocked because they are OS specific - + File.stub(:join) do |a, b| [a,b].join("++") end diff --git a/spec/unit/util/dsc/local_configuration_manager_spec.rb b/spec/unit/util/dsc/local_configuration_manager_spec.rb index 1b0d8b27db..fb6664bd40 100644 --- a/spec/unit/util/dsc/local_configuration_manager_spec.rb +++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb @@ -1,134 +1,134 @@ -#
-# Author:: Adam Edwards <adamed@getchef.com>
-# Copyright:: Copyright (c) 2014 Chef Software, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'chef'
-require 'chef/util/dsc/local_configuration_manager'
-
-describe Chef::Util::DSC::LocalConfigurationManager do
-
- let(:lcm) { Chef::Util::DSC::LocalConfigurationManager.new(nil, 'tmp') }
-
- let(:normal_lcm_output) { <<-EOH
-logtype: [machinename]: LCM: [ Start Set ]
-logtype: [machinename]: LCM: [ Start Resource ] [name]
-logtype: [machinename]: LCM: [ End Resource ] [name]
-logtype: [machinename]: LCM: [ End Set ]
-EOH
- }
-
- let(:no_whatif_lcm_output) { <<-EOH
-Start-DscConfiguration : A parameter cannot be found that matches parameter name 'whatif'.
-At line:1 char:123
-+ run-somecommand -whatif
-+ ~~~~~~~~
- + CategoryInfo : InvalidArgument: (:) [Start-DscConfiguration], ParameterBindingException
- + FullyQualifiedErrorId : NamedParameterNotFound,SomeCompany.SomeAssembly.Commands.RunSomeCommand
-EOH
- }
-
- let(:dsc_resource_import_failure_output) { <<-EOH
-PowerShell provider MSFT_xWebsite failed to execute Test-TargetResource functionality with error message: Please ensure that WebAdministration module is installed. + CategoryInfo : InvalidOperation: (:) [], CimException + FullyQualifiedErrorId : ProviderOperationExecutionFailure + PSComputerName : . PowerShell provider MSFT_xWebsite failed to execute Test-TargetResource functionality with error message: Please ensure that WebAdministration module is installed. + CategoryInfo : InvalidOperation: (:) [], CimException + FullyQualifiedErrorId : ProviderOperationExecutionFailure + PSComputerName : . The SendConfigurationApply function did not succeed. + CategoryInfo : NotSpecified: (root/Microsoft/...gurationManager:String) [], CimException + FullyQualifiedErrorId : MI RESULT 1 + PSComputerName : .
-EOH
- }
-
- let(:lcm_status) {
- double("LCM cmdlet status", :stderr => lcm_standard_error, :return_value => lcm_standard_output, :succeeded? => lcm_cmdlet_success)
- }
-
- describe 'test_configuration method invocation' do
- context 'when interacting with the LCM using a PowerShell cmdlet' do
- before(:each) do
- allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status)
- end
- context 'that returns successfully' do
- before(:each) do
- allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status)
- end
-
- let(:lcm_standard_output) { normal_lcm_output }
- let(:lcm_standard_error) { nil }
- let(:lcm_cmdlet_success) { true }
-
- it 'should successfully return resource information for normally formatted output when cmdlet the cmdlet succeeds' do
- test_configuration_result = lcm.test_configuration('config')
- expect(test_configuration_result.class).to be(Array)
- expect(test_configuration_result.length).to be > 0
- expect(Chef::Log).not_to receive(:warn)
- end
- end
-
- context 'that fails due to missing what-if switch in DSC resource cmdlet implementation' do
- let(:lcm_standard_output) { '' }
- let(:lcm_standard_error) { no_whatif_lcm_output }
- let(:lcm_cmdlet_success) { false }
-
- it 'should should return a (possibly empty) array of ResourceInfo instances' do
- expect(Chef::Log).to receive(:warn)
- test_configuration_result = nil
- expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error
- expect(test_configuration_result.class).to be(Array)
- end
- end
-
- context 'that fails due to a DSC resource not being imported before StartDSCConfiguration -whatif is executed' do
- let(:lcm_standard_output) { '' }
- let(:lcm_standard_error) { dsc_resource_import_failure_output }
- let(:lcm_cmdlet_success) { false }
-
- it 'should log a warning if the message is formatted as expected when a resource import failure occurs' do
- expect(Chef::Log).to receive(:warn)
- expect(lcm).to receive(:output_has_dsc_module_failure?).and_call_original
- test_configuration_result = nil
- expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error
- end
-
- it 'should return a (possibly empty) array of ResourceInfo instances' do
- expect(Chef::Log).to receive(:warn)
- test_configuration_result = nil
- expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error
- expect(test_configuration_result.class).to be(Array)
- end
- end
-
- context 'that fails due to an PowerShell cmdlet error that cannot be handled' do
- let(:lcm_standard_output) { 'some output' }
- let(:lcm_standard_error) { 'Abort, Retry, Fail?' }
- let(:lcm_cmdlet_success) { false }
-
- it 'should raise a Chef::Exceptions::PowershellCmdletException' do
- expect(Chef::Log).not_to receive(:warn)
- expect(lcm).to receive(:output_has_dsc_module_failure?).and_call_original
- expect {lcm.test_configuration('config')}.to raise_error(Chef::Exceptions::PowershellCmdletException)
- end
- end
- end
-
- it 'should identify a correctly formatted error message as a resource import failure' do
- expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output)).to be(true)
- end
-
- it 'should not identify an incorrectly formatted error message as a resource import failure' do
- expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output.gsub('module', 'gibberish'))).to be(false)
- end
-
- it 'should not identify a message without a CimException reference as a resource import failure' do
- expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output.gsub('CimException', 'ArgumentException'))).to be(false)
- end
- end
-end
-
+# +# Author:: Adam Edwards <adamed@getchef.com> +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef' +require 'chef/util/dsc/local_configuration_manager' + +describe Chef::Util::DSC::LocalConfigurationManager do + + let(:lcm) { Chef::Util::DSC::LocalConfigurationManager.new(nil, 'tmp') } + + let(:normal_lcm_output) { <<-EOH +logtype: [machinename]: LCM: [ Start Set ] +logtype: [machinename]: LCM: [ Start Resource ] [name] +logtype: [machinename]: LCM: [ End Resource ] [name] +logtype: [machinename]: LCM: [ End Set ] +EOH + } + + let(:no_whatif_lcm_output) { <<-EOH +Start-DscConfiguration : A parameter cannot be found that matches parameter name 'whatif'. +At line:1 char:123 ++ run-somecommand -whatif ++ ~~~~~~~~ + + CategoryInfo : InvalidArgument: (:) [Start-DscConfiguration], ParameterBindingException + + FullyQualifiedErrorId : NamedParameterNotFound,SomeCompany.SomeAssembly.Commands.RunSomeCommand +EOH + } + + let(:dsc_resource_import_failure_output) { <<-EOH +PowerShell provider MSFT_xWebsite failed to execute Test-TargetResource functionality with error message: Please ensure that WebAdministration module is installed. + CategoryInfo : InvalidOperation: (:) [], CimException + FullyQualifiedErrorId : ProviderOperationExecutionFailure + PSComputerName : . PowerShell provider MSFT_xWebsite failed to execute Test-TargetResource functionality with error message: Please ensure that WebAdministration module is installed. + CategoryInfo : InvalidOperation: (:) [], CimException + FullyQualifiedErrorId : ProviderOperationExecutionFailure + PSComputerName : . The SendConfigurationApply function did not succeed. + CategoryInfo : NotSpecified: (root/Microsoft/...gurationManager:String) [], CimException + FullyQualifiedErrorId : MI RESULT 1 + PSComputerName : . +EOH + } + + let(:lcm_status) { + double("LCM cmdlet status", :stderr => lcm_standard_error, :return_value => lcm_standard_output, :succeeded? => lcm_cmdlet_success) + } + + describe 'test_configuration method invocation' do + context 'when interacting with the LCM using a PowerShell cmdlet' do + before(:each) do + allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status) + end + context 'that returns successfully' do + before(:each) do + allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status) + end + + let(:lcm_standard_output) { normal_lcm_output } + let(:lcm_standard_error) { nil } + let(:lcm_cmdlet_success) { true } + + it 'should successfully return resource information for normally formatted output when cmdlet the cmdlet succeeds' do + test_configuration_result = lcm.test_configuration('config') + expect(test_configuration_result.class).to be(Array) + expect(test_configuration_result.length).to be > 0 + expect(Chef::Log).not_to receive(:warn) + end + end + + context 'that fails due to missing what-if switch in DSC resource cmdlet implementation' do + let(:lcm_standard_output) { '' } + let(:lcm_standard_error) { no_whatif_lcm_output } + let(:lcm_cmdlet_success) { false } + + it 'should should return a (possibly empty) array of ResourceInfo instances' do + expect(Chef::Log).to receive(:warn) + test_configuration_result = nil + expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error + expect(test_configuration_result.class).to be(Array) + end + end + + context 'that fails due to a DSC resource not being imported before StartDSCConfiguration -whatif is executed' do + let(:lcm_standard_output) { '' } + let(:lcm_standard_error) { dsc_resource_import_failure_output } + let(:lcm_cmdlet_success) { false } + + it 'should log a warning if the message is formatted as expected when a resource import failure occurs' do + expect(Chef::Log).to receive(:warn) + expect(lcm).to receive(:output_has_dsc_module_failure?).and_call_original + test_configuration_result = nil + expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error + end + + it 'should return a (possibly empty) array of ResourceInfo instances' do + expect(Chef::Log).to receive(:warn) + test_configuration_result = nil + expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error + expect(test_configuration_result.class).to be(Array) + end + end + + context 'that fails due to an PowerShell cmdlet error that cannot be handled' do + let(:lcm_standard_output) { 'some output' } + let(:lcm_standard_error) { 'Abort, Retry, Fail?' } + let(:lcm_cmdlet_success) { false } + + it 'should raise a Chef::Exceptions::PowershellCmdletException' do + expect(Chef::Log).not_to receive(:warn) + expect(lcm).to receive(:output_has_dsc_module_failure?).and_call_original + expect {lcm.test_configuration('config')}.to raise_error(Chef::Exceptions::PowershellCmdletException) + end + end + end + + it 'should identify a correctly formatted error message as a resource import failure' do + expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output)).to be(true) + end + + it 'should not identify an incorrectly formatted error message as a resource import failure' do + expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output.gsub('module', 'gibberish'))).to be(false) + end + + it 'should not identify a message without a CimException reference as a resource import failure' do + expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output.gsub('CimException', 'ArgumentException'))).to be(false) + end + end +end + |