diff --git a/lib/ansible/modules/windows/win_find.ps1 b/lib/ansible/modules/windows/win_find.ps1 index fc30b0f211b..36fb58fb3bc 100644 --- a/lib/ansible/modules/windows/win_find.ps1 +++ b/lib/ansible/modules/windows/win_find.ps1 @@ -1,21 +1,10 @@ #!powershell # This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -# WANT_JSON -# POWERSHELL_COMMON + +# Copyright (c) 2016 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#Requires -Module Ansible.ModuleUtils.Legacy $ErrorActionPreference = "Stop" @@ -23,21 +12,20 @@ $params = Parse-Args -arguments $args -supports_check_mode $true $paths = Get-AnsibleParam -obj $params -name 'paths' -failifempty $true -$age = Get-AnsibleParam -obj $params -name 'age' -failifempty $false -default $null -$age_stamp = Get-AnsibleParam -obj $params -name 'age_stamp' -failifempty $false -default 'mtime' -ValidateSet 'mtime','ctime','atime' -$file_type = Get-AnsibleParam -obj $params -name 'file_type' -failifempty $false -default 'file' -ValidateSet 'file','directory' -$follow = Get-AnsibleParam -obj $params -name 'follow' -type "bool" -failifempty $false -default $false -$hidden = Get-AnsibleParam -obj $params -name 'hidden' -type "bool" -failifempty $false -default $false -$patterns = Get-AnsibleParam -obj $params -name 'patterns' -failifempty $false -default $null -$recurse = Get-AnsibleParam -obj $params -name 'recurse' -type "bool" -failifempty $false -default $false -$size = Get-AnsibleParam -obj $params -name 'size' -failifempty $false -default $null -$use_regex = Get-AnsibleParam -obj $params -name 'use_regex' -type "bool" -failifempty $false -default $false -$get_checksum = Get-AnsibleParam -obj $params -name 'get_checksum' -type "bool" -failifempty $false -default $true -$checksum_algorithm = Get-AnsibleParam -obj $params -name 'checksum_algorithm' -failifempty $false -default 'sha1' -ValidateSet 'md5', 'sha1', 'sha256', 'sha384', 'sha512' +$age = Get-AnsibleParam -obj $params -name 'age' +$age_stamp = Get-AnsibleParam -obj $params -name 'age_stamp' -default 'mtime' -ValidateSet 'mtime','ctime','atime' +$file_type = Get-AnsibleParam -obj $params -name 'file_type' -default 'file' -ValidateSet 'file','directory' +$follow = Get-AnsibleParam -obj $params -name 'follow' -type "bool" -default $false +$hidden = Get-AnsibleParam -obj $params -name 'hidden' -type "bool" -default $false +$patterns = Get-AnsibleParam -obj $params -name 'patterns' +$recurse = Get-AnsibleParam -obj $params -name 'recurse' -type "bool" -default $false +$size = Get-AnsibleParam -obj $params -name 'size' +$use_regex = Get-AnsibleParam -obj $params -name 'use_regex' -type "bool" -default $false +$get_checksum = Get-AnsibleParam -obj $params -name 'get_checksum' -type "bool" -default $true +$checksum_algorithm = Get-AnsibleParam -obj $params -name 'checksum_algorithm' -default 'sha1' -ValidateSet 'md5', 'sha1', 'sha256', 'sha384', 'sha512' $result = @{ files = @() - warnings = @() examined = 0 matched = 0 changed = $false @@ -121,7 +109,7 @@ Function Assert-Age($info) { } } } else { - Fail-Json $result "failed to process age" + throw "failed to process age for file $($info.FullName)" } } @@ -204,7 +192,7 @@ Function Assert-Size($info) { } } } else { - Fail-Json $result "failed to process size" + throw "failed to process size for file $($info.FullName)" } } @@ -282,8 +270,12 @@ Function Get-FileStat($file) { $file_stat.extension = $file.Extension if ($get_checksum) { - $checksum = Get-FileChecksum -path $path -algorithm $checksum_algorithm - $file_stat.checksum = $checksum + try { + $checksum = Get-FileChecksum -path $path -algorithm $checksum_algorithm + $file_stat.checksum = $checksum + } catch { + throw "failed to get checksum for file $($file.FullName)" + } } } @@ -329,8 +321,14 @@ foreach ($path in $paths) { $paths_to_check = $paths_to_check | Select-Object -Unique foreach ($path in $paths_to_check) { - $file = Get-Item -Force -Path $path - $info = Get-FileStat -file $file + try { + $file = Get-Item -Force -Path $path + $info = Get-FileStat -file $file + } catch { + Add-Warning -obj $result -message "win_find failed to check some files, these files were ignored and will not be part of the result output" + break + } + $new_examined = $result.examined + 1 $result.examined = $new_examined diff --git a/lib/ansible/modules/windows/win_find.py b/lib/ansible/modules/windows/win_find.py index c048582911b..f07443ccb29 100644 --- a/lib/ansible/modules/windows/win_find.py +++ b/lib/ansible/modules/windows/win_find.py @@ -1,23 +1,11 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# (c) 2016, Ansible, inc -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . -# +# Copyright (c) 2016 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# this is a windows documentation stub. actual code lives in the .ps1 +# file of the same name ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], @@ -27,7 +15,7 @@ DOCUMENTATION = r''' --- module: win_find version_added: "2.3" -short_description: return a list of files based on specific criteria +short_description: Return a list of files based on specific criteria description: - Return a list of files based on specified criteria. - Multiple criteria are AND'd together. @@ -40,45 +28,38 @@ options: less than the specified time. You can choose seconds, minutes, hours, days or weeks by specifying the first letter of an of those words (e.g., "2s", "10d", 1w"). - required: false age_stamp: description: - Choose the file property against which we compare C(age). The default attribute we compare with is the last modification time. - required: false default: mtime choices: ['atime', 'mtime', 'ctime'] checksum_algorithm: description: - Algorithm to determine the checksum of a file. Will throw an error if the host is unable to use specified algorithm. - required: false default: sha1 choices: ['md5', 'sha1', 'sha256', 'sha384', 'sha512'] file_type: - description: Type of file to search for - required: false + description: Type of file to search for. default: file choices: ['file', 'directory'] follow: description: - Set this to true to follow symlinks in the path. This needs to be used in conjunction with C(recurse). - required: false - default: false - choices: ['true', 'false'] + type: bool + default: 'no' get_checksum: description: - Whether to return a checksum of the file in the return info (default sha1), use C(checksum_algorithm) to change from the default. - required: false - default: true - choices: ['true', 'false'] + type: bool + default: 'yes' hidden: - description: Set this to include hidden files or folders - required: false - default: false - choices: ['true', 'false'] + description: Set this to include hidden files or folders. + type: bool + default: 'no' paths: description: - List of paths of directories to search for files or folders in. @@ -91,14 +72,12 @@ options: option. The patterns retrict the list of files or folders to be returned based on the filenames. For a file to be matched it only has to match with one pattern in a list provided. - required: false recurse: description: - Will recursively descend into the directory looking for files - or folders - required: false - default: false - choices: ['true', 'false'] + or folders. + type: bool + default: 'no' size: description: - Select files or folders whose size is equal to or greater than @@ -106,123 +85,114 @@ options: or less than the specified size. You can specify the size with a suffix of the byte type i.e. kilo = k, mega = m... Size is not evaluated for symbolic links. - required: false - default: false use_regex: description: - - Will set patterns to run as a regex check if true - required: false - default: false - choices: ['true', 'false'] -notes: - - For non-Windows targets, use the M(find) module instead. -author: "Jordan Borean (@jborean93)" + - Will set patterns to run as a regex check if true. + type: bool + default: 'no' +author: +- Jordan Borean (@jborean93) ''' EXAMPLES = r''' -# Find files in path -- win_find: +- name: Find files in path + win_find: paths: D:\temp -# Find hidden files in path -- win_find: +- name: Find hidden files in path + win_find: paths: D:\temp hidden: True -# Find files in multiple paths -- win_find: +- name: Find files in multiple paths + win_find: paths: ['C:\temp', 'D:\temp'] -# Find files in directory while searching recursively -- win_find: +- name: Find files in directory while searching recursively + win_find: paths: D:\temp recurse: True -# Find files in directory while following symlinks -- win_find: +- name: Find files in directory while following symlinks + win_find: paths: D:\temp recurse: True follow: True -# Find files with .log and .out extension using powershell wildcards -- win_find: +- name: Find files with .log and .out extension using powershell wildcards + win_find: paths: D:\temp patterns: ['*.log', '*.out'] -# Find files in path based on regex pattern -- win_find: +- name: Find files in path based on regex pattern + win_find: paths: D:\temp patterns: 'out_\d{8}-\d{6}.log' -# Find files older than 1 day -- win_find: +- name: Find files older than 1 day + win_find: paths: D:\temp age: 86400 -# Find files older than 1 day based on create time -- win_find: +- name: Find files older than 1 day based on create time + win_find: paths: D:\temp age: 86400 age_stamp: ctime -# Find files older than 1 day with unit syntax -- win_find: +- name: Find files older than 1 day with unit syntax + win_find: paths: D:\temp age: 1d -# Find files newer than 1 hour -- win_find: +- name: Find files newer than 1 hour + win_find: paths: D:\temp age: -3600 -# Find files newer than 1 hour with unit syntax -- win_find: +- name: Find files newer than 1 hour with unit syntax + win_find: paths: D:\temp age: -1h -# Find files larger than 1MB -- win_find: +- name: Find files larger than 1MB + win_find: paths: D:\temp size: 1048576 -# Find files larger than 1GB with unit syntax -- win_find: +- name: Find files larger than 1GB with unit syntax + win_find: paths: D:\temp size: 1g -# Find files smaller than 1MB -- win_find: +- name: Find files smaller than 1MB + win_find: paths: D:\temp size: -1048576 -# Find files smaller than 1GB with unit syntax -- win_find: +- name: Find files smaller than 1GB with unit syntax + win_find: paths: D:\temp size: -1g -# Find folders/symlinks in multiple paths -- win_find: +- name: Find folders/symlinks in multiple paths + win_find: paths: ['C:\temp', 'D:\temp'] file_type: directory -# Find files and return SHA256 checksum of files found -- win_find: +- name: Find files and return SHA256 checksum of files found + win_find: paths: C:\temp get_checksum: True checksum_algorithm: sha256 -# Find files and do not return the checksum -- win_find: +- name: Find files and do not return the checksum + win_find: path: C:\temp get_checksum: False ''' RETURN = r''' -changed: - description: Whether anything was chagned - returned: always - type: boolean - sample: True examined: description: The number of files/folders that was checked returned: always diff --git a/test/integration/targets/win_find/defaults/main.yml b/test/integration/targets/win_find/defaults/main.yml index d3d03f767fe..d04ec5f422b 100644 --- a/test/integration/targets/win_find/defaults/main.yml +++ b/test/integration/targets/win_find/defaults/main.yml @@ -1 +1,2 @@ win_find_dir: "{{win_output_dir}}\\win_find" +test_win_find_username: testuser diff --git a/test/integration/targets/win_find/files/set_attributes.ps1 b/test/integration/targets/win_find/files/set_attributes.ps1 deleted file mode 100644 index b57a368c438..00000000000 --- a/test/integration/targets/win_find/files/set_attributes.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -$path = $args[0] -$attr = $args[1] -$item = Get-Item "$path" - -$attributes = $item.Attributes -split ',' -If ($attributes -notcontains $attr) { - $attributes += $attr -} -$item.Attributes = $attributes -join ',' diff --git a/test/integration/targets/win_find/files/set_filedate.ps1 b/test/integration/targets/win_find/files/set_filedate.ps1 deleted file mode 100644 index 3bc525a4ff0..00000000000 --- a/test/integration/targets/win_find/files/set_filedate.ps1 +++ /dev/null @@ -1,6 +0,0 @@ -$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 diff --git a/test/integration/targets/win_find/files/set_share.ps1 b/test/integration/targets/win_find/files/set_share.ps1 deleted file mode 100644 index c56242cf40f..00000000000 --- a/test/integration/targets/win_find/files/set_share.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -$share_name = $args[1] -$share_stat = Get-WmiObject -Class Win32_Share -Filter "name='$share_name'" -If ($share_stat) { - $share_stat.Delete() -} -$wmi = [wmiClass] 'Win32_Share' -$wmi.Create($args[0], $share_name, 0) diff --git a/test/integration/targets/win_find/tasks/main.yml b/test/integration/targets/win_find/tasks/main.yml index 092b72a5486..a44d5217c39 100644 --- a/test/integration/targets/win_find/tasks/main.yml +++ b/test/integration/targets/win_find/tasks/main.yml @@ -1,736 +1,110 @@ --- - name: ensure the testing directory is cleared before setting up test win_file: - path: "{{win_find_dir}}" + path: '{{win_find_dir}}' state: absent -- name: ensure testing directories exist - win_file: - path: "{{item}}" - state: directory - with_items: - - '{{win_find_dir}}\nested' - - '{{win_find_dir}}\single' - - '{{win_find_dir}}\link-dest' - - '{{win_find_dir}}\link-dest\sub-link' - - '{{win_find_dir}}\hard-link-dest' - - '{{win_find_dir}}\junction-link-dest' - - '{{win_find_dir}}\broken-link-dest' - - '{{win_find_dir}}\nested\sub-nest' - - '{{win_find_dir}}\shared' - - '{{win_find_dir}}\shared\folder' - - '{{win_find_dir}}\hidden' - - '{{win_find_dir}}\date' - - '{{win_find_dir}}\emptynested\nest\dir1' - - '{{win_find_dir}}\emptynested\nest\dir2' - -- name: create empty test files - win_file: - path: "{{item}}" - state: touch - with_items: - - "{{win_find_dir}}\\nested\\file.ps1" - - "{{win_find_dir}}\\nested\\test.ps1" - - "{{win_find_dir}}\\nested\\out.log" - - "{{win_find_dir}}\\nested\\archive.log" - - "{{win_find_dir}}\\nested\\sub-nest\\test.ps1" - - "{{win_find_dir}}\\nested\\sub-nest\\readonly.txt" - - "{{win_find_dir}}\\link-dest\\link.ps1" - - "{{win_find_dir}}\\single\\large.ps1" - - "{{win_find_dir}}\\single\\small.ps1" - - "{{win_find_dir}}\\single\\test.ps1" - - "{{win_find_dir}}\\single\\hidden.ps1" - - "{{win_find_dir}}\\date\\new.ps1" - - "{{win_find_dir}}\\date\\old.ps1" - - "{{win_find_dir}}\\single\\out_20161101-091005.log" - - "{{win_find_dir}}\\hidden\\out_20161101-091005.log" - - "{{win_find_dir}}\\hard-link-dest\\file-abc.log" - -- name: populate files with a test string - win_lineinfile: - dest: "{{item.path}}" - line: "{{item.text}}" - with_items: - - { 'path': "{{win_find_dir}}\\nested\\file.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\nested\\test.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\nested\\out.log", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\nested\\archive.log", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\nested\\sub-nest\\test.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\nested\\sub-nest\\readonly.txt", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\link-dest\\link.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\single\\test.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\single\\hidden.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\date\\new.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\date\\old.ps1", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\single\\out_20161101-091005.log", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\hidden\\out_20161101-091005.log", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\hard-link-dest\\file-abc.log", 'text': 'abcdefg1234567' } - - { 'path': "{{win_find_dir}}\\single\\small.ps1", 'text': "a" } - - { 'path': "{{win_find_dir}}\\date\\new.ps1", 'text': "random text for new date" } - - { 'path': "{{win_find_dir}}\\date\\old.ps1", 'text': "random text for old date" } - -- name: populate large text file - win_command: powershell "Set-Content {{win_find_dir}}\\single\\large.ps1 ('abcdefghijklmnopqrstuvwxyz' * 10000)" - -- name: create share - script: set_share.ps1 "{{win_find_dir}}\shared\folder" "folder-share" - -- name: create links - win_command: cmd.exe /c mklink /{{item.type}} "{{item.source}}" "{{item.target}}" - with_items: - - { type: 'D', source: "{{win_find_dir}}\\nested\\link", target: "{{win_find_dir}}\\link-dest" } - - { type: 'D', source: "{{win_find_dir}}\\broken-link", target: "{{win_find_dir}}\\broken-link-dest" } - - { type: 'H', source: "{{win_find_dir}}\\hard-link-dest\\hard-link.log", target: "{{win_find_dir}}\\hard-link-dest\\file-abc.log" } - - { type: 'J', source: "{{win_find_dir}}\\junction-link", target: "{{win_find_dir}}\\junction-link-dest" } - -- name: set modification date on files/folders - script: set_filedate.ps1 "{{item}}" - with_items: - - "{{win_find_dir}}\\nested\\file.ps1" - - "{{win_find_dir}}\\nested\\test.ps1" - - "{{win_find_dir}}\\nested\\out.log" - - "{{win_find_dir}}\\nested\\archive.log" - - "{{win_find_dir}}\\nested\\sub-nest\\test.ps1" - - "{{win_find_dir}}\\nested\\sub-nest\\readonly.txt" - - "{{win_find_dir}}\\link-dest\\link.ps1" - - "{{win_find_dir}}\\single\\large.ps1" - - "{{win_find_dir}}\\single\\small.ps1" - - "{{win_find_dir}}\\single\\test.ps1" - - "{{win_find_dir}}\\single\\hidden.ps1" - - "{{win_find_dir}}\\date\\old.ps1" - - "{{win_find_dir}}\\single\\out_20161101-091005.log" - - "{{win_find_dir}}\\hidden\\out_20161101-091005.log" - - "{{win_find_dir}}\\hard-link-dest\\file-abc.log" - - "{{win_find_dir}}\\nested" - - "{{win_find_dir}}\\single" - - "{{win_find_dir}}\\link-dest" - - "{{win_find_dir}}\\link-dest\\sub-link" - - "{{win_find_dir}}\\hard-link-dest" - - "{{win_find_dir}}\\junction-link-dest" - - "{{win_find_dir}}\\broken-link-dest" - - "{{win_find_dir}}\\nested\\sub-nest" - - "{{win_find_dir}}\\shared" - - "{{win_find_dir}}\\shared\\folder" - - "{{win_find_dir}}\\hidden" - - "{{win_find_dir}}\\date" - -- name: set file attributes for test - script: set_attributes.ps1 "{{item.path}}" {{item.attr}} - with_items: - - { 'path': "{{win_find_dir}}\\hidden", 'attr': "Hidden" } - - { 'path': "{{win_find_dir}}\\date", 'attr': "Hidden" } - - { 'path': "{{win_find_dir}}\\nested\\archive.log", 'attr': "Archive" } - - { 'path': "{{win_find_dir}}\\nested\\sub-nest\\readonly.txt", 'attr': "ReadOnly" } - - { 'path': "{{win_find_dir}}\\single\\hidden.ps1", 'attr': "Hidden" } - -- name: break the broken link target - win_file: - path: "{{win_find_dir}}\\broken-link-dest" - state: absent -# end test setup - -- name: expect failure when not setting paths - win_find: - patterns: a - register: actual - failed_when: "actual.msg != 'Get-AnsibleParam: Missing required argument: paths'" - -- name: expect failure when setting paths to a file - win_find: - paths: "{{win_output_dir}}\\win_find\\single\\large.ps1" - register: actual - failed_when: actual.msg != 'Argument path ' + win_output_dir + '\\win_find\\single\\large.ps1 is a file not a directory' - -- name: expect failure whe path is set to a non existent folder - win_find: - paths: "{{win_output_dir}}\\win_find\\thisisafakefolder" - register: actual - failed_when: actual.msg != 'Argument path ' + win_output_dir + '\\win_find\\thisisafakefolder does not exist cannot get information on' - -- name: get files in single directory - win_find: - paths: "{{win_output_dir}}\\win_find\\single" - register: actual - -- name: set expected value for files in a single directory - set_fact: - expected: - changed: False - examined: 5 - failed: False - files: - - { isarchive: True, - attributes: Archive, - checksum: f8d100cdcf0e6c1007db2f8dd0b7ee2884df89af, - creationtime: 1477984205, - extension: .ps1, - filename: large.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\large.ps1", - isreadonly: False, - isshared: False, - size: 260002 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .log, - filename: out_20161101-091005.log, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\out_20161101-091005.log", - isreadonly: False, - isshared: False, - size: 14 } - - { isarchive: True, - attributes: Archive, - checksum: 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, - creationtime: 1477984205, - extension: .ps1, - filename: small.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\small.ps1", - isreadonly: False, - isshared: False, - size: 1 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: test.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\test.ps1", - isreadonly: False, - isshared: False, - size: 14 } - matched: 4 - -- name: assert actual == expected - assert: - that: actual == expected - -- name: find hidden files - win_find: - paths: ['{{win_find_dir}}\\single', '{{win_find_dir}}\\nested'] - hidden: True - register: actual - -- name: set fact for hidden files - set_fact: - expected: - changed: False - examined: 11 - failed: False - files: - - { isarchive: True, - attributes: "Hidden, Archive", - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: hidden.ps1, - ishidden: True, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\hidden.ps1", - isreadonly: False, - isshared: False, - size: 14 } - matched: 1 - -- name: assert actual == expected - assert: - that: actual == expected - -- name: find file based on pattern - win_find: - paths: '{{win_find_dir}}\\single' - patterns: ['*.log', 'out_*'] - register: actual_pattern - -- name: find file based on pattern regex - win_find: - paths: '{{win_find_dir}}\\single' - patterns: "out_\\d{8}-\\d{6}.log" - use_regex: True - register: actual_regex - -- name: set fact for pattern files - set_fact: - expected: - changed: False - examined: 5 - failed: False - files: - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .log, - filename: out_20161101-091005.log, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\out_20161101-091005.log", - isreadonly: False, - isshared: False, - size: 14 } - matched: 1 - -- name: assert actual == expected - assert: - that: - - actual_pattern == expected - - actual_regex == expected - -- name: find files with recurse set - win_find: - paths: "{{win_find_dir}}\\nested" - recurse: True - patterns: "*.ps1" - register: actual - -- name: set expected value for files in a nested directory - set_fact: - expected: - changed: False - examined: 8 - failed: False - files: - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: test.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\sub-nest\\test.ps1", - isreadonly: False, - isshared: False, - size: 14 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: file.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\file.ps1", - isreadonly: False, - isshared: False, - size: 14 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: test.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\test.ps1", - isreadonly: False, - isshared: False, - size: 14 } - matched: 3 - -- name: assert actual == expected - assert: - that: actual == expected - -- name: find files with recurse set and follow links - win_find: - paths: "{{win_find_dir}}\\nested" - recurse: True - follow: True - patterns: "*.ps1" - register: actual - -- name: set expected value for files in a nested directory while following links - set_fact: - expected: - changed: False - examined: 10 - failed: False - files: - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: link.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\link\\link.ps1", - isreadonly: False, - isshared: False, - size: 14 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: test.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\sub-nest\\test.ps1", - isreadonly: False, - isshared: False, - size: 14 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: file.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\file.ps1", - isreadonly: False, - isshared: False, - size: 14 } - - { isarchive: True, - attributes: Archive, - checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, - creationtime: 1477984205, - extension: .ps1, - filename: test.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\nested\\test.ps1", - isreadonly: False, - isshared: False, - size: 14 } - matched: 4 - -- name: assert actual == expected - assert: - that: actual == expected - -- name: find directories - win_find: - paths: "{{win_find_dir}}\\link-dest" - file_type: directory - register: actual - -- name: set expected fact for directories with recurse and follow - set_fact: - expected: - changed: False - examined: 2 - failed: False - files: - - { isarchive: False, - attributes: Directory, - creationtime: 1477984205, - filename: sub-link, - ishidden: False, - isdir: True, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\link-dest\\sub-link", - isreadonly: False, - isshared: False, - size: 0 } - matched: 1 - -- name: assert actual == expected - assert: - that: actual == expected - -- name: find directories recurse and follow with a broken link - win_find: - paths: "{{win_find_dir}}" - file_type: directory - recurse: True - follow: True - register: actual - -- name: check directory count with recurse and follow is correct - assert: - that: - - actual.examined == 37 - - actual.matched == 17 - - actual.files[0].filename == 'broken-link' - - actual.files[0].islnk == True - - actual.files[6].filename == 'junction-link' - - actual.files[6].islnk == True - - actual.files[6].lnk_source == win_find_dir + '\\junction-link-dest' - - actual.files[11].filename == 'link' - - actual.files[11].islnk == True - - actual.files[11].lnk_source == win_find_dir + '\\link-dest' - - actual.files[15].filename == 'folder' - - actual.files[15].islnk == False - - actual.files[15].isshared == True - - actual.files[15].sharename == 'folder-share' - -- name: filter files by size without byte specified - win_find: - paths: "{{win_find_dir}}\\single" - size: 260002 - register: actual_without_byte - -- name: filter files by size with byte specified - win_find: - paths: "{{win_find_dir}}\\single" - size: 253k - register: actual_with_byte - -- name: set expected fact for files by size - set_fact: - expected: - changed: False - examined: 5 - failed: False - files: - - { isarchive: True, - attributes: Archive, - checksum: f8d100cdcf0e6c1007db2f8dd0b7ee2884df89af, - creationtime: 1477984205, - extension: ".ps1", - filename: large.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\large.ps1", - isreadonly: False, - isshared: False, - size: 260002 } - matched: 1 - -- name: assert actual == expected - assert: - that: - - actual_without_byte == expected - - actual_with_byte == expected - -- name: filter files by size (less than) without byte specified - win_find: - paths: "{{win_find_dir}}\\single" - size: -4 - register: actual_without_byte - -- name: filter files by size (less than) with byte specified - win_find: - paths: "{{win_find_dir}}\\single" - size: -4b - register: actual_with_byte - -- name: set expected fact for files by size (less than) - set_fact: - expected: - changed: False - examined: 5 - failed: False - files: - - { isarchive: True, - attributes: Archive, - checksum: 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, - creationtime: 1477984205, - extension: ".ps1", - filename: small.ps1, - ishidden: False, - isdir: False, - islnk: False, - lastaccesstime: 1477984205, - lastwritetime: 1477984205, - owner: BUILTIN\Administrators, - path: "{{win_find_dir}}\\single\\small.ps1", - isreadonly: False, - isshared: False, - size: 1 } - matched: 1 - -- name: assert actual == expected - assert: - that: - - actual_without_byte == expected - - actual_with_byte == expected - -# For dates we cannot assert against expected as the times change, this is a poor mans attempt at testing -- name: filter files by age without unit specified - win_find: - paths: "{{win_find_dir}}\\date" - age: 3600 - register: actual_without_unit - -- name: filter files by age with unit specified - win_find: - paths: "{{win_find_dir}}\\date" - age: 1h - register: actual_with_unit - -- name: assert dates match each other - assert: - that: - - actual_without_unit == actual_with_unit - - actual_without_unit.matched == 1 - - actual_without_unit.files[0].checksum == '031a04ecc76f794d7842651de732075dec6fef04' - - actual_without_unit.files[0].path == win_find_dir + '\\date\\old.ps1' - -- name: filter files by age (newer than) without unit specified - win_find: - paths: "{{win_find_dir}}\\date" - age: -3600 - register: actual_without_unit - -- name: filter files by age (newer than) without unit specified - win_find: - paths: "{{win_find_dir}}\\date" - age: -1h - register: actual_with_unit - -- name: assert dates match each other - assert: - that: - - actual_without_unit == actual_with_unit - - actual_without_unit.matched == 1 - - actual_without_unit.files[0].checksum == '7454f04e3ac587f711a416f4edf26507255e0a2e' - - actual_without_unit.files[0].path == win_find_dir + '\\date\\new.ps1' - -- name: get list of files with md5 checksum - win_find: - paths: "{{win_find_dir}}\\single" - patterns: test.ps1 - checksum_algorithm: md5 - register: actual_md5_checksum - -- name: assert md5 checksum value - assert: - that: - - actual_md5_checksum.files[0].checksum == 'd1713d0f1d2e8fae230328d8fd59de01' +# while most of the setup can be done with modules, it is quicker to do them +# all in bulk than with with_items to save each round trip over WinRM +- name: set test files and folders + win_shell: | + $directories = @( + "nested", + "single", + "link-dest\sub-link", + "hard-link-dest", + "junction-link-dest", + "broken-link-dest", + "nested\sub-nest", + "shared\folder", + "hidden", + "date", + "emptynested\nest\dir1", + "emptynested\nest\dir2" + ) + foreach ($directory in $directories) { + New-Item -Path "{{win_find_dir}}\$directory" -ItemType Directory + } + + $normal_content = "abcdefg1234567" + $normal_files = @( + "nested\file.ps1", + "nested\test.ps1", + "nested\out.log", + "nested\archive.log", + "nested\sub-nest\test.ps1", + "nested\sub-nest\readonly.txt", + "link-dest\link.ps1", + "single\test.ps1", + "single\hidden.ps1", + "single\out_20161101-091005.log", + "hidden\out_20161101-091005.log", + "hard-link-dest\file-abc.log" + ) + foreach ($file in $normal_files) { + New-Item -Path "{{win_find_dir}}\$file" -ItemType File + [System.IO.File]::WriteAllText("{{win_find_dir}}\$file", $normal_content) + } + + New-Item -Path "{{win_find_dir}}\single\small.ps1" -ItemType File + [System.IO.File]::WriteAllText("{{win_find_dir}}\single\small.ps1", "a") + + New-Item -Path "{{win_find_dir}}\date\new.ps1" -ItemType File + [System.IO.File]::WriteAllText("{{win_find_dir}}\date\new.ps1", "random text for new date") + + New-Item -Path "{{win_find_dir}}\date\old.ps1" -ItemType File + [System.IO.File]::WriteAllText("{{win_find_dir}}\date\old.ps1", "random text for old date") + + New-Item -Path "{{win_find_dir}}\single\large.ps1" -ItemType File + Set-Content -Path "{{win_find_dir}}\single\large.ps1" -Value ('abcdefghijklmnopqrstuvwxyz' * 10000) + + $share_stat = Get-WmiObject -Class Win32_Share -Filter "name='folder-share'" + if ($share_stat) { + $share_stat.Delete() + } + $wmi = [wmiClass] 'Win32_Share' + $wmi.Create("{{win_find_dir}}\shared\folder", "folder-share", 0) + + cmd.exe /c mklink /D "{{win_find_dir}}\nested\link" "{{win_find_dir}}\link-dest" + cmd.exe /c mklink /D "{{win_find_dir}}\broken-link" "{{win_find_dir}}\broken-link-dest" + cmd.exe /c mklink /H "{{win_find_dir}}\hard-link-dest\hard-link.log" "{{win_find_dir}}\hard-link-dest\file-abc.log" + cmd.exe /c mklink /J "{{win_find_dir}}\junction-link" "{{win_find_dir}}\junction-link-dest" -- name: get list of files with sha1 checksum - win_find: - paths: "{{win_find_dir}}\\single" - patterns: test.ps1 - checksum_algorithm: sha1 - register: actual_sha1_checksum - -- name: assert sha1 checksum value - assert: - that: - - actual_sha1_checksum.files[0].checksum == '8df33cee3325596517df5bb5aa980cf9c5c1fda3' - -- name: get list of files with sha256 checksum - win_find: - paths: "{{win_find_dir}}\\single" - patterns: test.ps1 - checksum_algorithm: sha256 - register: actual_sha256_checksum - -- name: assert sha256 checksum value - assert: - that: - - actual_sha256_checksum.files[0].checksum == 'c20d2eba7ffda0079812721b6f4e4e109e2f0c5e8cc3d1273a060df6f7d9f339' - -- name: get list of files with sha384 checksum - win_find: - paths: "{{win_find_dir}}\\single" - patterns: test.ps1 - checksum_algorithm: sha384 - register: actual_sha384_checksum - -- name: assert sha384 checksum value - assert: - that: - - actual_sha384_checksum.files[0].checksum == 'aed515eb216b9c7009ae8c4680f46c1e22004528b231aa0482a8587543bca47d3504e9f77e884eb2d11b2f9f5dc01651' - -- name: get list of files with sha512 checksum - win_find: - paths: "{{win_find_dir}}\\single" - patterns: test.ps1 - checksum_algorithm: sha512 - register: actual_sha512_checksum - -- name: assert sha512 checksum value - assert: - that: - - actual_sha512_checksum.files[0].checksum == '05abf64a68c4731699c23b4fc6894a36646fce525f3c96f9cf743b5d0c3bfd933dad0e95e449e3afe1f74d534d69a53b8f46cf835763dd42915813c897b02b87' - -- name: get list of files without checksum - win_find: - paths: "{{win_find_dir}}\\single" - patterns: test.ps1 - get_checksum: False - register: actual_no_checksum - -- name: assert no checksum is returned - assert: - that: - - actual_no_checksum.files[0].checksum is undefined - -# https://github.com/ansible/ansible/issues/26158 -- name: get list of files in an empty nested directory - win_find: - paths: '{{win_find_dir}}\emptynested' - register: actual_empty_nested - -- name: assert get list of files in an empty nested directory - assert: - that: - - actual_empty_nested.matched == 0 - -- name: remove testing folder - win_file: - path: "{{win_find_dir}}" - state: absent + $date = Get-Date -Year 2016 -Month 11 -Day 1 -Hour 7 -Minute 10 -Second 5 -Millisecond 0 + Get-ChildItem -Path "{{win_find_dir}}" -Recurse | Where-Object { $_.Name -ne "new.ps1" } | ForEach-Object { + $_.CreationTime = $date + $_.LastAccessTime = $date + $_.LastWriteTime = $date + } + + $attributes = @{ + "hidden" = "Hidden" + "date" = "Hidden" + "nested\archive.log" = "Archive" + "nested\sub-nest\readonly.txt" = "ReadOnly" + "single\hidden.ps1" = "Hidden" + } + foreach ($attribute in $attributes.GetEnumerator()) { + $item = Get-Item -Path "{{win_find_dir}}\$($attribute.Name)" + $file_attributes = $item.Attributes -split ',' + if ($file_attributes -notcontains $attribute.Value) { + $file_attributes += $attribute.Value + } + $item.Attributes = $file_attributes -join ',' + } + + Remove-Item -Path "{{win_find_dir}}\broken-link-dest" -Force + +- block: + - include_tasks: tests.yml + + always: + - name: remove test user + win_user: + name: '{{test_win_find_username}}' + state: absent + + - name: remove testing folder + win_file: + path: '{{win_find_dir}}' + state: absent diff --git a/test/integration/targets/win_find/tasks/tests.yml b/test/integration/targets/win_find/tasks/tests.yml new file mode 100644 index 00000000000..0afe771946b --- /dev/null +++ b/test/integration/targets/win_find/tasks/tests.yml @@ -0,0 +1,662 @@ +--- +- name: expect failure when not setting paths + win_find: + patterns: a + register: actual + failed_when: "actual.msg != 'Get-AnsibleParam: Missing required argument: paths'" + +- name: expect failure when setting paths to a file + win_find: + paths: "{{win_output_dir}}\\win_find\\single\\large.ps1" + register: actual + failed_when: actual.msg != 'Argument path ' + win_output_dir + '\\win_find\\single\\large.ps1 is a file not a directory' + +- name: expect failure when path is set to a non existent folder + win_find: + paths: "{{win_output_dir}}\\win_find\\thisisafakefolder" + register: actual + failed_when: actual.msg != 'Argument path ' + win_output_dir + '\\win_find\\thisisafakefolder does not exist cannot get information on' + +- name: get files in single directory + win_find: + paths: "{{win_output_dir}}\\win_find\\single" + register: actual + +- name: set expected value for files in a single directory + set_fact: + expected: + changed: False + examined: 5 + failed: False + files: + - { isarchive: True, + attributes: Archive, + checksum: f8d100cdcf0e6c1007db2f8dd0b7ee2884df89af, + creationtime: 1477984205, + extension: .ps1, + filename: large.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\large.ps1", + isreadonly: False, + isshared: False, + size: 260002 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .log, + filename: out_20161101-091005.log, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\out_20161101-091005.log", + isreadonly: False, + isshared: False, + size: 14 } + - { isarchive: True, + attributes: Archive, + checksum: 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, + creationtime: 1477984205, + extension: .ps1, + filename: small.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\small.ps1", + isreadonly: False, + isshared: False, + size: 1 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: test.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\test.ps1", + isreadonly: False, + isshared: False, + size: 14 } + matched: 4 + +- name: assert actual == expected + assert: + that: actual == expected + +- name: find hidden files + win_find: + paths: ['{{win_find_dir}}\\single', '{{win_find_dir}}\\nested'] + hidden: True + register: actual + +- name: set fact for hidden files + set_fact: + expected: + changed: False + examined: 11 + failed: False + files: + - { isarchive: True, + attributes: "Hidden, Archive", + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: hidden.ps1, + ishidden: True, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\hidden.ps1", + isreadonly: False, + isshared: False, + size: 14 } + matched: 1 + +- name: assert actual == expected + assert: + that: actual == expected + +- name: find file based on pattern + win_find: + paths: '{{win_find_dir}}\\single' + patterns: ['*.log', 'out_*'] + register: actual_pattern + +- name: find file based on pattern regex + win_find: + paths: '{{win_find_dir}}\\single' + patterns: "out_\\d{8}-\\d{6}.log" + use_regex: True + register: actual_regex + +- name: set fact for pattern files + set_fact: + expected: + changed: False + examined: 5 + failed: False + files: + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .log, + filename: out_20161101-091005.log, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\out_20161101-091005.log", + isreadonly: False, + isshared: False, + size: 14 } + matched: 1 + +- name: assert actual == expected + assert: + that: + - actual_pattern == expected + - actual_regex == expected + +- name: find files with recurse set + win_find: + paths: "{{win_find_dir}}\\nested" + recurse: True + patterns: "*.ps1" + register: actual + +- name: set expected value for files in a nested directory + set_fact: + expected: + changed: False + examined: 8 + failed: False + files: + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: test.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\sub-nest\\test.ps1", + isreadonly: False, + isshared: False, + size: 14 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: file.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\file.ps1", + isreadonly: False, + isshared: False, + size: 14 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: test.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\test.ps1", + isreadonly: False, + isshared: False, + size: 14 } + matched: 3 + +- name: assert actual == expected + assert: + that: actual == expected + +- name: find files with recurse set and follow links + win_find: + paths: "{{win_find_dir}}\\nested" + recurse: True + follow: True + patterns: "*.ps1" + register: actual + +- name: set expected value for files in a nested directory while following links + set_fact: + expected: + changed: False + examined: 10 + failed: False + files: + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: link.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\link\\link.ps1", + isreadonly: False, + isshared: False, + size: 14 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: test.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\sub-nest\\test.ps1", + isreadonly: False, + isshared: False, + size: 14 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: file.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\file.ps1", + isreadonly: False, + isshared: False, + size: 14 } + - { isarchive: True, + attributes: Archive, + checksum: 8df33cee3325596517df5bb5aa980cf9c5c1fda3, + creationtime: 1477984205, + extension: .ps1, + filename: test.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\nested\\test.ps1", + isreadonly: False, + isshared: False, + size: 14 } + matched: 4 + +- name: assert actual == expected + assert: + that: actual == expected + +- name: find directories + win_find: + paths: "{{win_find_dir}}\\link-dest" + file_type: directory + register: actual + +- name: set expected fact for directories with recurse and follow + set_fact: + expected: + changed: False + examined: 2 + failed: False + files: + - { isarchive: False, + attributes: Directory, + creationtime: 1477984205, + filename: sub-link, + ishidden: False, + isdir: True, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\link-dest\\sub-link", + isreadonly: False, + isshared: False, + size: 0 } + matched: 1 + +- name: assert actual == expected + assert: + that: actual == expected + +- name: find directories recurse and follow with a broken link + win_find: + paths: "{{win_find_dir}}" + file_type: directory + recurse: True + follow: True + register: actual + +- name: check directory count with recurse and follow is correct + assert: + that: + - actual.examined == 37 + - actual.matched == 17 + - actual.files[0].filename == 'broken-link' + - actual.files[0].islnk == True + - actual.files[6].filename == 'junction-link' + - actual.files[6].islnk == True + - actual.files[6].lnk_source == win_find_dir + '\\junction-link-dest' + - actual.files[11].filename == 'link' + - actual.files[11].islnk == True + - actual.files[11].lnk_source == win_find_dir + '\\link-dest' + - actual.files[15].filename == 'folder' + - actual.files[15].islnk == False + - actual.files[15].isshared == True + - actual.files[15].sharename == 'folder-share' + +- name: filter files by size without byte specified + win_find: + paths: "{{win_find_dir}}\\single" + size: 260002 + register: actual_without_byte + +- name: filter files by size with byte specified + win_find: + paths: "{{win_find_dir}}\\single" + size: 253k + register: actual_with_byte + +- name: set expected fact for files by size + set_fact: + expected: + changed: False + examined: 5 + failed: False + files: + - { isarchive: True, + attributes: Archive, + checksum: f8d100cdcf0e6c1007db2f8dd0b7ee2884df89af, + creationtime: 1477984205, + extension: ".ps1", + filename: large.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\large.ps1", + isreadonly: False, + isshared: False, + size: 260002 } + matched: 1 + +- name: assert actual == expected + assert: + that: + - actual_without_byte == expected + - actual_with_byte == expected + +- name: filter files by size (less than) without byte specified + win_find: + paths: "{{win_find_dir}}\\single" + size: -4 + register: actual_without_byte + +- name: filter files by size (less than) with byte specified + win_find: + paths: "{{win_find_dir}}\\single" + size: -4b + register: actual_with_byte + +- name: set expected fact for files by size (less than) + set_fact: + expected: + changed: False + examined: 5 + failed: False + files: + - { isarchive: True, + attributes: Archive, + checksum: 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, + creationtime: 1477984205, + extension: ".ps1", + filename: small.ps1, + ishidden: False, + isdir: False, + islnk: False, + lastaccesstime: 1477984205, + lastwritetime: 1477984205, + owner: BUILTIN\Administrators, + path: "{{win_find_dir}}\\single\\small.ps1", + isreadonly: False, + isshared: False, + size: 1 } + matched: 1 + +- name: assert actual == expected + assert: + that: + - actual_without_byte == expected + - actual_with_byte == expected + +# For dates we cannot assert against expected as the times change, this is a poor mans attempt at testing +- name: filter files by age without unit specified + win_find: + paths: "{{win_find_dir}}\\date" + age: 3600 + register: actual_without_unit + +- name: filter files by age with unit specified + win_find: + paths: "{{win_find_dir}}\\date" + age: 1h + register: actual_with_unit + +- name: assert dates match each other + assert: + that: + - actual_without_unit == actual_with_unit + - actual_without_unit.matched == 1 + - actual_without_unit.files[0].checksum == 'd1185139c47f5bc951e2e9135922fe31059206b1' + - actual_without_unit.files[0].path == win_find_dir + '\\date\\old.ps1' + +- name: filter files by age (newer than) without unit specified + win_find: + paths: "{{win_find_dir}}\\date" + age: -3600 + register: actual_without_unit + +- name: filter files by age (newer than) without unit specified + win_find: + paths: "{{win_find_dir}}\\date" + age: -1h + register: actual_with_unit + +- name: assert dates match each other + assert: + that: + - actual_without_unit == actual_with_unit + - actual_without_unit.matched == 1 + - actual_without_unit.files[0].checksum == 'af99d0e98df4531b9f26c942f41d65c58766bfa9' + - actual_without_unit.files[0].path == win_find_dir + '\\date\\new.ps1' + +- name: get list of files with md5 checksum + win_find: + paths: "{{win_find_dir}}\\single" + patterns: test.ps1 + checksum_algorithm: md5 + register: actual_md5_checksum + +- name: assert md5 checksum value + assert: + that: + - actual_md5_checksum.files[0].checksum == 'd1713d0f1d2e8fae230328d8fd59de01' + +- name: get list of files with sha1 checksum + win_find: + paths: "{{win_find_dir}}\\single" + patterns: test.ps1 + checksum_algorithm: sha1 + register: actual_sha1_checksum + +- name: assert sha1 checksum value + assert: + that: + - actual_sha1_checksum.files[0].checksum == '8df33cee3325596517df5bb5aa980cf9c5c1fda3' + +- name: get list of files with sha256 checksum + win_find: + paths: "{{win_find_dir}}\\single" + patterns: test.ps1 + checksum_algorithm: sha256 + register: actual_sha256_checksum + +- name: assert sha256 checksum value + assert: + that: + - actual_sha256_checksum.files[0].checksum == 'c20d2eba7ffda0079812721b6f4e4e109e2f0c5e8cc3d1273a060df6f7d9f339' + +- name: get list of files with sha384 checksum + win_find: + paths: "{{win_find_dir}}\\single" + patterns: test.ps1 + checksum_algorithm: sha384 + register: actual_sha384_checksum + +- name: assert sha384 checksum value + assert: + that: + - actual_sha384_checksum.files[0].checksum == 'aed515eb216b9c7009ae8c4680f46c1e22004528b231aa0482a8587543bca47d3504e9f77e884eb2d11b2f9f5dc01651' + +- name: get list of files with sha512 checksum + win_find: + paths: "{{win_find_dir}}\\single" + patterns: test.ps1 + checksum_algorithm: sha512 + register: actual_sha512_checksum + +- name: assert sha512 checksum value + assert: + that: + - actual_sha512_checksum.files[0].checksum == '05abf64a68c4731699c23b4fc6894a36646fce525f3c96f9cf743b5d0c3bfd933dad0e95e449e3afe1f74d534d69a53b8f46cf835763dd42915813c897b02b87' + +- name: get list of files without checksum + win_find: + paths: "{{win_find_dir}}\\single" + patterns: test.ps1 + get_checksum: False + register: actual_no_checksum + +- name: assert no checksum is returned + assert: + that: + - actual_no_checksum.files[0].checksum is undefined + +# https://github.com/ansible/ansible/issues/26158 +- name: get list of files in an empty nested directory + win_find: + paths: '{{win_find_dir}}\emptynested' + register: actual_empty_nested + +- name: assert get list of files in an empty nested directory + assert: + that: + - actual_empty_nested.matched == 0 + +- name: create new folders for security tests + win_file: + path: '{{win_find_dir}}\{{item}}' + state: directory + with_items: + - secure-tests\secure\internal-folder + - secure-tests\open\internal-folder + +- name: create random password for test user + set_fact: + test_win_find_password: password123! + {{ lookup('password', '/dev/null chars=ascii_letters,digits length=8') }} + +- name: create test user who does not have access to secure folder + win_user: + name: '{{test_win_find_username}}' + password: '{{test_win_find_password}}' + state: present + groups: + - Users + +- name: change owner of secure folder + win_owner: + path: '{{win_find_dir}}\secure-tests\secure' + user: BUILTIN\Administrators + recurse: yes + +- name: set explicit inheritance of secure folder for the Administrators accounts + win_acl: + user: BUILTIN\Administrators + path: '{{win_find_dir}}\secure-tests\secure' + rights: FullControl + type: allow + state: present + inherit: None + +- name: remove inheritance on the secure folder + win_acl_inheritance: + path: '{{win_find_dir}}\secure-tests\secure' + reorganize: no + state: absent + +- name: run win_find with under-privileged account + win_find: + paths: '{{win_find_dir}}\secure-tests' + recurse: yes + file_type: directory + register: secure_result + become: yes + become_method: runas + become_user: '{{test_win_find_username}}' + vars: + ansible_become_password: '{{test_win_find_password}}' + +- name: assert win_find only examined 2 files with under-privileged account + assert: + that: + - secure_result.examined == 2 + - secure_result.matched == 2 + - secure_result.files[0].path == win_find_dir + "\secure-tests\open" + - secure_result.files[1].path == win_find_dir + "\secure-tests\open\internal-folder"