diff options
-rw-r--r-- | lib/chef/mixin/windows_architecture_helper.rb | 48 | ||||
-rw-r--r-- | lib/chef/provider/script.rb | 9 | ||||
-rw-r--r-- | lib/chef/provider/windows_script.rb | 41 | ||||
-rw-r--r-- | lib/chef/resource/batch.rb | 5 | ||||
-rw-r--r-- | lib/chef/resource/powershell.rb | 7 | ||||
-rw-r--r-- | lib/chef/resource/windows_script.rb (renamed from lib/chef/resource/windows_system_script.rb) | 40 | ||||
-rw-r--r-- | spec/functional/resource/batch_spec.rb | 29 | ||||
-rw-r--r-- | spec/functional/resource/powershell_spec.rb | 31 | ||||
-rw-r--r-- | spec/support/shared/functional/windows_script_resource.rb | 65 | ||||
-rw-r--r-- | spec/support/shared/unit/windows_script_resource.rb (renamed from spec/support/shared/unit/windows_system_script_resource.rb) | 10 | ||||
-rw-r--r-- | spec/unit/provider/powershell_spec.rb | 2 | ||||
-rw-r--r-- | spec/unit/resource/batch_spec.rb | 4 | ||||
-rw-r--r-- | spec/unit/resource/powershell_spec.rb | 4 |
13 files changed, 235 insertions, 60 deletions
diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb index 7744c20b5f..38c08e236d 100644 --- a/lib/chef/mixin/windows_architecture_helper.rb +++ b/lib/chef/mixin/windows_architecture_helper.rb @@ -16,7 +16,9 @@ # limitations under the License. # -require 'chef/exceptions' + +require 'chef/exceptions' +require 'win32/api' if Chef::Platform.windows? class Chef module Mixin @@ -26,9 +28,16 @@ class Chef node[:kernel][:machine].to_sym end + def wow64_architecture_override_required?(node, desired_architecture) + is_i386_windows_process? && + node_windows_architecture(node) == :x86_64 && + desired_architecture == :x86_64 + end + def node_supports_windows_architecture?(node, desired_architecture) assert_valid_windows_architecture!(desired_architecture) - return (node_windows_architecture(node) == :x86_64 || desired_architecture == :i386) ? true : false + return (node_windows_architecture(node) == :x86_64 || + desired_architecture == :i386) ? true : false end def valid_windows_architecture?(architecture) @@ -41,6 +50,41 @@ class Chef "The specified architecture was not valid. It must be one of :i386 or :x86_64" end end + + def is_i386_windows_process? + Chef::Platform.windows? && 'X86'.casecmp(ENV['PROCESSOR_ARCHITECTURE']) == 0 + end + + def disable_wow64_file_redirection( node ) + original_redirection_state = ['0'].pack('P') + + if ( ( node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?) + win32_wow_64_disable_wow_64_fs_redirection = + ::Win32::API.new('Wow64DisableWow64FsRedirection', 'P', 'L', 'kernel32') + + succeeded = win32_wow_64_disable_wow_64_fs_redirection.call(original_redirection_state) + + if succeeded == 0 + raise Win32APIError "Failed to disable Wow64 file redirection" + end + + end + + original_redirection_state + end + + def restore_wow64_file_redirection( node, original_redirection_state ) + if ( (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?) + win32_wow_64_revert_wow_64_fs_redirection = + ::Win32::API.new('Wow64RevertWow64FsRedirection', 'P', 'L', 'kernel32') + + succeeded = win32_wow_64_revert_wow_64_fs_redirection.call(original_redirection_state) + + if succeeded == 0 + raise Win32APIError "Failed to revert Wow64 file redirection" + end + end + end end end diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb index 4d405e59f1..f1b765d52a 100644 --- a/lib/chef/provider/script.rb +++ b/lib/chef/provider/script.rb @@ -29,7 +29,7 @@ class Chef set_owner_and_group - @new_resource.command("\"#{interpreter}\" #{flags} \"#{interpreter_script_path}\"") + @new_resource.command("\"#{interpreter}\" #{flags} \"#{script_file.path}\"") super converge_by(nil) do # ensure script is unlinked at end of converge! @@ -59,13 +59,6 @@ class Chef def flags @new_resource.flags end - - protected - - def interpreter_script_path - script_file.path - end - end end end diff --git a/lib/chef/provider/windows_script.rb b/lib/chef/provider/windows_script.rb index 94ffa1d3be..398e1aee6e 100644 --- a/lib/chef/provider/windows_script.rb +++ b/lib/chef/provider/windows_script.rb @@ -17,21 +17,50 @@ # require 'chef/provider/script' +require 'chef/mixin/windows_architecture_helper' class Chef class Provider class WindowsScript < Chef::Provider::Script + protected + + include Chef::Mixin::WindowsArchitectureHelper + def initialize( new_resource, run_context, script_extension='') super( new_resource, run_context ) @script_extension = script_extension + + target_architecture = new_resource.architecture.nil? ? + node_windows_architecture(run_context.node) : new_resource.architecture + + @is_wow64 = wow64_architecture_override_required?(run_context.node, target_architecture) + + if ( target_architecture == :i386 ) && ! is_i386_windows_process? + raise Chef::Exceptions::Win32ArchitectureIncorrect, + "Support for the i386 architecture from a 64-bit Ruby runtime is not yet implemented" + end end - def flags - @new_resource.flags - end + public + + def action_run + wow64_redirection_state = nil - protected + if @is_wow64 + wow64_redirection_state = disable_wow64_file_redirection(@run_context.node) + end + + begin + super + rescue + raise + ensure + if ! wow64_redirection_state.nil? + restore_wow64_file_redirection(@run_context.node, wow64_redirection_state) + end + end + end def script_file base_script_name = "chef-script" @@ -39,10 +68,6 @@ class Chef @script_file ||= Tempfile.open(temp_file_arguments) end - - def interpreter_script_path - script_file.path.gsub(::File::SEPARATOR) { | replace | ::File::ALT_SEPARATOR } - end end end end diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb index b44489c549..705260bbce 100644 --- a/lib/chef/resource/batch.rb +++ b/lib/chef/resource/batch.rb @@ -16,12 +16,11 @@ # limitations under the License. # -require 'chef/resource/windows_system_script' -require 'chef/mixin/windows_architecture_helper' +require 'chef/resource/windows_script' class Chef class Resource - class Batch < Chef::Resource::WindowsSystemScript + class Batch < Chef::Resource::WindowsScript def initialize(name, run_context=nil) super(name, run_context, :batch, "cmd.exe") diff --git a/lib/chef/resource/powershell.rb b/lib/chef/resource/powershell.rb index 35474a1af9..e726e6f35a 100644 --- a/lib/chef/resource/powershell.rb +++ b/lib/chef/resource/powershell.rb @@ -16,15 +16,14 @@ # limitations under the License. # -require 'chef/resource/script' -require 'chef/mixin/windows_architecture_helper' +require 'chef/resource/windows_script' class Chef class Resource - class Powershell < Chef::Resource::WindowsSystemScript + class Powershell < Chef::Resource::WindowsScript def initialize(name, run_context=nil) - super(name, run_context, :powershell, "WindowsPowerShell\\v1.0\\powershell.exe") + super(name, run_context, :powershell, "powershell.exe") end end diff --git a/lib/chef/resource/windows_system_script.rb b/lib/chef/resource/windows_script.rb index 1bc618aea1..e210985e47 100644 --- a/lib/chef/resource/windows_system_script.rb +++ b/lib/chef/resource/windows_script.rb @@ -21,9 +21,20 @@ require 'chef/mixin/windows_architecture_helper' class Chef class Resource - class WindowsSystemScript < Chef::Resource::Script + class WindowsScript < Chef::Resource::Script + + protected + + def initialize(name, run_context=nil, resource_name, interpreter_command) + super(name, run_context) + @interpreter = interpreter_command + @resource_name = resource_name + end + include Chef::Mixin::WindowsArchitectureHelper + public + def architecture(arg=nil) assert_architecture_compatible!(arg) if ! arg.nil? result = set_or_return( @@ -32,34 +43,19 @@ class Chef :kind_of => Symbol ) end - - def interpreter - target_architecture = architecture.nil? ? node_windows_architecture(node) : architecture - path_prefix = (target_architecture == :x86_64) ? INTERPRETER_64_BIT_PATH_PREFIX : INTERPRETER_32_BIT_PATH_PREFIX - interpreter_path = "#{path_prefix}\\#{@interpreter_relative_path}" - end - INTERPRETER_64_BIT_PATH_PREFIX = "#{ENV['systemroot']}\\sysnative" - INTERPRETER_32_BIT_PATH_PREFIX = "#{ENV['systemroot']}\\system32" - - def initialize(name, run_context=nil, resource_name, interpreter_relative_path) - super(name, run_context) - @resource_name = resource_name - @interpreter_relative_path = interpreter_relative_path - init_arch = node_windows_architecture(node) - end - protected - def node - run_context && run_context.node - end - def assert_architecture_compatible!(desired_architecture) if ! node_supports_windows_architecture?(node, desired_architecture) - raise Chef::Exceptions::Win32ArchitectureIncorrect, "cannot execute script with requested architecture '#{desired_architecture.to_s}' on a system with architecture '#{node_windows_architecture(node)}'" + raise Chef::Exceptions::Win32ArchitectureIncorrect, + "cannot execute script with requested architecture '#{desired_architecture.to_s}' on a system with architecture '#{node_windows_architecture(node)}'" end end + + def node + run_context && run_context.node + end end end diff --git a/spec/functional/resource/batch_spec.rb b/spec/functional/resource/batch_spec.rb new file mode 100644 index 0000000000..3c73ff2e65 --- /dev/null +++ b/spec/functional/resource/batch_spec.rb @@ -0,0 +1,29 @@ +# +# Author:: Adam Edwards (<adamed@opscode.com>) +# Copyright:: Copyright (c) 2013 Opscode, 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' + +describe Chef::Resource::WindowsScript::Batch, :windows_only do + let(:script_content) { "whoami" } + + let!(:resource) do + Chef::Resource::WindowsScript::Batch.new("Batch resource functional test", run_context) + end + + it_behaves_like "a functional Windows script resource" +end diff --git a/spec/functional/resource/powershell_spec.rb b/spec/functional/resource/powershell_spec.rb new file mode 100644 index 0000000000..410f41f442 --- /dev/null +++ b/spec/functional/resource/powershell_spec.rb @@ -0,0 +1,31 @@ +# +# Author:: Adam Edwards (<adamed@opscode.com>) +# Copyright:: Copyright (c) 2013 Opscode, 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' + +describe Chef::Resource::WindowsScript::Powershell, :windows_only do + let(:script_content) { "whoami" } + + let!(:resource) do + r = Chef::Resource::WindowsScript::Powershell.new("Powershell resource functional test", run_context) + r.code(script_content) + r + end + + it_behaves_like "a functional Windows script resource" +end diff --git a/spec/support/shared/functional/windows_script_resource.rb b/spec/support/shared/functional/windows_script_resource.rb new file mode 100644 index 0000000000..8bc15313b7 --- /dev/null +++ b/spec/support/shared/functional/windows_script_resource.rb @@ -0,0 +1,65 @@ +# +# Author:: Adam Edwards (<adamed@opscode.com>) +# Copyright:: Copyright (c) 2013 Opscode, 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' + +shared_context Chef::Resource::WindowsScript do + let(:ohai) do + ohai_reader = Ohai::System.new + ohai_reader.require_plugin("os") + ohai_reader.require_plugin("windows::platform") + ohai_reader + end + + let(:node) do + new_node = Chef::Node.new + new_node.consume_external_attrs(ohai.data,{}) + new_node + end + + let(:run_context) do + events = Chef::EventDispatch::Dispatcher.new + + run_context = Chef::RunContext.new(node, {}, events) + end + + let(:script_output_path) do + File.join(Dir.tmpdir, make_tmpname("windows_script_test")) + end + + before(:each) do +k File.delete(script_output_path) if File.exists?(script_output_path) + end + + after(:each) do + File.delete(script_output_path) if File.exists?(script_output_path) + end +end + +describe Chef::Resource::WindowsScript, :windows_only do + shared_examples_for "a functional Windows script resource", :windows_only do + include_context Chef::Resource::WindowsScript + context "when a Windows script resource run action is invoked " do + it "executes the script code" do + resource.code(script_content + " > #{script_output_path}") + resource.returns(0) + resource.run_action(:run) + end + end + end +end diff --git a/spec/support/shared/unit/windows_system_script_resource.rb b/spec/support/shared/unit/windows_script_resource.rb index 75d7933209..0a0079a287 100644 --- a/spec/support/shared/unit/windows_system_script_resource.rb +++ b/spec/support/shared/unit/windows_script_resource.rb @@ -21,7 +21,7 @@ require 'spec_helper' require 'support/shared/unit/execute_resource' require 'support/shared/unit/script_resource' -shared_examples_for "a Windows system script resource" do +shared_examples_for "a Windows script resource" do before(:each) do node = Chef::Node.new @@ -34,15 +34,11 @@ shared_examples_for "a Windows system script resource" do end - it "should be a kind of Chef::Resource::WindowsSystemScript" do + it "should be a kind of Chef::Resource::WindowsScript" do @resource.should be_a_kind_of(Chef::Resource) - @resource.should be_a_kind_of(Chef::Resource::WindowsSystemScript) + @resource.should be_a_kind_of(Chef::Resource::WindowsScript) end - it "should have an interpreter with a file name of cmd.exe" do - @resource.interpreter.split('\\').pop.casecmp(interpreter_file_name).should == 0 - end - context "script" do let(:script_resource) { resource_instance } it_should_behave_like "a script resource" diff --git a/spec/unit/provider/powershell_spec.rb b/spec/unit/provider/powershell_spec.rb index fc973a686a..038de47742 100644 --- a/spec/unit/provider/powershell_spec.rb +++ b/spec/unit/provider/powershell_spec.rb @@ -27,8 +27,6 @@ describe Chef::Provider::Powershell, "action_run" do @run_context = Chef::RunContext.new(@node, {}, @events) @new_resource = Chef::Resource::Powershell.new('run some powershell code', @run_context) -# @new_resource.code "$| = 1; print 'i like beans'" -# @new_resource.interpreter 'perl' @provider = Chef::Provider::Powershell.new(@new_resource, @run_context) end diff --git a/spec/unit/resource/batch_spec.rb b/spec/unit/resource/batch_spec.rb index 119b0dd5f1..91b840908e 100644 --- a/spec/unit/resource/batch_spec.rb +++ b/spec/unit/resource/batch_spec.rb @@ -36,13 +36,13 @@ describe Chef::Resource::Batch do @resource.should be_a_kind_of(Chef::Resource::Batch) end - context "windowssystemscript" do + context "windows script" do let(:resource_instance) { @resource } let(:resource_instance_name ) { @resource.command } let(:resource_name) { :batch } let(:interpreter_file_name) { 'cmd.exe' } - it_should_behave_like "a Windows system script resource" + it_should_behave_like "a Windows script resource" end end diff --git a/spec/unit/resource/powershell_spec.rb b/spec/unit/resource/powershell_spec.rb index c6650f4daa..22d5b5371b 100644 --- a/spec/unit/resource/powershell_spec.rb +++ b/spec/unit/resource/powershell_spec.rb @@ -36,13 +36,13 @@ describe Chef::Resource::Powershell do @resource.should be_a_kind_of(Chef::Resource::Powershell) end - context "windowssystemscript" do + context "windowsscript" do let(:resource_instance) { @resource } let(:resource_instance_name ) { @resource.command } let(:resource_name) { :powershell } let(:interpreter_file_name) { 'powershell.exe' } - it_should_behave_like "a Windows system script resource" + it_should_behave_like "a Windows script resource" end end |