Feature/win stat extra info (#19148)

* Added more return results to win_stat

* Changed Win2012 methods to support older versions in setup

* staging of the tests to work with older servers
This commit is contained in:
Jordan Borean 2017-01-27 23:51:12 +01:00 committed by Matt Davis
parent a655e90e41
commit 971783a7fd
8 changed files with 925 additions and 108 deletions

View file

@ -225,14 +225,28 @@ Function Parse-Args($arguments, $supports_check_mode = $false)
# Helper function to calculate a hash of a file in a way which powershell 3 # Helper function to calculate a hash of a file in a way which powershell 3
# and above can handle: # and above can handle:
Function Get-FileChecksum($path) Function Get-FileChecksum($path, $algorithm = 'sha1')
{ {
If (Test-Path -PathType Leaf $path) If (Test-Path -PathType Leaf $path)
{ {
$sp = new-object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider; switch ($algorithm)
$fp = [System.IO.File]::Open($path, [System.IO.Filemode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite); {
$hash = [System.BitConverter]::ToString($sp.ComputeHash($fp)).Replace("-", "").ToLower(); 'md5' { $sp = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider }
$fp.Dispose(); 'sha1' { $sp = New-Object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider }
'sha256' { $sp = New-Object -TypeName System.Security.Cryptography.SHA256CryptoServiceProvider }
'sha384' { $sp = New-Object -TypeName System.Security.Cryptography.SHA384CryptoServiceProvider }
'sha512' { $sp = New-Object -TypeName System.Security.Cryptography.SHA512CryptoServiceProvider }
default { Fail-Json (New-Object PSObject) "Unsupported hash algorithm supplied '$algorithm'" }
}
If ($PSVersionTable.PSVersion.Major -ge 4) {
$raw_hash = Get-FileHash $path -Algorithm $algorithm
$hash = $raw_hash.Hash.ToLower()
} Else {
$fp = [System.IO.File]::Open($path, [System.IO.Filemode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite);
$hash = [System.BitConverter]::ToString($sp.ComputeHash($fp)).Replace("-", "").ToLower();
$fp.Dispose();
}
} }
ElseIf (Test-Path -PathType Container $path) ElseIf (Test-Path -PathType Container $path)
{ {

View file

@ -17,7 +17,51 @@
# WANT_JSON # WANT_JSON
# POWERSHELL_COMMON # POWERSHELL_COMMON
$params = Parse-Args $args $true; $params = Parse-Args -arguments $args -supports_check_mode $true;
# C# code to determine link target, copied from http://chrisbensen.blogspot.com.au/2010/06/getfinalpathnamebyhandle.html
$symlink_util = @"
using System;
using System.Text;
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Ansible.Command
{
public class SymLinkHelper
{
private const int FILE_SHARE_WRITE = 2;
private const int CREATION_DISPOSITION_OPEN_EXISTING = 3;
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags);
[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess,
int dwShareMode, IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
public static string GetSymbolicLinkTarget(System.IO.DirectoryInfo symlink)
{
SafeFileHandle directoryHandle = CreateFile(symlink.FullName, 0, 2, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero);
if(directoryHandle.IsInvalid)
throw new Win32Exception(Marshal.GetLastWin32Error());
StringBuilder path = new StringBuilder(512);
int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(), path, path.Capacity, 0);
if (size<0)
throw new Win32Exception(Marshal.GetLastWin32Error()); // The remarks section of GetFinalPathNameByHandle mentions the return being prefixed with "\\?\" // More information about "\\?\" here -> http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx
if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
return path.ToString().Substring(4);
else
return path.ToString();
}
}
}
"@
Add-Type -TypeDefinition $symlink_util
function Date_To_Timestamp($start_date, $end_date) function Date_To_Timestamp($start_date, $end_date)
{ {
@ -27,15 +71,26 @@ function Date_To_Timestamp($start_date, $end_date)
} }
} }
$path = Get-Attr $params "path" $FALSE; function Get-Hash($path, $algorithm) {
If ($path -eq $FALSE) # Using PowerShell V4 and above we can use some powershell cmdlets instead of .net
{ If ($PSVersionTable.PSVersion.Major -ge 4)
Fail-Json (New-Object psobject) "missing required argument: path"; {
$hash = (Get-FileHash $path -Algorithm $algorithm).Hash
}
Else
{
$net_algorithm = [Security.Cryptography.HashAlgorithm]::Create($algorithm)
$raw_hash = [System.BitConverter]::ToString($net_algorithm.ComputeHash([System.IO.File]::ReadAllBytes($path)))
$hash = $raw_hash -replace '-'
}
$hash.ToLower()
} }
$get_md5 = Get-Attr $params "get_md5" $TRUE | ConvertTo-Bool; $path = Get-AnsibleParam -obj $params -name 'path' -failifempty $true;
# until we support real aliasing, get the default value from get_md5 $get_md5 = Get-AnsibleParam -obj $params -name 'get_md5' -failifempty $false -default $true | ConvertTo-Bool;
$get_checksum = Get-Attr $params "get_checksum" $get_md5 | ConvertTo-Bool; $get_checksum = Get-AnsibleParam -obj $params -name 'get_checksum' -failifempty $false -default $true | ConvertTo-Bool;
$checksum_algorithm = Get-AnsibleParam -obj $params -name 'checksum_algorithm' -failifempty $false -default 'sha1' -ValidateSet 'sha1','sha256','sha384','sha512'
$result = New-Object psobject @{ $result = New-Object psobject @{
stat = New-Object psobject stat = New-Object psobject
@ -46,11 +101,20 @@ If (Test-Path $path)
{ {
Set-Attr $result.stat "exists" $TRUE; Set-Attr $result.stat "exists" $TRUE;
$info = Get-Item $path; # Need to use -Force so it picks up hidden files
$iscontainer = Get-Attr $info "PSIsContainer" $null; $info = Get-Item -Force $path;
$length = Get-Attr $info "Length" $null; $iscontainer = $info.PSIsContainer;
$extension = Get-Attr $info "Extension" $null; $filename = $info.Name;
$attributes = Get-Attr $info "Attributes" ""; $filepath = $info.FullName;
$attributes = @()
foreach ($attribute in ($info.Attributes -split ',')) {
$attributes += $attribute.Trim();
}
$attributes_string = $info.Attributes.ToString();
$isreadonly = $attributes -contains 'ReadOnly';
$ishidden = $attributes -contains 'Hidden';
$isarchive = $attributes -contains 'Archive';
If ($info) If ($info)
{ {
$accesscontrol = $info.GetAccessControl(); $accesscontrol = $info.GetAccessControl();
@ -59,26 +123,72 @@ If (Test-Path $path)
{ {
$accesscontrol = $null; $accesscontrol = $null;
} }
$owner = Get-Attr $accesscontrol "Owner" $null; $owner = $accessControl.Owner;
$creationtime = Get-Attr $info "CreationTime" $null; $creationtime = $info.CreationTime;
$lastaccesstime = Get-Attr $info "LastAccessTime" $null; $lastaccesstime = $info.LastAccessTime;
$lastwritetime = Get-Attr $info "LastWriteTime" $null; $lastwritetime = $info.LastAccessTime;
$epoch_date = Get-Date -Date "01/01/1970" $epoch_date = Get-Date -Date "01/01/1970"
If ($iscontainer) $islink = $false
$isdir = $false
$isshared = $false
If ($attributes -contains 'ReparsePoint')
{ {
Set-Attr $result.stat "isdir" $TRUE; # TODO: Find a way to differenciate between soft and junction links
$islink = $true
$isdir = $true
# Try and get the symlink source, can result in failure if link is broken
try {
$lnk_source = [Ansible.Command.SymLinkHelper]::GetSymbolicLinkTarget($path)
Set-Attr $result.stat "lnk_source" $lnk_source
} catch {}
}
ElseIf ($iscontainer)
{
$isdir = $true
$share_info = Get-WmiObject -Class Win32_Share -Filter "Path='$($info.Fullname -replace '\\', '\\')'";
If ($share_info -ne $null)
{
$isshared = $true
Set-Attr $result.stat "sharename" $share_info.Name;
}
$dir_files_sum = Get-ChildItem $info.FullName -Recurse | Measure-Object -property length -sum;
If ($dir_files_sum -eq $null)
{
Set-Attr $result.stat "size" 0;
}
Else{
Set-Attr $result.stat "size" $dir_files_sum.Sum;
}
} }
Else Else
{ {
Set-Attr $result.stat "isdir" $FALSE; Set-Attr $result.stat "size" $info.Length;
Set-Attr $result.stat "size" $length; Set-Attr $result.stat "extension" $info.extension;
If ($get_md5) {
$md5 = Get-Hash -path $path -algorithm 'md5'
Set-Attr $result.stat "md5" $md5
}
If ($get_checksum) {
$checksum = Get-Hash -path $path -algorithm $checksum_algorithm
Set-Attr $result.stat "checksum" $checksum
}
} }
Set-Attr $result.stat "extension" $extension;
Set-Attr $result.stat "attributes" $attributes.ToString(); Set-Attr $result.stat "islink" $islink;
# Set-Attr $result.stat "owner" $getaccesscontrol.Owner; Set-Attr $result.stat "isdir" $isdir;
# Set-Attr $result.stat "owner" $info.GetAccessControl().Owner; Set-Attr $result.stat "isshared" $isshared;
Set-Attr $result.stat "isreadonly" $isreadonly;
Set-Attr $result.stat "ishidden" $ishidden;
Set-Attr $result.stat "isarchive" $isarchive;
Set-Attr $result.stat "filename" $filename;
Set-Attr $result.stat "path" $filepath;
Set-Attr $result.stat "attributes" $attributes_string;
Set-Attr $result.stat "owner" $owner; Set-Attr $result.stat "owner" $owner;
Set-Attr $result.stat "creationtime" (Date_To_Timestamp $epoch_date $creationtime); Set-Attr $result.stat "creationtime" (Date_To_Timestamp $epoch_date $creationtime);
Set-Attr $result.stat "lastaccesstime" (Date_To_Timestamp $epoch_date $lastaccesstime); Set-Attr $result.stat "lastaccesstime" (Date_To_Timestamp $epoch_date $lastaccesstime);
@ -89,12 +199,4 @@ Else
Set-Attr $result.stat "exists" $FALSE; Set-Attr $result.stat "exists" $FALSE;
} }
# only check get_checksum- it either got its value from get_md5 or was set directly.
If (($get_checksum) -and $result.stat.exists -and -not $result.stat.isdir)
{
$hash = Get-FileChecksum($path);
Set-Attr $result.stat "md5" $hash;
Set-Attr $result.stat "checksum" $hash;
}
Exit-Json $result; Exit-Json $result;

View file

@ -29,27 +29,33 @@ short_description: returns information about a Windows file
description: description:
- Returns information about a Windows file - Returns information about a Windows file
options: options:
path: path:
description: description:
- The full path of the file/object to get the facts of; both forward and - The full path of the file/object to get the facts of; both forward and
back slashes are accepted. back slashes are accepted.
required: true required: yes
default: null get_md5:
aliases: [] description:
get_md5: - Whether to return the checksum sum of the file. Between Ansible 1.9
description: and 2.2 this is no longer an MD5, but a SHA1 isntead. As of Ansible
- Whether to return the checksum sum of the file. As of Ansible 1.9 this 2.3 this is back to an MD5. Will return None if host is unable to
is no longer a MD5, but a SHA1 instead. use specified algorithm
required: false required: no
default: yes default: True
aliases: [] get_checksum:
get_checksum: description:
description: - Whether to return a checksum of the file (default sha1)
- Whether to return a checksum of the file required: no
(only sha1 currently supported) default: True
required: false version_added: "2.1"
default: yes checksum_algorithm:
version_added: "2.1" description:
- Algorithm to determine checksum of file. Will throw an error if
the host is unable to use specified algorithm.
required: no
default: sha1
choices: ['sha1', 'sha256', 'sha384', 'sha512']
version_added: "2.3"
author: "Chris Church (@cchurch)" author: "Chris Church (@cchurch)"
''' '''
@ -59,7 +65,140 @@ EXAMPLES = r'''
path: C:\foo.ini path: C:\foo.ini
register: file_info register: file_info
# Obtain information about a folder
- win_stat:
path: C:\\bar
register: folder_info
# Get MD5 checksum of a file
- win_stat:
path: C:\\foo.ini
get_md5: True
register: md5_checksum
- debug: - debug:
var: file_info var: md5_checksum.stat.md5
# Get SHA1 checksum of file
- win_stat:
path: C:\\foo.ini
get_checksum: True
register: sha1_checksum
- debug:
var: sha1_checksum.stat.checksum
# Get SHA256 checksum of file
- win_stat:
path: C:\\foo.ini
get_checksum: True
checksum_algorithm: sha256
register: sha256_checksum
- debug:
var: sha256_checksum.stat.checksum
''' '''
RETURN = '''
changed:
description: Whether anything was changed
returned: always
type: boolean
sample: True
stat:
description: dictionary containing all the stat data
returned: success
type: dictionary
contains:
attributes:
description: attributes of the file at path in raw form
returned: success, path exists
type: string
sample: "Archive, Hidden"
checksum:
description: The checksum of a file based on checksum_algorithm specified
returned: success, path exist, path is a file, get_checksum == True
checksum_algorithm specified is supported
type: string
sample: 09cb79e8fc7453c84a07f644e441fd81623b7f98
creationtime:
description: the create time of the file represented in seconds since epoch
returned: success, path exists
type: float
sample: 1477984205.15
extension:
description: the extension of the file at path
returned: success, path exists, path is a file
type: string
sample: ".ps1"
isarchive:
description: if the path is ready for archiving or not
returned: success, path exists
type: boolean
sample: True
isdir:
description: if the path is a directory or not
returned: success, path exists
type: boolean
sample: True
ishidden:
description: if the path is hidden or not
returned: success, path exists
type: boolean
sample: True
islink:
description: if the path is a symbolic link or junction or not
returned: success, path exists
type: boolean
sample: True
isreadonly:
description: if the path is read only or not
returned: success, path exists
type: boolean
sample: True
isshared:
description: if the path is shared or not
returned: success, path exists
type: boolean
sample: True
lastaccesstime:
description: the last access time of the file represented in seconds since epoch
returned: success, path exists
type: float
sample: 1477984205.15
lastwritetime:
description: the last modification time of the file represented in seconds since epoch
returned: success, path exists
type: float
sample: 1477984205.15
lnk_source:
description: the target of the symbolic link, will return null if not a link or the link is broken
return: success, path exists, file is a symbolic link
type: string
sample: C:\\temp
md5:
description: The MD5 checksum of a file (Between Ansible 1.9 and 2.2 this was returned as a SHA1 hash)
returned: success, path exist, path is a file, get_md5 == True, md5 is supported
type: string
sample: 09cb79e8fc7453c84a07f644e441fd81623b7f98
owner:
description: the owner of the file
returned: success, path exists
type: string
sample: BUILTIN\\Administrators
path:
description: the full absolute path to the file
returned: success, path exists
type: string
sample: BUILTIN\\Administrators
sharename:
description: the name of share if folder is shared
returned: success, path exists, file is a directory and isshared == True
type: string
sample: file-share
size:
description: the size in bytes of a file or folder
returned: success, path exists, file is not a link
type: int
sample: 1024
'''

View file

@ -0,0 +1 @@
win_stat_dir: "{{win_output_dir}}\\win_stat"

View file

@ -0,0 +1,9 @@
$path = $args[0]
$attr = $args[1]
$item = Get-Item "$path"
$attributes = $item.Attributes -split ','
If ($attributes -notcontains $attr) {
$attributes += $attr
}
$item.Attributes = $attributes -join ','

View file

@ -0,0 +1,6 @@
$date = Get-Date -Year 2016 -Month 11 -Day 1 -Hour 7 -Minute 10 -Second 5 -Millisecond 0
$item = Get-Item -Path "$($args[0])"
$item.CreationTime = $date
$item.LastAccessTime = $date
$item.LastWriteTime = $date

View file

@ -0,0 +1,6 @@
$share_stat = Get-WmiObject -Class Win32_Share -Filter "name='folder-share'"
If ($share_stat) {
$share_stat.Delete()
}
$wmi = [wmiClass] 'Win32_Share'
$wmi.Create($args[0], 'folder-share', 0)

View file

@ -16,66 +16,583 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
- name: remove links if they exist as win_file struggles
win_command: cmd.exe /c rmdir "{{item}}"
ignore_errors: True
with_items:
- "{{win_stat_dir}}\\link"
- "{{win_stat_dir}}\\nested\\hard-link.ps1"
- "{{win_stat_dir}}\\junction-link"
- name: ensure the testing directory is cleared before the run
win_file:
path: "{{win_stat_dir}}"
state: absent
- name: ensure win testing directories exist
win_file:
path: "{{item}}"
state: directory
with_items:
- "{{win_stat_dir}}\\folder"
- "{{win_stat_dir}}\\folder space"
- "{{win_stat_dir}}\\nested"
- "{{win_stat_dir}}\\nested\\nested"
- "{{win_stat_dir}}\\shared"
- "{{win_stat_dir}}\\hidden"
- "{{win_stat_dir}}\\link-dest"
- "{{win_stat_dir}}\\junction-dest"
- name: create empty test files
win_file:
path: "{{item}}"
state: touch
with_items:
- "{{win_stat_dir}}\\nested\\file.ps1"
- "{{win_stat_dir}}\\nested\\read-only.ps1"
- "{{win_stat_dir}}\\nested\\archive.ps1"
- "{{win_stat_dir}}\\nested\\hidden.ps1"
- "{{win_stat_dir}}\\nested\\nested\\file.ps1"
- "{{win_stat_dir}}\\folder space\\file.ps1"
- name: populate files with a test string
win_lineinfile:
dest: "{{item}}"
line: abc
with_items:
- "{{win_stat_dir}}\\nested\\file.ps1"
- "{{win_stat_dir}}\\nested\\read-only.ps1"
- "{{win_stat_dir}}\\nested\\archive.ps1"
- "{{win_stat_dir}}\\nested\\hidden.ps1"
- "{{win_stat_dir}}\\nested\\nested\\file.ps1"
- "{{win_stat_dir}}\\folder space\\file.ps1"
- name: create share
script: setup_share.ps1 {{win_stat_dir}}\shared
- name: create links
win_command: cmd.exe /c mklink /{{item.type}} {{item.source}} {{item.target}}
with_items:
- { type: 'D', source: "{{win_stat_dir}}\\link", target: "{{win_stat_dir}}\\link-dest" }
- { type: 'H', source: "{{win_stat_dir}}\\nested\\hard-link.ps1", target: "{{win_stat_dir}}\\nested\\file.ps1" }
- { type: 'J', source: "{{win_stat_dir}}\\junction-link", target: "{{win_stat_dir}}\\junction-dest" }
- name: set modification date on files/folders
script: set_filedate.ps1 "{{item}}"
with_items:
- "{{win_stat_dir}}\\nested\\file.ps1"
- "{{win_stat_dir}}\\nested\\read-only.ps1"
- "{{win_stat_dir}}\\nested\\archive.ps1"
- "{{win_stat_dir}}\\nested\\hidden.ps1"
- "{{win_stat_dir}}\\nested\\nested\\file.ps1"
- "{{win_stat_dir}}\\folder space\\file.ps1"
- "{{win_stat_dir}}\\folder"
- "{{win_stat_dir}}\\folder space"
- "{{win_stat_dir}}\\nested"
- "{{win_stat_dir}}\\nested\\nested"
- "{{win_stat_dir}}\\shared"
- "{{win_stat_dir}}\\hidden"
- "{{win_stat_dir}}\\link-dest"
- "{{win_stat_dir}}\\junction-dest"
- name: set file attributes for test
script: set_attributes.ps1 {{item.path}} {{item.attr}}
with_items:
- { path: "{{win_stat_dir}}\\hidden", attr: "Hidden" }
- { path: "{{win_stat_dir}}\\nested\\read-only.ps1", attr: "ReadOnly" }
- { path: "{{win_stat_dir}}\\nested\\archive.ps1", attr: "Archive" }
- { path: "{{win_stat_dir}}\\nested\\hidden.ps1", attr: "Hidden" }
# End setup of test files
- name: test win_stat module on file - name: test win_stat module on file
win_stat: path="C:/Windows/win.ini" win_stat:
register: win_stat_file path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
register: actual
- name: check win_stat file result - name: set expected fact for file
set_fact:
expected:
changed: False
stat:
attributes: Archive
checksum: 5943831380243c1269c8b68bb92de6e2f1844590
creationtime: 1477984205
exists: True
extension: .ps1
filename: file.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
size: 8
- name: check actual for file
assert: assert:
that: that:
- "win_stat_file.stat.exists" - "actual == expected"
- "not win_stat_file.stat.isdir"
- "win_stat_file.stat.size > 0"
- "win_stat_file.stat.md5"
- "win_stat_file.stat.extension"
- "win_stat_file.stat.attributes"
- "win_stat_file.stat.owner"
- "win_stat_file.stat.creationtime"
- "win_stat_file.stat.lastaccesstime"
- "win_stat_file.stat.lastwritetime"
- "not win_stat_file|failed"
- "not win_stat_file|changed"
- name: test win_stat module on file without md5 and backslashes - name: test win_stat module on file without md5
win_stat: path="C:\Windows\win.ini" get_md5=no win_stat:
register: win_stat_file_no_md5 path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
get_md5: False
register: actual
- name: check win_stat file result without md5 - name: set expected fact for file without md5
set_fact:
expected:
changed: False
stat:
attributes: Archive
checksum: 5943831380243c1269c8b68bb92de6e2f1844590
creationtime: 1477984205
exists: True
extension: .ps1
filename: file.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
size: 8
- name: check actual for file without md5
assert: assert:
that: that:
- "win_stat_file_no_md5.stat.exists" - "actual == expected"
- "not win_stat_file_no_md5.stat.isdir"
- "win_stat_file_no_md5.stat.size > 0"
- "not win_stat_file_no_md5.stat.md5|default('')"
- "win_stat_file_no_md5.stat.extension"
- "win_stat_file_no_md5.stat.attributes"
- "win_stat_file_no_md5.stat.owner"
- "win_stat_file_no_md5.stat.creationtime"
- "win_stat_file_no_md5.stat.lastaccesstime"
- "win_stat_file_no_md5.stat.lastwritetime"
- "not win_stat_file_no_md5|failed"
- "not win_stat_file_no_md5|changed"
- name: test win_stat module on directory - name: test win_stat module on file with sha256
win_stat: path="C:\\Windows" win_stat:
register: win_stat_dir path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
checksum_algorithm: sha256
register: actual
- name: check win_stat dir result - name: set expected fact for file with sha256
set_fact:
expected:
changed: False
stat:
attributes: Archive
checksum: aec4cd5ed4c05ed5cf9dea5a8b30f5e655ad87b937b36e3c059840ce3cf3642f
creationtime: 1477984205
exists: True
extension: .ps1
filename: file.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
size: 8
- name: check actual for file with sha256
assert: assert:
that: that:
- "win_stat_dir.stat.exists" - "actual == expected"
- "win_stat_dir.stat.isdir"
- "win_stat_dir.stat.extension == ''" - name: test win_stat module on file with sha384
- "win_stat_dir.stat.attributes" win_stat:
- "win_stat_dir.stat.owner" path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
- "win_stat_dir.stat.creationtime" checksum_algorithm: sha384
- "win_stat_dir.stat.lastaccesstime" register: actual
- "win_stat_dir.stat.lastwritetime"
- "not win_stat_dir|failed" - name: set expected fact for file with sha384
- "not win_stat_dir|changed" set_fact:
expected:
changed: False
stat:
attributes: Archive
checksum: 862076ed4ef117cb61395daa839ccfe20a880e8cd048e76b3b1503d39d72f4c09d58ab3c44cdd5a3272ca8da9d8d8666
creationtime: 1477984205
exists: True
extension: .ps1
filename: file.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
size: 8
- name: check actual for file with sha384
assert:
that:
- "actual == expected"
- name: test win_stat module on file with sha512
win_stat:
path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
checksum_algorithm: sha512
register: actual
- name: set expected fact for file with sha512
set_fact:
expected:
changed: False
stat:
attributes: Archive
checksum: 6d821d068cd8f09582de9ef14550666547eb6d4ae1d34cfc5aea921e595dbb9c462bf7f4c88a90190a69e52d69ac157e8146b555ed679a3e997061ca69632d0f
creationtime: 1477984205
exists: True
extension: .ps1
filename: file.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\file.ps1"
size: 8
- name: check actual for file with sha512
assert:
that:
- "actual == expected"
- name: test win_stat on hidden file
win_stat:
path: "{{win_output_dir}}\\win_stat\\nested\\hidden.ps1"
register: actual
- name: set expected fact for hidden file
set_fact:
expected:
changed: False
stat:
attributes: "Hidden, Archive"
checksum: 5943831380243c1269c8b68bb92de6e2f1844590
creationtime: 1477984205
exists: True
extension: .ps1
filename: hidden.ps1
isarchive: True
isdir: False
ishidden: True
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\hidden.ps1"
size: 8
- name: check actual for hidden file
assert:
that:
- "actual == expected"
- name: test win_stat on readonly file
win_stat:
path: "{{win_output_dir}}\\win_stat\\nested\\read-only.ps1"
register: actual
- name: set expected fact for readonly file
set_fact:
expected:
changed: False
stat:
attributes: "ReadOnly, Archive"
checksum: 5943831380243c1269c8b68bb92de6e2f1844590
creationtime: 1477984205
exists: True
extension: .ps1
filename: read-only.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: True
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\read-only.ps1"
size: 8
- name: check actual for readonly file
assert:
that:
- "actual == expected"
- name: test win_stat on hard link file
win_stat:
path: "{{win_output_dir}}\\win_stat\\nested\\hard-link.ps1"
register: actual
- name: set expected fact for hard link file
set_fact:
expected:
changed: False
stat:
attributes: Archive
checksum: 5943831380243c1269c8b68bb92de6e2f1844590
creationtime: 1477984205
exists: True
extension: .ps1
filename: hard-link.ps1
isarchive: True
isdir: False
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
md5: c627105fad747457b7e88ed1016e065f
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested\\hard-link.ps1"
size: 8
- name: check actual for hard link file
assert:
that:
- "actual == expected"
- name: test win_stat on directory
win_stat:
path: "{{win_output_dir}}\\win_stat\\nested"
register: actual
- name: set expected fact for directory
set_fact:
expected:
changed: False
stat:
attributes: Directory
creationtime: 1477984205
exists: True
filename: nested
isarchive: False
isdir: True
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\nested"
size: 40
- name: check actual for directory
assert:
that:
- "actual == expected"
- name: test win_stat on empty directory
win_stat:
path: "{{win_output_dir}}\\win_stat\\folder"
register: actual
- name: set expected fact for empty directory
set_fact:
expected:
changed: False
stat:
attributes: Directory
creationtime: 1477984205
exists: True
filename: folder
isarchive: False
isdir: True
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\folder"
size: 0
- name: check actual for empty directory
assert:
that:
- "actual == expected"
- name: test win_stat on directory with space in name
win_stat:
path: "{{win_output_dir}}\\win_stat\\folder space"
register: actual
- name: set expected fact for directory with space in name
set_fact:
expected:
changed: False
stat:
attributes: Directory
creationtime: 1477984205
exists: True
filename: folder space
isarchive: False
isdir: True
ishidden: False
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\folder space"
size: 8
- name: check actual for directory with space in name
assert:
that:
- "actual == expected"
- name: test win_stat on hidden directory
win_stat:
path: "{{win_output_dir}}\\win_stat\\hidden"
register: actual
- name: set expected fact for hidden directory
set_fact:
expected:
changed: False
stat:
attributes: "Hidden, Directory"
creationtime: 1477984205
exists: True
filename: hidden
isarchive: False
isdir: True
ishidden: True
islink: False
isreadonly: False
isshared: False
lastaccesstime: 1477984205
lastwritetime: 1477984205
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\hidden"
size: 0
- name: check actual for hidden directory
assert:
that:
- "actual == expected"
- name: test win_stat on shared directory
win_stat:
path: "{{win_output_dir}}\\win_stat\\shared"
register: actual
- name: set expected fact for shared directory
set_fact:
expected:
changed: False
stat:
attributes: Directory
creationtime: 1477984205
exists: True
filename: shared
isarchive: False
isdir: True
ishidden: False
islink: False
isreadonly: False
isshared: True
lastaccesstime: 1477984205
lastwritetime: 1477984205
owner: BUILTIN\Administrators
path: "{{win_output_dir}}\\win_stat\\shared"
sharename: folder-share
size: 0
- name: check actual for shared directory
assert:
that:
- "actual == expected"
- name: test win_stat on symlink
win_stat:
path: "{{win_output_dir}}\\win_stat\\link"
register: actual
# I cannot change modification time on links so we are resorting to checking the dict against known valuea
- name: assert symlink actual
assert:
that:
- "actual.stat.attributes == 'Directory, ReparsePoint'"
- "actual.stat.creationtime is defined"
- "actual.stat.exists == True"
- "actual.stat.filename == 'link'"
- "actual.stat.isarchive == False"
- "actual.stat.isdir == True"
- "actual.stat.ishidden == False"
- "actual.stat.islink == True"
- "actual.stat.isreadonly == False"
- "actual.stat.isshared == False"
- "actual.stat.lastaccesstime is defined"
- "actual.stat.lastwritetime is defined"
- "actual.stat.lnk_source == '{{win_output_dir|regex_replace('\\\\', '\\\\\\\\')}}\\\\win_stat\\\\link-dest'"
- "actual.stat.owner == 'BUILTIN\\Administrators'"
- "actual.stat.path == '{{win_output_dir|regex_replace('\\\\', '\\\\\\\\')}}\\\\win_stat\\\\link'"
- "actual.stat.size is not defined"
- "actual.stat.checksum is not defined"
- "actual.stat.md5 is not defined"
- name: test win_stat on junction
win_stat:
path: "{{win_output_dir}}\\win_stat\\junction-link"
register: actual
- name: assert symlink actual
assert:
that:
- "actual.stat.attributes == 'Directory, ReparsePoint'"
- "actual.stat.creationtime is defined"
- "actual.stat.exists == True"
- "actual.stat.filename == 'junction-link'"
- "actual.stat.isarchive == False"
- "actual.stat.isdir == True"
- "actual.stat.ishidden == False"
- "actual.stat.islink == True"
- "actual.stat.isreadonly == False"
- "actual.stat.isshared == False"
- "actual.stat.lastaccesstime is defined"
- "actual.stat.lastwritetime is defined"
- "actual.stat.lnk_source == '{{win_output_dir|regex_replace('\\\\', '\\\\\\\\')}}\\\\win_stat\\\\junction-dest'"
- "actual.stat.owner == 'BUILTIN\\Administrators'"
- "actual.stat.path == '{{win_output_dir|regex_replace('\\\\', '\\\\\\\\')}}\\\\win_stat\\\\junction-link'"
- "actual.stat.size is not defined"
- "actual.stat.checksum is not defined"
- "actual.stat.md5 is not defined"
- name: test win_stat module non-existent path - name: test win_stat module non-existent path
win_stat: path="C:/this_file_should_not_exist.txt" win_stat:
path: "{{win_output_dir}}\\win_stat\\this_file_should_not_exist"
register: win_stat_missing register: win_stat_missing
- name: check win_stat missing result - name: check win_stat missing result
@ -96,3 +613,26 @@
- "win_stat_no_args|failed" - "win_stat_no_args|failed"
- "win_stat_no_args.msg" - "win_stat_no_args.msg"
- "not win_stat_no_args|changed" - "not win_stat_no_args|changed"
- name: check if junction symbolic link exists
win_stat:
path: "{{win_output_dir}}\\win_stat\\junction-link"
register: junction_link_exists
- name: delete junction symbolic link if it exists
win_command: cmd.exe /c rmdir {{win_output_dir}}\win_stat\junction-link
when: junction_link_exists.stat.exists
- name: check if symbolic link exists
win_stat:
path: "{{win_output_dir}}\\win_stat\\link"
register: nested_link_exists
- name: delete nested symbolic link if it exists
win_shell: cmd.exe /c rmdir {{win_output_dir}}\win_stat\link
when: nested_link_exists.stat.exists
- name: remove testing folder
win_file:
path: "{{win_output_dir}}\\win_stat"
state: absent