summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Edwards <adamed@opscode.com>2013-02-19 16:23:59 -0800
committerAdam Edwards <adamed@opscode.com>2013-02-19 16:23:59 -0800
commit5f65e7984d0f65ad6a991eddaedfc98f42c6739d (patch)
treebff0d3ac4bc5a0e9781c5c4e4b39f1e21d3e9aee
parent5e9dad16efadd17c046654895095dcb7d2052612 (diff)
parent95a7372e70a66e3b2a9831c6d35bddbd969dd0ce (diff)
downloadchef-5f65e7984d0f65ad6a991eddaedfc98f42c6739d.tar.gz
Merge pull request #646 from opscode/chef-oc-4739-rebase
Addition of Batch and Powershell resources for Windows
-rw-r--r--lib/chef/exceptions.rb4
-rw-r--r--lib/chef/mixin/windows_architecture_helper.rb91
-rw-r--r--lib/chef/provider/batch.rb35
-rw-r--r--lib/chef/provider/powershell.rb35
-rw-r--r--lib/chef/provider/script.rb9
-rw-r--r--lib/chef/provider/windows_script.rb73
-rw-r--r--lib/chef/providers.rb2
-rw-r--r--lib/chef/resource/batch.rb31
-rw-r--r--lib/chef/resource/powershell.rb31
-rw-r--r--lib/chef/resource/windows_script.rb62
-rw-r--r--lib/chef/resources.rb2
-rw-r--r--spec/functional/resource/batch_spec.rb70
-rw-r--r--spec/functional/resource/powershell_spec.rb40
-rw-r--r--spec/support/shared/unit/execute_resource.rb125
-rw-r--r--spec/support/shared/unit/script_resource.rb52
-rw-r--r--spec/support/shared/unit/windows_script_resource.rb48
-rw-r--r--spec/unit/mixin/windows_architecture_helper_spec.rb83
-rw-r--r--spec/unit/provider/powershell_spec.rb38
-rw-r--r--spec/unit/resource/batch_spec.rb48
-rw-r--r--spec/unit/resource/execute_spec.rb104
-rw-r--r--spec/unit/resource/powershell_spec.rb48
-rw-r--r--spec/unit/resource/script_spec.rb49
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
+