diff options
author | Matt Davis <nitzmahone@users.noreply.github.com> | 2016-09-06 17:38:12 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-06 17:38:12 -0700 |
commit | f239e1e61f71e23300ce64e320c7962a1ba2ad8b (patch) | |
tree | b5971a1da2773f6f0afb37a671e3207c50625258 /test/integration | |
parent | 056a7cb957ab649e5facb9a3047727d04595de3b (diff) | |
download | ansible-f239e1e61f71e23300ce64e320c7962a1ba2ad8b.tar.gz |
windows async changes and tests (#17400)
Diffstat (limited to 'test/integration')
3 files changed, 245 insertions, 0 deletions
diff --git a/test/integration/roles/test_win_async_wrapper/library/async_test.ps1 b/test/integration/roles/test_win_async_wrapper/library/async_test.ps1 new file mode 100644 index 0000000000..3b891b9fac --- /dev/null +++ b/test/integration/roles/test_win_async_wrapper/library/async_test.ps1 @@ -0,0 +1,57 @@ +#!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 <http://www.gnu.org/licenses/>. + +# WANT_JSON +# POWERSHELL_COMMON + +$parsed_args = Parse-Args $args + +$sleep_delay_sec = Get-AnsibleParam $parsed_args "sleep_delay_sec" -default 0 +$fail_mode = Get-AnsibleParam $parsed_args "fail_mode" -default "success" -validateset "success","graceful","exception" + +If($fail_mode -isnot [array]) { + $fail_mode = @($fail_mode) +} + +$result = @{changed=$true; module_pid=$pid; module_tempdir=$PSScriptRoot} + +If($sleep_delay_sec -gt 0) { + Sleep -Seconds $sleep_delay_sec + $result["slept_sec"] = $sleep_delay_sec +} + +If($fail_mode -contains "leading_junk") { + Write-Output "leading junk before module output" +} + +Try { + + If($fail_mode -contains "graceful") { + Fail-Json $result "failed gracefully" + } + + If($fail_mode -eq "exception") { + Throw "failing via exception" + } + + Exit-Json $result +} +Finally +{ + If($fail_mode -contains "trailing_junk") { + Write-Output "trailing junk after module output" + } +} diff --git a/test/integration/roles/test_win_async_wrapper/tasks/main.yml b/test/integration/roles/test_win_async_wrapper/tasks/main.yml new file mode 100644 index 0000000000..d3d24bb753 --- /dev/null +++ b/test/integration/roles/test_win_async_wrapper/tasks/main.yml @@ -0,0 +1,187 @@ +- name: async fire and forget + async_test: + sleep_delay_sec: 5 + async: 20 + poll: 0 + register: asyncresult + +- name: validate response + assert: + that: + - asyncresult.ansible_job_id is match('\d+\.\d+') + - asyncresult.started == 1 + - asyncresult.finished == 0 + - asyncresult.results_file is search('\.ansible_async.+\d+\.\d+') + - asyncresult._suppress_tmpdir_delete == true + +- name: async poll immediate success + async_test: + sleep_delay_sec: 0 + async: 10 + poll: 1 + register: asyncresult + +- name: validate response + assert: + that: + - asyncresult.ansible_job_id is match('\d+\.\d+') + - asyncresult.finished == 1 + - asyncresult.changed == true + - asyncresult.ansible_async_watchdog_pid is number + - asyncresult.module_tempdir is search('ansible-tmp-') + - asyncresult.module_pid is number + +# this part of the test is flaky- Windows PIDs are reused aggressively, so this occasionally fails due to a new process with the same ID +# FUTURE: consider having the test module hook to a kernel object we can poke at that gets signaled/released on exit +#- name: ensure that watchdog and module procs have exited +# raw: Get-Process | Where { $_.Id -in ({{ asyncresult.ansible_async_watchdog_pid }}, {{ asyncresult.module_pid }}) } +# register: proclist +# +#- name: validate no running watchdog/module processes were returned +# assert: +# that: +# - proclist.stdout.strip() == '' + +- name: ensure that module_tempdir was deleted + raw: Test-Path {{ asyncresult.module_tempdir }} + register: tempdircheck + +- name: validate tempdir response + assert: + that: + - tempdircheck.stdout | search('False') + +- name: async poll retry + async_test: + sleep_delay_sec: 5 + async: 10 + poll: 1 + register: asyncresult + +- name: validate response + assert: + that: + - asyncresult.ansible_job_id is match('\d+\.\d+') + - asyncresult.finished == 1 + - asyncresult.changed == true + - asyncresult.module_tempdir is search('ansible-tmp-') + - asyncresult.module_pid is number + +# this part of the test is flaky- Windows PIDs are reused aggressively, so this occasionally fails due to a new process with the same ID +# FUTURE: consider having the test module hook to a kernel object we can poke at that gets signaled/released on exit +#- name: ensure that watchdog and module procs have exited +# raw: Get-Process | Where { $_.Id -in ({{ asyncresult.ansible_async_watchdog_pid }}, {{ asyncresult.module_pid }}) } +# register: proclist +# +#- name: validate no running watchdog/module processes were returned +# assert: +# that: +# - proclist.stdout.strip() == '' + +- name: ensure that module_tempdir was deleted + raw: Test-Path {{ asyncresult.module_tempdir }} + register: tempdircheck + +- name: validate tempdir response + assert: + that: + - tempdircheck.stdout | search('False') + +- name: async poll timeout + async_test: + sleep_delay_sec: 5 + async: 3 + poll: 1 + register: asyncresult + ignore_errors: true + +- name: validate response + assert: + that: + - asyncresult.ansible_job_id is match('\d+\.\d+') + - asyncresult.finished == 1 + - asyncresult.changed == false + - asyncresult | failed == true + - asyncresult.msg is search('timed out') + +- name: async poll graceful module failure + async_test: + fail_mode: graceful + async: 5 + poll: 1 + register: asyncresult + ignore_errors: true + +- name: validate response + assert: + that: + - asyncresult.ansible_job_id is match('\d+\.\d+') + - asyncresult.finished == 1 + - asyncresult.changed == false + - asyncresult | failed == true + - asyncresult.msg == 'failed gracefully' + +- name: async poll exception module failure + async_test: + fail_mode: exception + async: 5 + poll: 1 + register: asyncresult + ignore_errors: true + +- name: validate response + assert: + that: + - asyncresult.ansible_job_id is match('\d+\.\d+') + - asyncresult.finished == 1 + - asyncresult.changed == false + - asyncresult | failed == true + - asyncresult.msg is search('failing via exception') + +- name: loop async success + async_test: + sleep_delay_sec: 3 + async: 10 + poll: 0 + with_sequence: start=1 end=4 + register: async_many + +- name: wait for completion + async_status: + jid: "{{ item }}" + register: asyncout + until: asyncout.finished == 1 + retries: 10 + delay: 1 + with_items: "{{ async_many.results | map(attribute='ansible_job_id') | list }}" + +- name: validate results + assert: + that: + - item.finished == 1 + - item.slept_sec == 3 + - item.changed == true + - item.ansible_job_id is match('\d+\.\d+') + with_items: "{{ asyncout.results }}" + +# this part of the test is flaky- Windows PIDs are reused aggressively, so this occasionally fails due to a new process with the same ID +# FUTURE: consider having the test module hook to a kernel object we can poke at that gets signaled/released on exit +#- name: ensure that all watchdog and module procs have exited +# raw: Get-Process | Where { $_.Id -in ({{ asyncout.results | join(',', attribute='ansible_async_watchdog_pid') }}, {{ asyncout.results | join(',', attribute='module_pid') }}) } +# register: proclist +# +#- name: validate no processes were returned +# assert: +# that: +# - proclist.stdout.strip() == "" + +# FUTURE: test junk before/after JSON +# FUTURE: verify tempdir stays through module exec +# FUTURE: verify tempdir is deleted after module exec +# FUTURE: verify tempdir is permanent with ANSIBLE_KEEP_REMOTE_FILES=1 (how?) +# FUTURE: verify binary modules work + +# FUTURE: test status/return +# FUTURE: test status/cleanup +# FUTURE: test reboot/connection failure +# FUTURE: figure out how to ensure that processes and tempdirs are cleaned up in all exceptional cases diff --git a/test/integration/test_win_group3.yml b/test/integration/test_win_group3.yml index f8bcdcd780..7ade0cb122 100644 --- a/test/integration/test_win_group3.yml +++ b/test/integration/test_win_group3.yml @@ -4,3 +4,4 @@ - { role: test_win_service, tags: test_win_service } - { role: test_win_feature, tags: test_win_feature } - { role: test_win_user, tags: test_win_user } + - { role: test_win_async_wrapper, tags: test_win_async_wrapper } |