Skip to content

Commit

Permalink
(puppetlabsGH-2651) Add pwsh_params option to run_script function
Browse files Browse the repository at this point in the history
This adds a `pwsh_params` option to the `run_script` plan function.
The option accepts a hash of named parameters to pass to a PowerShell
script, where each key is the name of the parameter. If the `run_script`
function is called with both the `arguments` and `pwsh_params` options,
Bolt will error and provide a helpful message that both cannot be
specified.

This also adds a `pwsh_params` key to the YAML plan script step.

!feature

* **Add `pwsh_params` option to `run_script` plan function**
  ([puppetlabs#2651](puppetlabs#2651))

  The `run_script` plan function now accepts a `pwsh_params` option
  which can be used to pass named parameters to a PowerShell script.
  • Loading branch information
beechtom committed Mar 2, 2021
1 parent 7c9c971 commit 69427bb
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 3 deletions.
6 changes: 6 additions & 0 deletions bolt-modules/boltlib/lib/puppet/functions/run_script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ def run_script_with_description(scope, script, targets, description = nil, optio
.from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'run_script')
end

if options.key?('arguments') && options.key?('pwsh_params')
raise Bolt::ValidationError, "Cannot specify both 'arguments' and 'pwsh_params'"
end

arguments = options['arguments'] || []
pwsh_params = options['pwsh_params']
options = options.select { |opt| opt.start_with?('_') }.transform_keys { |k| k.sub(/^_/, '').to_sym }
options[:description] = description if description
options[:pwsh_params] = pwsh_params if pwsh_params

executor = Puppet.lookup(:bolt_executor)
inventory = Puppet.lookup(:bolt_inventory)
Expand Down
21 changes: 21 additions & 0 deletions bolt-modules/boltlib/spec/functions/run_script_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@
.and_return(result_set)
end

it 'with pwsh_params' do
executor.expects(:run_script)
.with([target], full_path, [], { pwsh_params: { 'Name' => 'BoltyMcBoltface' } }, [])
.returns(result_set)
inventory.expects(:get_targets).with(hostname).returns([target])

is_expected.to run
.with_params('test/uploads/hostname.sh',
hostname,
{ 'pwsh_params' => { 'Name' => 'BoltyMcBoltface' } })
.and_return(result_set)
end

it 'with _run_as' do
executor.expects(:run_script)
.with([target], full_path, [], { run_as: 'root' }, [])
Expand Down Expand Up @@ -246,4 +259,12 @@
.and_raise_error(/Plan language function 'run_script' cannot be used/)
end
end

context 'with arguments and pwsh_params' do
it 'fails' do
is_expected.to run
.with_params('test/uploads/script.sh', [], 'arguments' => [], 'pwsh_params' => {})
.and_raise_error(/Cannot specify both 'arguments' and 'pwsh_params'/)
end
end
end
11 changes: 8 additions & 3 deletions lib/bolt/shell/powershell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,21 @@ def run_script(script, arguments, options = {}, position = [])
arguments = unwrap_sensitive_args(arguments)
with_tmpdir do |dir|
script_path = write_executable(dir, script)
command = if powershell_file?(script_path)
command = if powershell_file?(script_path) && options[:pwsh_params]
# Scripts run with pwsh_params can be run like tasks
Snippets.ps_task(script_path, options[:pwsh_params])
elsif powershell_file?(script_path)
Snippets.run_script(arguments, script_path)
else
path, args = *process_from_extension(script_path)
args += escape_arguments(arguments)
execute_process(path, args)
end
command = [*env_declarations(options[:env_vars]), command].join("\r\n") if options[:env_vars]
env_assignments = options[:env_vars] ? env_declarations(options[:env_vars]) : []
shell_init = options[:pwsh_params] ? Snippets.shell_init : ''

output = execute([shell_init, *env_assignments, command].join("\r\n"))

output = execute(command)
Bolt::Result.for_command(target,
output.stdout.string,
output.stderr.string,
Expand Down
1 change: 1 addition & 0 deletions lib/bolt/shell/powershell/snippets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def run_script(arguments, script_path)
build_arg_list = arguments.map do |a|
"$invokeArgs.ArgumentList += @'\n#{a}\n'@"
end.join("\n")

<<~PS
$invokeArgs = @{
ScriptBlock = (Get-Command "#{script_path}").ScriptBlock
Expand Down
18 changes: 18 additions & 0 deletions spec/integration/transport/winrm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,24 @@ def stub_winrm_to_raise(klass, message)
end
end

it "can run a PowerShell script with named parameters", winrm: true do
contents = <<~PS
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True)]
[String]
$Name
)
Write-Output "Hello $Name"
PS

with_tempfile_containing('script-test-winrm', contents, '.ps1') do |file|
result = winrm.run_script(target, file.path, [], pwsh_params: { 'Name' => 'BoltyMcBoltface' })
expect(result['stdout']).to eq("Hello BoltyMcBoltface\r\n")
end
end

it "ignores run_as", winrm: true do
contents = "Write-Output \"hellote\""
with_tempfile_containing('script-test-winrm', contents, '.ps1') do |file|
Expand Down

0 comments on commit 69427bb

Please sign in to comment.