diff options
author | Steven Murawski <steven.murawski@gmail.com> | 2015-11-13 17:56:21 -0600 |
---|---|---|
committer | Steven Murawski <steven.murawski@gmail.com> | 2015-11-18 10:18:50 -0600 |
commit | 9f6a1bbe020c2664fbe96f18ed8d5861a9e3da84 (patch) | |
tree | aad306daf0b56602f050204747e24b1bfece1cec | |
parent | fbdf03d3c174f1c2309a497efcf92227e191fdc0 (diff) | |
download | chef-9f6a1bbe020c2664fbe96f18ed8d5861a9e3da84.tar.gz |
WMF 5 RTM and Win 10 Threshold 2 allow the RefreshMode to be enabled.
-rw-r--r-- | lib/chef/platform/query_helpers.rb | 17 | ||||
-rw-r--r-- | lib/chef/provider/dsc_resource.rb | 28 | ||||
-rw-r--r-- | spec/unit/provider/dsc_resource_spec.rb | 103 |
3 files changed, 102 insertions, 46 deletions
diff --git a/lib/chef/platform/query_helpers.rb b/lib/chef/platform/query_helpers.rb index dfb99ed750..699e98737c 100644 --- a/lib/chef/platform/query_helpers.rb +++ b/lib/chef/platform/query_helpers.rb @@ -85,10 +85,12 @@ class Chef end def supports_dsc_invoke_resource?(node) - require 'rubygems' supports_dsc?(node) && - Gem::Version.new(node[:languages][:powershell][:version]) >= - Gem::Version.new("5.0.10018.0") + supported_powershell_version?(node, "5.0.10018.0") + end + + def supports_refresh_mode_enabled?(node) + supported_powershell_version?(node, "5.0.10586.0") end def dsc_refresh_mode_disabled?(node) @@ -97,6 +99,15 @@ class Chef metadata = cmdlet.run!.return_value metadata['RefreshMode'] == 'Disabled' end + + + def supported_powershell_version?(node, version_string) + return false unless node[:languages] && node[:languages][:powershell] + require 'rubygems' + Gem::Version.new(node[:languages][:powershell][:version]) >= + Gem::Version.new(version_string) + end + end end end diff --git a/lib/chef/provider/dsc_resource.rb b/lib/chef/provider/dsc_resource.rb index c06e062e3c..212e3b0e09 100644 --- a/lib/chef/provider/dsc_resource.rb +++ b/lib/chef/provider/dsc_resource.rb @@ -19,6 +19,7 @@ require 'chef/util/powershell/cmdlet' require 'chef/util/dsc/local_configuration_manager' require 'chef/mixin/powershell_type_coercions' require 'chef/util/dsc/resource_store' + class Chef class Provider class DscResource < Chef::Provider @@ -30,6 +31,7 @@ class Chef @module_name = new_resource.module_name @reboot_resource = nil end + def action_run if ! test_resource converge_by(generate_description) do @@ -38,11 +40,14 @@ class Chef end end end + def load_current_resource end + def whyrun_supported? true end + def define_resource_requirements requirements.assert(:run) do |a| a.assertion { supports_dsc_invoke_resource? } @@ -53,35 +58,48 @@ class Chef a.block_action! end requirements.assert(:run) do |a| - a.assertion { dsc_refresh_mode_disabled? } - err = ["The LCM must have its RefreshMode set to Disabled. "] + a.assertion { supports_refresh_mode_enabled? || dsc_refresh_mode_disabled? } + err = ["The LCM must have its RefreshMode set to Disabled for" \ + " PowerShell versions before 5.0.10586.0."] a.failure_message Chef::Exceptions::ProviderNotFound, err.join(' ') a.whyrun err + ["Assuming a previous resource sets the RefreshMode."] a.block_action! end end + protected + def local_configuration_manager @local_configuration_manager ||= Chef::Util::DSC::LocalConfigurationManager.new( node, nil ) end + def resource_store Chef::Util::DSC::ResourceStore.instance end + def supports_dsc_invoke_resource? run_context && Chef::Platform.supports_dsc_invoke_resource?(node) end + def dsc_refresh_mode_disabled? Chef::Platform.dsc_refresh_mode_disabled?(node) end + + def supports_refresh_mode_enabled? + Chef::Platform.supports_refresh_mode_enabled?(node) + end + def generate_description @converge_description end + def dsc_resource_name new_resource.resource.to_s end + def module_name @module_name ||= begin found = resource_store.find(dsc_resource_name) @@ -101,6 +119,7 @@ class Chef end end end + def test_resource result = invoke_resource(:test) # We really want this information from the verbose stream, @@ -109,6 +128,7 @@ class Chef @converge_description = result.stdout return_dsc_resource_result(result, "InDesiredState") end + def set_resource result = invoke_resource(:set) if return_dsc_resource_result(result, 'RebootRequired') @@ -116,6 +136,7 @@ class Chef end result.return_value end + def invoke_resource(method, output_format=:object) properties = translate_type(@new_resource.properties) switches = "-Method #{method.to_s} -Name #{@new_resource.resource}"\ @@ -130,6 +151,7 @@ class Chef ) cmdlet.run! end + def return_dsc_resource_result(result, property_name) if result.return_value.is_a?(Array) # WMF Feb 2015 Preview @@ -139,6 +161,7 @@ class Chef result.return_value[property_name] end end + def create_reboot_resource @reboot_resource = Chef::Resource::Reboot.new( "Reboot for #{@new_resource.name}", @@ -147,6 +170,7 @@ class Chef r.reason("Reboot for #{@new_resource.resource}.") end end + def reboot_if_required reboot_action = @new_resource.reboot_action unless @reboot_resource.nil? diff --git a/spec/unit/provider/dsc_resource_spec.rb b/spec/unit/provider/dsc_resource_spec.rb index b95b1d7bcf..46cdbd93a6 100644 --- a/spec/unit/provider/dsc_resource_spec.rb +++ b/spec/unit/provider/dsc_resource_spec.rb @@ -41,55 +41,76 @@ describe Chef::Provider::DscResource do end context 'when Powershell supports Invoke-DscResource' do + + context 'when RefreshMode is not set to Disabled' do + context 'and the WMF 5 is a preview release' do + let (:node) { + node = Chef::Node.new + node.automatic[:languages][:powershell][:version] = '5.0.10018.0' + node + } + it 'raises an exception' do + expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(false) + expect { provider.run_action(:run) }.to raise_error( + Chef::Exceptions::ProviderNotFound, /Disabled/) + end + end + context 'and the WMF is 5 RTM or newer' do + let (:node) { + node = Chef::Node.new + node.automatic[:languages][:powershell][:version] = '5.0.10586.0' + node + } + it 'does not raises an exception' do + expect(provider).to receive(:test_resource) + expect(provider).to receive(:set_resource) + expect(provider).to receive(:reboot_if_required) + expect { provider.run_action(:run) }.to_not raise_error + end + end + end + end + + context 'when the LCM supports Invoke-DscResource' do let (:node) { node = Chef::Node.new node.automatic[:languages][:powershell][:version] = '5.0.10018.0' node } - context 'when RefreshMode is not set to Disabled' do - it 'raises an exception' do - expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(false) - expect { provider.run_action(:run) }.to raise_error( - Chef::Exceptions::ProviderNotFound, /Disabled/) - end + it 'does not update the resource if it is up to date' do + expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) + expect(provider).to receive(:test_resource).and_return(true) + provider.run_action(:run) + expect(resource).not_to be_updated end - context 'when RefreshMode is set to Disabled' do - it 'does not update the resource if it is up to date' do - expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) - expect(provider).to receive(:test_resource).and_return(true) - provider.run_action(:run) - expect(resource).not_to be_updated - end - - it 'converges the resource if it is not up to date' do - expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) - expect(provider).to receive(:test_resource).and_return(false) - expect(provider).to receive(:set_resource) - provider.run_action(:run) - expect(resource).to be_updated - end - - it 'flags the resource as reboot required when required' do - expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) - expect(provider).to receive(:test_resource).and_return(false) - expect(provider).to receive(:invoke_resource). - and_return(double(:stdout => '', :return_value =>nil)) - expect(provider).to receive(:return_dsc_resource_result).and_return(true) - expect(provider).to receive(:create_reboot_resource) - provider.run_action(:run) - end - - it 'does not flag the resource as reboot required when not required' do - expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) - expect(provider).to receive(:test_resource).and_return(false) - expect(provider).to receive(:invoke_resource). - and_return(double(:stdout => '', :return_value =>nil)) - expect(provider).to receive(:return_dsc_resource_result).and_return(false) - expect(provider).to_not receive(:create_reboot_resource) - provider.run_action(:run) - end + it 'converges the resource if it is not up to date' do + expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) + expect(provider).to receive(:test_resource).and_return(false) + expect(provider).to receive(:set_resource) + provider.run_action(:run) + expect(resource).to be_updated + end + + it 'flags the resource as reboot required when required' do + expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) + expect(provider).to receive(:test_resource).and_return(false) + expect(provider).to receive(:invoke_resource). + and_return(double(:stdout => '', :return_value =>nil)) + expect(provider).to receive(:return_dsc_resource_result).and_return(true) + expect(provider).to receive(:create_reboot_resource) + provider.run_action(:run) + end + + it 'does not flag the resource as reboot required when not required' do + expect(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true) + expect(provider).to receive(:test_resource).and_return(false) + expect(provider).to receive(:invoke_resource). + and_return(double(:stdout => '', :return_value =>nil)) + expect(provider).to receive(:return_dsc_resource_result).and_return(false) + expect(provider).to_not receive(:create_reboot_resource) + provider.run_action(:run) end end end
\ No newline at end of file |