diff --git a/lib/ansible/modules/windows/win_regedit.ps1 b/lib/ansible/modules/windows/win_regedit.ps1 index 8bcc79c92cf..8b02c9fae28 100644 --- a/lib/ansible/modules/windows/win_regedit.ps1 +++ b/lib/ansible/modules/windows/win_regedit.ps1 @@ -2,6 +2,7 @@ # This file is part of Ansible # # (c) 2015, Adam Keech , Josh Ludwig +# (c) 2017, Jordan Borean # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,15 +22,16 @@ $ErrorActionPreference = "Stop" -$params = Parse-Args $args -supports_check_mode $true +$params = Parse-Args -arguments $args -supports_check_mode $true $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false -$diff_support = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false +$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false -$path = Get-AnsibleParam -obj $params -name "path" -type "string" -failifempty $true -aliases "key" -$name = Get-AnsibleParam -obj $params -name "name" -type "string" -aliases "entry","value" +$path = Get-AnsibleParam -obj $params -name "path" -type "str" -failifempty $true -aliases "key" +$name = Get-AnsibleParam -obj $params -name "name" -type "str" -aliases "entry","value" $data = Get-AnsibleParam -obj $params -name "data" -$type = Get-AnsibleParam -obj $params -name "type" -type "string" -validateSet "none","binary","dword","expandstring","multistring","string","qword" -aliases "datatype" -default "string" -$state = Get-AnsibleParam -obj $params -name "state" -type "string" -validateSet "present","absent" -default "present" +$type = Get-AnsibleParam -obj $params -name "type" -type "str" -default "string" -validateset "none","binary","dword","expandstring","multistring","string","qword" -aliases "datatype" +$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent" +$delete_key = Get-AnsibleParam -obj $params -name "delete_key" -type "bool" -default $true $result = @{ changed = $false @@ -37,7 +39,7 @@ $result = @{ data_type_changed = $false } -if ($diff_support) { +if ($diff_mode) { $result.diff = @{ prepared = "" } @@ -45,289 +47,292 @@ if ($diff_support) { # Fix HCCC:\ PSDrive for pre-2.3 compatibility if ($path -match "^HCCC:\\") { - Add-Warning $result "Please use path: HKCC:\... instead of path: $path" + Add-DeprecationWarning -obj $result -message "Please use path: HKCC:\... instead of path: $path" -version 2.6 $path = $path -replace "HCCC:\\","HKCC:\\" } +# fire a warning if the property name isn't specified, the (Default) key ($null) can only be a string +if ($name -eq $null -and $type -ne "string") { + Add-Warning -obj $result -message "the data type when name is not specified can only be 'string', the type has automatically been converted" + $type = "string" +} + # Check that the registry path is in PSDrive format: HKCC, HKCR, HKCU, HKLM, HKU -if (-not ($path -match "^HK(CC|CR|CU|LM|U):\\")) { +if ($path -notmatch "^HK(CC|CR|CU|LM|U):\\") { Fail-Json $result "path: $path is not a valid powershell path, see module documentation for examples." -} - -Function Test-ValueData { - Param ( - [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Path, - [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Name - ) - - try { - Get-ItemProperty -Path $Path -Name $Name | Out-Null - return $true - } catch { - return $false - } } -# Returns true if registry data matches. -# Handles binary, integer(dword) and string registry data -Function Compare-Data { - Param ( - [parameter(Mandatory=$true)] [AllowEmptyString()] [AllowNull()] $ReferenceData, - [parameter(Mandatory=$true)] [AllowEmptyString()] [AllowNull()] $DifferenceData - ) - - if ($ReferenceData -eq $null) { - if ($DifferenceData -eq $null) { - return $true - } else { - return $false - } - } elseif ($ReferenceData -is [object[]]) { - if (@(Compare-Object $ReferenceData $DifferenceData -SyncWindow 0).Length -eq 0) { - return $true - } else { - return $false - } - } else { - if ($ReferenceData -ceq $DifferenceData) { - return $true - } else { - return $false - } - } +# Create the required PSDrives if missing +$registry_hive = Split-Path -Path $path -Qualifier +if ($registry_hive -eq "HKCR:" -and (-not (Test-Path HKCR:\))) { + New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT +} +if ($registry_hive -eq "HKU:" -and (-not (Test-Path HKU:\))) { + New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS +} +if ($registry_hive -eq "HKCC:" -and (-not (Test-Path HKCC:\))) { + New-PSDrive -Name HKCC -PSProvider Registry -Root HKEY_CURRENT_CONFIG } # Simplified version of Convert-HexStringToByteArray from # https://cyber-defense.sans.org/blog/2010/02/11/powershell-byte-array-hex-convert # Expects a hex in the format you get when you run reg.exe export, # and converts to a byte array so powershell can modify binary registry entries -function Convert-RegExportHexStringToByteArray { - Param ( - [parameter(Mandatory=$true)] [String] $String - ) - +# import format is like 'hex:be,ef,be,ef,be,ef,be,ef,be,ef' +Function Convert-RegExportHexStringToByteArray($string) { # Remove 'hex:' from the front of the string if present - $String = $String.ToLower() -replace '^hex\:','' + $string = $string.ToLower() -replace '^hex\:','' # Remove whitespace and any other non-hex crud. - $String = $String.ToLower() -replace '[^a-f0-9\\,x\-\:]','' + $string = $string -replace '[^a-f0-9\\,x\-\:]','' # Turn commas into colons - $String = $String -replace ',',':' + $string = $string -replace ',',':' # Maybe there's nothing left over to convert... - if ($String.Length -eq 0) { + if ($string.Length -eq 0) { return ,@() } # Split string with or without colon delimiters. - if ($String.Length -eq 1) { - return ,@([System.Convert]::ToByte($String,16)) - } elseif (($String.Length % 2 -eq 0) -and ($String.IndexOf(":") -eq -1)) { - return ,@($String -split '([a-f0-9]{2})' | foreach-object { if ($_) {[System.Convert]::ToByte($_,16)}}) - } elseif ($String.IndexOf(":") -ne -1) { - return ,@($String -split ':+' | foreach-object {[System.Convert]::ToByte($_,16)}) + if ($string.Length -eq 1) { + return ,@([System.Convert]::ToByte($string,16)) + } elseif (($string.Length % 2 -eq 0) -and ($string.IndexOf(":") -eq -1)) { + return ,@($string -split '([a-f0-9]{2})' | foreach-object { if ($_) {[System.Convert]::ToByte($_,16)}}) + } elseif ($string.IndexOf(":") -ne -1) { + return ,@($string -split ':+' | foreach-object {[System.Convert]::ToByte($_,16)}) } else { return ,@() } } -# Create the required PSDrives if missing -if (-not (Test-Path HKCR:\)) { - New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT -} -if (-not (Test-Path HKU:\)) { - New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS -} -if (-not (Test-Path HKCC:\)) { - New-PSDrive -Name HKCC -PSProvider Registry -Root HKEY_CURRENT_CONFIG +Function Test-RegistryProperty($path, $name) { + # will validate if the registry key contains the property, returns true + # if the property exists and false if the property does not + try { + $value = (Get-Item -Path $path).GetValue($name) + # need to do it this way return ($value -eq $null) does not work + if ($value -eq $null) { + return $false + } else { + return $true + } + } catch [System.Management.Automation.ItemNotFoundException] { + # key didn't exist so the property mustn't + return $false + } } +Function Compare-RegistryProperties($existing, $new) { + $mismatch = $false + if ($existing -is [Array]) { + if ((Compare-Object -ReferenceObject $existing -DifferenceObject $new -SyncWindow 0).Length -ne 0) { + $mismatch = $true + } + } else { + if ($existing -cne $new) { + $mismatch = $true + } + } -# Convert HEX string to binary if type binary -if ($type -eq "binary" -and $data -ne $null -and $data -is [string]) { - $data = Convert-RegExportHexStringToByteArray($data) + return $mismatch } -# Special case handling for the path's default property. -if ($name -eq "" -or ($name -ne $null -and $name.ToLower() -eq "(default)")) { - # Apparently, "(default)" cannot be of type expandstring, do it ourselves - if ($type -eq "expandstring" -and $data -ne $null -and $data -is [string]) { - $data = Expand-Environment($data) - } - $name = "(default)" - $type = "string" +# convert property names "" to $null as "" refers to (Default) +if ($name -eq "") { + $name = $null } -# Support REG_NONE with empty value -# FIXME: REG_NONE support is not idempotent yet -if ($type -eq "none" -or $data -eq $null) { - $data = New-Object byte[] 0 -# $data = ([byte[]] @()) -} +# convert the data to the required format +if ($type -in @("binary", "none")) { + if ($data -eq $null) { + $data = "" + } -if ($state -eq "present") { + # convert the data from string to byte array if in hex: format + if ($data -is [String]) { + $data = [byte[]](Convert-RegExportHexStringToByteArray -string $data) + } elseif ($data -is [Int]) { + if ($data -gt 255) { + Fail-Json $result "cannot convert binary data '$data' to byte array, please specify this value as a yaml byte array or a comma separated hex value string" + } + $data = [byte[]]@([byte]$data) + } elseif ($data -is [Array]) { + $data = [byte[]]$data + } +} elseif ($type -in @("dword", "qword")) { + # dword's and dword's don't allow null values, set to 0 + if ($data -eq $null) { + $data = 0 + } - if ((Test-Path $path) -and $name -ne $null) { + if ($data -is [String]) { + # if the data is a string we need to convert it to an unsigned int64 + # it needs to be unsigned as Ansible passes in an unsigned value while + # powershell uses a signed data type. The value will then be converted + # below + $data = [UInt64]$data + } - if (Test-ValueData -Path $path -Name $name) { + if ($type -eq "dword") { + if ($data -gt [UInt32]::MaxValue) { + Fail-Json $result "data cannot be larger than 0xffffffff when type is dword" + } elseif ($data -gt [Int32]::MaxValue) { + # when dealing with larger int32 (> 2147483647 or 0x7FFFFFFF) powershell + # automatically converts it to a signed int64. We need to convert this to + # signed int32 by parsing the hex string value. + $data = "0x$("{0:x}" -f $data)" + } + $data = [Int32]$data + } else { + if ($data -gt [UInt64]::MaxValue) { + Fail-Json $result "data cannot be larger than 0xffffffffffffffff when type is qword" + } elseif ($data -gt [Int64]::MaxValue) { + $data = "0x$("{0:x}" -f $data)" + } + $data = [Int64]$data + } +} elseif ($type -in @("string", "expandstring")) { + # a null string or expandstring must be empty quotes + if ($data -eq $null) { + $data = "" + } +} elseif ($type -eq "multistring") { + # convert the data for a multistring to a String[] array + if ($data -eq $null) { + $data = [String[]]@() + } elseif ($data -isnot [Array]) { + $new_data = New-Object -TypeName String[] -ArgumentList 1 + $new_data[0] = $data.ToString([CultureInfo]::InvariantCulture) + $data = $new_data + } else { + $new_data = New-Object -TypeName String[] -ArgumentList $data.Count + foreach ($entry in $data) { + $new_data[$data.IndexOf($entry)] = $entry.ToString([CultureInfo]::InvariantCulture) + } + $data = $new_data + } +} - # Handle binary data - $old_data = (Get-ItemProperty -Path $path | Select-Object -ExpandProperty $name) - if ($name -eq "(default)") { - # Special case handling for the path's default property. - # Because .GetValueKind() doesn't work for the (default) path property - $old_type = "String".ToLower() - } else { - $old_type = (Get-Item $path).GetValueKind($name).ToString().ToLower() - } +# convert the type string to the .NET class +$type = [System.Enum]::Parse([Microsoft.Win32.RegistryValueKind], $type, $true) - if ($type -ne $old_type) { - # Changes Data and DataType - if (-not $check_mode) { - try { - if ($name.ToLower() -eq "(default)") { - $null = $(Get-Item -Path $path -ErrorAction 'Stop').OpenSubKey('','ReadWriteSubTree').SetValue($null,$data) - } else { - Remove-ItemProperty -Path $path -Name $name - New-ItemProperty -Path $path -Name $name -Value $data -PropertyType $type -Force | Out-Null - } - } catch { - Fail-Json $result $_.Exception.Message - } - } - $result.changed = $true - $result.data_changed = $true - $result.data_type_changed = $true +if ($state -eq "present") { + if (-not (Test-Path -path $path)) { + # the key doesn't exist, create it so the next steps work + try { + New-Item -Path $path -Type directory -Force -WhatIf:$check_mode + } catch { + Fail-Json $result "failed to create registry key at $($path): $($_.Exception.Message)" + } + $result.changed = $true - if ($diff_support) { - $result.diff.prepared += @" - [$path] --"$name" = "$old_type`:$data" -+"$name" = "$type`:$data" + if ($diff_mode) { + $result.diff.prepared += @" ++[$path] "@ - } + } + } - # FIXME: Compare-Data fails to work for null-length byte arrays - } elseif (-not (Compare-Data -ReferenceData $old_data -DifferenceData $data)) { - # Changes Only Data - if (-not $check_mode) { - try { - if ($type -eq "none") { - Remove-ItemProperty -Path $path -Name $name - New-ItemProperty -Path $path -Name $name -Value $data -PropertyType $type -Force | Out-Null - } else { - Set-ItemProperty -Path $path -Name $name -Value $data - } - } catch { - Fail-Json $result $_.Exception.Message - } - } - $result.changed = $true + if (Test-RegistryProperty -path $path -name $name) { + # property exists, need to compare the values and type + $existing_key = Get-Item -Path $path + $existing_type = $existing_key.GetValueKind($name) + $existing_data = $existing_key.GetValue($name, $false, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) + $change_value = $false + + if ($type -ne $existing_type) { + $change_value = $true + $result.data_type_changed = $true + $data_mismatch = Compare-RegistryProperties -existing $existing_data -new $data + if ($data_mismatch) { $result.data_changed = $true - - if ($diff_support) { - $result.diff.prepared += @" - [$path] --"$name" = "$type`:$old_data" -+"$name" = "$type`:$data" -"@ - } - - } else { - # Nothing to do, everything is already as requested } - } else { - # Add missing entry + $data_mismatch = Compare-RegistryProperties -existing $existing_data -new $data + if ($data_mismatch) { + $change_value = $true + $result.data_changed = $true + } + } + + if ($change_value) { if (-not $check_mode) { try { - New-ItemProperty -Path $path -Name $name -Value $data -PropertyType $type | Out-Null - } Catch { - Fail-Json $result $_.Exception.Message + (Get-Item -Path $path).OpenSubKey($null, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree).SetValue($name, $data, $type) + } catch { + Fail-Json $result "failed to change registry property '$name' at $($path): $($_.Exception.Message)" } } $result.changed = $true - if ($diff_support) { + if ($diff_mode) { $result.diff.prepared += @" - [$path] -+"$name" = "$type`:$data" +[$path] +-"$name" = "$existing_type`:$existing_data" ++"$name" = "$type`:$data" "@ } - } - - } elseif (-not (Test-Path $path)) { - + } else { + # property doesn't exist just create a new one if (-not $check_mode) { try { - $new_path = New-Item $path -Type directory -Force - if ($name -ne $null) { - $new_path | New-ItemProperty -Name $name -Value $data -PropertyType $type -Force | Out-Null - } + (Get-Item -Path $path).OpenSubKey($null, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree).SetValue($name, $data, $type) } catch { - Fail-Json $result $_.Exception.Message + Fail-Json $result "failed to change registry property '$name' at $($path): $($_.Exception.Message)" } } $result.changed = $true - - if ($diff_support) { + if ($diff_mode) { $result.diff.prepared += @" -+[$path"] -"@ - if ($name -ne $null) { - $result.diff.prepared += @" +[$path] +"$name" = "$type`:$data" "@ - } } - } - -} elseif ($state -eq "absent") { - - if (Test-Path $path) { - if ($name -eq $null) { - - if (-not $check_mode) { - try { - Remove-Item -Path $path -Recurse - } catch { - Fail-Json $result $_.Exception.Message - } +} else { + if (Test-Path -path $path) { + if ($delete_key -and $name -eq $null) { + # the clear_key flag is set and name is null so delete the entire key + try { + Remove-Item -Path $path -Force -Recurse -WhatIf:$check_mode + } catch { + Fail-Json $result "failed to delete registry key at $($path): $($_.Exception.Message)" } $result.changed = $true - if ($diff_support) { + if ($diff_mode) { $result.diff.prepared += @" -[$path] --"$name" = "$type`:$data" "@ } + } else { + # the clear_key flag is set or name is not null, check whether we need to delete a property + if (Test-RegistryProperty -path $path -name $name) { + $existing_key = Get-Item -Path $path + $existing_type = $existing_key.GetValueKind($name) + $existing_data = $existing_key.GetValue($name, $false, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) - } elseif (Test-ValueData -Path $path -Name $name) { - - if (-not $check_mode) { - try { - Remove-ItemProperty -Path $path -Name $name - } catch { - Fail-Json $result $_.Exception.Message + # cannot use Remove-ItemProperty as it fails when deleting the (Default) key ($name = $null) + if (-not $check_mode) { + try { + (Get-Item -Path $path).OpenSubKey($null, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree).DeleteValue($name) + } catch { + Fail-Json $result "failed to delete registry property '$name' at $($path): $($_.Exception.Message)" + } } - } - $result.changed = $true + $result.changed = $true - if ($diff_support) { - $result.diff.prepared += @" - [$path] --"$name" = "$type`:$data" + if ($diff_mode) { + $result.diff.prepared += @" +[$path] +-"$name" = "$existing_type`:$existing_data" "@ + } } - } - } else { - # Nothing to do, everything is already as requested } } diff --git a/lib/ansible/modules/windows/win_regedit.py b/lib/ansible/modules/windows/win_regedit.py index d1bedd469b7..72181895d62 100644 --- a/lib/ansible/modules/windows/win_regedit.py +++ b/lib/ansible/modules/windows/win_regedit.py @@ -29,55 +29,69 @@ ANSIBLE_METADATA = {'metadata_version': '1.0', DOCUMENTATION = r''' --- module: win_regedit -version_added: "2.0" +version_added: '2.0' short_description: Add, change, or remove registry keys and values description: - - Add, modify or remove registry keys and values. - - More information about the windows registry from Wikipedia (https://en.wikipedia.org/wiki/Windows_Registry). +- Add, modify or remove registry keys and values. +- More information about the windows registry from Wikipedia + U(https://en.wikipedia.org/wiki/Windows_Registry). options: path: description: - - Name of registry path. - - 'Should be in one of the following registry hives: HKCC, HKCR, HKCU, HKLM, HKU.' + - Name of the registry path. + - 'Should be in one of the following registry hives: HKCC, HKCR, HKCU, + HKLM, HKU.' required: true aliases: [ key ] name: description: - - Name of registry entry in C(path). - - This is an entry in the above C(key) parameter. - - If not provided, or empty we use the default name '(default)'. + - Name of the registry entry in the above C(path) parameters. + - If not provided, or empty then the '(Default)' property for the key will + be used. aliases: [ entry ] data: description: - - Value of the registry entry C(name) in C(path). - - Binary data should be expressed a yaml byte array or as comma separated hex values. An easy way to generate this is to run C(regedit.exe) and - use the I(Export) option to save the registry values to a file. In the exported file binary values will look like C(hex:be,ef,be,ef). - The C(hex:) prefix is optional. + - Value of the registry entry C(name) in C(path). + - If not specified then the value for the property will be null for the + corresponding C(type). + - Binary and None data should be expressed in a yaml byte array or as comma + separated hex values. + - An easy way to generate this is to run C(regedit.exe) and use the + I(export) option to save the registry values to a file. + - In the exported file, binary value will look like C(hex:be,ef,be,ef), the + C(hex:) prefix is optional. + - DWORD and QWORD values should either be represented as a decimal number + or a hex value. + - Multistring values should be passed in as a list. + - See the examples for more details on how to format this data. type: description: - - Registry value data type. - choices: - - binary - - dword - - expandstring - - multistring - - string - - qword + - The registry value data type. + choices: [ binary, dword, expandstring, multistring, string, qword ] default: string aliases: [ datatype ] state: description: - - State of registry entry. - choices: - - present - - absent + - The state of the registry entry. + choices: [ present, absent ] default: present + delete_key: + description: + - When C(state) is 'absent' then this will delete the entire key. + - If this is False then it will only clear out the '(Default)' property for + that key. + type: bool + default: 'yes' + version_added: '2.4' notes: - Check-mode C(-C/--check) and diff output C(-D/--diff) are supported, so that you can test every change against the active configuration before applying changes. - Beware that some registry hives (C(HKEY_USERS) in particular) do not allow to create new registry paths. -- Since ansible 2.4, when checking if a string registry value has changed, a case-sensitive test is used. Previously the test was case-insensitive. -author: "Adam Keech (@smadam813), Josh Ludwig (@joshludwig)" +- Since ansible 2.4, when checking if a string registry value has changed, a case-sensitive test is used. Previously the test was case-insensitive. +author: +- Adam Keech (@smadam813) +- Josh Ludwig (@joshludwig) +- Jordan Borean (@jborean93) ''' EXAMPLES = r''' @@ -91,27 +105,48 @@ EXAMPLES = r''' name: hello data: world -- name: Add or update registry path MyCompany, with entry 'hello', and containing 1337 +- name: Add or update registry path MyCompany, with dword entry 'hello', and containing 1337 as the decimal value win_regedit: path: HKCU:\Software\MyCompany name: hello data: 1337 type: dword -- name: Add or update registry path MyCompany, with entry 'hello', and containing binary data in hex-string format +- name: Add or update registry path MyCompany, with dword entry 'hello', and containing 0xff2500ae as the hex value + win_regedit: + path: HKCU:\Software\MyCompany + name: hello + data: 0xff2500ae + type: dword + +- name: Add or update registry path MyCompany, with binary entry 'hello', and containing binary data in hex-string format win_regedit: path: HKCU:\Software\MyCompany name: hello data: hex:be,ef,be,ef,be,ef,be,ef,be,ef type: binary -- name: Add or update registry path MyCompany, with entry 'hello', and containing binary data in yaml format +- name: Add or update registry path MyCompany, with binary entry 'hello', and containing binary data in yaml format win_regedit: path: HKCU:\Software\MyCompany name: hello data: [0xbe,0xef,0xbe,0xef,0xbe,0xef,0xbe,0xef,0xbe,0xef] type: binary +- name: Add or update registry path MyCompany, with expand string entry 'hello' + win_regedit: + path: HKCU:\Software\MyCompany + name: hello + data: '%appdata%\local' + type: expandstring + +- name: Add or update registry path MyCompany, with multi string entry 'hello' + win_regedit: + path: HKCU:\Software\MyCompany + name: hello + data: ['hello', 'world'] + type: multistring + - name: Disable keyboard layout hotkey for all users (changes existing) win_regedit: path: HKU:\.DEFAULT\Keyboard Layout\Toggle @@ -130,6 +165,13 @@ EXAMPLES = r''' win_regedit: path: HKCU:\Software\MyCompany state: absent + delete_key: yes + +- name: Clear the existing (Default) entry at path MyCompany + win_regedit: + path: HKCU:\Software\MyCompany + state: absent + delete_key: no - name: Remove entry 'hello' from registry path MyCompany win_regedit: diff --git a/test/integration/targets/win_regedit/defaults/main.yml b/test/integration/targets/win_regedit/defaults/main.yml new file mode 100644 index 00000000000..87aa3e597ce --- /dev/null +++ b/test/integration/targets/win_regedit/defaults/main.yml @@ -0,0 +1,2 @@ +test_win_regedit_local_key: HKLM:\Software\Cow Corp +test_win_regedit_classes_key: HKCR:\.test-ansible diff --git a/test/integration/targets/win_regedit/meta/main.yml b/test/integration/targets/win_regedit/meta/main.yml deleted file mode 100644 index d328716dfa4..00000000000 --- a/test/integration/targets/win_regedit/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - prepare_win_tests diff --git a/test/integration/targets/win_regedit/tasks/create_tests.yml b/test/integration/targets/win_regedit/tasks/create_tests.yml new file mode 100644 index 00000000000..34287a1a823 --- /dev/null +++ b/test/integration/targets/win_regedit/tasks/create_tests.yml @@ -0,0 +1,236 @@ +# repeatable tests for each key type +# takes in the following variables +# test_win_regedit_key_type: the type of key +# test_win_regedit_key_expected_type: the expected key type +# test_win_regedit_key_data1: the data to create first +# test_win_regedit_key_data2: the data to change tp +# test_win_regedit_key_expected_value_null: the expected value for a null key +# test_win_regedit_key_expected_value1: the expected value for the data1 +# test_win_regedit_key_expected_value2: the expected value for the data2 +--- +- name: create a null {{test_win_regedit_key_type}} check + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: empty_{{test_win_regedit_key_type}} + type: '{{test_win_regedit_key_type}}' + state: present + register: null_check + check_mode: yes + +- name: get actual on null {{test_win_regedit_key_type}} check + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: empty_{{test_win_regedit_key_type}} + register: null_actual_check + +- name: assert create a null {{test_win_regedit_key_type}} check + assert: + that: + - null_check|changed + - null_check.data_changed == False + - null_check.data_type_changed == False + - null_actual_check.exists == False + +- name: create a null {{test_win_regedit_key_type}} + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: empty_{{test_win_regedit_key_type}} + type: '{{test_win_regedit_key_type}}' + state: present + register: null_create + +- name: get actual on null {{test_win_regedit_key_type}} + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: empty_{{test_win_regedit_key_type}} + register: null_create_actual + +- name: assert create a null {{test_win_regedit_key_type}} + assert: + that: + - null_create|changed + - null_create.data_changed == False + - null_create.data_type_changed == False + - null_create_actual.exists == True + - null_create_actual.raw_value == test_win_regedit_key_expected_value_null + - null_create_actual.type == test_win_regedit_key_expected_type + when: test_win_regedit_key_type not in ['dword', 'qword'] + +# dword and qword are different, need to convert the expected value null to an int +- name: assert create a null {{test_win_regedit_key_type}} for dword and qword + assert: + that: + - null_create|changed + - null_create.data_changed == False + - null_create.data_type_changed == False + - null_create_actual.exists == True + - null_create_actual.raw_value == test_win_regedit_key_expected_value_null|int + - null_create_actual.type == test_win_regedit_key_expected_type + when: test_win_regedit_key_type in ['dword', 'qword'] + +- name: create a null {{test_win_regedit_key_type}} again + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: empty_{{test_win_regedit_key_type}} + type: '{{test_win_regedit_key_type}}' + state: present + register: null_create_again + +- name: assert create a null {{test_win_regedit_key_type}} again + assert: + that: + - not null_create_again|changed + +- name: create a {{test_win_regedit_key_type}} check + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + data: '{{test_win_regedit_key_data1}}' + type: '{{test_win_regedit_key_type}}' + state: present + register: data_create_check + check_mode: yes + +- name: get actual on {{test_win_regedit_key_type}} check + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + register: data_create_actual_check + +- name: assert create a {{test_win_regedit_key_type}} check + assert: + that: + - data_create_check|changed + - data_create_check.data_changed == False + - data_create_check.data_type_changed == False + - data_create_actual_check.exists == False + +- name: create a {{test_win_regedit_key_type}} + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + data: '{{test_win_regedit_key_data1}}' + type: '{{test_win_regedit_key_type}}' + state: present + register: data_create + +- name: get actual on {{test_win_regedit_key_type}} + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + register: data_create_actual + +- name: assert create a {{test_win_regedit_key_type}} + assert: + that: + - data_create|changed + - data_create.data_changed == False + - data_create.data_type_changed == False + - data_create_actual.exists == True + - data_create_actual.raw_value == test_win_regedit_key_expected_value1 + - data_create_actual.type == test_win_regedit_key_expected_type + when: test_win_regedit_key_type not in ['dword', 'qword'] + +- name: debug 1 + debug: + var: test_win_regedit_key_expected_value1 + +- name: debug 2 + debug: + var: test_win_regedit_key_expected_value1|int + +- name: assert create a {{test_win_regedit_key_type}} for dword or qword + assert: + that: + - data_create|changed + - data_create.data_changed == False + - data_create.data_type_changed == False + - data_create_actual.exists == True + - data_create_actual.raw_value == test_win_regedit_key_expected_value1|int + - data_create_actual.type == test_win_regedit_key_expected_type + when: test_win_regedit_key_type in ['dword', 'qword'] + +- name: create a {{test_win_regedit_key_type}} again + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + data: '{{test_win_regedit_key_data1}}' + type: '{{test_win_regedit_key_type}}' + state: present + register: data_create_again + +- name: assert create a {{test_win_regedit_key_type}} again + assert: + that: + - not data_create_again|changed + +- name: change existing {{test_win_regedit_key_type}} data check + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + data: '{{test_win_regedit_key_data2}}' + type: '{{test_win_regedit_key_type}}' + state: present + register: change_data_check + check_mode: yes + +- name: get actual of change existing {{test_win_regedit_key_type}} data check + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + register: change_data_actual_check + +- name: assert change existing {{test_win_regedit_key_type}} data check + assert: + that: + - change_data_check|changed + - change_data_check.data_changed == True + - change_data_check.data_type_changed == False + - change_data_actual_check == data_create_actual + +- name: change existing {{test_win_regedit_key_type}} data + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + data: '{{test_win_regedit_key_data2}}' + type: '{{test_win_regedit_key_type}}' + state: present + register: change_data + +- name: get actual of change existing {{test_win_regedit_key_type}} data + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + register: change_data_actual + +- name: assert change existing {{test_win_regedit_key_type}} data + assert: + that: + - change_data|changed + - change_data.data_changed == True + - change_data.data_type_changed == False + - change_data_actual.raw_value == test_win_regedit_key_expected_value2 + when: test_win_regedit_key_type not in ['dword', 'qword'] + +- name: assert change existing {{test_win_regedit_key_type}} data for dword or qword + assert: + that: + - change_data|changed + - change_data.data_changed == True + - change_data.data_type_changed == False + - change_data_actual.raw_value == test_win_regedit_key_expected_value2|int + when: test_win_regedit_key_type in ['dword', 'qword'] + +- name: change existing {{test_win_regedit_key_type}} data again + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_{{test_win_regedit_key_type}} + data: '{{test_win_regedit_key_data2}}' + type: '{{test_win_regedit_key_type}}' + state: present + register: change_data_again + +- name: assert change existing {{test_win_regedit_key_type}} data again + assert: + that: + - not change_data_again|changed diff --git a/test/integration/targets/win_regedit/tasks/main.yml b/test/integration/targets/win_regedit/tasks/main.yml index 11aa02e3e84..50b2cae4ca7 100644 --- a/test/integration/targets/win_regedit/tasks/main.yml +++ b/test/integration/targets/win_regedit/tasks/main.yml @@ -1,473 +1,93 @@ -# test code for the win_regedit module -# (c) 2014, Michael DeHaan - -# 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 . - -# clear the area of the registry we are using for tests - -# test mangled registry key gets caught following https://github.com/ansible/ansible-modules-extras/issues/2412 - -- name: test mangled registry key is caught (avoids bizare error message from powershell) - win_regedit: - key: HKCU\Software - value: invalid_key - data: invalid_key - datatype: string - register: check00_result - ignore_errors: True - -- assert: - that: - - "check00_result.failed == true" - - "check00_result.msg == 'path: HKCU\\Software is not a valid powershell path, see module documentation for examples.'" - -- name: remove setting - win_regedit: - key: 'HKCU:\SOFTWARE\Cow Corp' - state: absent - -- name: check basic set works - win_regedit: - key: HKCU:\Software\Cow Corp - value: hello - data: world - register: check01_result - -- assert: - that: - - "check01_result.changed == true" - -- name: check that setting the same again is not changed - win_regedit: - key: HKCU:\Software\Cow Corp - value: hello - data: world - register: check02_result - -- assert: - that: - - "check02_result.changed == false" - -# binary mode checks -# tests with 'hex:' prefix (as intended) - -- name: check binary with hex(colon) prefix - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:be,ef,be,ef,be,ef,be,ef,be,ef - datatype: binary - register: check03_result - -- assert: - that: - - "check03_result.changed == true" - -- name: check binary with hex(colon) prefix not modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:be,ef,be,ef,be,ef,be,ef,be,ef - datatype: binary - register: check04_result - -- assert: - that: - - "check04_result.changed == false" - -- name: check binary with hex(colon) prefix modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:de,ad,be,ef,de,ad,be,ef,de,ad,be,ef - datatype: binary - register: check05_result - -- assert: - that: - - "check05_result.changed == true" - -# reset -- name: reset test - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - state: absent - register: check06_result - -- assert: - that: - - "check06_result.changed == true" - -# check without hex(colon) prefix - -# tests without 'hex:' prefix (optional) -- name: check binary with hex(colon) prefix - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: be,ef,be,ef,be,ef,be,ef,be,ef - datatype: binary - register: check13_result - -- assert: - that: - - "check13_result.changed == true" - -- name: check binary without hex(colon) prefix not modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: be,ef,be,ef,be,ef,be,ef,be,ef - datatype: binary - register: check14_result - -- assert: - that: - - "check14_result.changed == false" - -- name: check binary without hex(colon) prefix modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: de,ad,be,ef,de,ad,be,ef,de,ad,be,ef - datatype: binary - register: check15_result - -- assert: - that: - - "check15_result.changed == true" - -# reset -- name: reset test - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - state: absent - register: check16_result - -- assert: - that: - - "check16_result.changed == true" - -# check mixed case hex values with hex: prefix - -- name: check mixed case binary with hex(colon) prefix - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:be,EF,be,EF,be,EF,be,EF,be,EF - datatype: binary - register: check23_result - -- assert: - that: - - "check23_result.changed == true" - -- name: check mixed case binary with hex(colon) prefix not modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:be,EF,be,EF,be,EF,be,EF,be,EF - datatype: binary - register: check24_result - -- assert: - that: - - "check24_result.changed == false" - -- name: check mixed case binary with hex(colon) prefix modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:DE,ad,be,EF,DE,ad,be,EF,DE,ad,be,EF - datatype: binary - register: check25_result - -- assert: - that: - - "check25_result.changed == true" - -# reset -- name: reset test - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - state: absent - register: check26_result - -- assert: - that: - - "check26_result.changed == true" - -# check mixed case without hex: prefix - -# tests without 'hex:' prefix (optional) -- name: check mixed case binary without hex(colon) prefix - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: be,EF,be,EF,be,EF,be,EF,be,EF - datatype: binary - register: check33_result - -- assert: - that: - - "check33_result.changed == true" - -- name: check mixed case binary without hex(colon) prefix not modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: be,EF,be,EF,be,EF,be,EF,be,EF - datatype: binary - register: check34_result - -- assert: - that: - - "check34_result.changed == false" - -- name: check mixed case binary without hex(colon) prefix modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: DE,ad,be,EF,DE,ad,be,EF,DE,ad,be,EF - datatype: binary - register: check35_result - -- assert: - that: - - "check35_result.changed == true" - -# reset -- name: reset test - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - state: absent - register: check36_result - -- assert: - that: - - "check36_result.changed == true" - -# check colon separated hex values with hex: prefix - -- name: check colon separated hex values with hex(colon) prefix - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:be:ef:be:ef:be:ef:be:ef:be:ef - datatype: binary - register: check43_result - -- assert: - that: - - "check43_result.changed == true" - -- name: check colon separated binary with hex(colon) prefix not modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:be:ef:be:ef:be:ef:be:ef:be:ef - datatype: binary - register: check44_result - -- assert: - that: - - "check44_result.changed == false" - -- name: check colon separated binary with hex(colon) prefix modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: hex:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef - datatype: binary - register: check45_result - -- assert: - that: - - "check45_result.changed == true" - -# reset -- name: reset test - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - state: absent - register: check46_result - -- assert: - that: - - "check46_result.changed == true" - -# check colon separated hex values without hex(colon) prefix - -# tests without 'hex:' prefix (optional) -- name: check colon separated binary with hex(colon) prefix - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: be:ef:be:ef:be:ef:be:ef:be:ef - datatype: binary - register: check53_result - -- assert: - that: - - "check53_result.changed == true" - -- name: check colon separated binary without hex(colon) prefix not modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: be:ef:be:ef:be:ef:be:ef:be:ef - datatype: binary - register: check54_result - -- assert: - that: - - "check54_result.changed == false" - -- name: check colon separated binary without hex(colon) prefix modified - win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary - data: de:ad:be:ef:de:ad:be:ef:de:ad:be:ef - datatype: binary - register: check55_result - -- assert: - that: - - "check55_result.changed == true" - -# reset -- name: reset test +--- +- name: make sure testing keys are removed before test win_regedit: - key: HKCU:\Software\Cow Corp - value: hellobinary + path: '{{item}}' + delete_key: yes state: absent - register: check56_result - -- assert: - that: - - "check56_result.changed == true" - -# test empty data value (some things depend on this, having no data is not equivalent) - -- name: set an empty data value - win_regedit: - key: HKCU:\Software\Cow Corp - value: helloempty - data: "" - register: check61_result - -- assert: - that: - - "check61_result.changed == true" - -- name: set an empty data value again (should not change) - win_regedit: - key: HKCU:\Software\Cow Corp - value: helloempty - data: "" - register: check62_result - -- assert: - that: - - "check62_result.changed == false" - -# check can use yaml array of bytes as input -- name: regedit binary data using yaml syntax - win_regedit: - key: 'HKCU:\SOFTWARE\Cow Corp' - value: hellobinaryfromyaml - data: [0x21, 0xb3, 0x33, 0xf9, 0x0d, 0xff, 0xd0, 0x01] - datatype: binary - register: check63_result - -- assert: - that: - - "check63_result.changed == true" - -- name: regedit binary data using yaml syntax again - win_regedit: - key: 'HKCU:\SOFTWARE\Cow Corp' - value: hellobinaryfromyaml - data: [0x21, 0xb3, 0x33, 0xf9, 0x0d, 0xff, 0xd0, 0x01] - datatype: binary - register: check64_result - -- assert: - that: - - "check64_result.changed == false" - -# test dword - -- name: check basic set dword works - win_regedit: - key: HKCU:\Software\Cow Corp - value: hello_dword - data: 00000000 - datatype: dword - register: check71_result - -- assert: - that: - - "check71_result.changed == true" - -- name: check that setting the same dword again is not changed - win_regedit: - key: HKCU:\Software\Cow Corp - value: hello_dword - data: 00000000 - datatype: dword - register: check72_result - -- assert: - that: - - "check72_result.changed == false" - -# https://github.com/ansible/ansible/issues/26049 -# module reports change on dword with hex value even with same value -- name: create hex value with prepending 0x - win_regedit: - key: HKCU:\Software\Cow Corp - value: full_hex_dword - data: 0xffffffff - datatype: dword - register: dword_create - -- name: change hex value and report no changes - win_regedit: - key: HKCU:\Software\Cow Corp - value: full_hex_dword - data: 0xffffffff - datatype: dword - register: dword_create_again - -- assert: - that: - - not dword_create_again|changed - -# tear down - -- name: remove registry key used for testing - win_regedit: - key: 'HKCU:\SOFTWARE\Cow Corp' - state: absent - - -# END OF win_regedit tests + with_items: + - '{{test_win_regedit_local_key}}' + - '{{test_win_regedit_classes_key}}' + +- block: + - name: run old tests for PR only + include_tasks: old_tests.yml + + - name: run tests for each property type + include_tasks: create_tests.yml + vars: + test_win_regedit_key_type: '{{item.type}}' + test_win_regedit_key_expected_type: '{{item.reg_type}}' + test_win_regedit_key_data1: '{{item.data1}}' + test_win_regedit_key_data2: '{{item.data2}}' + test_win_regedit_key_expected_value_null: '{{item.value_null}}' + test_win_regedit_key_expected_value1: '{{item.value1}}' + test_win_regedit_key_expected_value2: '{{item.value2}}' + items: + - type: dword + reg_type: REG_DWORD + data1: 1337 # decimal format + data2: 0xffffffff # hex format and larger number + value_null: 0 + value1: 1337 + value2: 4294967295 + + - type: qword + reg_type: REG_QWORD + data1: 18446744073709551615 # larger decimal format + data2: 0x1ffffffff # hex format and larger number + value_null: 0 + value1: 18446744073709551615 + value2: 8589934591 + + - type: string + reg_type: REG_SZ + data1: hello world + data2: new hello world + value_null: "" + value1: hello world + value2: new hello world + + - type: expandstring + reg_type: REG_EXPAND_SZ + data1: '%windir%\test' + data2: '%AppData%\local' + value_null: "" + value1: '%windir%\test' + value2: '%AppData%\local' + + - type: multistring + reg_type: REG_MULTI_SZ + data1: 'entry1' # test single entry as multi string + data2: ['entry1', 2] + value_null: [] + value1: ['entry1'] + value2: ['entry1', '2'] + + - type: binary + reg_type: REG_BINARY + data1: hex:00,01,ee,ff # testing hex string format with hex: in front + data2: [0xff, 0xee, 0x01, 0x00] # testing using just raw hex values + value_null: [] + value1: ["0x00", "0x01", "0xee", "0xff"] + value2: ["0xff", "0xee", "0x01", "0x00"] + + - type: none + reg_type: REG_NONE + data1: aa,bb,be,ef # testing hex string format with hex: in front + data2: [0x01, 0x02] + value_null: [] + value1: ["0xaa", "0xbb", "0xbe", "0xef"] + value2: ["0x01", "0x02"] + + - name: run remaining tests + include_tasks: tests.yml + + always: + - name: make sure testing keys are removed after test + win_regedit: + path: '{{item}}' + delete_key: yes + state: absent + with_items: + - '{{test_win_regedit_local_key}}' + - '{{test_win_regedit_classes_key}}' diff --git a/test/integration/targets/win_regedit/tasks/old_tests.yml b/test/integration/targets/win_regedit/tasks/old_tests.yml new file mode 100644 index 00000000000..11aa02e3e84 --- /dev/null +++ b/test/integration/targets/win_regedit/tasks/old_tests.yml @@ -0,0 +1,473 @@ +# test code for the win_regedit module +# (c) 2014, Michael DeHaan + +# 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 . + +# clear the area of the registry we are using for tests + +# test mangled registry key gets caught following https://github.com/ansible/ansible-modules-extras/issues/2412 + +- name: test mangled registry key is caught (avoids bizare error message from powershell) + win_regedit: + key: HKCU\Software + value: invalid_key + data: invalid_key + datatype: string + register: check00_result + ignore_errors: True + +- assert: + that: + - "check00_result.failed == true" + - "check00_result.msg == 'path: HKCU\\Software is not a valid powershell path, see module documentation for examples.'" + +- name: remove setting + win_regedit: + key: 'HKCU:\SOFTWARE\Cow Corp' + state: absent + +- name: check basic set works + win_regedit: + key: HKCU:\Software\Cow Corp + value: hello + data: world + register: check01_result + +- assert: + that: + - "check01_result.changed == true" + +- name: check that setting the same again is not changed + win_regedit: + key: HKCU:\Software\Cow Corp + value: hello + data: world + register: check02_result + +- assert: + that: + - "check02_result.changed == false" + +# binary mode checks +# tests with 'hex:' prefix (as intended) + +- name: check binary with hex(colon) prefix + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:be,ef,be,ef,be,ef,be,ef,be,ef + datatype: binary + register: check03_result + +- assert: + that: + - "check03_result.changed == true" + +- name: check binary with hex(colon) prefix not modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:be,ef,be,ef,be,ef,be,ef,be,ef + datatype: binary + register: check04_result + +- assert: + that: + - "check04_result.changed == false" + +- name: check binary with hex(colon) prefix modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:de,ad,be,ef,de,ad,be,ef,de,ad,be,ef + datatype: binary + register: check05_result + +- assert: + that: + - "check05_result.changed == true" + +# reset +- name: reset test + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + state: absent + register: check06_result + +- assert: + that: + - "check06_result.changed == true" + +# check without hex(colon) prefix + +# tests without 'hex:' prefix (optional) +- name: check binary with hex(colon) prefix + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: be,ef,be,ef,be,ef,be,ef,be,ef + datatype: binary + register: check13_result + +- assert: + that: + - "check13_result.changed == true" + +- name: check binary without hex(colon) prefix not modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: be,ef,be,ef,be,ef,be,ef,be,ef + datatype: binary + register: check14_result + +- assert: + that: + - "check14_result.changed == false" + +- name: check binary without hex(colon) prefix modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: de,ad,be,ef,de,ad,be,ef,de,ad,be,ef + datatype: binary + register: check15_result + +- assert: + that: + - "check15_result.changed == true" + +# reset +- name: reset test + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + state: absent + register: check16_result + +- assert: + that: + - "check16_result.changed == true" + +# check mixed case hex values with hex: prefix + +- name: check mixed case binary with hex(colon) prefix + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:be,EF,be,EF,be,EF,be,EF,be,EF + datatype: binary + register: check23_result + +- assert: + that: + - "check23_result.changed == true" + +- name: check mixed case binary with hex(colon) prefix not modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:be,EF,be,EF,be,EF,be,EF,be,EF + datatype: binary + register: check24_result + +- assert: + that: + - "check24_result.changed == false" + +- name: check mixed case binary with hex(colon) prefix modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:DE,ad,be,EF,DE,ad,be,EF,DE,ad,be,EF + datatype: binary + register: check25_result + +- assert: + that: + - "check25_result.changed == true" + +# reset +- name: reset test + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + state: absent + register: check26_result + +- assert: + that: + - "check26_result.changed == true" + +# check mixed case without hex: prefix + +# tests without 'hex:' prefix (optional) +- name: check mixed case binary without hex(colon) prefix + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: be,EF,be,EF,be,EF,be,EF,be,EF + datatype: binary + register: check33_result + +- assert: + that: + - "check33_result.changed == true" + +- name: check mixed case binary without hex(colon) prefix not modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: be,EF,be,EF,be,EF,be,EF,be,EF + datatype: binary + register: check34_result + +- assert: + that: + - "check34_result.changed == false" + +- name: check mixed case binary without hex(colon) prefix modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: DE,ad,be,EF,DE,ad,be,EF,DE,ad,be,EF + datatype: binary + register: check35_result + +- assert: + that: + - "check35_result.changed == true" + +# reset +- name: reset test + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + state: absent + register: check36_result + +- assert: + that: + - "check36_result.changed == true" + +# check colon separated hex values with hex: prefix + +- name: check colon separated hex values with hex(colon) prefix + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:be:ef:be:ef:be:ef:be:ef:be:ef + datatype: binary + register: check43_result + +- assert: + that: + - "check43_result.changed == true" + +- name: check colon separated binary with hex(colon) prefix not modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:be:ef:be:ef:be:ef:be:ef:be:ef + datatype: binary + register: check44_result + +- assert: + that: + - "check44_result.changed == false" + +- name: check colon separated binary with hex(colon) prefix modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: hex:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef + datatype: binary + register: check45_result + +- assert: + that: + - "check45_result.changed == true" + +# reset +- name: reset test + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + state: absent + register: check46_result + +- assert: + that: + - "check46_result.changed == true" + +# check colon separated hex values without hex(colon) prefix + +# tests without 'hex:' prefix (optional) +- name: check colon separated binary with hex(colon) prefix + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: be:ef:be:ef:be:ef:be:ef:be:ef + datatype: binary + register: check53_result + +- assert: + that: + - "check53_result.changed == true" + +- name: check colon separated binary without hex(colon) prefix not modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: be:ef:be:ef:be:ef:be:ef:be:ef + datatype: binary + register: check54_result + +- assert: + that: + - "check54_result.changed == false" + +- name: check colon separated binary without hex(colon) prefix modified + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + data: de:ad:be:ef:de:ad:be:ef:de:ad:be:ef + datatype: binary + register: check55_result + +- assert: + that: + - "check55_result.changed == true" + +# reset +- name: reset test + win_regedit: + key: HKCU:\Software\Cow Corp + value: hellobinary + state: absent + register: check56_result + +- assert: + that: + - "check56_result.changed == true" + +# test empty data value (some things depend on this, having no data is not equivalent) + +- name: set an empty data value + win_regedit: + key: HKCU:\Software\Cow Corp + value: helloempty + data: "" + register: check61_result + +- assert: + that: + - "check61_result.changed == true" + +- name: set an empty data value again (should not change) + win_regedit: + key: HKCU:\Software\Cow Corp + value: helloempty + data: "" + register: check62_result + +- assert: + that: + - "check62_result.changed == false" + +# check can use yaml array of bytes as input +- name: regedit binary data using yaml syntax + win_regedit: + key: 'HKCU:\SOFTWARE\Cow Corp' + value: hellobinaryfromyaml + data: [0x21, 0xb3, 0x33, 0xf9, 0x0d, 0xff, 0xd0, 0x01] + datatype: binary + register: check63_result + +- assert: + that: + - "check63_result.changed == true" + +- name: regedit binary data using yaml syntax again + win_regedit: + key: 'HKCU:\SOFTWARE\Cow Corp' + value: hellobinaryfromyaml + data: [0x21, 0xb3, 0x33, 0xf9, 0x0d, 0xff, 0xd0, 0x01] + datatype: binary + register: check64_result + +- assert: + that: + - "check64_result.changed == false" + +# test dword + +- name: check basic set dword works + win_regedit: + key: HKCU:\Software\Cow Corp + value: hello_dword + data: 00000000 + datatype: dword + register: check71_result + +- assert: + that: + - "check71_result.changed == true" + +- name: check that setting the same dword again is not changed + win_regedit: + key: HKCU:\Software\Cow Corp + value: hello_dword + data: 00000000 + datatype: dword + register: check72_result + +- assert: + that: + - "check72_result.changed == false" + +# https://github.com/ansible/ansible/issues/26049 +# module reports change on dword with hex value even with same value +- name: create hex value with prepending 0x + win_regedit: + key: HKCU:\Software\Cow Corp + value: full_hex_dword + data: 0xffffffff + datatype: dword + register: dword_create + +- name: change hex value and report no changes + win_regedit: + key: HKCU:\Software\Cow Corp + value: full_hex_dword + data: 0xffffffff + datatype: dword + register: dword_create_again + +- assert: + that: + - not dword_create_again|changed + +# tear down + +- name: remove registry key used for testing + win_regedit: + key: 'HKCU:\SOFTWARE\Cow Corp' + state: absent + + +# END OF win_regedit tests diff --git a/test/integration/targets/win_regedit/tasks/tests.yml b/test/integration/targets/win_regedit/tasks/tests.yml new file mode 100644 index 00000000000..17e66d4d7c3 --- /dev/null +++ b/test/integration/targets/win_regedit/tasks/tests.yml @@ -0,0 +1,423 @@ +--- +- name: fail run win_regedit with larger dword + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: test + data: 0xffffffff1 + type: dword + state: present + register: large_dword + failed_when: large_dword.msg != 'data cannot be larger than 0xffffffff when type is dword' + +- name: fail run win_regedit with larger qword + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: test + data: 0xffffffffffffffff1 + type: qword + state: present + register: large_qword + failed_when: large_qword.msg != 'data cannot be larger than 0xffffffffffffffff when type is qword' + +- name: run win_regedit with invalid path + win_regedit: + path: ABCD:\efg + register: invalid_path + failed_when: "invalid_path.msg != 'path: ABCD:\\efg is not a valid powershell path, see module documentation for examples.'" + +- name: change string to binary check + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_string + data: hex:00,01 + type: binary + state: present + register: change_string_binary_check + check_mode: yes + +- name: get actual change string to binary check + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_string + register: change_string_binary_actual_check + +- name: assert change string to binary check + assert: + that: + - change_string_binary_check|changed + - change_string_binary_check.data_changed == True + - change_string_binary_check.data_type_changed == True + - change_string_binary_actual_check.type == 'REG_SZ' + - change_string_binary_actual_check.raw_value == "new hello world" + +- name: change string to binary + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_string + data: hex:00,01 + type: binary + state: present + register: change_string_binary + +- name: get actual change string to binary + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_string + register: change_string_binary_actual + +- name: assert change string to binary check + assert: + that: + - change_string_binary|changed + - change_string_binary.data_changed == True + - change_string_binary.data_type_changed == True + - change_string_binary_actual.type == 'REG_BINARY' + - change_string_binary_actual.raw_value == ["0x00", "0x01"] + +- name: modify the (Default) key property check + win_regedit: + path: '{{test_win_regedit_local_key}}' + data: default value + state: present + register: modify_default_check + check_mode: yes + +# win_reg_stat struggles with the (Default) property just use powershell +- name: get actual modify the (Default) key property check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: modify_default_actual_check + +- name: assert modify the (Default) key property check + assert: + that: + - modify_default_check|changed + - modify_default_actual_check.stdout == "" + +- name: modify the (Default) key property + win_regedit: + path: '{{test_win_regedit_local_key}}' + data: default value + state: present + register: modify_default + +- name: get actual modify the (Default) key property + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: modify_default_actual + +- name: assert modify the (Default) key property + assert: + that: + - modify_default|changed + - modify_default_actual.stdout == "default value\r\n" + +- name: create an actual property called (Default) + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: (Default) + data: custom default value + type: expandstring + state: present + register: create_specific_default_check + check_mode: yes + +- name: get actual value for (Default) property to ensure it didn't change check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: create_specific_default_actual_default_check + +- name: get actual for create specific property called (Default) check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue('(Default)', $null)" + register: create_specific_default_actual_check + +- name: assert create specific property called (Default) check + assert: + that: + - create_specific_default_check|changed + - create_specific_default_actual_default_check.stdout == "default value\r\n" + - create_specific_default_actual_check.stdout == "" + +- name: create an actual property called (Default) + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: (Default) + data: custom default value + type: expandstring + state: present + register: create_specific_default + +- name: get actual value for (Default) property to ensure it didn't change + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: create_specific_default_actual_default + +- name: get actual for specific property called (Default) + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue('(Default)', $null)" + register: create_specific_default_actual + +- name: assert create specific property called (Default) + assert: + that: + - create_specific_default|changed + - create_specific_default_actual_default.stdout == "default value\r\n" + - create_specific_default_actual.stdout == "custom default value\r\n" + +- name: delete property check + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_binary + state: absent + register: delete_property_check + check_mode: yes + +- name: get actual of delete property check + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_binary + register: delete_property_actual_check + +- name: assert delete property check + assert: + that: + - delete_property_check|changed + - delete_property_actual_check.exists == True + +- name: delete property + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_binary + state: absent + register: delete_property + +- name: get actual of delete property + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + name: data_binary + register: delete_property_actual + +- name: assert delete property + assert: + that: + - delete_property|changed + - delete_property_actual.exists == False + +- name: delete property again + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: data_binary + state: absent + register: delete_property_again + +- name: assert delete property again + assert: + that: + - not delete_property_again|changed + +- name: delete the key's (Default) property check + win_regedit: + path: '{{test_win_regedit_local_key}}' + state: absent + delete_key: no + register: delete_default_check + check_mode: yes + +- name: get actual of key's (Default) property check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: delete_default_actual_check + +- name: get actual of custom (Default) property check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue('(Default)', $null)" + register: delete_default_custom_actual_check + +- name: assert delete the key's (Default) property check + assert: + that: + - delete_default_check|changed + - delete_default_actual_check.stdout == "default value\r\n" + - delete_default_custom_actual_check.stdout == "custom default value\r\n" + +- name: delete the key's (Default) property + win_regedit: + path: '{{test_win_regedit_local_key}}' + state: absent + delete_key: no + register: delete_default + +- name: get actual of key's (Default) property + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: delete_default_actual + +- name: get actual of custom (Default) property + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue('(Default)', $null)" + register: delete_default_custom_actual + +- name: assert delete the key's (Default) property + assert: + that: + - delete_default|changed + - delete_default_actual.stdout == "" + - delete_default_custom_actual.stdout == "custom default value\r\n" + +- name: recreate the key's (Default) property for next test + win_regedit: + path: '{{test_win_regedit_local_key}}' + data: default value + +- name: delete the custom (Default) property check + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: (Default) + state: absent + delete_key: no + register: delete_custom_default_check + check_mode: yes + +- name: get actual of key's (Default) property check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: delete_custom_default_actual_check + +- name: get actual of custom (Default) property check + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue('(Default)', $null)" + register: delete_custom_default_custom_actual_check + +- name: assert delete the custom (Default) property check + assert: + that: + - delete_custom_default_check|changed + - delete_custom_default_actual_check.stdout == "default value\r\n" + - delete_custom_default_custom_actual_check.stdout == "custom default value\r\n" + +- name: delete the custom (Default) property + win_regedit: + path: '{{test_win_regedit_local_key}}' + name: (Default) + state: absent + delete_key: no + register: delete_custom_default + +- name: get actual of key's (Default) property + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue($null, $null)" + register: delete_custom_default_actual + +- name: get actual of custom (Default) property + win_command: powershell.exe "(Get-Item -Path '{{test_win_regedit_local_key}}').GetValue('(Default)', $null)" + register: delete_custom_default_custom_actual + +- name: assert delete the custom (Default) property + assert: + that: + - delete_custom_default|changed + - delete_custom_default_actual.stdout == "default value\r\n" + - delete_custom_default_custom_actual.stdout == "" + +- name: add some nested keys for later deletion + win_regedit: + path: '{{test_win_regedit_local_key}}\{{item}}' + state: present + items: + - nest1 + - nest2 + - nest1\nested + +- name: delete key and it's sub keys check + win_regedit: + path: '{{test_win_regedit_local_key}}' + state: absent + delete_key: yes + register: delete_key_check + check_mode: yes + +- name: get actual of delete key and it's sub keys check + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + register: delete_key_actual_check + +- name: assert delete key and it's sub keys check + assert: + that: + - delete_key_check|changed + - delete_key_actual_check.exists + - delete_key_actual_check.sub_keys == ["nest1", "nest2"] + +- name: delete key and it's sub keys + win_regedit: + path: '{{test_win_regedit_local_key}}' + state: absent + delete_key: yes + register: delete_key + +- name: get actual of delete key and it's sub keys + win_reg_stat: + path: '{{test_win_regedit_local_key}}' + register: delete_key_actual + +- name: assert delete key and it's sub keys + assert: + that: + - delete_key|changed + - delete_key_actual.exists == False + +- name: delete key and it's sub keys again + win_regedit: + path: '{{test_win_regedit_local_key}}' + state: absent + delete_key: yes + register: delete_key_again + +- name: assert delete key and it's sub keys again + assert: + that: + - not delete_key_again|changed + +- name: create key in HKEY_CLASSES_ROOT check + win_regedit: + path: '{{test_win_regedit_classes_key}}' + name: test + data: test + type: string + state: present + register: create_hkcr_key_check + check_mode: yes + +- name: get actual of create key in HKEY_CLASSES_ROOT check + win_reg_stat: + path: '{{test_win_regedit_classes_key}}' + register: create_hkcr_key_actual_check + +- name: assert create key in HKEY_CLASSES_ROOT check + assert: + that: + - create_hkcr_key_check|changed + - create_hkcr_key_actual_check.exists == False + +- name: create key in HKEY_CLASSES_ROOT + win_regedit: + path: '{{test_win_regedit_classes_key}}' + name: test + data: test + type: string + state: present + register: create_hkcr_key + +- name: get actual of create key in HKEY_CLASSES_ROOT + win_reg_stat: + path: '{{test_win_regedit_classes_key}}' + register: create_hkcr_key_actual + +- name: assert create key in HKEY_CLASSES_ROOT + assert: + that: + - create_hkcr_key|changed + - create_hkcr_key_actual.exists == True + - create_hkcr_key_actual.properties.test is defined + +- name: create key in HKEY_CLASSES_ROOT again + win_regedit: + path: '{{test_win_regedit_classes_key}}' + name: test + data: test + type: string + state: present + register: create_hkcr_key_again + +- name: assert create key in HKEY_CLASSES_ROOT again + assert: + that: + - not create_hkcr_key_again|changed