From 06dc840b5102ba004788dae6d4e54dbf31183a6e Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Mon, 22 Jan 2018 21:10:25 -0800 Subject: [PATCH] implement gather_subset on Windows setup (#35212) --- lib/ansible/modules/windows/setup.ps1 | 520 +++++++++++------- .../targets/win_setup/tasks/main.yml | 134 ++++- 2 files changed, 436 insertions(+), 218 deletions(-) diff --git a/lib/ansible/modules/windows/setup.ps1 b/lib/ansible/modules/windows/setup.ps1 index 8be498b3b5..ae618d8fd4 100644 --- a/lib/ansible/modules/windows/setup.ps1 +++ b/lib/ansible/modules/windows/setup.ps1 @@ -1,21 +1,9 @@ #!powershell -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . -# WANT_JSON -# POWERSHELL_COMMON +# Copyright (c) 2018 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#Requires -Module Ansible.ModuleUtils.Legacy Function Get-CustomFacts { [cmdletBinding()] @@ -46,7 +34,7 @@ Function Get-MachineSid { $user_principal = New-Object -TypeName System.DirectoryServices.AccountManagement.UserPrincipal($principal_context) $searcher = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalSearcher($user_principal) $users = $searcher.FindAll() | Where-Object { $_.Sid -like "*-500" } - + $machine_sid = $null if ($users -ne $null) { $machine_sid = $users.Sid.AccountDomainSid.Value @@ -54,213 +42,361 @@ Function Get-MachineSid { return $machine_sid } +$cim_instances = @{} + +Function Get-LazyCimInstance([string]$instance_name) { + if(-not $cim_instances.ContainsKey($instance_name)) { + $cim_instances[$instance_name] = $(Get-CimInstance $instance_name) + } + + return $cim_instances[$instance_name] +} + $result = @{ ansible_facts = @{ } changed = $false } +$grouped_subsets = @{ + min=[System.Collections.Generic.List[string]]@('date_time','distribution','dns','env','local','platform','powershell_version','user') + network=[System.Collections.Generic.List[string]]@('all_ipv4_addresses','all_ipv6_addresses','interfaces','windows_domain', 'winrm') + hardware=[System.Collections.Generic.List[string]]@('bios','memory','processor','uptime') + external=[System.Collections.Generic.List[string]]@('facter') +} + +# build "all" set from everything mentioned in the group- this means every value must be in at least one subset to be considered legal +$all_set = [System.Collections.Generic.HashSet[string]]@() + +foreach($kv in $grouped_subsets.GetEnumerator()) { + [void] $all_set.UnionWith($kv.Value) +} + +# dynamically create an "all" subset now that we know what should be in it +$grouped_subsets['all'] = [System.Collections.Generic.List[string]]$all_set + +# start with all, build up gather and exclude subsets +$gather_subset = [System.Collections.Generic.HashSet[string]]$grouped_subsets.all +$explicit_subset = [System.Collections.Generic.HashSet[string]]@() +$exclude_subset = [System.Collections.Generic.HashSet[string]]@() + $params = Parse-Args $args -supports_check_mode $true $factpath = Get-AnsibleParam -obj $params -name "fact_path" -type "path" +$gather_subset_source = Get-AnsibleParam -obj $params -name "gather_subset" -type "list" -default "all" -if ($factpath -ne $null) { - # Get any custom facts +foreach($item in $gather_subset_source) { + if(([string]$item).StartsWith("!")) { + $item = ([string]$item).Substring(1) + if($item -eq "all") { + $all_minus_min = [System.Collections.Generic.HashSet[string]]@($all_set) + [void] $all_minus_min.ExceptWith($grouped_subsets.min) + [void] $exclude_subset.UnionWith($all_minus_min) + } + elseif($grouped_subsets.ContainsKey($item)) { + [void] $exclude_subset.UnionWith($grouped_subsets[$item]) + } + elseif($all_set.Contains($item)) { + [void] $exclude_subset.Add($item) + } + # NB: invalid exclude values are ignored, since that's what posix setup does + } + else { + if($grouped_subsets.ContainsKey($item)) { + [void] $explicit_subset.UnionWith($grouped_subsets[$item]) + } + elseif($all_set.Contains($item)) { + [void] $explicit_subset.Add($item) + } + else { + # NB: POSIX setup fails on invalid value; we warn, because we don't implement the same set as POSIX + # and we don't have platform-specific config for this... + Add-Warning $result "invalid value $item specified in gather_subset" + } + } +} + +[void] $gather_subset.ExceptWith($exclude_subset) +[void] $gather_subset.UnionWith($explicit_subset) + +$ansible_facts = @{ + gather_subset=@($gather_subset_source) + module_setup=$true +} + +$osversion = [Environment]::OSVersion + +if($gather_subset.Contains('all_ipv4_addresses') -or $gather_subset.Contains('all_ipv6_addresses')) { + $netcfg = Get-LazyCimInstance Win32_NetworkAdapterConfiguration + + # TODO: split v4/v6 properly, return in separate keys + $ips = @() + Foreach ($ip in $netcfg.IPAddress) { + If ($ip) { + $ips += $ip + } + } + + $ansible_facts += @{ + ansible_ip_addresses = $ips + } +} + +if($gather_subset.Contains('bios')) { + $win32_bios = Get-LazyCimInstance Win32_Bios + $win32_cs = Get-LazyCimInstance Win32_ComputerSystem + $ansible_facts += @{ + ansible_bios_date = $win32_bios.ReleaseDate.ToString("MM/dd/yyyy") + ansible_bios_version = $win32_bios.SMBIOSBIOSVersion + ansible_product_name = $win32_cs.Model.Trim() + ansible_product_serial = $win32_bios.SerialNumber + # ansible_product_version = ([string] $win32_cs.SystemFamily) + } +} + +if($gather_subset.Contains('date_time')) { + $datetime = (Get-Date) + $datetime_utc = $datetime.ToUniversalTime() + $date = @{ + date = $datetime.ToString("yyyy-MM-dd") + day = $datetime.ToString("dd") + epoch = (Get-Date -UFormat "%s") + hour = $datetime.ToString("HH") + iso8601 = $datetime_utc.ToString("yyyy-MM-ddTHH:mm:ssZ") + iso8601_basic = $datetime.ToString("yyyyMMddTHHmmssffffff") + iso8601_basic_short = $datetime.ToString("yyyyMMddTHHmmss") + iso8601_micro = $datetime_utc.ToString("yyyy-MM-ddTHH:mm:ss.ffffffZ") + minute = $datetime.ToString("mm") + month = $datetime.ToString("MM") + second = $datetime.ToString("ss") + time = $datetime.ToString("HH:mm:ss") + tz = ([System.TimeZoneInfo]::Local.Id) + tz_offset = $datetime.ToString("zzzz") + # Ensure that the weekday is in English + weekday = $datetime.ToString("dddd", [System.Globalization.CultureInfo]::InvariantCulture) + weekday_number = (Get-Date -UFormat "%w") + weeknumber = (Get-Date -UFormat "%W") + year = $datetime.ToString("yyyy") + } + + $ansible_facts += @{ + ansible_date_time = $date + } +} + +if($gather_subset.Contains('distribution')) { + $win32_os = Get-LazyCimInstance Win32_OperatingSystem + $ansible_facts += @{ + ansible_distribution = $win32_os.Caption + ansible_distribution_version = $osversion.Version.ToString() + ansible_distribution_major_version = $osversion.Version.Major.ToString() + ansible_os_family = "Windows" + ansible_os_name = ($win32_os.Name.Split('|')[0]).Trim() + } +} + +if($gather_subset.Contains('env')) { + $env_vars = @{ } + foreach ($item in Get-ChildItem Env:) { + $name = $item | select -ExpandProperty Name + # Powershell ConvertTo-Json fails if string ends with \ + $value = ($item | select -ExpandProperty Value).TrimEnd("\") + $env_vars.Add($name, $value) + } + + $ansible_facts += @{ + ansible_env = $env_vars + } +} + +if($gather_subset.Contains('facter')) { + # See if Facter is on the System Path + Try { + $facter_exe = Get-Command facter -ErrorAction Stop + $facter_installed = $true + } Catch { + $facter_installed = $false + } + + # Get JSON from Facter, and parse it out. + if ($facter_installed) { + &facter -j | Tee-Object -Variable facter_output | Out-Null + $facts = "$facter_output" | ConvertFrom-Json + ForEach($fact in $facts.PSObject.Properties) { + $fact_name = $fact.Name + $ansible_facts.Add("facter_$fact_name", $fact.Value) + } + } +} + +if($gather_subset.Contains('interfaces')) { + $netcfg = Get-LazyCimInstance Win32_NetworkAdapterConfiguration + + $ActiveNetcfg = @() + $ActiveNetcfg += $netcfg | where {$_.ipaddress -ne $null} + + $formattednetcfg = @() + foreach ($adapter in $ActiveNetcfg) + { + $thisadapter = @{ + default_gateway = $null + dns_domain = $adapter.dnsdomain + interface_index = $adapter.InterfaceIndex + interface_name = $adapter.description + macaddress = $adapter.macaddress + } + + if ($adapter.defaultIPGateway) + { + $thisadapter.default_gateway = $adapter.DefaultIPGateway[0].ToString() + } + + $formattednetcfg += $thisadapter + } + + $ansible_facts += @{ + ansible_interfaces = $formattednetcfg + } +} + +if ($gather_subset.Contains("local") -and $factpath -ne $null) { + # Get any custom facts; results are updated in the Get-CustomFacts -factpath $factpath } -$win32_os = Get-CimInstance Win32_OperatingSystem -$win32_cs = Get-CimInstance Win32_ComputerSystem -$win32_bios = Get-CimInstance Win32_Bios -$win32_cpu = Get-CimInstance Win32_Processor -if ($win32_cpu -is [array]) { - # multi-socket, pick first - $win32_cpu = $win32_cpu[0] -} - -$ip_props = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties() -$osversion = [Environment]::OSVersion -$user = [Security.Principal.WindowsIdentity]::GetCurrent() -$netcfg = Get-WmiObject win32_NetworkAdapterConfiguration - -$ActiveNetcfg = @() -$ActiveNetcfg += $netcfg | where {$_.ipaddress -ne $null} - -$formattednetcfg = @() -foreach ($adapter in $ActiveNetcfg) -{ - $thisadapter = @{ - default_gateway = $null - dns_domain = $adapter.dnsdomain - interface_index = $adapter.InterfaceIndex - interface_name = $adapter.description - macaddress = $adapter.macaddress - } - - if ($adapter.defaultIPGateway) - { - $thisadapter.default_gateway = $adapter.DefaultIPGateway[0].ToString() - } - - $formattednetcfg += $thisadapter -} - -$cpu_list = @( ) -for ($i=1; $i -le ($win32_cpu.NumberOfLogicalProcessors / $win32_cs.NumberOfProcessors); $i++) { - $cpu_list += $win32_cpu.Manufacturer - $cpu_list += $win32_cpu.Name -} - -$datetime = (Get-Date) -$datetime_utc = $datetime.ToUniversalTime() - -$date = @{ - date = $datetime.ToString("yyyy-MM-dd") - day = $datetime.ToString("dd") - epoch = (Get-Date -UFormat "%s") - hour = $datetime.ToString("HH") - iso8601 = $datetime_utc.ToString("yyyy-MM-ddTHH:mm:ssZ") - iso8601_basic = $datetime.ToString("yyyyMMddTHHmmssffffff") - iso8601_basic_short = $datetime.ToString("yyyyMMddTHHmmss") - iso8601_micro = $datetime_utc.ToString("yyyy-MM-ddTHH:mm:ss.ffffffZ") - minute = $datetime.ToString("mm") - month = $datetime.ToString("MM") - second = $datetime.ToString("ss") - time = $datetime.ToString("HH:mm:ss") - tz = ([System.TimeZoneInfo]::Local.Id) - tz_offset = $datetime.ToString("zzzz") - # Ensure that the weekday is in English - weekday = $datetime.ToString("dddd", [System.Globalization.CultureInfo]::InvariantCulture) - weekday_number = (Get-Date -UFormat "%w") - weeknumber = (Get-Date -UFormat "%W") - year = $datetime.ToString("yyyy") -} - -$ips = @() -Foreach ($ip in $netcfg.IPAddress) { - If ($ip) { - $ips += $ip +if($gather_subset.Contains('memory')) { + $win32_cs = Get-LazyCimInstance Win32_ComputerSystem + $win32_os = Get-LazyCimInstance Win32_OperatingSystem + $ansible_facts += @{ + # Win32_PhysicalMemory is empty on some virtual platforms + ansible_memtotal_mb = ([math]::round($win32_cs.TotalPhysicalMemory / 1024 / 1024)) + ansible_swaptotal_mb = ([math]::round($win32_os.TotalSwapSpaceSize / 1024 / 1024)) } } -$env_vars = @{ } -foreach ($item in Get-ChildItem Env:) { - $name = $item | select -ExpandProperty Name - # Powershell ConvertTo-Json fails if string ends with \ - $value = ($item | select -ExpandProperty Value).TrimEnd("\") - $env_vars.Add($name, $value) + +if($gather_subset.Contains('platform')) { + $win32_cs = Get-LazyCimInstance Win32_ComputerSystem + $win32_os = Get-LazyCimInstance Win32_OperatingSystem + $ip_props = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties() + + $ansible_facts += @{ + ansible_architecture = $win32_os.OSArchitecture + ansible_domain = $ip_props.DomainName + ansible_fqdn = ($ip_props.Hostname + "." + $ip_props.DomainName) + ansible_hostname = $env:COMPUTERNAME + ansible_kernel = $osversion.Version.ToString() + ansible_nodename = ($ip_props.HostName + "." + $ip_props.DomainName) + ansible_machine_id = Get-MachineSid + ansible_owner_contact = ([string] $win32_cs.PrimaryOwnerContact) + ansible_owner_name = ([string] $win32_cs.PrimaryOwnerName) + # FUTURE: should this live in its own subset? + ansible_reboot_pending = (Get-PendingRebootStatus) + ansible_system = $osversion.Platform.ToString() + ansible_system_description = ([string] $win32_os.Description) + ansible_system_vendor = $win32_cs.Manufacturer + } } -$domain_roles = @{ - 0 = "Stand-alone workstation" - 1 = "Member workstation" - 2 = "Stand-alone server" - 3 = "Member server" - 4 = "Backup domain controller" - 5 = "Primary domain controller" +if($gather_subset.Contains('powershell_version')) { + $ansible_facts += @{ + ansible_powershell_version = ($PSVersionTable.PSVersion.Major) + } } -$domain_role = $domain_roles.Get_Item([Int32]$win32_cs.DomainRole) +if($gather_subset.Contains('processor')) { + $win32_cs = Get-LazyCimInstance Win32_ComputerSystem + $win32_cpu = Get-LazyCimInstance Win32_Processor + if ($win32_cpu -is [array]) { + # multi-socket, pick first + $win32_cpu = $win32_cpu[0] + } -$ansible_facts = @{ - ansible_architecture = $win32_os.OSArchitecture - ansible_bios_date = $win32_bios.ReleaseDate.ToString("MM/dd/yyyy") - ansible_bios_version = $win32_bios.SMBIOSBIOSVersion - ansible_date_time = $date - ansible_distribution = $win32_os.Caption - ansible_distribution_version = $osversion.Version.ToString() - ansible_distribution_major_version = $osversion.Version.Major.ToString() - ansible_domain = $ip_props.DomainName - ansible_env = $env_vars - ansible_fqdn = ($ip_props.Hostname + "." + $ip_props.DomainName) - ansible_hostname = $env:COMPUTERNAME - ansible_interfaces = $formattednetcfg - ansible_ip_addresses = $ips - ansible_kernel = $osversion.Version.ToString() - ansible_lastboot = $win32_os.lastbootuptime.ToString("u") - ansible_machine_id = Get-MachineSid - ansible_nodename = ($ip_props.HostName + "." + $ip_props.DomainName) - ansible_os_family = "Windows" - ansible_os_name = ($win32_os.Name.Split('|')[0]).Trim() - ansible_owner_contact = ([string] $win32_cs.PrimaryOwnerContact) - ansible_owner_name = ([string] $win32_cs.PrimaryOwnerName) - ansible_powershell_version = ($PSVersionTable.PSVersion.Major) - ansible_processor = $cpu_list - ansible_processor_cores = $win32_cpu.NumberOfCores - ansible_processor_count = $win32_cs.NumberOfProcessors - ansible_processor_threads_per_core = ($win32_cpu.NumberOfLogicalProcessors / $win32_cs.NumberOfProcessors / $win32_cpu.NumberOfCores) - ansible_processor_vcpus = ($win32_cpu.NumberOfLogicalProcessors / $win32_cs.NumberOfProcessors) - ansible_product_name = $win32_cs.Model.Trim() - ansible_product_serial = $win32_bios.SerialNumber -# ansible_product_version = ([string] $win32_cs.SystemFamily) - ansible_reboot_pending = (Get-PendingRebootStatus) - ansible_system = $osversion.Platform.ToString() - ansible_system_description = ([string] $win32_os.Description) - ansible_system_vendor = $win32_cs.Manufacturer - ansible_uptime_seconds = $([System.Convert]::ToInt64($(Get-Date).Subtract($win32_os.lastbootuptime).TotalSeconds)) + $cpu_list = @( ) + for ($i=1; $i -le ($win32_cpu.NumberOfLogicalProcessors / $win32_cs.NumberOfProcessors); $i++) { + $cpu_list += $win32_cpu.Manufacturer + $cpu_list += $win32_cpu.Name + } - ansible_user_dir = $env:userprofile - # Win32_UserAccount.FullName is probably the right thing here, but it can be expensive to get on large domains - ansible_user_gecos = "" - ansible_user_id = $env:username - ansible_user_sid = $user.User.Value - ansible_windows_domain = $win32_cs.Domain - ansible_windows_domain_member = $win32_cs.PartOfDomain - ansible_windows_domain_role = $domain_role - - # Win32_PhysicalMemory is empty on some virtual platforms - ansible_memtotal_mb = ([math]::round($win32_cs.TotalPhysicalMemory / 1024 / 1024)) - ansible_swaptotal_mb = ([math]::round($win32_os.TotalSwapSpaceSize / 1024 / 1024)) - - module_setup = $true + $ansible_facts += @{ + ansible_processor = $cpu_list + ansible_processor_cores = $win32_cpu.NumberOfCores + ansible_processor_count = $win32_cs.NumberOfProcessors + ansible_processor_threads_per_core = ($win32_cpu.NumberOfLogicalProcessors / $win32_cs.NumberOfProcessors / $win32_cpu.NumberOfCores) + ansible_processor_vcpus = ($win32_cpu.NumberOfLogicalProcessors / $win32_cs.NumberOfProcessors) + } } -$winrm_https_listener_parent_paths = Get-ChildItem -Path WSMan:\localhost\Listener -Recurse | Where-Object {$_.PSChildName -eq "Transport" -and $_.Value -eq "HTTPS"} | select PSParentPath -if ($winrm_https_listener_parent_paths -isnot [array]) { - $winrm_https_listener_parent_paths = @($winrm_https_listener_parent_paths) +if($gather_subset.Contains('uptime')) { + $win32_os = Get-LazyCimInstance Win32_OperatingSystem + $ansible_facts += @{ + ansible_lastboot = $win32_os.lastbootuptime.ToString("u") + ansible_uptime_seconds = $([System.Convert]::ToInt64($(Get-Date).Subtract($win32_os.lastbootuptime).TotalSeconds)) + } } -$winrm_https_listener_paths = @() -foreach ($winrm_https_listener_parent_path in $winrm_https_listener_parent_paths) { - $winrm_https_listener_paths += $winrm_https_listener_parent_path.PSParentPath.Substring($winrm_https_listener_parent_path.PSParentPath.LastIndexOf("\")) +if($gather_subset.Contains('user')) { + $user = [Security.Principal.WindowsIdentity]::GetCurrent() + $ansible_facts += @{ + ansible_user_dir = $env:userprofile + # Win32_UserAccount.FullName is probably the right thing here, but it can be expensive to get on large domains + ansible_user_gecos = "" + ansible_user_id = $env:username + ansible_user_sid = $user.User.Value + } } -$https_listeners = @() -foreach ($winrm_https_listener_path in $winrm_https_listener_paths) { - $https_listeners += Get-ChildItem -Path "WSMan:\localhost\Listener$winrm_https_listener_path" +if($gather_subset.Contains('windows_domain')) { + $win32_cs = Get-LazyCimInstance Win32_ComputerSystem + $domain_roles = @{ + 0 = "Stand-alone workstation" + 1 = "Member workstation" + 2 = "Stand-alone server" + 3 = "Member server" + 4 = "Backup domain controller" + 5 = "Primary domain controller" + } + + $domain_role = $domain_roles.Get_Item([Int32]$win32_cs.DomainRole) + + $ansible_facts += @{ + ansible_windows_domain = $win32_cs.Domain + ansible_windows_domain_member = $win32_cs.PartOfDomain + ansible_windows_domain_role = $domain_role + } } -$winrm_cert_thumbprints = @() -foreach ($https_listener in $https_listeners) { - $winrm_cert_thumbprints += $https_listener | where {$_.Name -EQ "CertificateThumbprint" } | select Value -} +if($gather_subset.Contains('winrm')) { -$winrm_cert_expiry = @() -foreach ($winrm_cert_thumbprint in $winrm_cert_thumbprints) { - Try { - $winrm_cert_expiry += Get-ChildItem -Path Cert:\LocalMachine\My | where Thumbprint -EQ $winrm_cert_thumbprint.Value.ToString().ToUpper() | select NotAfter - } Catch {} -} + $winrm_https_listener_parent_paths = Get-ChildItem -Path WSMan:\localhost\Listener -Recurse | Where-Object {$_.PSChildName -eq "Transport" -and $_.Value -eq "HTTPS"} | select PSParentPath + if ($winrm_https_listener_parent_paths -isnot [array]) { + $winrm_https_listener_parent_paths = @($winrm_https_listener_parent_paths) + } -$winrm_cert_expirations = $winrm_cert_expiry | Sort-Object NotAfter -if ($winrm_cert_expirations) { - # this fact was renamed from ansible_winrm_certificate_expires due to collision with ansible_winrm_X connection var pattern - $ansible_facts.Add("ansible_win_rm_certificate_expires", $winrm_cert_expirations[0].NotAfter.ToString("yyyy-MM-dd HH:mm:ss")) -} + $winrm_https_listener_paths = @() + foreach ($winrm_https_listener_parent_path in $winrm_https_listener_parent_paths) { + $winrm_https_listener_paths += $winrm_https_listener_parent_path.PSParentPath.Substring($winrm_https_listener_parent_path.PSParentPath.LastIndexOf("\")) + } -# See if Facter is on the System Path -Try { - $facter_exe = Get-Command facter -ErrorAction Stop - $facter_installed = $true -} Catch { - $facter_installed = $false -} + $https_listeners = @() + foreach ($winrm_https_listener_path in $winrm_https_listener_paths) { + $https_listeners += Get-ChildItem -Path "WSMan:\localhost\Listener$winrm_https_listener_path" + } -# Get JSON from Facter, and parse it out. -if ($facter_installed) { - &facter -j | Tee-Object -Variable facter_output | Out-Null - $facts = "$facter_output" | ConvertFrom-Json - ForEach($fact in $facts.PSObject.Properties) { - $fact_name = $fact.Name - $ansible_facts.Add("facter_$fact_name", $fact.Value) + $winrm_cert_thumbprints = @() + foreach ($https_listener in $https_listeners) { + $winrm_cert_thumbprints += $https_listener | where {$_.Name -EQ "CertificateThumbprint" } | select Value + } + + $winrm_cert_expiry = @() + foreach ($winrm_cert_thumbprint in $winrm_cert_thumbprints) { + Try { + $winrm_cert_expiry += Get-ChildItem -Path Cert:\LocalMachine\My | where Thumbprint -EQ $winrm_cert_thumbprint.Value.ToString().ToUpper() | select NotAfter + } Catch {} + } + + $winrm_cert_expirations = $winrm_cert_expiry | Sort-Object NotAfter + if ($winrm_cert_expirations) { + # this fact was renamed from ansible_winrm_certificate_expires due to collision with ansible_winrm_X connection var pattern + $ansible_facts.Add("ansible_win_rm_certificate_expires", $winrm_cert_expirations[0].NotAfter.ToString("yyyy-MM-dd HH:mm:ss")) } } diff --git a/test/integration/targets/win_setup/tasks/main.yml b/test/integration/targets/win_setup/tasks/main.yml index 73de10334e..516fbb4130 100644 --- a/test/integration/targets/win_setup/tasks/main.yml +++ b/test/integration/targets/win_setup/tasks/main.yml @@ -23,35 +23,117 @@ - name: check windows setup result assert: that: - - "setup_result is not failed" - - "setup_result is not changed" - - "setup_result.ansible_facts" - - "setup_result.ansible_facts.ansible_os_family == 'Windows'" - - "setup_result.ansible_facts.ansible_date_time" - - "setup_result.ansible_facts.ansible_date_time.date" - - "setup_result.ansible_facts.ansible_date_time.year" - - "setup_result.ansible_facts.ansible_date_time.month" - - "setup_result.ansible_facts.ansible_date_time.day" - - "setup_result.ansible_facts.ansible_date_time.hour is defined" - - "setup_result.ansible_facts.ansible_date_time.minute is defined" - - "setup_result.ansible_facts.ansible_date_time.iso8601" - - "setup_result.ansible_facts.ansible_distribution" - - "setup_result.ansible_facts.ansible_distribution_version" - - "setup_result.ansible_facts.ansible_fqdn" - - "setup_result.ansible_facts.ansible_hostname" - - "setup_result.ansible_facts.ansible_ip_addresses" - - "setup_result.ansible_facts.ansible_system" - - "setup_result.ansible_facts.ansible_memtotal_mb" - - "setup_result.ansible_facts.ansible_interfaces" - - "setup_result.ansible_facts.ansible_interfaces[0]" - - "setup_result.ansible_facts.ansible_interfaces[0].interface_name" - - "setup_result.ansible_facts.ansible_interfaces[0].interface_index" - - "setup_result.ansible_facts.ansible_architecture" - - "setup_result.ansible_facts.ansible_os_name" - - "setup_result.ansible_facts.ansible_powershell_version" + - setup_result is not failed + - setup_result is not changed + - setup_result.ansible_facts + - setup_result.ansible_facts.ansible_os_family == 'Windows' + - setup_result.ansible_facts.ansible_date_time + - setup_result.ansible_facts.ansible_date_time.date + - setup_result.ansible_facts.ansible_date_time.year + - setup_result.ansible_facts.ansible_date_time.month + - setup_result.ansible_facts.ansible_date_time.day + - setup_result.ansible_facts.ansible_date_time.hour is defined + - setup_result.ansible_facts.ansible_date_time.minute is defined + - setup_result.ansible_facts.ansible_date_time.iso8601 + - setup_result.ansible_facts.ansible_distribution + - setup_result.ansible_facts.ansible_distribution_version + - setup_result.ansible_facts.ansible_fqdn + - setup_result.ansible_facts.ansible_hostname + - setup_result.ansible_facts.ansible_ip_addresses + - setup_result.ansible_facts.ansible_system + - setup_result.ansible_facts.ansible_memtotal_mb + - setup_result.ansible_facts.ansible_interfaces + - setup_result.ansible_facts.ansible_interfaces[0] + - setup_result.ansible_facts.ansible_interfaces[0].interface_name + - setup_result.ansible_facts.ansible_interfaces[0].interface_index + - setup_result.ansible_facts.ansible_architecture + - setup_result.ansible_facts.ansible_os_name + - setup_result.ansible_facts.ansible_powershell_version + - setup_result.ansible_facts.gather_subset is defined + - setup_result.ansible_facts.gather_subset[0] == 'all' + - setup_result.ansible_facts.module_setup == true - name: check setup result only when using https assert: that: - "setup_result.ansible_facts.ansible_win_rm_certificate_expires" when: ansible_ssh_port|default(5986) != 5985 + +- name: test gather_subset "!all" + setup: + gather_subset: '!all' + register: setup_result + +- name: verify that some known "all" keys are missing (should just be "min" subset) + assert: + that: + - setup_result is not failed + - setup_result is not changed + - setup_result.ansible_facts is defined + - setup_result.ansible_facts.gather_subset[0] == '!all' + - setup_result.ansible_facts.gather_subset is defined + - setup_result.ansible_facts.ansible_ip_addresses is not defined + - setup_result.ansible_facts.ansible_interfaces is not defined + +- name: test gather_subset "!all,!min" with list + setup: + gather_subset: + - '!all' + - '!min' + register: setup_result + +- name: verify that only status keys are returned + assert: + that: + - setup_result is not failed + - setup_result is not changed + - setup_result.ansible_facts is defined + - setup_result.ansible_facts.gather_subset is defined + - setup_result.ansible_facts.gather_subset[0] == '!all' + - setup_result.ansible_facts.gather_subset[1] == '!min' + - setup_result.ansible_facts.keys() | union(['gather_subset','module_setup']) | length == 2 + +- name: test gather_subset "!all,!min,interfaces" with list + setup: + gather_subset: + - '!all' + - '!min' + - interfaces + register: setup_result + +- name: verify that only status keys and ansible_interfaces are returned + assert: + that: + - setup_result is not failed + - setup_result is not changed + - setup_result.ansible_facts is defined + - setup_result.ansible_facts.gather_subset is defined + - setup_result.ansible_facts.gather_subset[0] == '!all' + - setup_result.ansible_facts.gather_subset[1] == '!min' + - setup_result.ansible_facts.gather_subset[2] == 'interfaces' + - setup_result.ansible_facts.ansible_interfaces + - setup_result.ansible_facts.ansible_interfaces[0] + - setup_result.ansible_facts.ansible_interfaces[0].interface_name + - setup_result.ansible_facts.ansible_interfaces[0].interface_index + - setup_result.ansible_facts.keys() | union(['ansible_interfaces','gather_subset','module_setup']) | length == 3 + +- name: test gather_subset "!all,!min,bogus" with list + setup: + gather_subset: + - '!all' + - '!min' + - bogus + register: setup_result + +- name: verify that only status keys are returned and that we got a warning + assert: + that: + - setup_result is not failed + - setup_result is not changed + - setup_result.ansible_facts is defined + - setup_result.ansible_facts.gather_subset is defined + - setup_result.ansible_facts.gather_subset[0] == '!all' + - setup_result.ansible_facts.gather_subset[1] == '!min' + - setup_result.ansible_facts.keys() | union(['gather_subset','module_setup']) | length == 2 + - setup_result.warnings | length == 1 + - setup_result.warnings[0] | regex_search('bogus')