lib/bolt/shell/powershell.rb in bolt-2.6.0 vs lib/bolt/shell/powershell.rb in bolt-2.7.0

- old
+ new

@@ -4,11 +4,11 @@ module Bolt class Shell class Powershell < Shell DEFAULT_EXTENSIONS = Set.new(%w[.ps1 .rb .pp]) - PS_ARGS = %w[-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -File].freeze + PS_ARGS = %w[-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass].freeze def initialize(target, conn) super extensions = [target.options['extensions'] || []].flatten.map { |ext| ext[0] != '.' ? '.' + ext : ext } @@ -43,11 +43,11 @@ %W[-S "#{path}"] ] when '.ps1' [ 'powershell.exe', - [*PS_ARGS, path] + [*PS_ARGS, '-File', path] ] when '.pp' [ 'puppet.bat', %W[apply "#{path}"] @@ -117,28 +117,38 @@ message = "Could not create directories: #{result.stderr.string}" raise Bolt::Node::FileError.new(message, 'MKDIR_ERROR') end end - def make_tempdir + def make_tmpdir find_parent = target.options['tmpdir'] ? "\"#{target.options['tmpdir']}\"" : '[System.IO.Path]::GetTempPath()' - result = execute(Snippets.make_tempdir(find_parent)) + result = execute(Snippets.make_tmpdir(find_parent)) if result.exit_code != 0 - raise Bolt::Node::FileError.new("Could not make tempdir: #{result.stderr.string}", 'TEMPDIR_ERROR') + raise Bolt::Node::FileError.new("Could not make tmpdir: #{result.stderr.string}", 'TMPDIR_ERROR') end result.stdout.string.chomp end def rmdir(dir) execute(Snippets.rmdir(dir)) end - def with_tempdir - dir = make_tempdir - yield dir + def with_tmpdir + unless @tmpdir + # Only cleanup the directory afterward if we made it to begin with + owner = true + @tmpdir = make_tmpdir + end + yield @tmpdir ensure - rmdir(dir) + if owner && @tmpdir + if target.options['cleanup'] + rmdir(@tmpdir) + else + @logger.warn("Skipping cleanup of tmpdir '#{@tmpdir}'") + end + end end def run_ps_task(task_path, arguments, input_method) # NOTE: cannot redirect STDIN to a .ps1 script inside of PowerShell # must create new powershell.exe process like other interpreters @@ -165,11 +175,11 @@ end def run_script(script, arguments, _options = {}) # unpack any Sensitive data arguments = unwrap_sensitive_args(arguments) - with_tempdir do |dir| + with_tmpdir do |dir| script_path = write_executable(dir, script) command = if powershell_file?(script_path) Snippets.run_script(arguments, script_path) else path, args = *process_from_extension(script_path) @@ -192,11 +202,11 @@ extra_files = implementation['files'] input_method ||= powershell_file?(executable) ? 'powershell' : 'both' # unpack any Sensitive data arguments = unwrap_sensitive_args(arguments) - with_tempdir do |dir| + with_tmpdir do |dir| if extra_files.empty? task_dir = dir else # TODO: optimize upload of directories arguments['_installdir'] = dir @@ -241,9 +251,19 @@ task.name) end end def execute(command) + if conn.max_command_length && command.length > conn.max_command_length + return with_tmpdir do |dir| + command += "\r\nif (!$?) { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }" + script_file = File.join(dir, "#{SecureRandom.uuid}_wrapper.ps1") + conn.copy_file(StringIO.new(command), script_file) + args = escape_arguments([script_file]) + script_invocation = ['powershell.exe', *PS_ARGS, '-File', *args].join(' ') + execute(script_invocation) + end + end inp, out, err, t = conn.execute(command) result = Bolt::Node::Output.new inp.close out.binmode