1 #!powershell
2 
3 # Copyright: (c) 2015, Corwin Brown <corwin.brown@maxpoint.com>
4 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5 
6 #Requires -Module Ansible.ModuleUtils.Legacy
7 
8 $params = Parse-Args $args -supports_check_mode $true
9 $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
10 
11 $src = Get-AnsibleParam -obj $params -name "src" -type "path" -failifempty $true
12 $dest = Get-AnsibleParam -obj $params -name "dest" -type "path" -failifempty $true
13 $purge = Get-AnsibleParam -obj $params -name "purge" -type "bool" -default $false
14 $recurse = Get-AnsibleParam -obj $params -name "recurse" -type "bool" -default $false
15 $flags = Get-AnsibleParam -obj $params -name "flags" -type "str"
16 
17 $result = @{
18     changed = $false
19     dest = $dest
20     purge = $purge
21     recurse = $recurse
22     src = $src
23 }
24 
25 # Search for an Error Message
26 # Robocopy seems to display an error after 3 '-----' separator lines
SearchForError($cmd_output, $default_msg)27 Function SearchForError($cmd_output, $default_msg) {
28     $separator_count = 0
29     $error_msg = $default_msg
30     ForEach ($line in $cmd_output) {
31         if (-not $line) {
32             continue
33         }
34 
35         if ($separator_count -ne 3) {
36             if (Select-String -InputObject $line -pattern "^(\s+)?(\-+)(\s+)?$") {
37                 $separator_count += 1
38             }
39         } else {
40             if (Select-String -InputObject $line -pattern "error") {
41                 $error_msg = $line
42                 break
43             }
44         }
45     }
46 
47     return $error_msg
48 }
49 
50 if (-not (Test-Path -Path $src)) {
51     Fail-Json $result "$src does not exist!"
52 }
53 
54 # Build Arguments
55 $robocopy_opts = @($src, $dest)
56 
57 if ($check_mode) {
58     $robocopy_opts += "/l"
59 }
60 
61 if ($null -eq $flags) {
62     if ($purge) {
63         $robocopy_opts += "/purge"
64     }
65 
66     if ($recurse) {
67         $robocopy_opts += "/e"
68     }
69 } else {
70     ForEach ($f in $flags.split(" ")) {
71         $robocopy_opts += $f
72     }
73 }
74 
75 $result.flags = $flags
76 $result.cmd = "$robocopy $robocopy_opts"
77 
78 Try {
79     $robocopy_output = &robocopy $robocopy_opts
80     $rc = $LASTEXITCODE
81 } Catch {
82     Fail-Json $result "Error synchronizing $src to $dest! Msg: $($_.Exception.Message)"
83 }
84 
85 $result.msg = "Success"
86 $result.output = $robocopy_output
87 $result.return_code = $rc # Backward compatibility
88 $result.rc = $rc
89 
90 switch ($rc) {
91 
92     0 {
93         $result.msg = "No files copied."
94     }
95     1 {
96         $result.msg = "Files copied successfully!"
97         $result.changed = $true
98         $result.failed = $false
99     }
100     2 {
101         $result.msg = "Some Extra files or directories were detected. No files were copied."
102         Add-Warning $result $result.msg
103         $result.failed = $false
104     }
105     3 {
106         $result.msg = "(2+1) Some files were copied. Additional files were present."
107         Add-Warning $result $result.msg
108         $result.changed = $true
109         $result.failed = $false
110     }
111     4 {
112         $result.msg = "Some mismatched files or directories were detected. Housekeeping might be required!"
113         Add-Warning $result $result.msg
114         $result.changed = $true
115         $result.failed = $false
116     }
117     5 {
118         $result.msg = "(4+1) Some files were copied. Some files were mismatched."
119         Add-Warning $result $result.msg
120         $result.changed = $true
121         $result.failed = $false
122     }
123     6 {
124         $result.msg = "(4+2) Additional files and mismatched files exist. No files were copied."
125         $result.failed = $false
126     }
127     7 {
128         $result.msg = "(4+1+2) Files were copied, a file mismatch was present, and additional files were present."
129         Add-Warning $result $result.msg
130         $result.changed = $true
131         $result.failed = $false
132     }
133     8 {
134         Fail-Json $result (SearchForError $robocopy_output "Some files or directories could not be copied!")
135     }
136     { @(9, 10, 11, 12, 13, 14, 15) -contains $_ } {
137         Fail-Json $result (SearchForError $robocopy_output "Fatal error. Check log message!")
138     }
139     16 {
140         Fail-Json $result (SearchForError $robocopy_output "Serious Error! No files were copied! Do you have permissions to access $src and $dest?")
141     }
142 
143 }
144 
145 Exit-Json $result
146