diff options
author | Adam Edwards <adamed@opscode.com> | 2013-02-19 16:23:59 -0800 |
---|---|---|
committer | Adam Edwards <adamed@opscode.com> | 2013-02-19 16:23:59 -0800 |
commit | 5f65e7984d0f65ad6a991eddaedfc98f42c6739d (patch) | |
tree | bff0d3ac4bc5a0e9781c5c4e4b39f1e21d3e9aee | |
parent | 5e9dad16efadd17c046654895095dcb7d2052612 (diff) | |
parent | 95a7372e70a66e3b2a9831c6d35bddbd969dd0ce (diff) | |
download | chef-5f65e7984d0f65ad6a991eddaedfc98f42c6739d.tar.gz |
Merge pull request #646 from opscode/chef-oc-4739-rebase
Addition of Batch and Powershell resources for Windows
22 files changed, 941 insertions, 139 deletions
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index c8654d7801..783a640654 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -97,6 +97,8 @@ class Chef # Attempting to run windows code on a not-windows node class Win32NotWindows < RuntimeError; end class WindowsNotAdmin < RuntimeError; end + # Attempting to access a 64-bit only resource on a 32-bit Windows system + class Win32ArchitectureIncorrect < RuntimeError; end class ObsoleteDependencySyntax < ArgumentError; end class InvalidDataBagPath < ArgumentError; end @@ -131,7 +133,7 @@ class Chef class StaleAttributeRead < StandardError; end #Registry Helper throws the following errors - class Win32RegArchitectureIncorrect < RuntimeError; end + class Win32RegArchitectureIncorrect < Win32ArchitectureIncorrect; end class Win32RegHiveMissing < ArgumentError; end class Win32RegKeyMissing < RuntimeError; end class Win32RegValueMissing < RuntimeError; end diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb new file mode 100644 index 0000000000..38c08e236d --- /dev/null +++ b/lib/chef/mixin/windows_architecture_helper.rb @@ -0,0 +1,91 @@ +# +# 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 'chef/exceptions' +require 'win32/api' if Chef::Platform.windows? + +class Chef + module Mixin + module WindowsArchitectureHelper + + def node_windows_architecture(node) + 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 + end + + def valid_windows_architecture?(architecture) + return (architecture == :x86_64) || (architecture == :i386) + end + + def assert_valid_windows_architecture!(architecture) + if ! valid_windows_architecture?(architecture) + raise Chef::Exceptions::Win32ArchitectureIncorrect, + "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 +end diff --git a/lib/chef/provider/batch.rb b/lib/chef/provider/batch.rb new file mode 100644 index 0000000000..e4b35b64f3 --- /dev/null +++ b/lib/chef/provider/batch.rb @@ -0,0 +1,35 @@ +# +# 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 'chef/provider/windows_script' + +class Chef + class Provider + class Batch < Chef::Provider::WindowsScript + + def initialize (new_resource, run_context) + super(new_resource, run_context, '.bat') + end + + def flags + @new_resource.flags.nil? ? '/c' : new_resource.flags + ' /c' + end + + end + end +end diff --git a/lib/chef/provider/powershell.rb b/lib/chef/provider/powershell.rb new file mode 100644 index 0000000000..aaa4a9255e --- /dev/null +++ b/lib/chef/provider/powershell.rb @@ -0,0 +1,35 @@ +# +# 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 'chef/provider/windows_script' + +class Chef + class Provider + class Powershell < Chef::Provider::WindowsScript + + def initialize (new_resource, run_context) + super(new_resource, run_context, '.ps1') + end + + def flags + @new_resource.flags.nil? ? '-ExecutionPolicy RemoteSigned -Command' : @new_resource.flags + '-ExecutionPolicy RemoteSigned -Command' + end + + end + end +end diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb index 9e5a7d7fe1..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("\"#{@new_resource.interpreter}\" #{@new_resource.flags} \"#{script_file.path}\"") + @new_resource.command("\"#{interpreter}\" #{flags} \"#{script_file.path}\"") super converge_by(nil) do # ensure script is unlinked at end of converge! @@ -52,6 +52,13 @@ class Chef @script_file && @script_file.close! end + def interpreter + @new_resource.interpreter + end + + def flags + @new_resource.flags + end end end end diff --git a/lib/chef/provider/windows_script.rb b/lib/chef/provider/windows_script.rb new file mode 100644 index 0000000000..398e1aee6e --- /dev/null +++ b/lib/chef/provider/windows_script.rb @@ -0,0 +1,73 @@ +# +# 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 '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 + + public + + def action_run + wow64_redirection_state = nil + + 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" + temp_file_arguments = [ base_script_name, @script_extension ] + + @script_file ||= Tempfile.open(temp_file_arguments) + end + end + end +end diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index be3f487ca3..ae95632eaa 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -16,6 +16,7 @@ # limitations under the License. # +require 'chef/provider/batch' require 'chef/provider/breakpoint' require 'chef/provider/cookbook_file' require 'chef/provider/cron' @@ -36,6 +37,7 @@ require 'chef/provider/ohai' require 'chef/provider/mdadm' require 'chef/provider/mount' require 'chef/provider/package' +require 'chef/provider/powershell' require 'chef/provider/remote_directory' require 'chef/provider/remote_file' require 'chef/provider/route' diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb new file mode 100644 index 0000000000..705260bbce --- /dev/null +++ b/lib/chef/resource/batch.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 'chef/resource/windows_script' + +class Chef + class Resource + class Batch < Chef::Resource::WindowsScript + + def initialize(name, run_context=nil) + super(name, run_context, :batch, "cmd.exe") + end + + end + end +end diff --git a/lib/chef/resource/powershell.rb b/lib/chef/resource/powershell.rb new file mode 100644 index 0000000000..e726e6f35a --- /dev/null +++ b/lib/chef/resource/powershell.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 'chef/resource/windows_script' + +class Chef + class Resource + class Powershell < Chef::Resource::WindowsScript + + def initialize(name, run_context=nil) + super(name, run_context, :powershell, "powershell.exe") + end + + end + end +end diff --git a/lib/chef/resource/windows_script.rb b/lib/chef/resource/windows_script.rb new file mode 100644 index 0000000000..e210985e47 --- /dev/null +++ b/lib/chef/resource/windows_script.rb @@ -0,0 +1,62 @@ +# +# 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 'chef/resource/script' +require 'chef/mixin/windows_architecture_helper' + +class Chef + class Resource + 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( + :architecture, + arg, + :kind_of => Symbol + ) + end + + protected + + 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)}'" + end + end + + def node + run_context && run_context.node + end + + end + end +end diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 6dea46bfc9..1b295fc4e1 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -18,6 +18,7 @@ require 'chef/resource/apt_package' require 'chef/resource/bash' +require 'chef/resource/batch' require 'chef/resource/breakpoint' require 'chef/resource/cookbook_file' require 'chef/resource/chef_gem' @@ -49,6 +50,7 @@ require 'chef/resource/package' require 'chef/resource/pacman_package' require 'chef/resource/perl' require 'chef/resource/portage_package' +require 'chef/resource/powershell' require 'chef/resource/python' require 'chef/resource/registry_key' require 'chef/resource/remote_directory' diff --git a/spec/functional/resource/batch_spec.rb b/spec/functional/resource/batch_spec.rb new file mode 100644 index 0000000000..4374dd0730 --- /dev/null +++ b/spec/functional/resource/batch_spec.rb @@ -0,0 +1,70 @@ +# +# 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::Batch, :windows_only do + let(:script_content) { "whoami" } + + let!(:resource) do + Chef::Resource::WindowsScript::Batch.new("Batch resource functional test", run_context) + end + + context "when the run action is invoked on Windows" do + include_context Chef::Resource::WindowsScript + it "executes the script code" do + resource.code(script_content + " > #{script_output_path}") + resource.returns(0) + resource.run_action(:run) + end + end +end diff --git a/spec/functional/resource/powershell_spec.rb b/spec/functional/resource/powershell_spec.rb new file mode 100644 index 0000000000..0673e06126 --- /dev/null +++ b/spec/functional/resource/powershell_spec.rb @@ -0,0 +1,40 @@ +# +# 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' +require 'functional/resource/batch_spec.rb' + +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 + + include_context Chef::Resource::WindowsScript + + context "when the run action is invoked on Windows" do + it "executes the script code" do + resource.code(script_content + " > #{script_output_path}") + resource.returns(0) + resource.run_action(:run) + end + end +end diff --git a/spec/support/shared/unit/execute_resource.rb b/spec/support/shared/unit/execute_resource.rb new file mode 100644 index 0000000000..609e77ad63 --- /dev/null +++ b/spec/support/shared/unit/execute_resource.rb @@ -0,0 +1,125 @@ +# +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Tyler Cloke (<tyler@opscode.com>) +# Copyright:: Copyright (c) 2008 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_examples_for "an execute resource" do + + before(:each) do + @resource = execute_resource + end + + it "should create a new Chef::Resource::Execute" do + @resource.should be_a_kind_of(Chef::Resource) + @resource.should be_a_kind_of(Chef::Resource::Execute) + end + + it "should set the command to the first argument to new" do + @resource.command.should eql(resource_instance_name) + end + + it "should accept an array on instantiation, too" do + resource = Chef::Resource::Execute.new(%w{something else}) + resource.should be_a_kind_of(Chef::Resource) + resource.should be_a_kind_of(Chef::Resource::Execute) + resource.command.should eql(%w{something else}) + end + + it "should accept a string for the command to run" do + @resource.command "something" + @resource.command.should eql("something") + end + + it "should accept an array for the command to run" do + @resource.command %w{something else} + @resource.command.should eql(%w{something else}) + end + + it "should accept a string for the cwd" do + @resource.cwd "something" + @resource.cwd.should eql("something") + end + + it "should accept a hash for the environment" do + test_hash = { :one => :two } + @resource.environment(test_hash) + @resource.environment.should eql(test_hash) + end + + it "allows the environment to be specified with #env" do + @resource.should respond_to(:env) + end + + it "should accept a string for the group" do + @resource.group "something" + @resource.group.should eql("something") + end + + it "should accept an integer for the group" do + @resource.group 1 + @resource.group.should eql(1) + end + + it "should accept an array for the execution path" do + @resource.path ["woot"] + @resource.path.should eql(["woot"]) + end + + it "should accept an integer for the return code" do + @resource.returns 1 + @resource.returns.should eql(1) + end + + it "should accept an integer for the timeout" do + @resource.timeout 1 + @resource.timeout.should eql(1) + end + + it "should accept a string for the user" do + @resource.user "something" + @resource.user.should eql("something") + end + + it "should accept an integer for the user" do + @resource.user 1 + @resource.user.should eql(1) + end + + it "should accept a string for creates" do + @resource.creates "something" + @resource.creates.should eql("something") + end + + describe "when it has cwd, environment, group, path, return value, and a user" do + before do + @resource.command("grep") + @resource.cwd("/tmp/") + @resource.environment({ :one => :two }) + @resource.group("legos") + @resource.path(["/var/local/"]) + @resource.returns(1) + @resource.user("root") + end + + it "returns the command as its identity" do + @resource.identity.should == "grep" + end + end +end + diff --git a/spec/support/shared/unit/script_resource.rb b/spec/support/shared/unit/script_resource.rb new file mode 100644 index 0000000000..0451f4694a --- /dev/null +++ b/spec/support/shared/unit/script_resource.rb @@ -0,0 +1,52 @@ +# +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Tyler Cloke (<tyler@opscode.com>) +# Copyright:: Copyright (c) 2008 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_examples_for "a script resource" do + + before(:each) do + @resource = script_resource + end + + it "should create a new Chef::Resource::Script" do + @resource.should be_a_kind_of(Chef::Resource) + @resource.should be_a_kind_of(Chef::Resource::Script) + end + + it "should have a resource name of :script" do + @resource.resource_name.should eql(resource_name) + end + + it "should set command to the argument provided to new" do + @resource.command.should eql(resource_instance_name) + end + + it "should accept a string for the code" do + @resource.code "hey jude" + @resource.code.should eql("hey jude") + end + + it "should accept a string for the flags" do + @resource.flags "-f" + @resource.flags.should eql("-f") + end + +end + diff --git a/spec/support/shared/unit/windows_script_resource.rb b/spec/support/shared/unit/windows_script_resource.rb new file mode 100644 index 0000000000..0a0079a287 --- /dev/null +++ b/spec/support/shared/unit/windows_script_resource.rb @@ -0,0 +1,48 @@ +# +# 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' + +require 'support/shared/unit/execute_resource' +require 'support/shared/unit/script_resource' + +shared_examples_for "a Windows script resource" do + before(:each) do + node = Chef::Node.new + + node.default["kernel"] = Hash.new + node.default["kernel"][:machine] = :x86_64.to_s + + run_context = Chef::RunContext.new(node, nil, nil) + + @resource = resource_instance + + end + + 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::WindowsScript) + end + + context "script" do + let(:script_resource) { resource_instance } + it_should_behave_like "a script resource" + end + +end + diff --git a/spec/unit/mixin/windows_architecture_helper_spec.rb b/spec/unit/mixin/windows_architecture_helper_spec.rb new file mode 100644 index 0000000000..c7813a5efc --- /dev/null +++ b/spec/unit/mixin/windows_architecture_helper_spec.rb @@ -0,0 +1,83 @@ +# +# 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' +require 'chef/mixin/windows_architecture_helper' + + + +describe Chef::Mixin::WindowsArchitectureHelper do + include Chef::Mixin::WindowsArchitectureHelper + + before do + @valid_architectures = [ :i386, :x86_64 ] + @invalid_architectures = [ "i386", "x86_64", :x64, :x86, :arm ] + + @node_i386 = Chef::Node.new + @node_x86_64 = Chef::Node.new + end + + it "returns true when valid architectures are passed to valid_windows_architecture?" do + @valid_architectures.each do | architecture | + valid_windows_architecture?(architecture).should == true + end + end + + it "returns false when invalid architectures are passed to valid_windows_architecture?" do + @invalid_architectures.each do | architecture | + valid_windows_architecture?(architecture).should == false + end + end + + it "does not raise an exception when a valid architecture is passed to assert_valid_windows_architecture!" do + @valid_architectures.each do | architecture | + assert_valid_windows_architecture!(architecture) + end + end + + it "raises an error if an invalid architecture is passed to assert_valid_windows_architecture!" do + @invalid_architectures.each do | architecture | + begin + assert_valid_windows_architecture!(architecture).should raise_error Chef::Exceptions::Win32ArchitectureIncorrect + rescue Chef::Exceptions::Win32ArchitectureIncorrect + end + end + end + + it "returns true for each supported desired architecture for all nodes with each valid architecture passed to node_supports_windows_architecture" do + enumerate_architecture_node_combinations(true) + end + + it "returns false for each unsupported desired architecture for all nodes with each valid architecture passed to node_supports_windows_architecture?" do + enumerate_architecture_node_combinations(true) + end + + def enumerate_architecture_node_combinations(only_valid_combinations) + @valid_architectures.each do | node_architecture | + new_node = Chef::Node.new + new_node.default["kernel"] = Hash.new + new_node.default["kernel"][:machine] = node_architecture.to_s + + @valid_architectures.each do | supported_architecture | + node_supports_windows_architecture?(new_node, supported_architecture).should == true if only_valid_combinations && (supported_architecture != :x86_64 && node_architecture != :i386 ) + node_supports_windows_architecture?(new_node, supported_architecture).should == false if ! only_valid_combinations && (supported_architecture == :x86_64 && node_architecture == :i386 ) + end + end + end +end diff --git a/spec/unit/provider/powershell_spec.rb b/spec/unit/provider/powershell_spec.rb new file mode 100644 index 0000000000..038de47742 --- /dev/null +++ b/spec/unit/provider/powershell_spec.rb @@ -0,0 +1,38 @@ +# +# 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::Provider::Powershell, "action_run" do + + before(:each) do + @node = Chef::Node.new + + @node.default["kernel"] = Hash.new + @node.default["kernel"][:machine] = :x86_64.to_s + + @run_context = Chef::RunContext.new(@node, {}, @events) + @new_resource = Chef::Resource::Powershell.new('run some powershell code', @run_context) + + @provider = Chef::Provider::Powershell.new(@new_resource, @run_context) + end + + it "should set the -command flag as the last flag" do + @provider.flags.split(' ').pop.should == "-Command" + end + +end diff --git a/spec/unit/resource/batch_spec.rb b/spec/unit/resource/batch_spec.rb new file mode 100644 index 0000000000..91b840908e --- /dev/null +++ b/spec/unit/resource/batch_spec.rb @@ -0,0 +1,48 @@ +# +# 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::Batch do + + before(:each) do + node = Chef::Node.new + + node.default["kernel"] = Hash.new + node.default["kernel"][:machine] = :x86_64.to_s + + run_context = Chef::RunContext.new(node, nil, nil) + + @resource = Chef::Resource::Batch.new("batch_unit_test", run_context) + + end + + it "should create a new Chef::Resource::Batch" do + @resource.should be_a_kind_of(Chef::Resource::Batch) + end + + 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 script resource" + end + +end diff --git a/spec/unit/resource/execute_spec.rb b/spec/unit/resource/execute_spec.rb index 0dcdab7409..8c8dcfb6ca 100644 --- a/spec/unit/resource/execute_spec.rb +++ b/spec/unit/resource/execute_spec.rb @@ -20,105 +20,7 @@ require 'spec_helper' describe Chef::Resource::Execute do - - before(:each) do - @resource = Chef::Resource::Execute.new("some command") - end - - it "should create a new Chef::Resource::Execute" do - @resource.should be_a_kind_of(Chef::Resource) - @resource.should be_a_kind_of(Chef::Resource::Execute) - end - - it "should set the command to the first argument to new" do - @resource.command.should eql("some command") - end - - it "should accept an array on instantiation, too" do - resource = Chef::Resource::Execute.new(%w{something else}) - resource.should be_a_kind_of(Chef::Resource) - resource.should be_a_kind_of(Chef::Resource::Execute) - resource.command.should eql(%w{something else}) - end - - it "should accept a string for the command to run" do - @resource.command "something" - @resource.command.should eql("something") - end - - it "should accept an array for the command to run" do - @resource.command %w{something else} - @resource.command.should eql(%w{something else}) - end - - it "should accept a string for the cwd" do - @resource.cwd "something" - @resource.cwd.should eql("something") - end - - it "should accept a hash for the environment" do - test_hash = { :one => :two } - @resource.environment(test_hash) - @resource.environment.should eql(test_hash) - end - - it "allows the environment to be specified with #env" do - @resource.should respond_to(:env) - end - - it "should accept a string for the group" do - @resource.group "something" - @resource.group.should eql("something") - end - - it "should accept an integer for the group" do - @resource.group 1 - @resource.group.should eql(1) - end - - it "should accept an array for the execution path" do - @resource.path ["woot"] - @resource.path.should eql(["woot"]) - end - - it "should accept an integer for the return code" do - @resource.returns 1 - @resource.returns.should eql(1) - end - - it "should accept an integer for the timeout" do - @resource.timeout 1 - @resource.timeout.should eql(1) - end - - it "should accept a string for the user" do - @resource.user "something" - @resource.user.should eql("something") - end - - it "should accept an integer for the user" do - @resource.user 1 - @resource.user.should eql(1) - end - - it "should accept a string for creates" do - @resource.creates "something" - @resource.creates.should eql("something") - end - - describe "when it has cwd, environment, group, path, return value, and a user" do - before do - @resource.command("grep") - @resource.cwd("/tmp/") - @resource.environment({ :one => :two }) - @resource.group("legos") - @resource.path(["/var/local/"]) - @resource.returns(1) - @resource.user("root") - end - - it "returns the command as its identity" do - @resource.identity.should == "grep" - end - end + let(:resource_instance_name) { "some command" } + let(:execute_resource) { Chef::Resource::Execute.new(resource_instance_name) } + it_behaves_like "an execute resource" end diff --git a/spec/unit/resource/powershell_spec.rb b/spec/unit/resource/powershell_spec.rb new file mode 100644 index 0000000000..22d5b5371b --- /dev/null +++ b/spec/unit/resource/powershell_spec.rb @@ -0,0 +1,48 @@ +# +# 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::Powershell do + + before(:each) do + node = Chef::Node.new + + node.default["kernel"] = Hash.new + node.default["kernel"][:machine] = :x86_64.to_s + + run_context = Chef::RunContext.new(node, nil, nil) + + @resource = Chef::Resource::Powershell.new("powershell_unit_test", run_context) + + end + + it "should create a new Chef::Resource::Powershell" do + @resource.should be_a_kind_of(Chef::Resource::Powershell) + end + + 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 script resource" + end + +end diff --git a/spec/unit/resource/script_spec.rb b/spec/unit/resource/script_spec.rb index 569602008b..53735daf01 100644 --- a/spec/unit/resource/script_spec.rb +++ b/spec/unit/resource/script_spec.rb @@ -20,50 +20,27 @@ require 'spec_helper' describe Chef::Resource::Script do + let(:resource_instance_name) { "fakey_fakerton" } + let(:script_resource) { Chef::Resource::Script.new(resource_instance_name) } + let(:resource_name) { :script } - before(:each) do - @resource = Chef::Resource::Script.new("fakey_fakerton") - end - - it "should create a new Chef::Resource::Script" do - @resource.should be_a_kind_of(Chef::Resource) - @resource.should be_a_kind_of(Chef::Resource::Script) - end - - it "should have a resource name of :script" do - @resource.resource_name.should eql(:script) - end - - it "should set command to the argument provided to new" do - @resource.command.should eql("fakey_fakerton") - end - - it "should accept a string for the code" do - @resource.code "hey jude" - @resource.code.should eql("hey jude") - end - it "should accept a string for the interpreter" do - @resource.interpreter "naaaaNaNaNaaNaaNaaNaa" - @resource.interpreter.should eql("naaaaNaNaNaaNaaNaaNaa") - end - - it "should accept a string for the flags" do - @resource.flags "-f" - @resource.flags.should eql("-f") + script_resource.interpreter "naaaaNaNaNaaNaaNaaNaa" + script_resource.interpreter.should eql("naaaaNaNaNaaNaaNaaNaa") end describe "when it has interpreter and flags" do before do - @resource.command("grep") - @resource.interpreter("gcc") - @resource.flags("-al") + script_resource.command("grep") + script_resource.interpreter("gcc") + script_resource.flags("-al") end - it "returns the command as its identity" do - @resource.identity.should == "grep" + it "returns the command as its identity" do + script_resource.identity.should == "grep" end end - - + + it_behaves_like "a script resource" end + |