Add new windows module: win_hosts (#46450)
* Add win_hosts module added win_hosts module for easier manipulation of hosts entries in "%windir%\system32\drivers\etc\hosts" for windows systems * Update win_hosts.py * Add alias support to win_hosts module (#1) * win_hosts supports aliases added support for adding / removing aliases from a host entry, rather than adding a new entry added ability for win_hosts to detect aliases: `192.168.1.1 alias1 alias2 alias3` ``` win_hosts: host_name: alias2 ip_address: 192.168.1.1 ``` will result in `192.168.1.1 alias1 alias3` also includes `replace` and `add` as options for `ip_action` (`replace` is default) for example: ``` 192.168.1.1 my_reused_alias 192.168.1.2 my_reused_alias ``` with ``` win_hosts: host_name: my_reused_alias ip_address: 192.168.1.3 ip_action: add ``` the result will be ``` 192.168.1.1 my_reused_alias 192.168.1.2 my_reused_alias ``` but with `ip_action=replace` the result would be ``` 192.168.1.3 my_reused_alias ``` * fixed metadata version and version added * fix line endings * upload fixed line endings try to upload the file with the fixed line endings * aliases and canonical names are separate entities. added IPv4 and IPv6 validation * only makes changes if "check_mode" is false * improved behavior for duplicate aliases/entries. * adding tests * missing aliases file * fix trailing whitespace and uses explicit paths * Tweak tests to copy and restore original hosts file
This commit is contained in:
parent
09979e899f
commit
26d9341891
7 changed files with 638 additions and 0 deletions
298
lib/ansible/modules/windows/win_hosts.ps1
Normal file
298
lib/ansible/modules/windows/win_hosts.ps1
Normal file
|
@ -0,0 +1,298 @@
|
|||
#!powershell
|
||||
|
||||
# Copyright: (c) 2018, Micah Hunsberger (@mhunsber)
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
#Requires -Module Ansible.ModuleUtils.Legacy
|
||||
|
||||
Set-StrictMode -Version 2
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||
|
||||
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present"
|
||||
$aliases = Get-AnsibleParam -obj $params -name "aliases" -type "list" -failifempty $false
|
||||
$canonical_name = Get-AnsibleParam -obj $params -name "canonical_name" -type "str" -failifempty ($state -eq 'present')
|
||||
$ip_address = Get-AnsibleParam -obj $params -name "ip_address" -type "str" -default "" -failifempty ($state -eq 'present')
|
||||
$action = Get-AnsibleParam -obj $params -name "action" -type "str" -default "set" -validateset "add","remove","set"
|
||||
|
||||
$tmp = [ipaddress]::None
|
||||
if($ip_address -and -not [ipaddress]::TryParse($ip_address, [ref]$tmp)){
|
||||
Fail-Json -obj @{} -message "win_hosts: Argument ip_address needs to be a valid ip address, but was $ip_address"
|
||||
}
|
||||
$ip_address_type = $tmp.AddressFamily
|
||||
|
||||
$hosts_file = Get-Item -LiteralPath "$env:SystemRoot\System32\drivers\etc\hosts"
|
||||
|
||||
$result = @{
|
||||
changed = $false
|
||||
diff = @{
|
||||
prepared = ""
|
||||
}
|
||||
}
|
||||
|
||||
Function Get-CommentIndex($line) {
|
||||
$c_index = $line.IndexOf('#')
|
||||
if($c_index -lt 0) {
|
||||
$c_index = $line.Length
|
||||
}
|
||||
return $c_index
|
||||
}
|
||||
|
||||
Function Get-HostEntryParts($line) {
|
||||
$success = $true
|
||||
$c_index = Get-CommentIndex -line $line
|
||||
$pure_line = $line.Substring(0,$c_index).Trim()
|
||||
$bits = $pure_line -split "\s+"
|
||||
if($bits.Length -lt 2){
|
||||
return @{
|
||||
success = $false
|
||||
ip_address = ""
|
||||
ip_type = ""
|
||||
canonical_name = ""
|
||||
aliases = @()
|
||||
}
|
||||
}
|
||||
$ip_obj = [ipaddress]::None
|
||||
if(-not [ipaddress]::TryParse($bits[0], [ref]$ip_obj) ){
|
||||
$success = $false
|
||||
}
|
||||
$cname = $bits[1]
|
||||
$als = New-Object string[] ($bits.Length - 2)
|
||||
[array]::Copy($bits, 2, $als, 0, $als.Length)
|
||||
return @{
|
||||
success = $success
|
||||
ip_address = $ip_obj.IPAddressToString
|
||||
ip_type = $ip_obj.AddressFamily
|
||||
canonical_name = $cname
|
||||
aliases = $als
|
||||
}
|
||||
}
|
||||
|
||||
Function Find-HostName($line, $name) {
|
||||
$c_idx = Get-CommentIndex -line $line
|
||||
$re = New-Object regex ("\s+$($name.Replace('.',"\."))(\s|$)", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
|
||||
$match = $re.Match($line, 0, $c_idx)
|
||||
return $match
|
||||
}
|
||||
|
||||
Function Remove-HostEntry($list, $idx) {
|
||||
$result.changed = $true
|
||||
$removed = $false
|
||||
|
||||
if($diff_mode) {
|
||||
$result.diff.prepared += "`n-[$($list[$idx])]`n"
|
||||
}
|
||||
|
||||
if(-not $check_mode) {
|
||||
$list.RemoveAt($idx)
|
||||
$removed = $true
|
||||
}
|
||||
|
||||
return $removed
|
||||
}
|
||||
|
||||
Function Add-HostEntry($list, $cname, $aliases, $ip) {
|
||||
$result.changed = $true
|
||||
$line = "$ip $cname $($aliases -join ' ')"
|
||||
if($diff_mode) {
|
||||
$result.diff.prepared += "`n+[$line]`n"
|
||||
}
|
||||
if(-not $check_mode) {
|
||||
$list.Add($line) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
Function Remove-HostnamesFromEntry($list, $idx, $aliases) {
|
||||
$line = $list[$idx]
|
||||
$line_removed = $false
|
||||
|
||||
foreach($name in $aliases){
|
||||
$match = Find-HostName -line $line -name $name
|
||||
if($match.Success){
|
||||
$line = $line.Remove($match.Index + 1, $match.Length -1)
|
||||
# was this the last alias? (check for space characters after trimming)
|
||||
if($line.Substring(0,(Get-CommentIndex -line $line)).Trim() -inotmatch "\s") {
|
||||
if($diff_mode){
|
||||
$result.diff.prepared += "`n-[$($list[$idx])]`n"
|
||||
}
|
||||
if(-not $check_mode) {
|
||||
$list.RemoveAt($idx)
|
||||
$line_removed = $true
|
||||
}
|
||||
# we're done
|
||||
return @{
|
||||
line_removed = $line_removed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($line -ne $list[$idx]){
|
||||
$result.changed = $true
|
||||
if($diff_mode) {
|
||||
$result.diff.prepared += "`n-[$($list[$idx])]`n+[$line]`n"
|
||||
}
|
||||
if(-not $check_mode) {
|
||||
$list[$idx] = $line
|
||||
}
|
||||
}
|
||||
return @{
|
||||
line_removed = $line_removed
|
||||
}
|
||||
}
|
||||
|
||||
Function Add-AliasesToEntry($list, $idx, $aliases) {
|
||||
$line = $list[$idx]
|
||||
foreach($name in $aliases){
|
||||
$match = Find-HostName -line $line -name $name
|
||||
if(-not $match.Success) {
|
||||
# just add the alias before the comment
|
||||
$line = $line.Insert((Get-CommentIndex -line $line), " $name ")
|
||||
}
|
||||
}
|
||||
if($line -ne $list[$idx]){
|
||||
$result.changed = $true
|
||||
if($diff_mode) {
|
||||
$result.diff.prepared += "`n-[$($list[$idx])]`n+[$line]`n"
|
||||
}
|
||||
if(-not $check_mode) {
|
||||
$list[$idx] = $line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$hosts_lines = New-Object System.Collections.ArrayList
|
||||
|
||||
Get-Content -LiteralPath $hosts_file.FullName | ForEach-Object { $hosts_lines.Add($_) } | Out-Null
|
||||
|
||||
if ($state -eq 'absent') {
|
||||
# go through and remove canonical_name and ip
|
||||
for($idx = 0; $idx -lt $hosts_lines.Count; $idx++) {
|
||||
$entry = $hosts_lines[$idx]
|
||||
# skip comment lines
|
||||
if(-not $entry.Trim().StartsWith('#')) {
|
||||
$entry_parts = Get-HostEntryParts -line $entry
|
||||
if($entry_parts.success) {
|
||||
if(-not $ip_address -or $entry_parts.ip_address -eq $ip_address) {
|
||||
if(-not $canonical_name -or $entry_parts.canonical_name -eq $canonical_name) {
|
||||
if(Remove-HostEntry -list $hosts_lines -idx $idx){
|
||||
# keep index correct if we removed the line
|
||||
$idx = $idx - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($state -eq 'present') {
|
||||
$entry_idx = -1
|
||||
$aliases_to_keep = @()
|
||||
# go through lines, find the entry and determine what to remove based on action
|
||||
for($idx = 0; $idx -lt $hosts_lines.Count; $idx++) {
|
||||
$entry = $hosts_lines[$idx]
|
||||
# skip comment lines
|
||||
if(-not $entry.Trim().StartsWith('#')) {
|
||||
$entry_parts = Get-HostEntryParts -line $entry
|
||||
if($entry_parts.success) {
|
||||
$aliases_to_remove = @()
|
||||
if($entry_parts.ip_address -eq $ip_address) {
|
||||
if($entry_parts.canonical_name -eq $canonical_name) {
|
||||
# don't need to worry about line being removed since canonical_name is present
|
||||
$entry_idx = $idx
|
||||
|
||||
if($action -eq 'set') {
|
||||
# remove the entry's aliases that are not in $aliases
|
||||
$aliases_to_remove = $entry_parts.aliases | Where-Object { $aliases -notcontains $_ }
|
||||
} elseif($action -eq 'remove') {
|
||||
$aliases_to_remove = $aliases
|
||||
}
|
||||
} else {
|
||||
# this is the right ip_address, but not the cname we were looking for.
|
||||
# we need to make sure none of aliases or canonical_name exist for this entry
|
||||
# since the given canonical_name should be an A/AAAA record,
|
||||
# and aliases should be cname records for the canonical_name.
|
||||
$aliases_to_remove = $aliases + $canonical_name
|
||||
}
|
||||
} else {
|
||||
# this is not the ip_address we are looking for
|
||||
if ($ip_address_type -eq $entry_parts.ip_type) {
|
||||
if ($entry_parts.canonical_name -eq $canonical_name) {
|
||||
# remove the entry
|
||||
if (Remove-HostEntry -list $hosts_lines -idx $idx){
|
||||
# keep index correct if we removed the line
|
||||
$idx = $idx - 1
|
||||
}
|
||||
if ($action -ne "set") {
|
||||
# keep old aliases intact
|
||||
$aliases_to_keep += $entry_parts.aliases | Where-Object { ($aliases + $aliases_to_keep + $canonical_name) -notcontains $_ }
|
||||
}
|
||||
} elseif ($action -eq "remove") {
|
||||
# just remove canonical_name. user may want alias(es) mapped to this canonical name
|
||||
$aliases_to_remove = $canonical_name
|
||||
} elseif ($aliases -contains $entry_parts.canonical_name) {
|
||||
# remove the entry
|
||||
if (Remove-HostEntry -list $hosts_lines -idx $idx) {
|
||||
# keep index correct if we removed the line
|
||||
$idx = $idx - 1
|
||||
}
|
||||
if ($action -eq "add") {
|
||||
# keep old aliases intact
|
||||
$aliases_to_keep += $entry_parts.aliases | Where-Object { ($aliases + $aliases_to_keep + $canonical_name) -notcontains $_ }
|
||||
}
|
||||
} else {
|
||||
# ensure canonical_name and aliases removed from this entry
|
||||
$aliases_to_remove = $aliases + $canonical_name
|
||||
}
|
||||
} else {
|
||||
# Just ignore if the types don't match.
|
||||
# TODO: Better ipv6 support. There is odd behavior for when an alias can be used for both ipv6 and ipv4
|
||||
}
|
||||
}
|
||||
|
||||
if($aliases_to_remove) {
|
||||
if((Remove-HostnamesFromEntry -list $hosts_lines -idx $idx -aliases $aliases_to_remove).line_removed) {
|
||||
# keep index correct if we removed the line
|
||||
$idx = $idx - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($entry_idx -ge 0) {
|
||||
# we found the entry
|
||||
$aliases_to_add = @()
|
||||
$entry_parts = Get-HostEntryParts -line $hosts_lines[$entry_idx]
|
||||
if($action -eq 'remove') {
|
||||
# just preserve any previously removed aliases
|
||||
$aliases_to_add = $aliases_to_keep | Where-Object { $entry_parts.aliases -notcontains $_ }
|
||||
} else {
|
||||
# we want to add provided aliases and previously removed aliases that are not already in the list
|
||||
$aliases_to_add = ($aliases + $aliases_to_keep) | Where-Object { $entry_parts.aliases -notcontains $_ }
|
||||
}
|
||||
|
||||
if($aliases_to_add) {
|
||||
Add-AliasesToEntry -list $hosts_lines -idx $entry_idx -aliases $aliases_to_add
|
||||
}
|
||||
} else {
|
||||
# add the entry at the end
|
||||
if($action -eq 'remove') {
|
||||
if($aliases_to_keep) {
|
||||
Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name -aliases $aliases_to_keep
|
||||
} else {
|
||||
Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name
|
||||
}
|
||||
} else {
|
||||
Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name -aliases ($aliases + $aliases_to_keep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( $result.changed -and -not $check_mode ) {
|
||||
Set-Content -LiteralPath $hosts_file.FullName -Value $hosts_lines
|
||||
}
|
||||
|
||||
Exit-Json $result
|
118
lib/ansible/modules/windows/win_hosts.py
Normal file
118
lib/ansible/modules/windows/win_hosts.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2018, Micah Hunsberger (@mhunsber)
|
||||
# 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'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: win_hosts
|
||||
version_added: '2.8'
|
||||
short_description: Manages hosts file entries on Windows.
|
||||
description:
|
||||
- Manages hosts file entries on Windows.
|
||||
- Maps IPv4 or IPv6 addresses to canonical names
|
||||
- Adds, removes, or sets cname records for ip and hostname pairs
|
||||
- Modifies %windir%\system32\drivers\etc\hosts.
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Whether the entry should be present or absent.
|
||||
- If only C(canonical_name) is provided when C(state=absent), then
|
||||
all hosts entries with the canonical name of I(canonical_name)
|
||||
will be removed.
|
||||
- If only C(ip_address) is provided when C(state=absent), then all
|
||||
hosts entries with the ip address of I(ip_address) will be removed.
|
||||
- If C(ip_address) and C(canonical_name) are both omitted when
|
||||
C(state=absent), then all hosts entries will be removed.
|
||||
choices:
|
||||
- absent
|
||||
- present
|
||||
default: present
|
||||
canonical_name:
|
||||
description:
|
||||
- A canonical name for the host entry.
|
||||
- required for C(state=present).
|
||||
ip_address:
|
||||
description:
|
||||
- The ip address for the host entry.
|
||||
- Can be either IPv4 (A record) or IPv6 (AAAA record).
|
||||
- Required for C(state=present).
|
||||
aliases:
|
||||
description:
|
||||
- A list of additional names (cname records) for the host entry.
|
||||
- Only applicable when C(state=present).
|
||||
action:
|
||||
choices:
|
||||
- add
|
||||
- remove
|
||||
- set
|
||||
description:
|
||||
- Controls the behavior of C(aliases).
|
||||
- Only applicable when C(state=present).
|
||||
- If C(add), each alias in I(aliases) will be added to the host entry.
|
||||
- If C(set), each alias in I(aliases) will be added to the host entry,
|
||||
and other aliases will be removed from the entry.
|
||||
default: set
|
||||
author:
|
||||
- Micah Hunsberger (@mhunsber)
|
||||
notes:
|
||||
- Each canonical name can only be mapped to one IPv4 and one IPv6 address.
|
||||
If C(canonical_name) is provided with C(state=present) and is found
|
||||
to be mapped to another IP address that is the same type as, but unique
|
||||
from C(ip_address), then C(canonical_name) and all C(aliases) will
|
||||
be removed from the entry and added to an entry with the provided IP address.
|
||||
- Each alias can only be mapped to one canonical name. If C(aliases) is provided
|
||||
with C(state=present) and an alias is found to be mapped to another canonical
|
||||
name, then the alias will be removed from the entry and added to or removed
|
||||
from (based on I(action)) an entry with the provided canonical name.
|
||||
- See also M(win_template), M(win_file), M(win_copy)
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Add 127.0.0.1 as an A record for localhost
|
||||
win_hosts:
|
||||
state: present
|
||||
canonical_name: localhost
|
||||
ip_address: 127.0.0.1
|
||||
|
||||
- name: Add ::1 as an AAAA record for localhost
|
||||
win_environment:
|
||||
state: present
|
||||
canonical_name: localhost
|
||||
ip_address: '::1'
|
||||
|
||||
- name: Remove 'bar' and 'zed' from the list of aliases for foo (192.168.1.100)
|
||||
win_hosts:
|
||||
state: present
|
||||
canoncial_name: foo
|
||||
ip_address: 192.168.1.100
|
||||
action: remove
|
||||
aliases:
|
||||
- bar
|
||||
- zed
|
||||
|
||||
- name: Remove hosts entries with canonical name 'bar'
|
||||
win_hosts:
|
||||
state: absent
|
||||
canonical_name: bar
|
||||
|
||||
- name: Remove 10.2.0.1 from the list of hosts
|
||||
win_hosts:
|
||||
state: absent
|
||||
ip_address: 10.2.0.1
|
||||
|
||||
- name: Ensure all name resolution is handled by DNS
|
||||
win_hosts:
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
'''
|
1
test/integration/targets/win_hosts/aliases
Normal file
1
test/integration/targets/win_hosts/aliases
Normal file
|
@ -0,0 +1 @@
|
|||
shippable/windows/group3
|
13
test/integration/targets/win_hosts/defaults/main.yml
Normal file
13
test/integration/targets/win_hosts/defaults/main.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
test_win_hosts_cname: testhost
|
||||
test_win_hosts_ip: 192.168.168.1
|
||||
|
||||
test_win_hosts_aliases_set:
|
||||
- alias1
|
||||
- alias2
|
||||
- alias3
|
||||
- alias4
|
||||
|
||||
test_win_hosts_aliases_remove:
|
||||
- alias3
|
||||
- alias4
|
2
test/integration/targets/win_hosts/meta/main.yml
Normal file
2
test/integration/targets/win_hosts/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- setup_remote_tmp_dir
|
17
test/integration/targets/win_hosts/tasks/main.yml
Normal file
17
test/integration/targets/win_hosts/tasks/main.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
- name: take a copy of the original hosts file
|
||||
win_copy:
|
||||
src: C:\Windows\System32\drivers\etc\hosts
|
||||
dest: '{{ remote_tmp_dir }}\hosts'
|
||||
remote_src: yes
|
||||
|
||||
- block:
|
||||
- name: run tests
|
||||
include_tasks: tests.yml
|
||||
|
||||
always:
|
||||
- name: restore hosts file
|
||||
win_copy:
|
||||
src: '{{ remote_tmp_dir }}\hosts'
|
||||
dest: C:\Windows\System32\drivers\etc\hosts
|
||||
remote_src: yes
|
189
test/integration/targets/win_hosts/tasks/tests.yml
Normal file
189
test/integration/targets/win_hosts/tasks/tests.yml
Normal file
|
@ -0,0 +1,189 @@
|
|||
---
|
||||
|
||||
- name: add a simple host with address
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
register: add_ip
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "add_ip.changed == true"
|
||||
|
||||
- name: get actual dns result
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ test_win_hosts_cname }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: add_ip_actual
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "add_ip_actual.stdout_lines[0]|lower == 'true'"
|
||||
|
||||
- name: add a simple host with ipv4 address (idempotent)
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
register: add_ip
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "add_ip.changed == false"
|
||||
|
||||
- name: remove simple host
|
||||
win_hosts:
|
||||
state: absent
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
register: remove_ip
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "remove_ip.changed == true"
|
||||
|
||||
- name: get actual dns result
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ test_win_hosts_cname}}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: remove_ip_actual
|
||||
failed_when: "remove_ip_actual.rc == 0"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "remove_ip_actual.stdout_lines[0]|lower == 'false'"
|
||||
|
||||
- name: remove simple host (idempotent)
|
||||
win_hosts:
|
||||
state: absent
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
register: remove_ip
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "remove_ip.changed == false"
|
||||
|
||||
- name: add host and set aliases
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
aliases: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}"
|
||||
action: set
|
||||
register: set_aliases
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "set_aliases.changed == true"
|
||||
|
||||
- name: get actual dns result for host
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ test_win_hosts_cname }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: set_aliases_actual_host
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "set_aliases_actual_host.stdout_lines[0]|lower == 'true'"
|
||||
|
||||
- name: get actual dns results for aliases
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: set_aliases_actual
|
||||
with_items: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "item.stdout_lines[0]|lower == 'true'"
|
||||
with_items: "{{ set_aliases_actual.results }}"
|
||||
|
||||
- name: add host and set aliases (idempotent)
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
aliases: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}"
|
||||
action: set
|
||||
register: set_aliases
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "set_aliases.changed == false"
|
||||
|
||||
- name: remove aliases from the list
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
aliases: "{{ test_win_hosts_aliases_remove }}"
|
||||
action: remove
|
||||
register: remove_aliases
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "remove_aliases.changed == true"
|
||||
|
||||
- name: get actual dns result for removed aliases
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: remove_aliases_removed_actual
|
||||
failed_when: "remove_aliases_removed_actual.rc == 0"
|
||||
with_items: "{{ test_win_hosts_aliases_remove }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "item.stdout_lines[0]|lower == 'false'"
|
||||
with_items: "{{ remove_aliases_removed_actual.results }}"
|
||||
|
||||
- name: get actual dns result for remaining aliases
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: remove_aliases_remain_actual
|
||||
with_items: "{{ test_win_hosts_aliases_set | difference(test_win_hosts_aliases_remove) }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "item.stdout_lines[0]|lower == 'true'"
|
||||
with_items: "{{ remove_aliases_remain_actual.results }}"
|
||||
|
||||
- name: remove aliases from the list (idempotent)
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
aliases: "{{ test_win_hosts_aliases_remove }}"
|
||||
action: remove
|
||||
register: remove_aliases
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "remove_aliases.changed == false"
|
||||
|
||||
- name: add aliases back
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
aliases: "{{ test_win_hosts_aliases_remove }}"
|
||||
action: add
|
||||
register: add_aliases
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "add_aliases.changed == true"
|
||||
|
||||
- name: get actual dns results for aliases
|
||||
win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }"
|
||||
register: add_aliases_actual
|
||||
with_items: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "item.stdout_lines[0]|lower == 'true'"
|
||||
with_items: "{{ add_aliases_actual.results }}"
|
||||
|
||||
- name: add aliases back (idempotent)
|
||||
win_hosts:
|
||||
state: present
|
||||
ip_address: "{{ test_win_hosts_ip }}"
|
||||
canonical_name: "{{ test_win_hosts_cname }}"
|
||||
aliases: "{{ test_win_hosts_aliases_remove }}"
|
||||
action: add
|
||||
register: add_aliases
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "add_aliases.changed == false"
|
Loading…
Reference in a new issue