win_wait_for: added module (#26556)
* win_wait_for: added module * Increased timeout on async task * added more debug messages for test debug * revert to using win_shell instead of win_command * rebased from master and updated copyright string * Updated metadata version * Capitalised start of short_description * disabled win_wait_for tests until async issues are solved
This commit is contained in:
parent
40ea448c7b
commit
9b7dbc78c3
6 changed files with 751 additions and 0 deletions
269
lib/ansible/modules/windows/win_wait_for.ps1
Normal file
269
lib/ansible/modules/windows/win_wait_for.ps1
Normal file
|
@ -0,0 +1,269 @@
|
|||
#!powershell
|
||||
# This file is part of Ansible
|
||||
|
||||
# Copyright (c) 2017 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.psm1
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||
|
||||
$connect_timeout = Get-AnsibleParam -obj $params -name "connect_timeout" -type "int" -default 5
|
||||
$delay = Get-AnsibleParam -obj $params -name "delay" -type "int"
|
||||
$exclude_hosts = Get-AnsibleParam -obj $params -name "exclude_hosts" -type "list"
|
||||
$hostname = Get-AnsibleParam -obj $params -name "host" -type "str" -default "127.0.0.1"
|
||||
$path = Get-AnsibleParam -obj $params -name "path" -type "path"
|
||||
$port = Get-AnsibleParam -obj $params -name "port" -type "int"
|
||||
$search_regex = Get-AnsibleParam -obj $params -name "search_regex" -type "string"
|
||||
$sleep = Get-AnsibleParam -obj $params -name "sleep" -type "int" -default 1
|
||||
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "started" -validateset "present","started","stopped","absent","drained"
|
||||
$timeout = Get-AnsibleParam -obj $params -name "timeout" -type "int" -default 300
|
||||
|
||||
$result = @{
|
||||
changed = $false
|
||||
}
|
||||
|
||||
# validate the input with the various options
|
||||
if ($port -ne $null -and $path -ne $null) {
|
||||
Fail-Json $result "port and path parameter can not both be passed to win_wait_for"
|
||||
}
|
||||
if ($exclude_hosts -ne $null -and $state -ne "drained") {
|
||||
Fail-Json $result "exclude_hosts should only be with state=drained"
|
||||
}
|
||||
if ($path -ne $null) {
|
||||
if ($state -in @("stopped","drained")) {
|
||||
Fail-Json $result "state=$state should only be used for checking a port in the win_wait_for module"
|
||||
}
|
||||
|
||||
if ($exclude_hosts -ne $null) {
|
||||
Fail-Json $result "exclude_hosts should only be used when checking a port and state=drained in the win_wait_for module"
|
||||
}
|
||||
}
|
||||
|
||||
if ($port -ne $null) {
|
||||
if ($search_regex -ne $null) {
|
||||
Fail-Json $result "search_regex should by used when checking a string in a file in the win_wait_for module"
|
||||
}
|
||||
|
||||
if ($exclude_hosts -ne $null -and $state -ne "drained") {
|
||||
Fail-Json $result "exclude_hosts should be used when state=drained in the win_wait_for module"
|
||||
}
|
||||
}
|
||||
|
||||
Function Test-Port($hostname, $port) {
|
||||
# try and resolve the IP/Host, if it fails then just use the host passed in
|
||||
try {
|
||||
$resolve_hostname = ([System.Net.Dns]::GetHostEntry($hostname)).HostName
|
||||
} catch {
|
||||
# oh well just use the IP addres
|
||||
$resolve_hostname = $hostname
|
||||
}
|
||||
|
||||
$timeout = $connect_timeout * 1000
|
||||
$socket = New-Object -TypeName System.Net.Sockets.TcpClient
|
||||
$connect = $socket.BeginConnect($resolve_hostname, $port, $null, $null)
|
||||
$wait = $connect.AsyncWaitHandle.WaitOne($timeout, $false)
|
||||
|
||||
if ($wait) {
|
||||
try {
|
||||
$socket.EndConnect($connect) | Out-Null
|
||||
$valid = $true
|
||||
} catch {
|
||||
$valid = $false
|
||||
}
|
||||
} else {
|
||||
$valid = $false
|
||||
}
|
||||
|
||||
$socket.Close()
|
||||
$socket.Dispose()
|
||||
|
||||
$valid
|
||||
}
|
||||
|
||||
Function Get-PortConnections($hostname, $port) {
|
||||
$connections = @()
|
||||
|
||||
$conn_info = [Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
|
||||
if ($hostname -eq "0.0.0.0") {
|
||||
$active_connections = $conn_info.GetActiveTcpConnections() | Where-Object { $_.LocalEndPoint.Port -eq $port }
|
||||
} else {
|
||||
$active_connections = $conn_info.GetActiveTcpConnections() | Where-Object { $_.LocalEndPoint.Address -eq $hostname -and $_.LocalEndPoint.Port -eq $port }
|
||||
}
|
||||
|
||||
if ($active_connections -ne $null) {
|
||||
foreach ($active_connection in $active_connections) {
|
||||
$connections += $active_connection.RemoteEndPoint.Address
|
||||
}
|
||||
}
|
||||
|
||||
$connections
|
||||
}
|
||||
|
||||
$module_start = Get-Date
|
||||
|
||||
if ($delay -ne $null) {
|
||||
Start-Sleep -Seconds $delay
|
||||
}
|
||||
|
||||
$attempts = 0
|
||||
if ($path -eq $null -and $port -eq $null -and $state -eq "drained") {
|
||||
Start-Sleep -Seconds $timeout
|
||||
} elseif ($path -ne $null) {
|
||||
if ($state -in @("present", "started")) {
|
||||
# check if the file exists or string exists in file
|
||||
$start_time = Get-Date
|
||||
$complete = $false
|
||||
while (((Get-Date) - $start_time).TotalSeconds -lt $timeout) {
|
||||
$attempts += 1
|
||||
if (Test-Path -Path $path) {
|
||||
if ($search_regex -eq $null) {
|
||||
$complete = $true
|
||||
break
|
||||
} else {
|
||||
$file_contents = Get-Content -Path $path -Raw
|
||||
if ($file_contents -match $search_regex) {
|
||||
$complete = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
Start-Sleep -Seconds $sleep
|
||||
}
|
||||
|
||||
if ($complete -eq $false) {
|
||||
$elapsed_seconds = ((Get-Date) - $module_start).TotalSeconds
|
||||
$result.attempts = $attempts
|
||||
$result.elapsed = $elapsed_seconds
|
||||
if ($search_regex -eq $null) {
|
||||
Fail-Json $result "timeout while waiting for file $path to be present"
|
||||
} else {
|
||||
Fail-Json $result "timeout while waiting for string regex $search_regex in file $path to match"
|
||||
}
|
||||
}
|
||||
} elseif ($state -in @("absent")) {
|
||||
# check if the file is deleted or string doesn't exist in file
|
||||
$start_time = Get-Date
|
||||
$complete = $false
|
||||
while (((Get-Date) - $start_time).TotalSeconds -lt $timeout) {
|
||||
$attempts += 1
|
||||
if (Test-Path -Path $path) {
|
||||
if ($search_regex -ne $null) {
|
||||
$file_contents = Get-Content -Path $path -Raw
|
||||
if ($file_contents -notmatch $search_regex) {
|
||||
$complete = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$complete = $true
|
||||
break
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds $sleep
|
||||
}
|
||||
|
||||
if ($complete -eq $false) {
|
||||
$elapsed_seconds = ((Get-Date) - $module_start).TotalSeconds
|
||||
$result.attempts = $attempts
|
||||
$result.elapsed = $elapsed_seconds
|
||||
if ($search_regex -eq $null) {
|
||||
Fail-Json $result "timeout while waiting for file $path to be absent"
|
||||
} else {
|
||||
Fail-Json $result "timeout while waiting for string regex $search_regex in file $path to not match"
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($port -ne $null) {
|
||||
if ($state -in @("started","present")) {
|
||||
# check that the port is online and is listening
|
||||
$start_time = Get-Date
|
||||
$complete = $false
|
||||
while (((Get-Date) - $start_time).TotalSeconds -lt $timeout) {
|
||||
$attempts += 1
|
||||
$port_result = Test-Port -hostname $hostname -port $port
|
||||
if ($port_result -eq $true) {
|
||||
$complete = $true
|
||||
break
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds $sleep
|
||||
}
|
||||
|
||||
if ($complete -eq $false) {
|
||||
$elapsed_seconds = ((Get-Date) - $module_start).TotalSeconds
|
||||
$result.attempts = $attempts
|
||||
$result.elapsed = $elapsed_seconds
|
||||
Fail-Json $result "timeout while waiting for $($hostname):$port to start listening"
|
||||
}
|
||||
} elseif ($state -in @("stopped","absent")) {
|
||||
# check that the port is offline and is not listening
|
||||
$start_time = Get-Date
|
||||
$complete = $false
|
||||
while (((Get-Date) - $start_time).TotalSeconds -lt $timeout) {
|
||||
$attempts += 1
|
||||
$port_result = Test-Port -hostname $hostname -port $port
|
||||
if ($port_result -eq $false) {
|
||||
$complete = $true
|
||||
break
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds $sleep
|
||||
}
|
||||
|
||||
if ($complete -eq $false) {
|
||||
$elapsed_seconds = ((Get-Date) - $module_start).TotalSeconds
|
||||
$result.attempts = $attempts
|
||||
$result.elapsed = $elapsed_seconds
|
||||
Fail-Json $result "timeout while waiting for $($hostname):$port to stop listening"
|
||||
}
|
||||
} elseif ($state -eq "drained") {
|
||||
# check that the local port is online but has no active connections
|
||||
$start_time = Get-Date
|
||||
$complete = $false
|
||||
while (((Get-Date) - $start_time).TotalSeconds -lt $timeout) {
|
||||
$attempts += 1
|
||||
$active_connections = Get-PortConnections -hostname $hostname -port $port
|
||||
if ($active_connections -eq $null) {
|
||||
$complete = $true
|
||||
break
|
||||
} elseif ($active_connections.Count -eq 0) {
|
||||
# no connections on port
|
||||
$complete = $true
|
||||
break
|
||||
} else {
|
||||
# there are listeners, check if we should ignore any hosts
|
||||
if ($exclude_hosts -ne $null) {
|
||||
$connection_info = $active_connections
|
||||
foreach ($exclude_host in $exclude_hosts) {
|
||||
try {
|
||||
$exclude_ips = [System.Net.Dns]::GetHostAddresses($exclude_host) | ForEach-Object { Write-Output $_.IPAddressToString }
|
||||
$connection_info = $connection_info | Where-Object { $_ -notin $exclude_ips }
|
||||
} catch {} # ignore invalid hostnames
|
||||
}
|
||||
|
||||
if ($connection_info.Count -eq 0) {
|
||||
$complete = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds $sleep
|
||||
}
|
||||
|
||||
if ($complete -eq $false) {
|
||||
$elapsed_seconds = ((Get-Date) - $module_start).TotalSeconds
|
||||
$result.attempts = $attempts
|
||||
$result.elapsed = $elapsed_seconds
|
||||
Fail-Json $result "timeout while waiting for $($hostname):$port to drain"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result.attempts = $attempts
|
||||
$result.elapsed = ((Get-Date) - $module_start).TotalSeconds
|
||||
|
||||
Exit-Json $result
|
142
lib/ansible/modules/windows/win_wait_for.py
Normal file
142
lib/ansible/modules/windows/win_wait_for.py
Normal file
|
@ -0,0 +1,142 @@
|
|||
#!/usr/bin/python
|
||||
# This file is part of Ansible
|
||||
|
||||
# Copyright (c) 2017 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
# this is a windows documentation stub, actual code lives in the .ps1
|
||||
# file of the same name
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: win_wait_for
|
||||
version_added: '2.4'
|
||||
short_description: Waits for a condition before continuing
|
||||
description:
|
||||
- You can wait for a set amount of time C(timeout), this is the default if
|
||||
nothing is specified.
|
||||
- Waiting for a port to become available is useful for when services are not
|
||||
immediately available after their init scripts return which is true of
|
||||
certain Java application servers.
|
||||
- You can wait for a file to exist or not exist on the filesystem.
|
||||
- This module can also be used to wait for a regex match string to be present
|
||||
in a file.
|
||||
- You can wait for active connections to be closed before continuing on a
|
||||
local port.
|
||||
options:
|
||||
connect_timeout:
|
||||
description:
|
||||
- The maximum number of seconds to wait for a connection to happen before
|
||||
closing and retrying.
|
||||
default: 5
|
||||
delay:
|
||||
description:
|
||||
- The number of seconds to wait before starting to poll.
|
||||
exclude_hosts:
|
||||
description:
|
||||
- The list of hosts or IPs to ignore when looking for active TCP
|
||||
connections when C(state=drained).
|
||||
host:
|
||||
description:
|
||||
- A resolvable hostname or IP address to wait for.
|
||||
- If C(state=drained) then it will only check for connections on the IP
|
||||
specified, you can use '0.0.0.0' to use all host IPs.
|
||||
default: '127.0.0.1'
|
||||
path:
|
||||
description:
|
||||
- The path to a file on the filesystem to check.
|
||||
- If C(state) is present or started then it will wait until the file
|
||||
exists.
|
||||
- If C(state) is absent then it will wait until the file does not exist.
|
||||
port:
|
||||
description:
|
||||
- The port number to poll on C(host).
|
||||
search_regex:
|
||||
description:
|
||||
- Can be used to match a string in a file.
|
||||
- If C(state) is present or started then it will wait until the regex
|
||||
matches.
|
||||
- If C(state) is absent then it will wait until the regex does not match.
|
||||
- Defaults to a multiline regex.
|
||||
sleep:
|
||||
description:
|
||||
- Number of seconds to sleep between checks.
|
||||
default: 1
|
||||
state:
|
||||
description:
|
||||
- When checking a port, C(started) will ensure the port is open, C(stopped)
|
||||
will check that is it closed and C(drained) will check for active
|
||||
connections.
|
||||
- When checking for a file or a search string C(present) or C(started) will
|
||||
ensure that the file or string is present, C(absent) will check that the
|
||||
file or search string is absent or removed.
|
||||
default: started
|
||||
choices: [ present, started, stopped, absent, drained ]
|
||||
timeout:
|
||||
description:
|
||||
- The maximum number of seconds to wait for.
|
||||
default: 300
|
||||
author:
|
||||
- Jordan Borean (@jborean93)
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: wait 300 seconds for port 8000 to become open on the host, don't start checking for 10 seconds
|
||||
win_wait_for:
|
||||
port: 8000
|
||||
delay: 10
|
||||
|
||||
- name: wait 150 seconds for port 8000 of any IP to close active connections
|
||||
win_wait_for:
|
||||
host: 0.0.0.0
|
||||
port: 8000
|
||||
state: drained
|
||||
timeout: 150
|
||||
|
||||
- name: wait for port 8000 of any IP to close active connection, ignoring certain hosts
|
||||
win_wait_for:
|
||||
host: 0.0.0.0
|
||||
port: 8000
|
||||
state: drained
|
||||
exclude_hosts: ['10.2.1.2', '10.2.1.3']
|
||||
|
||||
- name: wait for file C:\temp\log.txt to exist before continuing
|
||||
win_wait_for:
|
||||
path: C:\temp\log.txt
|
||||
|
||||
- name: wait until process complete is in the file before continuing
|
||||
win_wait_for:
|
||||
path: C:\temp\log.txt
|
||||
search_regex: process complete
|
||||
|
||||
- name: wait until file if removed
|
||||
win_wait_for:
|
||||
path: C:\temp\log.txt
|
||||
state: absent
|
||||
|
||||
- name: wait until port 1234 is offline but try every 10 seconds
|
||||
win_wait_for:
|
||||
port: 1234
|
||||
state: absent
|
||||
sleep: 10
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
attempts:
|
||||
description: The number of attempts to poll the file or port before module
|
||||
finishes.
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1
|
||||
elapsed:
|
||||
description: The elapsed seconds between the start of poll and the end of the
|
||||
module. This includes the delay if the option is set.
|
||||
returned: always
|
||||
type: float
|
||||
sample: 2.1406487
|
||||
'''
|
0
test/integration/targets/win_wait_for/aliases
Normal file
0
test/integration/targets/win_wait_for/aliases
Normal file
2
test/integration/targets/win_wait_for/defaults/main.yml
Normal file
2
test/integration/targets/win_wait_for/defaults/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
test_win_wait_for_path: C:\ansible\win_wait_for
|
||||
test_win_wait_for_port: 1234
|
316
test/integration/targets/win_wait_for/tasks/main.yml
Normal file
316
test/integration/targets/win_wait_for/tasks/main.yml
Normal file
|
@ -0,0 +1,316 @@
|
|||
---
|
||||
- name: ensure test folder is deleted for clean slate
|
||||
win_file:
|
||||
path: '{{test_win_wait_for_path}}'
|
||||
state: absent
|
||||
|
||||
- name: ensure test folder exists
|
||||
win_file:
|
||||
path: '{{test_win_wait_for_path}}'
|
||||
state: directory
|
||||
|
||||
- name: template out the test server
|
||||
win_template:
|
||||
src: http-server.ps1
|
||||
dest: '{{test_win_wait_for_path}}\http-server.ps1'
|
||||
|
||||
# invalid arguments
|
||||
- name: fail to set port and path
|
||||
win_wait_for:
|
||||
path: a
|
||||
port: 0
|
||||
register: fail_port_and_path
|
||||
failed_when: fail_port_and_path.msg != 'port and path parameter can not both be passed to win_wait_for'
|
||||
|
||||
- name: fail to set exclude_hosts when state isn't drain
|
||||
win_wait_for:
|
||||
port: 0
|
||||
exclude_hosts: a
|
||||
state: present
|
||||
register: fail_exclude_hosts_not_drained
|
||||
failed_when: fail_exclude_hosts_not_drained.msg != 'exclude_hosts should only be with state=drained'
|
||||
|
||||
- name: fail to set state drained with path
|
||||
win_wait_for:
|
||||
path: a
|
||||
state: drained
|
||||
register: fail_path_drained
|
||||
failed_when: fail_path_drained.msg != 'state=drained should only be used for checking a port in the win_wait_for module'
|
||||
|
||||
- name: fail to set exclude_hosts with path
|
||||
win_wait_for:
|
||||
path: a
|
||||
exclude_hosts: a
|
||||
register: fail_path_exclude_hosts
|
||||
failed_when: fail_path_exclude_hosts.msg != 'exclude_hosts should only be with state=drained'
|
||||
|
||||
- name: fail to set search_regex with port
|
||||
win_wait_for:
|
||||
port: 0
|
||||
search_regex: a
|
||||
register: fail_port_search_regex
|
||||
failed_when: fail_port_search_regex.msg != 'search_regex should by used when checking a string in a file in the win_wait_for module'
|
||||
|
||||
- name: fail to set exclude_hosts with port whens tate is not drained
|
||||
win_wait_for:
|
||||
port: 0
|
||||
exclude_hosts: a
|
||||
state: present
|
||||
register: fail_port_exclude_hosts_not_drained
|
||||
failed_when: fail_port_exclude_hosts_not_drained.msg != 'exclude_hosts should only be with state=drained'
|
||||
|
||||
# path tests
|
||||
- name: timeout while waiting for file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: present
|
||||
timeout: 5
|
||||
register: fail_timeout_file_present
|
||||
ignore_errors: True
|
||||
|
||||
- name: assert timeout while waiting for file
|
||||
assert:
|
||||
that:
|
||||
- fail_timeout_file_present.msg == 'timeout while waiting for file ' + test_win_wait_for_path + '\\test.txt to be present'
|
||||
- fail_timeout_file_present.attempts == 5
|
||||
- fail_timeout_file_present.elapsed > 5
|
||||
|
||||
- name: wait for file to not exist - non existing file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
register: wait_remove_no_file
|
||||
|
||||
- name: assert wait for file to not exist - non existing file
|
||||
assert:
|
||||
that:
|
||||
- wait_remove_no_file.attempts == 1
|
||||
|
||||
- name: create file for next test
|
||||
win_file:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: touch
|
||||
|
||||
- name: run async task to remove file after a timeout
|
||||
win_shell: Start-Sleep -Seconds 5; Remove-Item -Path '{{test_win_wait_for_path}}\test.txt' -Force
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for file to not exist - existing file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
register: wait_remove_existing_file
|
||||
|
||||
- name: assert wait for file to not exist - existing file
|
||||
assert:
|
||||
that:
|
||||
- wait_remove_existing_file.attempts > 1
|
||||
|
||||
- name: run async task to create file after a timeout
|
||||
win_shell: Start-Sleep -Seconds 5; New-Item -Path '{{test_win_wait_for_path}}\test.txt' -Type File
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for file to exist - non existing file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: present
|
||||
register: wait_new_missing_file
|
||||
|
||||
- name: assert wait for file to exist - non existing file
|
||||
assert:
|
||||
that:
|
||||
- wait_new_missing_file.attempts > 1
|
||||
|
||||
- name: wait for file to exist - existing file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: present
|
||||
register: wait_new_existing_file
|
||||
|
||||
- name: assert wait for file to exist - existing file
|
||||
assert:
|
||||
that:
|
||||
- wait_new_existing_file.attempts == 1
|
||||
|
||||
- name: timeout while waiting for file to not exist
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
timeout: 5
|
||||
register: fail_timeout_file_absent
|
||||
ignore_errors: True
|
||||
|
||||
- name: assert timeout while waiting for file to not exist
|
||||
assert:
|
||||
that:
|
||||
- fail_timeout_file_absent.msg == 'timeout while waiting for file ' + test_win_wait_for_path + '\\test.txt to be absent'
|
||||
- fail_timeout_file_absent.attempts == 5
|
||||
- fail_timeout_file_absent.elapsed > 5
|
||||
|
||||
- name: run async task to populate file contents
|
||||
win_shell: Start-Sleep -Seconds 5; Set-Content -Path '{{test_win_wait_for_path}}\test.txt' -Value 'hello world`r`nfile contents`r`nEnd line'
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for file contents to match regex - empty file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: present
|
||||
search_regex: file c.*
|
||||
register: wait_regex_match_new
|
||||
|
||||
- name: assert wait for file contents to match regex - empty file
|
||||
assert:
|
||||
that:
|
||||
- wait_regex_match_new.attempts > 1
|
||||
|
||||
- name: wait for file contents to match regex - existing file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: present
|
||||
search_regex: file c.*
|
||||
register: wait_regex_match_existing
|
||||
|
||||
- name: assert wait for file contents to match regex - existing file
|
||||
assert:
|
||||
that:
|
||||
- wait_regex_match_existing.attempts == 1
|
||||
|
||||
- name: run async task to clear file contents
|
||||
win_shell: Start-Sleep -Seconds 5; Set-Content -Path '{{test_win_wait_for_path}}\test.txt' -Value 'hello world`r`nother contents for file`r`nEnd line'
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for file content to not match regex
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
search_regex: file c.*
|
||||
register: wait_regex_match_absent_remove
|
||||
|
||||
- name: assert wait for file content to not match regex
|
||||
assert:
|
||||
that:
|
||||
- wait_regex_match_absent_remove.attempts > 1
|
||||
|
||||
- name: wait for file content to not match regex - existing
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
search_regex: file c.*
|
||||
register: wait_regex_match_absent_existing
|
||||
|
||||
- name: assert wait for file content to not match regex
|
||||
assert:
|
||||
that:
|
||||
- wait_regex_match_absent_existing.attempts == 1
|
||||
|
||||
- name: remove file to test search_regex works on missing files
|
||||
win_file:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
|
||||
- name: wait for file content to not match regex - missing file
|
||||
win_wait_for:
|
||||
path: '{{test_win_wait_for_path}}\test.txt'
|
||||
state: absent
|
||||
search_regex: file c.*
|
||||
register: wait_regex_match_absent_missing
|
||||
|
||||
- name: assert wait for file content to not match regex - missing file
|
||||
assert:
|
||||
that:
|
||||
- wait_regex_match_absent_missing.attempts == 1
|
||||
|
||||
# port tests
|
||||
- name: timeout waiting for port to come online
|
||||
win_wait_for:
|
||||
port: '{{test_win_wait_for_port}}'
|
||||
timeout: 5
|
||||
state: started
|
||||
register: fail_timeout_port_online
|
||||
ignore_errors: True
|
||||
|
||||
- name: assert timeout while waiting for port to come online
|
||||
assert:
|
||||
that:
|
||||
- "fail_timeout_port_online.msg == 'timeout while waiting for 127.0.0.1:' + test_win_wait_for_port|string + ' to start listening'"
|
||||
- fail_timeout_port_online.attempts > 1
|
||||
- fail_timeout_port_online.elapsed > 5
|
||||
|
||||
- name: run async task to start web server
|
||||
win_shell: Start-Sleep -Seconds 5; {{test_win_wait_for_path}}\http-server.ps1
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for port to come online
|
||||
win_wait_for:
|
||||
port: '{{test_win_wait_for_port}}'
|
||||
state: started
|
||||
register: wait_for_port_to_start
|
||||
|
||||
- name: assert wait for port to come online
|
||||
assert:
|
||||
that:
|
||||
- wait_for_port_to_start.attempts > 1
|
||||
|
||||
- name: start web server
|
||||
win_shell: '{{test_win_wait_for_path}}\http-server.ps1'
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for port that is already online
|
||||
win_wait_for:
|
||||
port: '{{test_win_wait_for_port}}'
|
||||
state: started
|
||||
register: wait_for_port_already_started
|
||||
|
||||
- name: assert wait for port that is already online
|
||||
assert:
|
||||
that:
|
||||
- wait_for_port_already_started.attempts == 1
|
||||
|
||||
- name: wait for port that is already offline
|
||||
win_wait_for:
|
||||
port: '{{test_win_wait_for_port}}'
|
||||
state: stopped
|
||||
register: wait_for_port_already_stopped
|
||||
|
||||
- name: assert wait for port that is already offline
|
||||
assert:
|
||||
that:
|
||||
- wait_for_port_already_stopped.attempts == 1
|
||||
|
||||
- name: start web server for offline port test
|
||||
win_shell: '{{test_win_wait_for_path}}\http-server.ps1'
|
||||
async: 30
|
||||
poll: 0
|
||||
|
||||
- name: wait for port to go offline
|
||||
win_wait_for:
|
||||
port: '{{test_win_wait_for_port}}'
|
||||
state: stopped
|
||||
register: wait_for_port_to_be_stopped
|
||||
|
||||
- name: assert wait for port to go offline
|
||||
assert:
|
||||
that:
|
||||
- wait_for_port_to_be_stopped.attempts > 1
|
||||
|
||||
- name: wait for offline port to be drained
|
||||
win_wait_for:
|
||||
port: '{{test_win_wait_for_port}}'
|
||||
state: drained
|
||||
register: wait_for_drained_port_no_port
|
||||
|
||||
- name: assert wait for offline port to be drained
|
||||
assert:
|
||||
that:
|
||||
- wait_for_drained_port_no_port.attempts == 1
|
||||
|
||||
- name: clear testing folder
|
||||
win_file:
|
||||
path: '{{test_win_wait_for_path}}'
|
||||
state: absent
|
|
@ -0,0 +1,22 @@
|
|||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$port = {{test_win_wait_for_port}}
|
||||
|
||||
$endpoint = New-Object -TypeName System.Net.IPEndPoint([System.Net.IPAddress]::Parse("0.0.0.0"), $port)
|
||||
$listener = New-Object -TypeName System.Net.Sockets.TcpListener($endpoint)
|
||||
$listener.Server.ReceiveTimeout = 3000
|
||||
$listener.Start()
|
||||
|
||||
try {
|
||||
while ($true) {
|
||||
if (-not $listener.Pending()) {
|
||||
Start-Sleep -Seconds 1
|
||||
} else {
|
||||
$client = $listener.AcceptTcpClient()
|
||||
$client.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
$listener.Stop()
|
||||
}
|
Loading…
Reference in a new issue