win_file: Handle [] in paths, fix touch in check mode (#37901)
* win_file: Handle [] in paths, fix touch in check mode * Fixed typo for p/invoke command
This commit is contained in:
parent
bbfe7a8b2f
commit
4b57fa91d0
2 changed files with 120 additions and 32 deletions
|
@ -28,12 +28,19 @@ using System.Runtime.InteropServices;
|
|||
namespace Ansible.Command {
|
||||
public class SymLinkHelper {
|
||||
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
||||
public static extern bool RemoveDirectory(string lpPathName);
|
||||
public static extern bool DeleteFileW(string lpFileName);
|
||||
|
||||
public static void DeleteSymLink(string linkPathName) {
|
||||
bool result = RemoveDirectory(linkPathName);
|
||||
if (result == false)
|
||||
throw new Exception(String.Format("Error deleting symlink: {0}", new Win32Exception(Marshal.GetLastWin32Error()).Message));
|
||||
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
||||
public static extern bool RemoveDirectoryW(string lpPathName);
|
||||
|
||||
public static void DeleteDirectory(string path) {
|
||||
if (!RemoveDirectoryW(path))
|
||||
throw new Exception(String.Format("RemoveDirectoryW({0}) failed: {1}", path, new Win32Exception(Marshal.GetLastWin32Error()).Message));
|
||||
}
|
||||
|
||||
public static void DeleteFile(string path) {
|
||||
if (!DeleteFileW(path))
|
||||
throw new Exception(String.Format("DeleteFileW({0}) failed: {1}", path, new Win32Exception(Marshal.GetLastWin32Error()).Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,13 +53,19 @@ function Remove-File($file, $checkmode) {
|
|||
if ($file.Attributes -band [System.IO.FileAttributes]::ReparsePoint) {
|
||||
# Bug with powershell, if you try and delete a symbolic link that is pointing
|
||||
# to an invalid path it will fail, using Win32 API to do this instead
|
||||
if (-Not $checkmode) {
|
||||
[Ansible.Command.SymLinkHelper]::DeleteSymLink($file.FullName)
|
||||
if ($file.PSIsContainer) {
|
||||
if (-not $checkmode) {
|
||||
[Ansible.Command.SymLinkHelper]::DeleteDirectory($file.FullName)
|
||||
}
|
||||
} else {
|
||||
if (-not $checkmode) {
|
||||
[Ansible.Command.SymlinkHelper]::DeleteFile($file.FullName)
|
||||
}
|
||||
}
|
||||
} elseif ($file.PSIsContainer) {
|
||||
Remove-Directory -directory $file -checkmode $checkmode
|
||||
} else {
|
||||
Remove-Item -Path $file.FullName -Force -WhatIf:$checkmode
|
||||
Remove-Item -LiteralPath $file.FullName -Force -WhatIf:$checkmode
|
||||
}
|
||||
} catch [Exception] {
|
||||
Fail-Json $result "Failed to delete $($file.FullName): $($_.Exception.Message)"
|
||||
|
@ -63,21 +76,24 @@ function Remove-Directory($directory, $checkmode) {
|
|||
foreach ($file in Get-ChildItem $directory.FullName) {
|
||||
Remove-File -file $file -checkmode $checkmode
|
||||
}
|
||||
Remove-Item -Path $directory.FullName -Force -Recurse -WhatIf:$checkmode
|
||||
Remove-Item -LiteralPath $directory.FullName -Force -Recurse -WhatIf:$checkmode
|
||||
}
|
||||
|
||||
|
||||
if ($state -eq "touch") {
|
||||
if (Test-Path -Path $path) {
|
||||
(Get-ChildItem -Path $path).LastWriteTime = Get-Date
|
||||
if (Test-Path -LiteralPath $path) {
|
||||
if (-not $check_mode) {
|
||||
(Get-ChildItem -LiteralPath $path).LastWriteTime = Get-Date
|
||||
}
|
||||
$result.changed = $true
|
||||
} else {
|
||||
Write-Output $null | Out-File -FilePath $path -Encoding ASCII -WhatIf:$check_mode
|
||||
Write-Output $null | Out-File -LiteralPath $path -Encoding ASCII -WhatIf:$check_mode
|
||||
$result.changed = $true
|
||||
}
|
||||
}
|
||||
|
||||
if (Test-Path -Path $path) {
|
||||
$fileinfo = Get-Item -Path $path
|
||||
if (Test-Path -LiteralPath $path) {
|
||||
$fileinfo = Get-Item -LiteralPath $path
|
||||
if ($state -eq "absent") {
|
||||
Remove-File -file $fileinfo -checkmode $check_mode
|
||||
$result.changed = $true
|
||||
|
@ -109,7 +125,7 @@ if (Test-Path -Path $path) {
|
|||
New-Item -Path $path -ItemType Directory -WhatIf:$check_mode | Out-Null
|
||||
} catch {
|
||||
if ($_.CategoryInfo.Category -eq "ResourceExists") {
|
||||
$fileinfo = Get-Item $_.CategoryInfo.TargetName
|
||||
$fileinfo = Get-Item -LiteralPath $_.CategoryInfo.TargetName
|
||||
if ($state -eq "directory" -and -not $fileinfo.PsIsContainer) {
|
||||
Fail-Json $result "path $path is not a directory"
|
||||
}
|
||||
|
|
|
@ -41,27 +41,75 @@
|
|||
- "file2_result.changed == false"
|
||||
# - "file2_result.state == 'absent'"
|
||||
|
||||
- name: verify we can touch a file (check)
|
||||
win_file:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
state: touch
|
||||
register: touch_file_check
|
||||
check_mode: yes
|
||||
|
||||
- name: get details of touched file (check)
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
register: touch_file_actual_check
|
||||
|
||||
- name: assert touch a file (check)
|
||||
assert:
|
||||
that:
|
||||
- touch_file_check.changed
|
||||
- not touch_file_actual_check.stat.exists
|
||||
|
||||
- name: verify we can touch a file
|
||||
win_file: path={{win_output_dir}}/baz.txt state=touch
|
||||
register: file3_result
|
||||
win_file: path={{win_output_dir}}/touch.txt state=touch
|
||||
register: touch_file
|
||||
|
||||
- name: verify that the file was marked as changed
|
||||
- name: get details of touched file
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
register: touch_file_actual
|
||||
|
||||
- name: assert touch a file
|
||||
assert:
|
||||
that:
|
||||
- "file3_result.changed == true"
|
||||
# - "file3_result.state == 'file'"
|
||||
# - "file3_result.mode == '0644'"
|
||||
- touch_file.changed
|
||||
- touch_file_actual.stat.exists
|
||||
- touch_file_actual.stat.size == 0
|
||||
|
||||
- name: stat the touched file
|
||||
win_stat: path={{win_output_dir}}/baz.txt state=touch
|
||||
register: file3_stat_result
|
||||
- name: touch a file again
|
||||
win_file:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
state: touch
|
||||
register: touch_file_again
|
||||
|
||||
- name: verify that the touched file exists and is size 0
|
||||
- name: get details of touched file again
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
register: touch_file_actual_again
|
||||
|
||||
- name: assert touch a file again
|
||||
assert:
|
||||
that:
|
||||
- "file3_stat_result.changed == false"
|
||||
- "file3_stat_result.stat.size == 0"
|
||||
- "file3_stat_result.stat.exists == true"
|
||||
- touch_file_again.changed
|
||||
- touch_file_actual_again.stat.lastwritetime > touch_file_actual.stat.lastwritetime
|
||||
|
||||
- name: touch an existing file in check mode
|
||||
win_file:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
state: touch
|
||||
register: touch_file_again_check
|
||||
check_mode: yes
|
||||
|
||||
- name: get details of touched file in check mode
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\touch.txt'
|
||||
register: touch_file_again_actual_check
|
||||
|
||||
- name: assert touch an existing file in check mode
|
||||
assert:
|
||||
that:
|
||||
- touch_file_again_check.changed
|
||||
- touch_file_again_actual_check.stat.lastwritetime == touch_file_actual_again.stat.lastwritetime
|
||||
|
||||
#- name: change file mode
|
||||
# win_file: path={{win_output_dir}}/baz.txt mode=0600
|
||||
# register: file4_result
|
||||
|
@ -468,11 +516,14 @@
|
|||
- "stat_result.stat.exists == False"
|
||||
|
||||
- name: create dir with spaces and parens in the dir name
|
||||
win_file: path="{{win_output_dir}}/dir with spaces (and parens)" state=directory
|
||||
win_file:
|
||||
path: '{{win_output_dir}}\dir with spaces (and parens) [block]'
|
||||
state: directory
|
||||
register: file_result
|
||||
|
||||
- name: stat the directory with spaces and parens
|
||||
win_stat: path="{{win_output_dir}}/dir with spaces (and parens)"
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\dir with spaces (and parens) [block]'
|
||||
register: stat_result
|
||||
|
||||
- name: check dir with spaces and parens in the dir name has been created
|
||||
|
@ -482,12 +533,33 @@
|
|||
- stat_result.stat.exists
|
||||
- stat_result.stat.isdir
|
||||
|
||||
- name: create file in dir with special char
|
||||
win_file:
|
||||
path: '{{win_output_dir}}\dir with spaces (and parens) [block]\file[1].txt'
|
||||
state: touch
|
||||
register: file_result
|
||||
|
||||
- name: stat the file with spaces and parens
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\dir with spaces (and parens) [block]\file[1].txt'
|
||||
register: stat_result
|
||||
|
||||
- name: check file in dir with spaces and parens exist
|
||||
assert:
|
||||
that:
|
||||
- file_result.changed
|
||||
- stat_result.stat.exists
|
||||
- stat_result.stat.isreg
|
||||
|
||||
- name: remove dir with spaces and parens in the dir name
|
||||
win_file: path="{{win_output_dir}}/dir with spaces (and parens)" state=absent
|
||||
win_file:
|
||||
path: '{{win_output_dir}}/dir with spaces (and parens) [block]'
|
||||
state: absent
|
||||
register: file_result
|
||||
|
||||
- name: stat the dir with spaces and parens in the dir name
|
||||
win_stat: path="{{win_output_dir}}/dir with spaces (and parens)"
|
||||
win_stat:
|
||||
path: '{{win_output_dir}}\dir with spaces (and parens) [block]'
|
||||
register: stat_result
|
||||
|
||||
- name: assert dir with spaces and parens in the dir name was removed
|
||||
|
|
Loading…
Reference in a new issue