diff options
-rw-r--r-- | lib/chef/provider/powershell_script.rb | 13 | ||||
-rw-r--r-- | lib/chef/resource/powershell_script.rb | 8 | ||||
-rw-r--r-- | spec/functional/resource/powershell_script_spec.rb | 71 | ||||
-rw-r--r-- | spec/unit/provider/powershell_script_spec.rb | 11 | ||||
-rw-r--r-- | spec/unit/resource/powershell_script_spec.rb | 4 |
5 files changed, 89 insertions, 18 deletions
diff --git a/lib/chef/provider/powershell_script.rb b/lib/chef/provider/powershell_script.rb index 49d800b6d2..8360dd873b 100644 --- a/lib/chef/provider/powershell_script.rb +++ b/lib/chef/provider/powershell_script.rb @@ -54,7 +54,18 @@ class Chef def interpreter_path # Powershell.exe is always in "v1.0" folder (for backwards compatibility) - Chef::Util::PathHelper.join(basepath, "WindowsPowerShell", "v1.0", interpreter) + # pwsh is the other interpreter and we will assume that it is on the path. + # It will exist in different folders depending on the installed version. + # There can also be multiple versions installed. Depending on how it was installed, + # there might be a registry entry pointing to the installation path. The key will + # differ depending on version and architecture. It seems best to let the PATH + # determine the file path to use since that will provide the same pwsh.exe one + # would invoke from any shell. + if interpreter == "powershell" + Chef::Util::PathHelper.join(basepath, "WindowsPowerShell", "v1.0", "#{interpreter}.exe") + else + interpreter + end end def code diff --git a/lib/chef/resource/powershell_script.rb b/lib/chef/resource/powershell_script.rb index 7699c0a976..5c9b540f55 100644 --- a/lib/chef/resource/powershell_script.rb +++ b/lib/chef/resource/powershell_script.rb @@ -22,11 +22,18 @@ class Chef class PowershellScript < Chef::Resource::WindowsScript unified_mode true + set_guard_inherited_attributes(:interpreter) + provides :powershell_script, os: "windows" property :flags, String, description: "A string that is passed to the Windows PowerShell command" + property :interpreter, String, + default: "powershell", + equal_to: %w{powershell pwsh}, + description: "The interpreter type, `powershell` or `pwsh` (PowerShell Core)" + property :convert_boolean_return, [true, false], default: false, description: <<~DESC @@ -62,7 +69,6 @@ class Chef def initialize(*args) super - @interpreter = "powershell.exe" @default_guard_interpreter = resource_name end diff --git a/spec/functional/resource/powershell_script_spec.rb b/spec/functional/resource/powershell_script_spec.rb index 70442eb2b1..68fa94afe9 100644 --- a/spec/functional/resource/powershell_script_spec.rb +++ b/spec/functional/resource/powershell_script_spec.rb @@ -47,7 +47,7 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do r end - describe "when the run action is invoked on Windows" do + shared_examples_for "a running powershell script" do it "successfully executes a non-cmdlet Windows binary as the last command of the script" do resource.code(successful_executable_script_content + " | out-file -encoding ASCII #{script_output_path}") resource.returns(0) @@ -231,22 +231,54 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do resource.only_if { true } expect { resource.should_skip?(:run) }.to raise_error(ArgumentError, /guard_interpreter does not support blocks/) end + end + + context "when using the powershell interpreter" do + before do + resource.interpreter "powershell" + end + + it_behaves_like "a running powershell script" + + it "runs Windows Powershell" do + resource.code("$PSVersionTable.PSVersion.Major | out-file -encoding ASCII #{script_output_path}") + resource.returns(0) + resource.run_action(:run) + + expect(get_script_output.to_i).to be < 6 + end + end + + context "when using the pwsh interpreter", :pwsh_installed do + before do + resource.interpreter "pwsh" + end + + it_behaves_like "a running powershell script" - context "when dsc is supported", :windows_powershell_dsc_only do - it "can execute LCM configuration code" do - resource.code <<~EOF - configuration LCM + it "runs a version of powershell greater than 6" do + resource.code("$PSVersionTable.PSVersion.Major | out-file -encoding ASCII #{script_output_path}") + resource.returns(0) + resource.run_action(:run) + + expect(get_script_output.to_i).to be > 6 + end + end + + context "when dsc is supported", :windows_powershell_dsc_only do + it "can execute LCM configuration code" do + resource.code <<~EOF + configuration LCM + { + param ($thumbprint) + localconfigurationmanager { - param ($thumbprint) - localconfigurationmanager - { - RebootNodeIfNeeded = $false - ConfigurationMode = 'ApplyOnly' - } + RebootNodeIfNeeded = $false + ConfigurationMode = 'ApplyOnly' } - EOF - expect { resource.run_action(:run) }.not_to raise_error - end + } + EOF + expect { resource.run_action(:run) }.not_to raise_error end end @@ -347,6 +379,17 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do context "with powershell_script as the guard_interpreter" do + context "when pwsh is the interpreter", :pwsh_installed do + before do + resource.interpreter "pwsh" + end + + it "uses powershell core to evaluate the guard" do + resource.not_if "$PSVersionTable.PSEdition -eq 'Core'" + expect(resource.should_skip?(:run)).to be_truthy + end + end + it "has a guard_interpreter attribute set to :powershell_script" do expect(resource.guard_interpreter).to eq(:powershell_script) end diff --git a/spec/unit/provider/powershell_script_spec.rb b/spec/unit/provider/powershell_script_spec.rb index 1c49c52160..0bece73bd0 100644 --- a/spec/unit/provider/powershell_script_spec.rb +++ b/spec/unit/provider/powershell_script_spec.rb @@ -46,5 +46,16 @@ describe Chef::Provider::PowershellScript, "action_run" do expect(provider.command).to eq(expected) end + + it "uses pwsh when given the pwsh interpreter" do + new_resource.interpreter = "pwsh" + provider.send(:script_file_path=, "C:\\Temp\\Script.ps1") + + expected = <<~CMD.strip + "pwsh" -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass -InputFormat None -File "C:\\Temp\\Script.ps1" + CMD + + expect(provider.command).to eq(expected) + end end end diff --git a/spec/unit/resource/powershell_script_spec.rb b/spec/unit/resource/powershell_script_spec.rb index 9bc91204be..75fdf6ffc6 100644 --- a/spec/unit/resource/powershell_script_spec.rb +++ b/spec/unit/resource/powershell_script_spec.rb @@ -53,9 +53,9 @@ describe Chef::Resource::PowershellScript do allow(resource).to receive(:updated).and_return(true) end - it "inherits exactly the :cwd, :environment, :group, :path, :user, :umask, :architecture, :elevated properties from a parent resource class" do + it "inherits exactly the :cwd, :environment, :group, :path, :user, :umask, :architecture, :elevated, :interpreter properties from a parent resource class" do inherited_difference = Chef::Resource::PowershellScript.guard_inherited_attributes - - %i{cwd environment group path user umask architecture elevated} + %i{cwd environment group path user umask architecture elevated interpreter} expect(inherited_difference).to eq([]) end |