powershell: Respect remote_tmp path set by the user (#40210)
* powershell: Respect remote_tmp path set by the user * Fixed up linting error and typo * Added changelog
This commit is contained in:
parent
070a5557d1
commit
f84f3de7c2
18 changed files with 281 additions and 203 deletions
2
changelogs/fragments/powershell_use_set_tmpdir.yaml
Normal file
2
changelogs/fragments/powershell_use_set_tmpdir.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- powershell - use the tmpdir set by `remote_tmp` for become/async tasks instead of the generic $env:TEMP - https://github.com/ansible/ansible/pull/40210
|
|
@ -335,7 +335,25 @@ Function Load-CommandUtils {
|
|||
# [Ansible.CommandUtil]::RunCommand(string lpApplicationName, string lpCommandLine, string lpCurrentDirectory, string stdinInput, string environmentBlock)
|
||||
#
|
||||
# there are also numerous P/Invoke methods that can be called if you are feeling adventurous
|
||||
|
||||
# FUTURE: find a better way to get the _ansible_remote_tmp variable
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
|
||||
$remote_tmp = $original_tmp
|
||||
$module_params = Get-Variable -Name complex_args -ErrorAction SilentlyContinue
|
||||
if ($module_params) {
|
||||
if ($module_params.Value.ContainsKey("_ansible_remote_tmp") ) {
|
||||
$remote_tmp = $module_params.Value["_ansible_remote_tmp"]
|
||||
$remote_tmp = [System.Environment]::ExpandEnvironmentVariables($remote_tmp)
|
||||
}
|
||||
}
|
||||
|
||||
$env:TMP = $remote_tmp
|
||||
$env:TEMP = $remote_tmp
|
||||
Add-Type -TypeDefinition $process_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
}
|
||||
|
||||
Function Get-ExecutablePath($executable, $directory) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||
|
||||
Function Load-LinkUtils() {
|
||||
Add-Type -TypeDefinition @'
|
||||
$link_util = @'
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -464,6 +464,25 @@ namespace Ansible
|
|||
}
|
||||
'@
|
||||
|
||||
# FUTURE: find a better way to get the _ansible_remote_tmp variable
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
|
||||
$remote_tmp = $original_tmp
|
||||
$module_params = Get-Variable -Name complex_args -ErrorAction SilentlyContinue
|
||||
if ($module_params) {
|
||||
if ($module_params.Value.ContainsKey("_ansible_remote_tmp") ) {
|
||||
$remote_tmp = $module_params.Value["_ansible_remote_tmp"]
|
||||
$remote_tmp = [System.Environment]::ExpandEnvironmentVariables($remote_tmp)
|
||||
}
|
||||
}
|
||||
|
||||
$env:TMP = $remote_tmp
|
||||
$env:TEMP = $remote_tmp
|
||||
Add-Type -TypeDefinition $link_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
[Ansible.LinkUtil]::EnablePrivilege("SeBackupPrivilege")
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ $results = @{changed=$false}
|
|||
$parsed_args = Parse-Args $args
|
||||
$jid = Get-AnsibleParam $parsed_args "jid" -failifempty $true -resultobj $results
|
||||
$mode = Get-AnsibleParam $parsed_args "mode" -Default "status" -ValidateSet "status","cleanup"
|
||||
$_remote_tmp = Get-AnsibleParam $parsed_args "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
# setup logging directory
|
||||
$log_path = [System.IO.Path]::Combine($env:LOCALAPPDATA, ".ansible_async", $jid)
|
||||
$log_path = [System.IO.Path]::Combine($_remote_tmp, ".ansible_async", $jid)
|
||||
|
||||
If(-not $(Test-Path $log_path))
|
||||
{
|
||||
|
|
|
@ -120,7 +120,16 @@ namespace Ansible {
|
|||
}
|
||||
"@
|
||||
|
||||
$params = Parse-Args $args;
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
add-type $AdjustTokenPrivileges
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
Function SetPrivilegeTokens() {
|
||||
# Set privilege tokens only if admin.
|
||||
|
@ -143,7 +152,7 @@ Function SetPrivilegeTokens() {
|
|||
}
|
||||
|
||||
|
||||
$params = Parse-Args $args;
|
||||
|
||||
|
||||
$result = @{
|
||||
changed = $false
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
#Requires -Module Ansible.ModuleUtils.Legacy
|
||||
#Requires -Module Ansible.ModuleUtils.ArgvParser
|
||||
#Requires -Module Ansible.ModuleUtils.CommandUtil
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
|
@ -27,120 +29,60 @@ if (-not (Get-Command -Name $executable -ErrorAction SilentlyContinue)) {
|
|||
Fail-Json $result "Command '$executable' not found in $env:PATH."
|
||||
}
|
||||
|
||||
$util_def = @'
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ansible.Command {
|
||||
|
||||
public static class NativeUtil {
|
||||
|
||||
public static void GetProcessOutput(StreamReader stdoutStream, StreamReader stderrStream, out string stdout, out string stderr) {
|
||||
var sowait = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||
var sewait = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||
|
||||
string so = null, se = null;
|
||||
|
||||
ThreadPool.QueueUserWorkItem((s)=> {
|
||||
so = stdoutStream.ReadToEnd();
|
||||
sowait.Set();
|
||||
});
|
||||
|
||||
ThreadPool.QueueUserWorkItem((s) => {
|
||||
se = stderrStream.ReadToEnd();
|
||||
sewait.Set();
|
||||
});
|
||||
|
||||
foreach(var wh in new WaitHandle[] { sowait, sewait })
|
||||
wh.WaitOne();
|
||||
|
||||
stdout = so;
|
||||
stderr = se;
|
||||
}
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
Add-Type -TypeDefinition $util_def
|
||||
|
||||
$arguments = ""
|
||||
$arguments = @()
|
||||
|
||||
if ($include_volumes) {
|
||||
foreach ($volume in $include_volumes) {
|
||||
if ($volume.Length -eq 1) {
|
||||
$arguments += " $($volume):"
|
||||
$arguments += "$($volume):"
|
||||
} else {
|
||||
$arguments += " $volume"
|
||||
$arguments += $volume
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$arguments = " /C"
|
||||
$arguments += "/C"
|
||||
}
|
||||
|
||||
if ($exclude_volumes) {
|
||||
$arguments += " /E"
|
||||
$arguments += "/E"
|
||||
foreach ($volume in $exclude_volumes) {
|
||||
if ($volume.Length -eq 1) {
|
||||
$arguments += " $($volume):"
|
||||
$arguments += "$($volume):"
|
||||
} else {
|
||||
$arguments += " $volume"
|
||||
$arguments += $volume
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($check_mode) {
|
||||
$arguments += " /A"
|
||||
$arguments += "/A"
|
||||
} elseif ($freespace_consolidation) {
|
||||
$arguments += " /X"
|
||||
$arguments += "/X"
|
||||
}
|
||||
|
||||
if ($priority -eq "normal") {
|
||||
$arguments += " /H"
|
||||
$arguments += "/H"
|
||||
}
|
||||
|
||||
if ($parallel) {
|
||||
$arguments += " /M"
|
||||
$arguments += "/M"
|
||||
}
|
||||
|
||||
$arguments += " /V"
|
||||
$arguments += "/V"
|
||||
|
||||
$proc = New-Object System.Diagnostics.Process
|
||||
$psi = $proc.StartInfo
|
||||
$psi.FileName = $executable
|
||||
$psi.Arguments = $arguments
|
||||
$psi.RedirectStandardOutput = $true
|
||||
$psi.RedirectStandardError = $true
|
||||
$psi.UseShellExecute = $false
|
||||
|
||||
$result.cmd = "$executable$arguments"
|
||||
$argument_string = Argv-ToString -arguments $arguments
|
||||
|
||||
$start_datetime = [DateTime]::UtcNow
|
||||
$result.cmd = "$executable $argument_string"
|
||||
|
||||
Try {
|
||||
$proc.Start() | Out-Null # will always return $true for non shell-exec cases
|
||||
} Catch [System.ComponentModel.Win32Exception] {
|
||||
# fail nicely for "normal" error conditions
|
||||
# FUTURE: this probably won't work on Nano Server
|
||||
$excep = $_
|
||||
$result.rc = $excep.Exception.NativeErrorCode
|
||||
Fail-Json $result $excep.Exception.Message
|
||||
}
|
||||
|
||||
$stdout = $stderr = [string] $null
|
||||
|
||||
[Ansible.Command.NativeUtil]::GetProcessOutput($proc.StandardOutput, $proc.StandardError, [ref] $stdout, [ref] $stderr) | Out-Null
|
||||
|
||||
$result.stdout = $stdout
|
||||
$result.stderr = $stderr
|
||||
|
||||
$proc.WaitForExit() | Out-Null
|
||||
|
||||
$result.rc = $proc.ExitCode
|
||||
$command_result = Run-Command -command "$executable $argument_string"
|
||||
|
||||
$end_datetime = [DateTime]::UtcNow
|
||||
|
||||
$result.stdout = $command_result.stdout
|
||||
$result.stderr = $command_result.stderr
|
||||
$result.rc = $command_result.rc
|
||||
|
||||
$result.start = $start_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
|
||||
$result.end = $end_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
|
||||
$result.delta = $($end_datetime - $start_datetime).ToString("h\:mm\:ss\.ffffff")
|
||||
|
|
|
@ -11,6 +11,7 @@ $ErrorActionPreference = "Stop"
|
|||
$params = Parse-Args $args -supports_check_mode $true
|
||||
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default $false
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true -aliases "dest","name"
|
||||
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -validateset "absent","directory","file","touch"
|
||||
|
@ -51,7 +52,13 @@ namespace Ansible.Command {
|
|||
}
|
||||
}
|
||||
"@
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $symlink_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
# Used to delete directories and files with logic on handling symbolic links
|
||||
function Remove-File($file, $checkmode) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$paths = Get-AnsibleParam -obj $params -name 'paths' -failifempty $true
|
||||
|
||||
|
@ -70,7 +71,13 @@ namespace Ansible.Command {
|
|||
}
|
||||
}
|
||||
"@
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $symlink_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
Function Assert-Age($info) {
|
||||
$valid_match = $true
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$params = Parse-Args $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$webclient_util = @"
|
||||
using System.Net;
|
||||
|
@ -26,7 +29,13 @@ $webclient_util = @"
|
|||
}
|
||||
}
|
||||
"@
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $webclient_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
|
||||
Function CheckModified-File($url, $dest, $headers, $credentials, $timeout, $use_proxy, $proxy) {
|
||||
|
@ -138,10 +147,6 @@ Function Download-File($result, $url, $dest, $headers, $credentials, $timeout, $
|
|||
$result.dest = $dest
|
||||
}
|
||||
|
||||
|
||||
$params = Parse-Args $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||
|
||||
$url = Get-AnsibleParam -obj $params -name "url" -type "str" -failifempty $true
|
||||
$dest = Get-AnsibleParam -obj $params -name "dest" -type "path" -failifempty $true
|
||||
$timeout = Get-AnsibleParam -obj $params -name "timeout" -type "int" -default 10
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#!powershell
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
#Requires -Module Ansible.ModuleUtils.Legacy
|
||||
#Requires -Module Ansible.ModuleUtils.ArgvParser
|
||||
#Requires -Module Ansible.ModuleUtils.CommandUtil
|
||||
|
||||
# See also: https://technet.microsoft.com/en-us/sysinternals/pxexec.aspx
|
||||
|
||||
|
@ -35,153 +36,99 @@ If (-Not (Get-Command $executable -ErrorAction SilentlyContinue)) {
|
|||
Fail-Json $result "Executable '$executable' was not found."
|
||||
}
|
||||
|
||||
$util_def = @'
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ansible.Command {
|
||||
|
||||
public static class NativeUtil {
|
||||
|
||||
public static void GetProcessOutput(StreamReader stdoutStream, StreamReader stderrStream, out string stdout, out string stderr) {
|
||||
var sowait = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||
var sewait = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||
|
||||
string so = null, se = null;
|
||||
|
||||
ThreadPool.QueueUserWorkItem((s)=> {
|
||||
so = stdoutStream.ReadToEnd();
|
||||
sowait.Set();
|
||||
});
|
||||
|
||||
ThreadPool.QueueUserWorkItem((s) => {
|
||||
se = stderrStream.ReadToEnd();
|
||||
sewait.Set();
|
||||
});
|
||||
|
||||
foreach(var wh in new WaitHandle[] { sowait, sewait })
|
||||
wh.WaitOne();
|
||||
|
||||
stdout = so;
|
||||
stderr = se;
|
||||
}
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
Add-Type -TypeDefinition $util_def
|
||||
|
||||
$arguments = ""
|
||||
$arguments = @()
|
||||
|
||||
If ($nobanner -eq $true) {
|
||||
$arguments += " -nobanner"
|
||||
$arguments += "-nobanner"
|
||||
}
|
||||
|
||||
# Support running on local system if no hostname is specified
|
||||
If ($hostnames) {
|
||||
$arguments += " \\" + $($hostnames | sort -Unique) -join ','
|
||||
$hostname_argument = ($hostnames | sort -Unique) -join ','
|
||||
$arguments += "\\$hostname_argument"
|
||||
}
|
||||
|
||||
# Username is optional
|
||||
If ($username -ne $null) {
|
||||
$arguments += " -u `"$username`""
|
||||
$arguments += "-u"
|
||||
$arguments += $username
|
||||
}
|
||||
|
||||
# Password is optional
|
||||
If ($password -ne $null) {
|
||||
$arguments += " -p `"$password`""
|
||||
$arguments += "-p"
|
||||
$arguments += $password
|
||||
}
|
||||
|
||||
If ($chdir -ne $null) {
|
||||
$arguments += " -w `"$chdir`""
|
||||
$arguments += "-w"
|
||||
$arguments += $chdir
|
||||
}
|
||||
|
||||
If ($wait -eq $false) {
|
||||
$arguments += " -d"
|
||||
$arguments += "-d"
|
||||
}
|
||||
|
||||
If ($noprofile -eq $true) {
|
||||
$arguments += " -e"
|
||||
$arguments += "-e"
|
||||
}
|
||||
|
||||
If ($elevated -eq $true) {
|
||||
$arguments += " -h"
|
||||
$arguments += "-h"
|
||||
}
|
||||
|
||||
If ($system -eq $true) {
|
||||
$arguments += " -s"
|
||||
$arguments += "-s"
|
||||
}
|
||||
|
||||
If ($interactive -eq $true) {
|
||||
$arguments += " -i"
|
||||
$arguments += "-i"
|
||||
}
|
||||
|
||||
If ($limited -eq $true) {
|
||||
$arguments += " -l"
|
||||
$arguments += "-l"
|
||||
}
|
||||
|
||||
If ($priority -ne $null) {
|
||||
$arguments += " -$priority"
|
||||
$arguments += "-$priority"
|
||||
}
|
||||
|
||||
If ($timeout -ne $null) {
|
||||
$arguments += " -n $timeout"
|
||||
$arguments += "-n"
|
||||
$arguments += $timeout
|
||||
}
|
||||
|
||||
# Add additional advanced options
|
||||
If ($extra_opts) {
|
||||
ForEach ($opt in $extra_opts) {
|
||||
$arguments += " $opt"
|
||||
$arguments += $opt
|
||||
}
|
||||
}
|
||||
|
||||
$arguments += " -accepteula"
|
||||
$arguments += "-accepteula"
|
||||
$arguments += $command
|
||||
|
||||
$proc = New-Object System.Diagnostics.Process
|
||||
$psi = $proc.StartInfo
|
||||
$psi.FileName = $executable
|
||||
$psi.Arguments = "$arguments $command"
|
||||
$psi.RedirectStandardOutput = $true
|
||||
$psi.RedirectStandardError = $true
|
||||
$psi.UseShellExecute = $false
|
||||
|
||||
$result.psexec_command = "$executable$arguments $command"
|
||||
$argument_string = Argv-ToString -arguments $arguments
|
||||
|
||||
$start_datetime = [DateTime]::UtcNow
|
||||
$result.psexec_command = "$executable $argument_string"
|
||||
|
||||
Try {
|
||||
$proc.Start() | Out-Null # will always return $true for non shell-exec cases
|
||||
} Catch [System.ComponentModel.Win32Exception] {
|
||||
# fail nicely for "normal" error conditions
|
||||
# FUTURE: this probably won't work on Nano Server
|
||||
$excep = $_
|
||||
$result.rc = $excep.Exception.NativeErrorCode
|
||||
Fail-Json $result $excep.Exception.Message
|
||||
}
|
||||
|
||||
$stdout = $stderr = [string] $null
|
||||
|
||||
[Ansible.Command.NativeUtil]::GetProcessOutput($proc.StandardOutput, $proc.StandardError, [ref] $stdout, [ref] $stderr) | Out-Null
|
||||
|
||||
$result.stdout = $stdout
|
||||
$result.stderr = $stderr
|
||||
|
||||
$proc.WaitForExit() | Out-Null
|
||||
|
||||
If ($wait -eq $true) {
|
||||
$result.rc = $proc.ExitCode
|
||||
} else {
|
||||
$result.rc = 0
|
||||
$result.pid = $proc.ExitCode
|
||||
}
|
||||
$command_result = Run-Command -command "$executable $argument_string"
|
||||
|
||||
$end_datetime = [DateTime]::UtcNow
|
||||
|
||||
$result.stdout = $command_result.stdout
|
||||
$result.stderr = $command_result.stderr
|
||||
|
||||
If ($wait -eq $true) {
|
||||
$result.rc = $command_result.rc
|
||||
} else {
|
||||
$result.rc = 0
|
||||
$result.pid = $command_result.rc
|
||||
}
|
||||
|
||||
$result.start = $start_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
|
||||
$result.end = $end_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
|
||||
$result.delta = $($end_datetime - $start_datetime).ToString("h\:mm\:ss\.ffffff")
|
||||
|
||||
Exit-Json $result
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ $ErrorActionPreference = "Stop"
|
|||
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$path = Get-AnsibleParam -obj $params -name "path" -type "str" -failifempty $true -aliases "key"
|
||||
$name = Get-AnsibleParam -obj $params -name "name" -type "str" -aliases "entry","value"
|
||||
|
@ -370,7 +371,14 @@ if ($hive) {
|
|||
if (-not (Test-Path $hive)) {
|
||||
Fail-Json -obj $result -message "hive at path '$hive' is not valid or accessible, cannot load hive"
|
||||
}
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $registry_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
try {
|
||||
[Ansible.RegistryUtil]::EnablePrivileges()
|
||||
} catch [System.ComponentModel.Win32Exception] {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params "_ansible_check_mode" -type 'bool' -default $false
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$location = Get-AnsibleParam -obj $params -name 'location' -type 'str'
|
||||
$format = Get-AnsibleParam -obj $params -name 'format' -type 'str'
|
||||
|
@ -98,7 +99,14 @@ Function Copy-RegistryKey($source, $target) {
|
|||
Function Set-CultureLegacy($culture) {
|
||||
# For when Set-Culture is not available (Pre Windows 8 and Server 2012)
|
||||
$reg_key = 'HKCU:\Control Panel\International'
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $lctype_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
$lookup = New-Object Ansible.LocaleHelper($culture)
|
||||
# hex values are from http://www.pinvoke.net/default.aspx/kernel32/GetLocaleInfoEx.html
|
||||
|
|
|
@ -14,6 +14,7 @@ $ErrorActionPreference = "Stop"
|
|||
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
|
||||
$path = Get-AnsibleParam -obj $params -name "path" -type "str" -default "\"
|
||||
|
@ -82,7 +83,7 @@ if ($diff_mode) {
|
|||
$result.diff = @{}
|
||||
}
|
||||
|
||||
Add-Type -TypeDefinition @"
|
||||
$task_enums = @"
|
||||
public enum TASK_ACTION_TYPE // https://msdn.microsoft.com/en-us/library/windows/desktop/aa383553(v=vs.85).aspx
|
||||
{
|
||||
TASK_ACTION_EXEC = 0,
|
||||
|
@ -136,6 +137,14 @@ public enum TASK_TRIGGER_TYPE2 // https://msdn.microsoft.com/en-us/library/windo
|
|||
}
|
||||
"@
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $task_enums
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
########################
|
||||
### HELPER FUNCTIONS ###
|
||||
########################
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#Requires -Module Ansible.ModuleUtils.SID
|
||||
|
||||
$params = Parse-Args -arguments $args
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$path = Get-AnsibleParam -obj $params -name "path" -type "str" -default "\"
|
||||
$name = Get-AnsibleParam -obj $params -name "name" -type "str"
|
||||
|
||||
|
@ -15,7 +17,7 @@ $result = @{
|
|||
changed = $false
|
||||
}
|
||||
|
||||
Add-Type -TypeDefinition @"
|
||||
$task_enums = @"
|
||||
public enum TASK_ACTION_TYPE
|
||||
{
|
||||
TASK_ACTION_EXEC = 0,
|
||||
|
@ -67,6 +69,14 @@ public enum TASK_TRIGGER_TYPE2
|
|||
}
|
||||
"@
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $task_enums
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
Function Get-PropertyValue($task_property, $com, $property) {
|
||||
$raw_value = $com.$property
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ $ErrorActionPreference = 'Stop'
|
|||
$params = Parse-Args $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
|
||||
$users = Get-AnsibleParam -obj $params -name "users" -type "list" -failifempty $true
|
||||
|
@ -27,7 +28,7 @@ if ($diff_mode) {
|
|||
$result.diff = @{}
|
||||
}
|
||||
|
||||
Add-Type -TypeDefinition @"
|
||||
$sec_helper_util = @"
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -266,6 +267,14 @@ namespace Ansible
|
|||
}
|
||||
"@
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $sec_helper_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
Function Compare-UserList($existing_users, $new_users) {
|
||||
$added_users = [String[]]@()
|
||||
$removed_users = [String[]]@()
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$params = Parse-Args $args -supports_check_mode $true
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$session_util = @'
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
@ -780,7 +783,14 @@ namespace Ansible
|
|||
}
|
||||
'@
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $session_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
$session_info = [Ansible.SessionUtil]::GetSessionInfo()
|
||||
|
||||
Function Convert-Value($value) {
|
||||
|
|
|
@ -1090,27 +1090,6 @@ $exec_wrapper = {
|
|||
$DebugPreference = "Continue"
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# become process is run under a different console to the WinRM one so we
|
||||
# need to set the UTF-8 codepage again
|
||||
Add-Type -Debug:$false -TypeDefinition @'
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ansible
|
||||
{
|
||||
public class ConsoleCP
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool SetConsoleCP(UInt32 wCodePageID);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool SetConsoleOutputCP(UInt32 wCodePageID);
|
||||
}
|
||||
}
|
||||
'@
|
||||
[Ansible.ConsoleCP]::SetConsoleCP(65001) > $null
|
||||
[Ansible.ConsoleCP]::SetConsoleOutputCP(65001) > $null
|
||||
|
||||
Function ConvertTo-HashtableFromPsCustomObject($myPsObject) {
|
||||
$output = @{}
|
||||
$myPsObject | Get-Member -MemberType *Property | % {
|
||||
|
@ -1123,6 +1102,57 @@ namespace Ansible
|
|||
return $output
|
||||
}
|
||||
|
||||
Function Invoke-Win32Api {
|
||||
# Inspired by - Call a Win32 API in PowerShell without compiling C# code on
|
||||
# the disk
|
||||
# http://www.leeholmes.com/blog/2007/10/02/managing-ini-files-with-powershell/
|
||||
# https://blogs.technet.microsoft.com/heyscriptingguy/2013/06/27/use-powershell-to-interact-with-the-windows-api-part-3/
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)] [String]$DllName,
|
||||
[Parameter(Mandatory=$true)] [String]$MethodName,
|
||||
[Parameter(Mandatory=$true)] [Type]$ReturnType,
|
||||
[Parameter()] [Type[]]$ParameterTypes = [Type[]]@(),
|
||||
[Parameter()] [Object[]]$Parameters = [Object[]]@()
|
||||
)
|
||||
|
||||
$assembly = New-Object -TypeName System.Reflection.AssemblyName -ArgumentList "Win32ApiAssembly"
|
||||
$dynamic_assembly = [AppDomain]::CurrentDomain.DefineDynamicAssembly($assembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$dynamic_module = $dynamic_assembly.DefineDynamicModule("Win32Module", $false)
|
||||
$dynamic_type = $dynamic_module.DefineType("Win32Type", "Public, Class")
|
||||
|
||||
$dynamic_method = $dynamic_type.DefineMethod(
|
||||
$MethodName,
|
||||
[Reflection.MethodAttributes]"Public, Static",
|
||||
$ReturnType,
|
||||
$ParameterTypes
|
||||
)
|
||||
|
||||
$constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String])
|
||||
$custom_attributes = New-Object -TypeName Reflection.Emit.CustomAttributeBuilder -ArgumentList @(
|
||||
$constructor,
|
||||
$DllName
|
||||
)
|
||||
|
||||
$dynamic_method.SetCustomAttribute($custom_attributes)
|
||||
$win32_type = $dynamic_type.CreateType()
|
||||
$win32_type::$MethodName.Invoke($Parameters)
|
||||
}
|
||||
|
||||
# become process is run under a different console to the WinRM one so we
|
||||
# need to set the UTF-8 codepage again, this also needs to be set before
|
||||
# reading the stdin pipe that contains the module args specifying the
|
||||
# remote_tmp to use. Instead this will use reflection when calling the Win32
|
||||
# API no tmp files touch the disk
|
||||
$invoke_args = @{
|
||||
DllName = "kernel32.dll"
|
||||
ReturnType = [bool]
|
||||
ParameterTypes = @([UInt32])
|
||||
Parameters = @(65001)
|
||||
}
|
||||
Invoke-Win32Api -MethodName SetConsoleCP @invoke_args > $null
|
||||
Invoke-Win32Api -MethodName SetConsoleOutputCP @invoke_args > $null
|
||||
|
||||
# stream JSON including become_pw, ps_module_payload, bin_module_payload, become_payload, write_payload_path, preserve directives
|
||||
# exec runspace, capture output, cleanup, return module output
|
||||
|
||||
|
@ -1240,7 +1270,21 @@ Function Parse-BecomeFlags($flags) {
|
|||
Function Run($payload) {
|
||||
# NB: action popping handled inside subprocess wrapper
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$remote_tmp = $payload["module_args"]["_ansible_remote_tmp"]
|
||||
$remote_tmp = [System.Environment]::ExpandEnvironmentVariables($remote_tmp)
|
||||
if ($null -eq $remote_tmp) {
|
||||
$remote_tmp = $original_tmp
|
||||
}
|
||||
|
||||
# become process is run under a different console to the WinRM one so we
|
||||
# need to set the UTF-8 codepage again
|
||||
$env:TMP = $remote_tmp
|
||||
$env:TEMP = $remote_tmp
|
||||
Add-Type -TypeDefinition $helper_def -Debug:$false
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_tmp
|
||||
|
||||
$username = $payload.become_user
|
||||
$password = $payload.become_password
|
||||
|
@ -1252,7 +1296,7 @@ Function Run($payload) {
|
|||
}
|
||||
|
||||
# NB: CreateProcessWithTokenW commandline maxes out at 1024 chars, must bootstrap via filesystem
|
||||
$temp = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName() + ".ps1")
|
||||
$temp = [System.IO.Path]::Combine($remote_tmp, [System.IO.Path]::GetRandomFileName() + ".ps1")
|
||||
$exec_wrapper.ToString() | Set-Content -Path $temp
|
||||
$rc = 0
|
||||
|
||||
|
@ -1574,17 +1618,29 @@ Function Run($payload) {
|
|||
}
|
||||
"@ # END Ansible.Async native type definition
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$remote_tmp = $payload["module_args"]["_ansible_remote_tmp"]
|
||||
$remote_tmp = [System.Environment]::ExpandEnvironmentVariables($remote_tmp)
|
||||
if ($null -eq $remote_tmp) {
|
||||
$remote_tmp = $original_tmp
|
||||
}
|
||||
|
||||
# calculate the result path so we can include it in the worker payload
|
||||
$jid = $payload.async_jid
|
||||
$local_jid = $jid + "." + $pid
|
||||
|
||||
$results_path = [System.IO.Path]::Combine($env:LOCALAPPDATA, ".ansible_async", $local_jid)
|
||||
$results_path = [System.IO.Path]::Combine($remote_tmp, ".ansible_async", $local_jid)
|
||||
|
||||
$payload.async_results_path = $results_path
|
||||
|
||||
[System.IO.Directory]::CreateDirectory([System.IO.Path]::GetDirectoryName($results_path)) | Out-Null
|
||||
|
||||
$env:TMP = $remote_tmp
|
||||
$env:TEMP = $remote_tmp
|
||||
Add-Type -TypeDefinition $native_process_util -Debug:$false
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
# FUTURE: create under new job to ensure all children die on exit?
|
||||
|
||||
|
|
|
@ -159,6 +159,18 @@
|
|||
- nonascii_output.stdout_lines[0] == 'über den Fußgängerübergang gehen'
|
||||
- nonascii_output.stderr == ''
|
||||
|
||||
- name: test async with custom remote_tmp
|
||||
win_shell: echo hi
|
||||
register: async_custom_tmp
|
||||
async: 5
|
||||
vars:
|
||||
ansible_remote_tmp: '{{win_output_dir}}'
|
||||
|
||||
- name: assert results file is in the remote tmp specified
|
||||
assert:
|
||||
that:
|
||||
- async_custom_tmp.results_file == win_output_dir + '\\.ansible_async\\' + async_custom_tmp.ansible_job_id
|
||||
|
||||
# FUTURE: figure out why the last iteration of this test often fails on shippable
|
||||
#- name: loop async success
|
||||
# async_test:
|
||||
|
|
Loading…
Reference in a new issue