diff options
author | Matt Clay <matt@mystile.com> | 2016-10-13 10:03:19 -0700 |
---|---|---|
committer | John R Barker <john@johnrbarker.com> | 2016-10-13 18:03:19 +0100 |
commit | c2ec86cb78f3c43bc5f2484d1888571e27225702 (patch) | |
tree | 43602995d1b5b009de1e1d4a7bc1a835f60204b7 /test/integration/targets | |
parent | 9182619fef4151d04d28b30b8a6f33e469560f5f (diff) | |
download | ansible-c2ec86cb78f3c43bc5f2484d1888571e27225702.tar.gz |
Migrate Windows CI roles to test targets. (#18005)
Diffstat (limited to 'test/integration/targets')
77 files changed, 4965 insertions, 0 deletions
diff --git a/test/integration/targets/prepare_win_tests/meta/main.yml b/test/integration/targets/prepare_win_tests/meta/main.yml new file mode 100644 index 0000000000..cf5427b608 --- /dev/null +++ b/test/integration/targets/prepare_win_tests/meta/main.yml @@ -0,0 +1,3 @@ +--- + +allow_duplicates: yes diff --git a/test/integration/targets/prepare_win_tests/tasks/main.yml b/test/integration/targets/prepare_win_tests/tasks/main.yml new file mode 100644 index 0000000000..756c977fb1 --- /dev/null +++ b/test/integration/targets/prepare_win_tests/tasks/main.yml @@ -0,0 +1,30 @@ +# test code for the windows versions of copy, file and template module +# originally +# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com> + +# 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/>. + + +- name: clean out the test directory + win_file: name={{win_output_dir|mandatory}} state=absent + tags: + - prepare + +- name: create the test directory + win_file: name={{win_output_dir}} state=directory + tags: + - prepare + diff --git a/test/integration/targets/win_async_wrapper/library/async_test.ps1 b/test/integration/targets/win_async_wrapper/library/async_test.ps1 new file mode 100644 index 0000000000..3b891b9fac --- /dev/null +++ b/test/integration/targets/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/targets/win_async_wrapper/tasks/main.yml b/test/integration/targets/win_async_wrapper/tasks/main.yml new file mode 100644 index 0000000000..3ca0f3e7b9 --- /dev/null +++ b/test/integration/targets/win_async_wrapper/tasks/main.yml @@ -0,0 +1,189 @@ +- 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') + + +# this test is only flaky under shippable/AWS- the last iteration "until's" forever, cannot repro locally +#- 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/targets/win_command/tasks/main.yml b/test/integration/targets/win_command/tasks/main.yml new file mode 100644 index 0000000000..98f39b3c27 --- /dev/null +++ b/test/integration/targets/win_command/tasks/main.yml @@ -0,0 +1,134 @@ +- name: execute a command + win_command: whoami /groups + register: cmdout + +- name: validate result + assert: + that: + - cmdout|success + - cmdout|changed + - cmdout.cmd == 'whoami /groups' + - cmdout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$') + - cmdout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - cmdout.rc == 0 + - cmdout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - cmdout.stderr == "" + - cmdout.stdout is search('GROUP INFORMATION') + - '"GROUP INFORMATION" in cmdout.stdout_lines' + - cmdout.warnings == [] + +- name: execute something nonexistent + win_command: bogus_command1234 + register: cmdout + ignore_errors: true + +- name: validate result + assert: + that: + - cmdout|failed + - not cmdout|changed + - cmdout.cmd == 'bogus_command1234' + - cmdout.rc == 2 + - cmdout.msg is search('cannot find the file specified') + +- name: execute something with error output + win_command: cmd /c "echo some output & echo some error 1>&2" + register: cmdout + +- name: validate result + assert: + that: + - cmdout|success + - cmdout|changed + - cmdout.cmd == 'cmd /c "echo some output & echo some error 1>&2"' + - cmdout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$') + - cmdout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - cmdout.rc == 0 + - cmdout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - cmdout.stderr is search('some error') + - cmdout.stdout == "some output \r\n" + - cmdout.stdout_lines == ["some output "] + - cmdout.warnings == [] + +- name: ensure test file is absent + win_file: + path: c:\testfile.txt + state: absent + +- name: run with creates, should create + win_command: cmd /c "echo $null >> c:\testfile.txt" + args: + creates: c:\testfile.txt + register: cmdout + +- name: validate result + assert: + that: + - cmdout|success + - cmdout|changed + +- name: run again with creates, should skip + win_command: cmd /c "echo $null >> c:\testfile.txt" + args: + creates: c:\testfile.txt + register: cmdout + +- name: validate result + assert: + that: + - cmdout|skipped + - cmdout.msg is search('exists') + +- name: ensure testfile is still present + win_stat: + path: c:\testfile.txt + register: statout + +- name: validate result + assert: + that: + - statout.stat.exists == true + +- name: run with removes, should remove + win_command: cmd /c "del c:\testfile.txt" + args: + removes: c:\testfile.txt + register: cmdout + +- name: validate result + assert: + that: + - cmdout|success + - cmdout|changed + +- name: run again with removes, should skip + win_command: cmd /c "del c:\testfile.txt" + args: + removes: c:\testfile.txt + register: cmdout + +- name: validate result + assert: + that: + - cmdout|skipped + - cmdout.msg is search('does not exist') + +- name: run something with known nonzero exit code + win_command: cmd /c "exit 254" + register: cmdout + ignore_errors: true + +- name: validate result + assert: + that: + - cmdout|failed + - cmdout.rc == 254 + +- name: write large buffer to stdout + win_command: powershell /c "$ba = New-Object byte[] 16384; (New-Object System.Random 32).NextBytes($ba); [Convert]::ToBase64String($ba) | Write-Output" + register: cmdout + +# TODO: fix small buffer deadlock on large write to stderr before stdout has been consumed +#- name: write large buffer to stderr +# win_shell: $ba = New-Object byte[] 16384; (New-Object System.Random 32).NextBytes($ba); [Convert]::ToBase64String($ba) | Write-Error; Write-Output test +# register: cmdout
\ No newline at end of file diff --git a/test/integration/targets/win_copy/files/empty.txt b/test/integration/targets/win_copy/files/empty.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/integration/targets/win_copy/files/empty.txt diff --git a/test/integration/targets/win_copy/files/foo.txt b/test/integration/targets/win_copy/files/foo.txt new file mode 100644 index 0000000000..7c6ded14ec --- /dev/null +++ b/test/integration/targets/win_copy/files/foo.txt @@ -0,0 +1 @@ +foo.txt diff --git a/test/integration/targets/win_copy/files/subdir/bar.txt b/test/integration/targets/win_copy/files/subdir/bar.txt new file mode 100644 index 0000000000..76018072e0 --- /dev/null +++ b/test/integration/targets/win_copy/files/subdir/bar.txt @@ -0,0 +1 @@ +baz diff --git a/test/integration/targets/win_copy/files/subdir/subdir2/baz.txt b/test/integration/targets/win_copy/files/subdir/subdir2/baz.txt new file mode 100644 index 0000000000..76018072e0 --- /dev/null +++ b/test/integration/targets/win_copy/files/subdir/subdir2/baz.txt @@ -0,0 +1 @@ +baz diff --git a/test/integration/targets/win_copy/files/subdir/subdir2/subdir3/subdir4/qux.txt b/test/integration/targets/win_copy/files/subdir/subdir2/subdir3/subdir4/qux.txt new file mode 100644 index 0000000000..78df5b06bd --- /dev/null +++ b/test/integration/targets/win_copy/files/subdir/subdir2/subdir3/subdir4/qux.txt @@ -0,0 +1 @@ +qux
\ No newline at end of file diff --git a/test/integration/targets/win_copy/meta/main.yml b/test/integration/targets/win_copy/meta/main.yml new file mode 100644 index 0000000000..55200b3fc6 --- /dev/null +++ b/test/integration/targets/win_copy/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_win_tests + diff --git a/test/integration/targets/win_copy/tasks/main.yml b/test/integration/targets/win_copy/tasks/main.yml new file mode 100644 index 0000000000..f23ebf6350 --- /dev/null +++ b/test/integration/targets/win_copy/tasks/main.yml @@ -0,0 +1,296 @@ +# test code for the copy module and action plugin +# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com> + +# 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/>. + +- name: record the output directory + set_fact: output_file={{win_output_dir}}/foo.txt + +- name: copy an empty file + win_copy: + src: empty.txt + dest: "{{win_output_dir}}/empty.txt" + register: copy_empty_result + +- name: check copy empty result + assert: + that: + - copy_empty_result|changed + - copy_empty_result.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' + +- name: stat the empty file + win_stat: + path: "{{win_output_dir}}/empty.txt" + register: stat_empty_result + +- name: check that empty file really was created + assert: + that: + - stat_empty_result.stat.exists + - stat_empty_result.stat.size == 0 + +- name: copy an empty file again + win_copy: + src: empty.txt + dest: "{{win_output_dir}}/empty.txt" + register: copy_empty_again_result + +- name: check copy empty again result + assert: + that: + - not copy_empty_again_result|changed + - copy_empty_again_result.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' + +- name: initiate a basic copy +#- name: initiate a basic copy, and also test the mode +# win_copy: src=foo.txt dest={{output_file}} mode=0444 + win_copy: src=foo.txt dest={{output_file}} + register: copy_result + +- debug: var=copy_result + +#- name: check the presence of the output file +- name: check the mode of the output file + win_file: name={{output_file}} state=file + register: file_result_check + +- debug: var=file_result_check + + +#- name: assert the mode is correct +# assert: +# that: +# - "file_result_check.mode == '0444'" + +- name: assert basic copy worked + assert: + that: + - "'changed' in copy_result" +# - "'dest' in copy_result" +# - "'group' in copy_result" +# - "'gid' in copy_result" + - "'checksum' in copy_result" +# - "'owner' in copy_result" +# - "'size' in copy_result" +# - "'src' in copy_result" +# - "'state' in copy_result" +# - "'uid' in copy_result" + +- name: verify that the file was marked as changed + assert: + that: + - "copy_result.changed == true" + +- name: verify that the file checksum is correct + assert: + that: + - "copy_result.checksum == 'c79a6506c1c948be0d456ab5104d5e753ab2f3e6'" + +- name: check the stat results of the file + win_stat: path={{output_file}} + register: stat_results + +- debug: var=stat_results + +- name: assert the stat results are correct + assert: + that: + - "stat_results.stat.exists == true" +# - "stat_results.stat.isblk == false" +# - "stat_results.stat.isfifo == false" +# - "stat_results.stat.isreg == true" +# - "stat_results.stat.issock == false" + - "stat_results.stat.checksum == 'c79a6506c1c948be0d456ab5104d5e753ab2f3e6'" + +- name: overwrite the file via same means + win_copy: src=foo.txt dest={{output_file}} + register: copy_result2 + +- name: assert that the file was not changed + assert: + that: + - "not copy_result2|changed" + +# content system not available in win_copy right now +#- name: overwrite the file using the content system +# win_copy: content="modified" dest={{output_file}} +# register: copy_result3 +# +#- name: assert that the file has changed +# assert: +# that: +# - "copy_result3|changed" +# - "'content' not in copy_result3" + +# test recursive copy + +- name: set the output subdirectory + set_fact: output_subdir={{win_output_dir}}/sub/ + +- name: make an output subdirectory + win_file: name={{output_subdir}} state=directory + +- name: test recursive copy to directory +# win_copy: src=subdir dest={{output_subdir}} directory_mode=0700 + win_copy: src=subdir dest={{output_subdir}} + register: recursive_copy_result + +- debug: var=recursive_copy_result + +- name: check that a file in a directory was transferred + win_stat: path={{win_output_dir}}/sub/subdir/bar.txt + register: stat_bar + +- name: check that a file in a deeper directory was transferred + win_stat: path={{win_output_dir}}/sub/subdir/subdir2/baz.txt + register: stat_bar2 + +- name: check that a file in a directory whose parent contains a directory alone was transferred + win_stat: path={{win_output_dir}}/sub/subdir/subdir2/subdir3/subdir4/qux.txt + register: stat_bar3 + +- name: assert recursive copy things + assert: + that: + - "stat_bar.stat.exists" + - "stat_bar2.stat.exists" + - "stat_bar3.stat.exists" + +- name: stat the recursively copied directories + win_stat: path={{win_output_dir}}/sub/{{item}} + register: dir_stats + with_items: + - "subdir" + - "subdir/subdir2" + - "subdir/subdir2/subdir3" + - "subdir/subdir2/subdir3/subdir4" + +# can't check file mode on windows so commenting this one out. +#- name: assert recursive copied directories mode +# assert: +# that: +# - "{{item.stat.mode}} == 0700" +# with_items: "{{dir_stats.results}}" + + +# errors on this aren't presently ignored so this test is commented out. But it would be nice to fix. +# + +# content param not available in win_copy +#- name: overwrite the file again using the content system, also passing along file params +# win_copy: content="modified" dest={{output_file}} +# register: copy_result4 + +#- name: assert invalid copy input location fails +# win_copy: src=invalid_file_location_does_not_exist dest={{win_output_dir}}/file.txt +# ignore_errors: True +# register: failed_copy + +# owner not available in win_copy, commenting out +#- name: copy already copied directory again +# win_copy: src=subdir dest={{output_subdir | expanduser}} owner={{ansible_ssh_user}} +# register: copy_result5 + +#- name: assert that the directory was not changed +# assert: +# that: +# - "not copy_result5|changed" + +# content not available in win_copy, commenting out. +# issue 8394 +#- name: create a file with content and a literal multiline block +# win_copy: | +# content='this is the first line +# this is the second line +# +# this line is after an empty line +# this line is the last line +# ' +# dest={{win_output_dir}}/multiline.txt +# register: copy_result6 + +#- debug: var=copy_result6 + +#- name: assert the multiline file was created correctly +# assert: +# that: +# - "copy_result6.changed" +# - "copy_result6.dest == '{{win_output_dir|expanduser}}/multiline.txt'" +# - "copy_result6.checksum == '1627d51e7e607c92cf1a502bf0c6cce3'" + +# test overwriting a file as an unprivileged user (pull request #8624) +# this can't be relative to {{win_output_dir}} as ~root usually has mode 700 + +#- name: create world writable directory + #win_file: dest=/tmp/worldwritable state=directory mode=0777 + +#- name: create world writable file +# win_copy: dest=/tmp/worldwritable/file.txt content="bar" mode=0666 + +#- name: overwrite the file as user nobody +# win_copy: dest=/tmp/worldwritable/file.txt content="baz" +# become: yes +# become_user: nobody +# register: copy_result7 + +#- name: assert the file was overwritten +# assert: +# that: +# - "copy_result7.changed" +# - "copy_result7.dest == '/tmp/worldwritable/file.txt'" +# - "copy_result7.checksum == '73feffa4b7f6bb68e44cf984c85f6e88'" + +#- name: clean up +# win_file: dest=/tmp/worldwritable state=absent + +# test overwritting a link using "follow=yes" so that the link +# is preserved and the link target is updated + +#- name: create a test file to symlink to +# win_copy: dest={{win_output_dir}}/follow_test content="this is the follow test file\n" +# +#- name: create a symlink to the test file +# win_file: path={{win_output_dir}}/follow_link src='./follow_test' state=link +# +#- name: update the test file using follow=True to preserve the link +# win_copy: dest={{win_output_dir}}/follow_link content="this is the new content\n" follow=yes +# register: replace_follow_result + +#- name: stat the link path +# win_stat: path={{win_output_dir}}/follow_link +# register: stat_link_result +# +#- name: assert that the link is still a link +# assert: +# that: +# - stat_link_result.stat.islnk +# +#- name: get the md5 of the link target +# shell: checksum {{win_output_dir}}/follow_test | cut -f1 -sd ' ' +# register: target_file_result + +#- name: assert that the link target was updated +# assert: +# that: +# - replace_follow_result.checksum == target_file_result.stdout + +- name: clean up sub + win_file: path={{win_output_dir}}/sub state=absent + +- name: clean up foo.txt + win_file: path={{win_output_dir}}/foo.txt state=absent + + diff --git a/test/integration/targets/win_feature/defaults/main.yml b/test/integration/targets/win_feature/defaults/main.yml new file mode 100644 index 0000000000..e1833cd8a8 --- /dev/null +++ b/test/integration/targets/win_feature/defaults/main.yml @@ -0,0 +1,4 @@ +--- + +# Feature not normally installed by default. +test_win_feature_name: Telnet-Client diff --git a/test/integration/targets/win_feature/tasks/main.yml b/test/integration/targets/win_feature/tasks/main.yml new file mode 100644 index 0000000000..4b31f8b358 --- /dev/null +++ b/test/integration/targets/win_feature/tasks/main.yml @@ -0,0 +1,149 @@ +# test code for the win_feature module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + + +- name: check whether servermanager module is available (windows 2008 r2 or later) + raw: PowerShell -Command Import-Module ServerManager + register: win_feature_has_servermanager + ignore_errors: true + +- name: start with feature absent + win_feature: + name: "{{ test_win_feature_name }}" + state: absent + when: win_feature_has_servermanager|success + +- name: install feature + win_feature: + name: "{{ test_win_feature_name }}" + state: present + restart: no + include_sub_features: yes + include_management_tools: yes + register: win_feature_install_result + when: win_feature_has_servermanager|success + +- name: check result of installing feature + assert: + that: + - "win_feature_install_result|changed" + - "win_feature_install_result.success" + - "win_feature_install_result.exitcode == 'Success'" + - "not win_feature_install_result.restart_needed" + - "win_feature_install_result.feature_result|length == 1" + - "win_feature_install_result.feature_result[0].id" + - "win_feature_install_result.feature_result[0].display_name" + - "win_feature_install_result.feature_result[0].message is defined" + - "win_feature_install_result.feature_result[0].restart_needed is defined" + - "win_feature_install_result.feature_result[0].skip_reason" + - "win_feature_install_result.feature_result[0].success is defined" + when: win_feature_has_servermanager|success + +- name: install feature again + win_feature: + name: "{{ test_win_feature_name }}" + state: present + restart: no + include_sub_features: yes + include_management_tools: yes + register: win_feature_install_again_result + when: win_feature_has_servermanager|success + +- name: check result of installing feature again + assert: + that: + - "not win_feature_install_again_result|changed" + - "win_feature_install_again_result.success" + - "win_feature_install_again_result.exitcode == 'NoChangeNeeded'" + - "not win_feature_install_again_result.restart_needed" + - "win_feature_install_again_result.feature_result == []" + when: win_feature_has_servermanager|success + +- name: remove feature + win_feature: + name: "{{ test_win_feature_name }}" + state: absent + register: win_feature_remove_result + when: win_feature_has_servermanager|success + +- name: check result of removing feature + assert: + that: + - "win_feature_remove_result|changed" + - "win_feature_remove_result.success" + - "win_feature_remove_result.exitcode == 'Success'" + - "not win_feature_remove_result.restart_needed" + - "win_feature_remove_result.feature_result|length == 1" + - "win_feature_remove_result.feature_result[0].id" + - "win_feature_remove_result.feature_result[0].display_name" + - "win_feature_remove_result.feature_result[0].message is defined" + - "win_feature_remove_result.feature_result[0].restart_needed is defined" + - "win_feature_remove_result.feature_result[0].skip_reason" + - "win_feature_remove_result.feature_result[0].success is defined" + when: win_feature_has_servermanager|success + +- name: remove feature again + win_feature: + name: "{{ test_win_feature_name }}" + state: absent + register: win_feature_remove_again_result + when: win_feature_has_servermanager|success + +- name: check result of removing feature again + assert: + that: + - "not win_feature_remove_again_result|changed" + - "win_feature_remove_again_result.success" + - "win_feature_remove_again_result.exitcode == 'NoChangeNeeded'" + - "not win_feature_remove_again_result.restart_needed" + - "win_feature_remove_again_result.feature_result == []" + when: win_feature_has_servermanager|success + +- name: try to install an invalid feature name + win_feature: + name: "Microsoft-Bob" + state: present + register: win_feature_install_invalid_result + ignore_errors: true + when: win_feature_has_servermanager|success + +- name: check result of installing invalid feature name + assert: + that: + - "win_feature_install_invalid_result|failed" + - "not win_feature_install_invalid_result|changed" + - "win_feature_install_invalid_result.msg" + - "win_feature_install_invalid_result.exitcode == 'InvalidArgs'" + when: win_feature_has_servermanager|success + +- name: try to remove an invalid feature name + win_feature: + name: "Microsoft-Bob" + state: absent + register: win_feature_remove_invalid_result + ignore_errors: true + when: win_feature_has_servermanager|success + +- name: check result of removing invalid feature name + assert: + that: + - "win_feature_remove_invalid_result|failed" + - "not win_feature_remove_invalid_result|changed" + - "win_feature_remove_invalid_result.msg" + - "win_feature_remove_invalid_result.exitcode == 'InvalidArgs'" + when: win_feature_has_servermanager|success diff --git a/test/integration/targets/win_fetch/tasks/main.yml b/test/integration/targets/win_fetch/tasks/main.yml new file mode 100644 index 0000000000..f8b1865744 --- /dev/null +++ b/test/integration/targets/win_fetch/tasks/main.yml @@ -0,0 +1,167 @@ +# test code for the fetch module when using winrm connection +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: clean out the test directory + local_action: file name={{ output_dir|mandatory }} state=absent + run_once: true + +- name: create the test directory + local_action: file name={{ output_dir }} state=directory + run_once: true + +- name: fetch a small file + fetch: src="C:/Windows/win.ini" dest={{ output_dir }} + register: fetch_small + +- name: check fetch small result + assert: + that: + - "fetch_small.changed" + +- name: check file created by fetch small + local_action: stat path={{ fetch_small.dest }} + register: fetch_small_stat + +- name: verify fetched small file exists locally + assert: + that: + - "fetch_small_stat.stat.exists" + - "fetch_small_stat.stat.isreg" + - "fetch_small_stat.stat.md5 == fetch_small.md5sum" + +- name: fetch the same small file + fetch: src="C:/Windows/win.ini" dest={{ output_dir }} + register: fetch_small_again + +- name: check fetch small result again + assert: + that: + - "not fetch_small_again.changed" + +- name: fetch a small file to flat namespace + fetch: src="C:/Windows/win.ini" dest="{{ output_dir }}/" flat=yes + register: fetch_flat + +- name: check fetch flat result + assert: + that: + - "fetch_flat.changed" + +- name: check file created by fetch flat + local_action: stat path="{{ output_dir }}/win.ini" + register: fetch_flat_stat + +- name: verify fetched file exists locally in output_dir + assert: + that: + - "fetch_flat_stat.stat.exists" + - "fetch_flat_stat.stat.isreg" + - "fetch_flat_stat.stat.md5 == fetch_flat.md5sum" + +#- name: fetch a small file to flat directory (without trailing slash) +# fetch: src="C:/Windows/win.ini" dest="{{ output_dir }}" flat=yes +# register: fetch_flat_dir + +#- name: check fetch flat to directory result +# assert: +# that: +# - "not fetch_flat_dir|changed" + +- name: fetch a large binary file + fetch: src="C:/Windows/explorer.exe" dest={{ output_dir }} + register: fetch_large + +- name: check fetch large binary file result + assert: + that: + - "fetch_large.changed" + +- name: check file created by fetch large binary + local_action: stat path={{ fetch_large.dest }} + register: fetch_large_stat + +- name: verify fetched large file exists locally + assert: + that: + - "fetch_large_stat.stat.exists" + - "fetch_large_stat.stat.isreg" + - "fetch_large_stat.stat.md5 == fetch_large.md5sum" + +- name: fetch a large binary file again + fetch: src="C:/Windows/explorer.exe" dest={{ output_dir }} + register: fetch_large_again + +- name: check fetch large binary file result again + assert: + that: + - "not fetch_large_again.changed" + +- name: fetch a small file using backslashes in src path + fetch: src="C:\\Windows\\system.ini" dest={{ output_dir }} + register: fetch_small_bs + +- name: check fetch small result with backslashes + assert: + that: + - "fetch_small_bs.changed" + +- name: check file created by fetch small with backslashes + local_action: stat path={{ fetch_small_bs.dest }} + register: fetch_small_bs_stat + +- name: verify fetched small file with backslashes exists locally + assert: + that: + - "fetch_small_bs_stat.stat.exists" + - "fetch_small_bs_stat.stat.isreg" + - "fetch_small_bs_stat.stat.md5 == fetch_small_bs.md5sum" + +- name: attempt to fetch a non-existent file - do not fail on missing + fetch: src="C:/this_file_should_not_exist.txt" dest={{ output_dir }} + register: fetch_missing_nofail + +- name: check fetch missing no fail result + assert: + that: + - "not fetch_missing_nofail|failed" + - "fetch_missing_nofail.msg" + - "not fetch_missing_nofail|changed" + +- name: attempt to fetch a non-existent file - fail on missing + fetch: src="~/this_file_should_not_exist.txt" dest={{ output_dir }} fail_on_missing=yes + register: fetch_missing + ignore_errors: true + +- name: check fetch missing with failure + assert: + that: + - "fetch_missing|failed" + - "fetch_missing.msg" + - "not fetch_missing|changed" + +- name: attempt to fetch a directory + fetch: src="C:\\Windows" dest={{ output_dir }} + register: fetch_dir + ignore_errors: true + +- name: check fetch directory result + assert: + that: + # Doesn't fail anymore, only returns a message. + - "not fetch_dir|changed" + - "fetch_dir.msg" diff --git a/test/integration/targets/win_file/files/foo.txt b/test/integration/targets/win_file/files/foo.txt new file mode 100644 index 0000000000..7c6ded14ec --- /dev/null +++ b/test/integration/targets/win_file/files/foo.txt @@ -0,0 +1 @@ +foo.txt diff --git a/test/integration/targets/win_file/files/foobar/directory/fileC b/test/integration/targets/win_file/files/foobar/directory/fileC new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/integration/targets/win_file/files/foobar/directory/fileC diff --git a/test/integration/targets/win_file/files/foobar/directory/fileD b/test/integration/targets/win_file/files/foobar/directory/fileD new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/integration/targets/win_file/files/foobar/directory/fileD diff --git a/test/integration/targets/win_file/files/foobar/fileA b/test/integration/targets/win_file/files/foobar/fileA new file mode 100644 index 0000000000..ab47708c98 --- /dev/null +++ b/test/integration/targets/win_file/files/foobar/fileA @@ -0,0 +1 @@ +fileA diff --git a/test/integration/targets/win_file/files/foobar/fileB b/test/integration/targets/win_file/files/foobar/fileB new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/integration/targets/win_file/files/foobar/fileB diff --git a/test/integration/targets/win_file/meta/main.yml b/test/integration/targets/win_file/meta/main.yml new file mode 100644 index 0000000000..55200b3fc6 --- /dev/null +++ b/test/integration/targets/win_file/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_win_tests + diff --git a/test/integration/targets/win_file/tasks/main.yml b/test/integration/targets/win_file/tasks/main.yml new file mode 100644 index 0000000000..674a18f357 --- /dev/null +++ b/test/integration/targets/win_file/tasks/main.yml @@ -0,0 +1,494 @@ +# Test code for the file module. +# (c) 2014, Richard Isaacson <richard.c.isaacson@gmail.com> + +# 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/>. + +- set_fact: output_file={{win_output_dir}}\\foo.txt + +- name: prep with a basic win copy + win_copy: src=foo.txt dest={{output_file}} + +- name: verify that we are checking a file and it is present + win_file: path={{output_file}} state=file + register: file_result + +- name: verify that the file was marked as changed + assert: + that: + - "file_result.changed == false" +# - "file_result.state == 'file'" + +- name: verify that we are checking an absent file + win_file: path={{win_output_dir}}/bar.txt state=absent + register: file2_result + +- name: verify that the file was marked as changed + assert: + that: + - "file2_result.changed == false" +# - "file2_result.state == 'absent'" + +- name: verify we can touch a file + win_file: path={{win_output_dir}}/baz.txt state=touch + register: file3_result + +- name: verify that the file was marked as changed + assert: + that: + - "file3_result.changed == true" +# - "file3_result.state == 'file'" +# - "file3_result.mode == '0644'" + +#- name: change file mode +# win_file: path={{win_output_dir}}/baz.txt mode=0600 +# register: file4_result + +#- name: verify that the file was marked as changed +# assert: +# that: +# - "file4_result.changed == true" +# - "file4_result.mode == '0600'" +# +#- name: change ownership and group +# win_file: path={{win_output_dir}}/baz.txt owner=1234 group=1234 +# +#- name: setup a tmp-like directory for ownership test +# win_file: path=/tmp/worldwritable mode=1777 state=directory + +#- name: Ask to create a file without enough perms to change ownership +# win_file: path=/tmp/worldwritable/baz.txt state=touch owner=root +# become: yes +# become_user: nobody +# register: chown_result +# ignore_errors: True + +#- name: Ask whether the new file exists +# win_stat: path=/tmp/worldwritable/baz.txt +# register: file_exists_result + +#- name: Verify that the file doesn't exist on failure +# assert: +# that: +# - "chown_result.failed == True" +# - "file_exists_result.stat.exists == False" +# +#- name: clean up +# win_file: path=/tmp/worldwritable state=absent + +#- name: create soft link to file +# win_file: src={{output_file}} dest={{win_output_dir}}/soft.txt state=link +# register: file5_result + +#- name: verify that the file was marked as changed +# assert: +# that: +# - "file5_result.changed == true" +# +#- name: create hard link to file +# win_file: src={{output_file}} dest={{win_output_dir}}/hard.txt state=hard +# register: file6_result +# +#- name: verify that the file was marked as changed +# assert: +# that: +# - "file6_result.changed == true" +# +- name: create a directory + win_file: path={{win_output_dir}}/foobar state=directory + register: file7_result + +- debug: var=file7_result + +- name: verify that the file was marked as changed + assert: + that: + - "file7_result.changed == true" +# - "file7_result.state == 'directory'" + +# windows and selinux unlikely to ever mix, removing these tests: +#- name: determine if selinux is installed +# shell: which getenforce || exit 0 +# register: selinux_installed + +#- name: determine if selinux is enabled +# shell: getenforce +# register: selinux_enabled +# when: selinux_installed.stdout != "" +# ignore_errors: true + +#- name: decide to include or not include selinux tests +# include: selinux_tests.yml +# when: selinux_installed.stdout != "" and selinux_enabled.stdout != "Disabled" + +- name: remote directory foobar + win_file: path={{win_output_dir}}/foobar state=absent + +- name: remove file foo.txt + win_file: path={{win_output_dir}}/foo.txt state=absent + +- name: remove file bar.txt + win_file: path={{win_output_dir}}/foo.txt state=absent + +- name: remove file baz.txt + win_file: path={{win_output_dir}}/foo.txt state=absent + +- name: win copy directory structure over + win_copy: src=foobar dest={{win_output_dir}} + +- name: remove directory foobar + win_file: path={{win_output_dir}}/foobar state=absent + register: file14_result + +- debug: var=file14_result + +- name: verify that the directory was removed + assert: + that: + - 'file14_result.changed == true' +# - 'file14_result.state == "absent"' + +- name: create a test sub-directory + win_file: dest={{win_output_dir}}/sub1 state=directory + register: file15_result + +- name: verify that the new directory was created + assert: + that: + - 'file15_result.changed == true' +# - 'file15_result.state == "directory"' + +- name: create test files in the sub-directory + win_file: dest={{win_output_dir}}/sub1/{{item}} state=touch + with_items: + - file1 + - file2 + - file3 + register: file16_result + +- name: verify the files were created + assert: + that: + - 'item.changed == true' +# - 'item.state == "file"' + with_items: "{{file16_result.results}}" + +#- name: try to force the sub-directory to a link +# win_file: src={{win_output_dir}}/testing dest={{win_output_dir}}/sub1 state=link force=yes +# register: file17_result +# ignore_errors: true + +#- name: verify the directory was not replaced with a link +# assert: +# that: +# - 'file17_result.failed == true' +# - 'file17_result.state == "directory"' + +#- name: create soft link to directory using absolute path +# win_file: src=/ dest={{win_output_dir}}/root state=link +# register: file18_result +# +#- name: verify that the result was marked as changed +# assert: +# that: +# - "file18_result.changed == true" +# +- name: create another test sub-directory + win_file: dest={{win_output_dir}}/sub2 state=directory + register: file19_result + +- name: verify that the new directory was created + assert: + that: + - 'file19_result.changed == true' +# - 'file19_result.state == "directory"' + +#- name: create soft link to relative file +# win_file: src=../sub1/file1 dest={{win_output_dir}}/sub2/link1 state=link +# register: file20_result +# +#- name: verify that the result was marked as changed +# assert: +# that: +# - "file20_result.changed == true" + +#- name: create soft link to relative directory +# win_file: src=sub1 dest={{win_output_dir}}/sub1-link state=link +# register: file21_result +# +#- name: verify that the result was marked as changed +# assert: +# that: +# - "file21_result.changed == true" +# +#- name: test file creation with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=u=rwx,g=rwx,o=rwx +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0777' + +#- name: modify symbolic mode for all +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=a=r +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0444' + +#- name: modify symbolic mode for owner +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=u+w +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0644' + +#- name: modify symbolic mode for group +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=g+w +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0664' +# +#- name: modify symbolic mode for world +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=o+w +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0666' +# +#- name: modify symbolic mode for owner +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=u+x +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0766' +## +#- name: modify symbolic mode for group +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=g+x +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0776' +# +#- name: modify symbolic mode for world +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=o+x +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0777' + +#- name: remove symbolic mode for world +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=o-wx +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0774' +# +#- name: remove symbolic mode for group +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=g-wx +# register: result +# +#- name: assert file mode +### assert: +# that: +# - result.mode == '0744' + +#- name: remove symbolic mode for owner +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=u-wx +# register: result + +#- name: assert file mode +# assert: +# that: +# - result.mode == '0444' +# +#- name: set sticky bit with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=o+t +# register: result + +#- name: assert file mode +# assert: +# that: +# - result.mode == '01444' +# +#- name: remove sticky bit with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=o-t +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0444' + +#- name: add setgid with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=g+s +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '02444' +# +#- name: remove setgid with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=g-s +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0444' + +#- name: add setuid with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=u+s +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '04444' + +#- name: remove setuid with symbolic mode +# win_file: dest={{win_output_dir}}/test_symbolic state=touch mode=u-s +# register: result +# +#- name: assert file mode +# assert: +# that: +# - result.mode == '0444' + +# test the file module using follow=yes, so that the target of a +# symlink is modified, rather than the link itself + +#- name: create a test file +# win_copy: dest={{win_output_dir}}\test_follow content="this is a test file\n" mode=0666 + +#- name: create a symlink to the test file +# win_file: path={{win_output_dir}}\test_follow_link src="./test_follow" state=link +# +#- name: modify the permissions on the link using follow=yes +# win_file: path={{win_output_dir}}\test_follow_link mode=0644 follow=yes +# register: result + +#- name: assert that the chmod worked +# assert: +# that: +# - result.changed +# +#- name: stat the link target +# win_stat: path={{win_output_dir}}/test_follow +# register: result +# +#- name: assert that the link target was modified correctly +# assert: +# that: +## - result.stat.mode == '0644' + +- name: create a directory + win_file: path={{win_output_dir}}/dirtest state=directory + register: file_result + +- name: stat the directory created + win_stat: path={{win_output_dir}}/dirtest + register: stat_result + +- name: assert the directory was created + assert: + that: + - file_result.changed + - stat_result.stat.exists + - stat_result.stat.isdir + +- name: re run create directory (bug 2147) + win_file: path={{win_output_dir}}/dirtest state=directory + register: file_result + +- name: stat the directory created again + win_stat: path={{win_output_dir}}/dirtest + register: stat_result + +- name: assert the directory exists but was not changed + assert: + that: + - file_result.changed == False + - stat_result.stat.exists + - stat_result.stat.isdir + +- name: remove empty dir we just created + win_file: path={{win_output_dir}}/dirtest state=absent + register: file_result + +- name: stat the removed directory + win_stat: path={{win_output_dir}}/dirtest + register: stat_result + +- name: assert the directory does not exist + assert: + that: + - file_result.changed + - "stat_result.stat.exists == False" + +- name: create dir with spaces and parens in the dir name + win_file: path="{{win_output_dir}}/dir with spaces (and parens)" state=directory + register: file_result + +- name: stat the directory with spaces and parens + win_stat: path="{{win_output_dir}}/dir with spaces (and parens)" + register: stat_result + +- name: check dir with spaces and parens in the dir name has been created + assert: + that: + - file_result.changed + - stat_result.stat.exists + - stat_result.stat.isdir + +- name: remove dir with spaces and parens in the dir name + win_file: path="{{win_output_dir}}/dir with spaces (and parens)" state=absent + register: file_result + +- name: stat the dir with spaces and parens in the dir name + win_stat: path="{{win_output_dir}}/dir with spaces (and parens)" + register: stat_result + +- name: assert dir with spaces and parens in the dir name was removed + assert: + that: + - file_result.changed + - "stat_result.stat.exists == False" + +- name: clean up sub1 + win_file: path={{win_output_dir}}/sub1 state=absent + +- name: clean up sub2 + win_file: path={{win_output_dir}}/sub2 state=absent + diff --git a/test/integration/targets/win_get_url/defaults/main.yml b/test/integration/targets/win_get_url/defaults/main.yml new file mode 100644 index 0000000000..c7a90e599f --- /dev/null +++ b/test/integration/targets/win_get_url/defaults/main.yml @@ -0,0 +1,6 @@ +--- + +test_win_get_url_link: http://docs.ansible.com +test_win_get_url_invalid_link: http://docs.ansible.com/skynet_module.html +test_win_get_url_invalid_path: "Q:\\Filez\\Cyberdyne.html" +test_win_get_url_path: "{{ test_win_get_url_dir_path }}\\docs_index.html"
\ No newline at end of file diff --git a/test/integration/targets/win_get_url/tasks/main.yml b/test/integration/targets/win_get_url/tasks/main.yml new file mode 100644 index 0000000000..52e49672d2 --- /dev/null +++ b/test/integration/targets/win_get_url/tasks/main.yml @@ -0,0 +1,105 @@ +# test code for the win_get_url module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: get tempdir path + raw: $env:TEMP + register: tempdir + +- name: set output path dynamically + set_fact: + test_win_get_url_dir_path: "{{ tempdir.stdout_lines[0] }}" + +- name: remove test file if it exists + raw: > + PowerShell -Command Remove-Item "{{test_win_get_url_path}}" -Force + ignore_errors: true + +- name: test win_get_url module + win_get_url: + url: "{{test_win_get_url_link}}" + dest: "{{test_win_get_url_path}}" + register: win_get_url_result + +- name: check that url was downloaded + assert: + that: + - "not win_get_url_result|failed" + - "win_get_url_result|changed" + - "win_get_url_result.win_get_url.url" + - "win_get_url_result.win_get_url.dest" + +- name: test win_get_url module again (force should be yes by default) + win_get_url: + url: "{{test_win_get_url_link}}" + dest: "{{test_win_get_url_path}}" + register: win_get_url_result_again + +- name: check that url was downloaded again + assert: + that: + - "not win_get_url_result_again|failed" + - "win_get_url_result_again|changed" + +- name: test win_get_url module again with force=no + win_get_url: + url: "{{test_win_get_url_link}}" + dest: "{{test_win_get_url_path}}" + force: no + register: win_get_url_result_noforce + +- name: check that url was not downloaded again + assert: + that: + - "not win_get_url_result_noforce|failed" + - "not win_get_url_result_noforce|changed" + +- name: test win_get_url module with url that returns a 404 + win_get_url: + url: "{{test_win_get_url_invalid_link}}" + dest: "{{test_win_get_url_path}}" + register: win_get_url_result_invalid_link + ignore_errors: true + +- name: check that the download failed for an invalid url + assert: + that: + - "win_get_url_result_invalid_link|failed" + +- name: test win_get_url module with an invalid path + win_get_url: + url: "{{test_win_get_url_link}}" + dest: "{{test_win_get_url_invalid_path}}" + register: win_get_url_result_invalid_path + ignore_errors: true + +- name: check that the download failed for an invalid path + assert: + that: + - "win_get_url_result_invalid_path|failed" + +- name: test win_get_url module with a valid path that is a directory + win_get_url: + url: "{{test_win_get_url_link}}" + dest: "{{test_win_get_url_dir_path}}" + register: win_get_url_result_dir_path + ignore_errors: true + +- name: check that the download failed if dest is a directory + assert: + that: + - "win_get_url_result_dir_path|failed" diff --git a/test/integration/targets/win_group/defaults/main.yml b/test/integration/targets/win_group/defaults/main.yml new file mode 100644 index 0000000000..2ab744e822 --- /dev/null +++ b/test/integration/targets/win_group/defaults/main.yml @@ -0,0 +1,4 @@ +--- + +test_win_group_name: Ansiblings +test_win_group_description: Test group for Ansible diff --git a/test/integration/targets/win_group/tasks/main.yml b/test/integration/targets/win_group/tasks/main.yml new file mode 100644 index 0000000000..e380ab18ec --- /dev/null +++ b/test/integration/targets/win_group/tasks/main.yml @@ -0,0 +1,101 @@ +# test code for the slurp module when using winrm connection +# (c) 2015, Chris Church <cchurch@ansible.com> + +# 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/>. + +- name: remove test group if it exists + win_group: + name: "{{test_win_group_name}}" + state: absent + +- name: create test group with missing name parameter + win_group: + description: "{{test_win_group_description}}" + register: win_group_create_noname + ignore_errors: true + +- name: check create result without name parameter + assert: + that: + - "win_group_create_noname|failed" + +- name: create test group with invalid state parameter + win_group: + name: "{{test_win_group_name}}" + state: "unknown" + register: win_group_create_invalid_state + ignore_errors: true + +- name: check create result with invalid state parameter + assert: + that: + - "win_group_create_invalid_state|failed" + +- name: create test group + win_group: + name: "{{test_win_group_name}}" + description: "{{test_win_group_description}}" + register: win_group_create + +- name: check create group results + assert: + that: + - "win_group_create|changed" + +- name: create test group again with same options + win_group: + name: "{{test_win_group_name}}" + description: "{{test_win_group_description}}" + state: "present" + register: win_group_create_again + +- name: check create group again results + assert: + that: + - "not win_group_create_again|changed" + +- name: create test group again but change description + win_group: + name: "{{test_win_group_name}}" + description: "{{test_win_group_description}} updated" + register: win_group_create_new_description + +- name: check create group results after updating description + assert: + that: + - "win_group_create_new_description|changed" + +- name: remove test group + win_group: + name: "{{test_win_group_name}}" + state: absent + register: win_group_remove + +- name: check remove group result + assert: + that: + - "win_group_remove|changed" + +- name: remove test group again + win_group: + name: "{{test_win_group_name}}" + state: absent + register: win_group_remove_again + +- name: check remove group again result + assert: + that: + - "not win_group_remove_again|changed" diff --git a/test/integration/targets/win_lineinfile/files/test.txt b/test/integration/targets/win_lineinfile/files/test.txt new file mode 100644 index 0000000000..8187db9f02 --- /dev/null +++ b/test/integration/targets/win_lineinfile/files/test.txt @@ -0,0 +1,5 @@ +This is line 1 +This is line 2 +REF this is a line for backrefs REF +This is line 4 +This is line 5 diff --git a/test/integration/targets/win_lineinfile/files/test_quoting.txt b/test/integration/targets/win_lineinfile/files/test_quoting.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/integration/targets/win_lineinfile/files/test_quoting.txt diff --git a/test/integration/targets/win_lineinfile/files/testempty.txt b/test/integration/targets/win_lineinfile/files/testempty.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/integration/targets/win_lineinfile/files/testempty.txt diff --git a/test/integration/targets/win_lineinfile/files/testnoeof.txt b/test/integration/targets/win_lineinfile/files/testnoeof.txt new file mode 100644 index 0000000000..152780b9ff --- /dev/null +++ b/test/integration/targets/win_lineinfile/files/testnoeof.txt @@ -0,0 +1,2 @@ +This is line 1 +This is line 2
\ No newline at end of file diff --git a/test/integration/targets/win_lineinfile/meta/main.yml b/test/integration/targets/win_lineinfile/meta/main.yml new file mode 100644 index 0000000000..55200b3fc6 --- /dev/null +++ b/test/integration/targets/win_lineinfile/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_win_tests + diff --git a/test/integration/targets/win_lineinfile/tasks/main.yml b/test/integration/targets/win_lineinfile/tasks/main.yml new file mode 100644 index 0000000000..45d0ae96a5 --- /dev/null +++ b/test/integration/targets/win_lineinfile/tasks/main.yml @@ -0,0 +1,641 @@ +# Test code for the win_lineinfile module, adapted from the standard lineinfile module tests +# +# 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/>. + + +- name: deploy the test file for lineinfile + win_copy: src=test.txt dest={{win_output_dir}}/test.txt + register: result + +- name: assert that the test file was deployed + assert: + that: + - "result.changed == true" + +- name: stat the test file + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: check win_stat file result + assert: + that: + - "result.stat.exists" + - "not result.stat.isdir" + - "result.stat.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'" + - "not result|failed" + - "not result|changed" + + +- name: insert a line at the beginning of the file, and back it up + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line at the beginning" insertbefore="BOF" backup=yes + register: result + +- name: assert that the line was inserted at the head of the file + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.backup != ''" + +- name: stat the backup file + win_stat: path={{result.backup}} + register: result + +- name: assert the backup file matches the previous hash + assert: + that: + - "result.stat.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'" + +- name: stat the test after the insert at the head + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test hash is what we expect for the file with the insert at the head + assert: + that: + - "result.stat.checksum == 'b526e2e044defc64dfb0fad2f56e105178f317d8'" + +- name: insert a line at the end of the file + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line at the end" insertafter="EOF" + register: result + +- name: assert that the line was inserted at the end of the file + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: stat the test after the insert at the end + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after the insert at the end + assert: + that: + - "result.stat.checksum == 'dd5e207e28ce694ab18e41c2b16deb74fde93b14'" + +- name: insert a line after the first line + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line after line 1" insertafter="^This is line 1$" + register: result + +- name: assert that the line was inserted after the first line + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: stat the test after insert after the first line + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after the insert after the first line + assert: + that: + - "result.stat.checksum == '604b17405f2088e6868af9680b7834087acdc8f4'" + +- name: insert a line before the last line + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line before line 5" insertbefore="^This is line 5$" + register: result + +- name: assert that the line was inserted before the last line + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: stat the test after the insert before the last line + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after the insert before the last line + assert: + that: + - "result.stat.checksum == '8f5b30e8f01578043d782e5a68d4c327e75a6e34'" + +- name: replace a line with backrefs + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="This is line 3" backrefs=yes regexp="^(REF).*$" + register: result + +- name: assert that the line with backrefs was changed + assert: + that: + - "result.changed == true" + - "result.msg == 'line replaced'" + +- name: stat the test after the backref line was replaced + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after backref line was replaced + assert: + that: + - "result.stat.checksum == 'ef6b02645908511a2cfd2df29d50dd008897c580'" + +- name: remove the middle line + win_lineinfile: dest={{win_output_dir}}/test.txt state=absent regexp="^This is line 3$" + register: result + +- name: assert that the line was removed + assert: + that: + - "result.changed == true" + - "result.msg == '1 line(s) removed'" + +- name: stat the test after the middle line was removed + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after the middle line was removed + assert: + that: + - "result.stat.checksum == '11695efa472be5c31c736bc43e055f8ac90eabdf'" + +- name: run a validation script that succeeds + win_lineinfile: dest={{win_output_dir}}/test.txt state=absent regexp="^This is line 5$" validate="sort.exe %s" + register: result + +- name: assert that the file validated after removing a line + assert: + that: + - "result.changed == true" + - "result.msg == '1 line(s) removed'" + +- name: stat the test after the validation succeeded + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after the validation succeeded + assert: + that: + - "result.stat.checksum == '39c38a30aa6ac6af9ec41f54c7ed7683f1249347'" + +- name: run a validation script that fails + win_lineinfile: dest={{win_output_dir}}/test.txt state=absent regexp="^This is line 1$" validate="sort.exe %s.foo" + register: result + ignore_errors: yes + +- name: assert that the validate failed + assert: + that: + - "result.failed == true" + +- name: stat the test after the validation failed + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches the previous after the validation failed + assert: + that: + - "result.stat.checksum == '39c38a30aa6ac6af9ec41f54c7ed7683f1249347'" + +- name: use create=yes + win_lineinfile: dest={{win_output_dir}}/new_test.txt create=yes insertbefore=BOF state=present line="This is a new file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/new_test.txt + register: result + ignore_errors: yes + +- name: assert the newly created test checksum matches + assert: + that: + - "result.stat.checksum == '84faac1183841c57434693752fc3debc91b9195d'" + +# Test EOF in cases where file has no newline at EOF +- name: testnoeof deploy the file for lineinfile + win_copy: src=testnoeof.txt dest={{win_output_dir}}/testnoeof.txt + register: result + +- name: testnoeof insert a line at the end of the file + win_lineinfile: dest={{win_output_dir}}/testnoeof.txt state=present line="New line at the end" insertafter="EOF" + register: result + +- name: testempty assert that the line was inserted at the end of the file + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: testnoeof stat the no newline EOF test after the insert at the end + win_stat: path={{win_output_dir}}/testnoeof.txt + register: result + +- name: testnoeof assert test checksum matches after the insert at the end + assert: + that: + - "result.stat.checksum == '229852b09f7e9921fbcbb0ee0166ba78f7f7f261'" + +- name: add multiple lines at the end of the file + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="This is a line\r\nwith newline character" insertafter="EOF" + register: result + +- name: assert that the multiple lines was inserted + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: stat file after adding multiple lines + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after inserting multiple lines + assert: + that: + - "result.stat.checksum == '1401413cd4eac732be66cd6aceddd334c4240f86'" + + + +# Test EOF with empty file to make sure no unnecessary newline is added +- name: testempty deploy the testempty file for lineinfile + win_copy: src=testempty.txt dest={{win_output_dir}}/testempty.txt + register: result + +- name: testempty insert a line at the end of the file + win_lineinfile: dest={{win_output_dir}}/testempty.txt state=present line="New line at the end" insertafter="EOF" + register: result + +- name: testempty assert that the line was inserted at the end of the file + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: testempty stat the test after the insert at the end + win_stat: path={{win_output_dir}}/testempty.txt + register: result + +- name: testempty assert test checksum matches after the insert at the end + assert: + that: + - "result.stat.checksum == 'd3d34f11edda51be7ca5dcb0757cf3e1257c0bfe'" + + + +- name: replace a line with backrefs included in the line + win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New $1 created with the backref" backrefs=yes regexp="^This is (line 4)$" + register: result + +- name: assert that the line with backrefs was changed + assert: + that: + - "result.changed == true" + - "result.msg == 'line replaced'" + +- name: stat the test after the backref line was replaced + win_stat: path={{win_output_dir}}/test.txt + register: result + +- name: assert test checksum matches after backref line was replaced + assert: + that: + - "result.stat.checksum == 'e6ff42e926dac2274c93dff0b8a323e07ae09149'" + +################################################################### +# issue 8535 + +- name: create a new file for testing quoting issues + win_copy: src=test_quoting.txt dest={{win_output_dir}}/test_quoting.txt + register: result + +- name: assert the new file was created + assert: + that: + - result.changed + +- name: use with_items to add code-like strings to the quoting txt file + win_lineinfile: > + dest={{win_output_dir}}/test_quoting.txt + line="{{ item }}" + insertbefore="BOF" + with_items: + - "'foo'" + - "dotenv.load();" + - "var dotenv = require('dotenv');" + register: result + +- name: assert the quote test file was modified correctly + assert: + that: + - result.results|length == 3 + - result.results[0].changed + - result.results[0].item == "'foo'" + - result.results[1].changed + - result.results[1].item == "dotenv.load();" + - result.results[2].changed + - result.results[2].item == "var dotenv = require('dotenv');" + +- name: stat the quote test file + win_stat: path={{win_output_dir}}/test_quoting.txt + register: result + +- name: assert test checksum matches for quote test file + assert: + that: + - "result.stat.checksum == 'f3bccdbdfa1d7176c497ef87d04957af40ab48d2'" + +- name: append a line into the quoted file with a single quote + win_lineinfile: dest={{win_output_dir}}/test_quoting.txt line="import g'" + register: result + +- name: assert that the quoted file was changed + assert: + that: + - result.changed + +- name: stat the quote test file + win_stat: path={{win_output_dir}}/test_quoting.txt + register: result + +- name: assert test checksum matches adding line with single quote + assert: + that: + - "result.stat.checksum == 'dabf4cbe471e1797d8dcfc773b6b638c524d5237'" + +- name: insert a line into the quoted file with many double quotation strings + win_lineinfile: dest={{win_output_dir}}/test_quoting.txt line='"quote" and "unquote"' + register: result + +- name: assert that the quoted file was changed + assert: + that: + - result.changed + +- name: stat the quote test file + win_stat: path={{win_output_dir}}/test_quoting.txt + register: result + +- name: assert test checksum matches quoted line added + assert: + that: + - "result.stat.checksum == '9dc1fc1ff19942e2936564102ad37134fa83b91d'" + + +# Windows vs. Unix line separator test cases + +- name: Create windows test file with initial line + win_lineinfile: dest={{win_output_dir}}/test_windows_sep.txt create=yes insertbefore=BOF state=present line="This is a new file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/test_windows_sep.txt + register: result + +- name: assert the newly created file checksum matches + assert: + that: + - "result.stat.checksum == '84faac1183841c57434693752fc3debc91b9195d'" + +- name: Test appending to the file using the default (windows) line separator + win_lineinfile: dest={{win_output_dir}}/test_windows_sep.txt insertbefore=EOF state=present line="This is the last line" + register: result + +- name: assert that the new line was added + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: stat the file + win_stat: path={{win_output_dir}}/test_windows_sep.txt + register: result + +- name: assert the file checksum matches expected checksum + assert: + that: + - "result.stat.checksum == '71a17ddd1d57ed7c7912e4fd11ecb2ead0b27033'" + + +- name: Create unix test file with initial line + win_lineinfile: dest={{win_output_dir}}/test_unix_sep.txt create=yes insertbefore=BOF state=present line="This is a new file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/test_unix_sep.txt + register: result + +- name: assert the newly created file checksum matches + assert: + that: + - "result.stat.checksum == '84faac1183841c57434693752fc3debc91b9195d'" + +- name: Test appending to the file using unix line separator + win_lineinfile: dest={{win_output_dir}}/test_unix_sep.txt insertbefore=EOF state=present line="This is the last line" newline="unix" + register: result + +- name: assert that the new line was added + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + +- name: stat the file + win_stat: path={{win_output_dir}}/test_unix_sep.txt + register: result + +- name: assert the file checksum matches expected checksum + assert: + that: + - "result.stat.checksum == 'f1f634a37ab1c73efb77a71a5ad2cc87b61b17ae'" + + +# Encoding management test cases + +# Default (auto) encoding should use utf-8 with no BOM +- name: Test create file without explicit encoding results in utf-8 without BOM + win_lineinfile: dest={{win_output_dir}}/test_auto_utf8.txt create=yes insertbefore=BOF state=present line="This is a new utf-8 file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-8'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/test_auto_utf8.txt + register: result + +- name: assert the newly created file checksum matches + assert: + that: + - "result.stat.checksum == 'b69fcbacca8291a4668f57fba91d7c022f1c3dc7'" + +- name: Test appending to the utf-8 without BOM file - should autodetect UTF-8 no BOM + win_lineinfile: dest={{win_output_dir}}/test_auto_utf8.txt insertbefore=EOF state=present line="This is the last line" + register: result + +- name: assert that the new line was added and encoding did not change + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-8'" + +- name: stat the file + win_stat: path={{win_output_dir}}/test_auto_utf8.txt + register: result + +- name: assert the file checksum matches + assert: + that: + - "result.stat.checksum == '64d747f1ebf8c9d793dbfd27126e4152d39a3848'" + + +# UTF-8 explicit (with BOM) +- name: Test create file with explicit utf-8 encoding results in utf-8 with a BOM + win_lineinfile: dest={{win_output_dir}}/test_utf8.txt create=yes encoding="utf-8" insertbefore=BOF state=present line="This is a new utf-8 file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-8'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/test_utf8.txt + register: result + +- name: assert the newly created file checksum matches + assert: + that: + - "result.stat.checksum == 'd45344b2b3bf1cf90eae851b40612f5f37a88bbb'" + +- name: Test appending to the utf-8 with BOM file - should autodetect utf-8 with BOM encoding + win_lineinfile: dest={{win_output_dir}}/test_utf8.txt insertbefore=EOF state=present line="This is the last line" + register: result + +- name: assert that the new line was added and encoding did not change + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-8'" + +- name: stat the file + win_stat: path={{win_output_dir}}/test_utf8.txt + register: result + +- name: assert the file checksum matches + assert: + that: + - "result.stat.checksum == '9b84254489f40f258871a4c6573cacc65895ee1a'" + + +# UTF-16 explicit +- name: Test create file with explicit utf-16 encoding + win_lineinfile: dest={{win_output_dir}}/test_utf16.txt create=yes encoding="utf-16" insertbefore=BOF state=present line="This is a new utf-16 file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-16'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/test_utf16.txt + register: result + +- name: assert the newly created file checksum matches + assert: + that: + - "result.stat.checksum == '785b0693cec13b60e2c232782adeda2f8a967434'" + +- name: Test appending to the utf-16 file - should autodetect utf-16 encoding + win_lineinfile: dest={{win_output_dir}}/test_utf16.txt insertbefore=EOF state=present line="This is the last line" + register: result + +- name: assert that the new line was added and encoding did not change + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-16'" + +- name: stat the file + win_stat: path={{win_output_dir}}/test_utf16.txt + register: result + +- name: assert the file checksum matches + assert: + that: + - "result.stat.checksum == '70e4eb3ba795e1ba94d262db47e4fd17c64b2e73'" + +# UTF-32 explicit +- name: Test create file with explicit utf-32 encoding + win_lineinfile: dest={{win_output_dir}}/test_utf32.txt create=yes encoding="utf-32" insertbefore=BOF state=present line="This is a new utf-32 file" + register: result + +- name: assert that the new file was created + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-32'" + +- name: validate that the newly created file exists + win_stat: path={{win_output_dir}}/test_utf32.txt + register: result + +- name: assert the newly created file checksum matches + assert: + that: + - "result.stat.checksum == '7a6e3f3604c0def431aaa813173a4ddaa10fd1fb'" + +- name: Test appending to the utf-32 file - should autodetect utf-32 encoding + win_lineinfile: dest={{win_output_dir}}/test_utf32.txt insertbefore=EOF state=present line="This is the last line" + register: result + +- name: assert that the new line was added and encoding did not change + assert: + that: + - "result.changed == true" + - "result.msg == 'line added'" + - "result.encoding == 'utf-32'" + +- name: stat the file + win_stat: path={{win_output_dir}}/test_utf32.txt + register: result + +- name: assert the file checksum matches + assert: + that: + - "result.stat.checksum == '66a72e71f42c4775f4326da95cfe82c8830e5022'" + diff --git a/test/integration/targets/win_msi/defaults/main.yml b/test/integration/targets/win_msi/defaults/main.yml new file mode 100644 index 0000000000..ebc97b84cc --- /dev/null +++ b/test/integration/targets/win_msi/defaults/main.yml @@ -0,0 +1,6 @@ +--- + +msi_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_win_msi/7z922-x64.msi +msi_download_path: "C:\\Program Files\\7z922-x64.msi" +msi_install_path: "C:\\Program Files\\7-Zip" +msi_product_code: "{23170F69-40C1-2702-0922-000001000000}" diff --git a/test/integration/targets/win_msi/tasks/main.yml b/test/integration/targets/win_msi/tasks/main.yml new file mode 100644 index 0000000000..f4f31d3a8a --- /dev/null +++ b/test/integration/targets/win_msi/tasks/main.yml @@ -0,0 +1,70 @@ +# test code for the win_msi module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: use win_get_url module to download msi + win_get_url: + url: "{{msi_url}}" + dest: "{{msi_download_path}}" + register: win_get_url_result + +- name: make sure msi is uninstalled + win_msi: + path: "{{msi_product_code|default(msi_download_path,true)}}" + state: absent + wait: true + ignore_errors: true + +- name: install msi + win_msi: + path: "{{msi_download_path}}" + wait: true + register: win_msi_install_result + +- name: check win_msi install result + assert: + that: + - "not win_msi_install_result|failed" + - "win_msi_install_result|changed" + +- name: install msi again with creates argument + win_msi: + path: "{{msi_download_path}}" + wait: true + creates: "{{msi_install_path}}" + register: win_msi_install_again_result + +- name: check win_msi install again result + # ignore errors because test/module is unreliable + ignore_errors: true + assert: + that: + - "not win_msi_install_again_result|failed" + - "not win_msi_install_again_result|changed" + +- name: uninstall msi + win_msi: + path: "{{msi_download_path}}" + wait: true + state: absent + register: win_msi_uninstall_result + +- name: check win_msi uninstall result + assert: + that: + - "not win_msi_uninstall_result|failed" + - "win_msi_uninstall_result|changed" diff --git a/test/integration/targets/win_package/defaults/main.yml b/test/integration/targets/win_package/defaults/main.yml new file mode 100644 index 0000000000..ebc97b84cc --- /dev/null +++ b/test/integration/targets/win_package/defaults/main.yml @@ -0,0 +1,6 @@ +--- + +msi_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_win_msi/7z922-x64.msi +msi_download_path: "C:\\Program Files\\7z922-x64.msi" +msi_install_path: "C:\\Program Files\\7-Zip" +msi_product_code: "{23170F69-40C1-2702-0922-000001000000}" diff --git a/test/integration/targets/win_package/tasks/main.yml b/test/integration/targets/win_package/tasks/main.yml new file mode 100644 index 0000000000..3df394fc75 --- /dev/null +++ b/test/integration/targets/win_package/tasks/main.yml @@ -0,0 +1,81 @@ +# test code for the win_package module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: use win_get_url module to download msi + win_get_url: + url: "{{msi_url}}" + dest: "{{msi_download_path}}" + register: win_get_url_result + +- name: make sure msi is uninstalled + win_package: + path: "{{msi_download_path}}" + product_id: "{{msi_product_code}}" + state: absent + +- name: install msi + win_package: + path: "{{msi_download_path}}" + product_id: "{{msi_product_code}}" + state: present + register: win_package_install_result + +- name: check win_package install result + assert: + that: + - "not win_package_install_result|failed" + - "win_package_install_result|changed" + +- name: install msi again (check for no change) + win_package: + path: "{{msi_download_path}}" + product_id: "{{msi_product_code}}" + state: present + register: win_package_install_again_result + +- name: check win_package install again result + assert: + that: + - "not win_package_install_again_result|failed" + - "not win_package_install_again_result|changed" + +- name: uninstall msi + win_package: + path: "{{msi_download_path}}" + product_id: "{{msi_product_code}}" + state: absent + register: win_package_uninstall_result + +- name: check win_package uninstall result + assert: + that: + - "not win_package_uninstall_result|failed" + - "win_package_uninstall_result|changed" + +- name: uninstall msi again (check for no change) + win_package: + path: "{{msi_download_path}}" + product_id: "{{msi_product_code}}" + state: absent + register: win_package_uninstall_again_result + +- name: check win_package uninstall result + assert: + that: + - "not win_package_uninstall_result|failed" + - "not win_package_uninstall_again_result|changed" diff --git a/test/integration/targets/win_ping/library/win_ping_set_attr.ps1 b/test/integration/targets/win_ping/library/win_ping_set_attr.ps1 new file mode 100644 index 0000000000..8279b4b414 --- /dev/null +++ b/test/integration/targets/win_ping/library/win_ping_set_attr.ps1 @@ -0,0 +1,31 @@ +#!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/>. + +# POWERSHELL_COMMON + +$params = Parse-Args $args $true; + +$data = Get-Attr $params "data" "pong"; + +$result = New-Object psobject @{ + changed = $false + ping = "pong" +}; + +# Test that Set-Attr will replace an existing attribute. +Set-Attr $result "ping" $data + +Exit-Json $result; diff --git a/test/integration/targets/win_ping/library/win_ping_strict_mode_error.ps1 b/test/integration/targets/win_ping/library/win_ping_strict_mode_error.ps1 new file mode 100644 index 0000000000..d498cbcf17 --- /dev/null +++ b/test/integration/targets/win_ping/library/win_ping_strict_mode_error.ps1 @@ -0,0 +1,30 @@ +#!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/>. + +# POWERSHELL_COMMON + +$params = Parse-Args $args $true; + +$x = $params.thisPropertyDoesNotExist + +$data = Get-Attr $params "data" "pong"; + +$result = New-Object psobject @{ + changed = $false + ping = $data +}; + +Exit-Json $result; diff --git a/test/integration/targets/win_ping/library/win_ping_syntax_error.ps1 b/test/integration/targets/win_ping/library/win_ping_syntax_error.ps1 new file mode 100644 index 0000000000..6bfe621a80 --- /dev/null +++ b/test/integration/targets/win_ping/library/win_ping_syntax_error.ps1 @@ -0,0 +1,30 @@ +#!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/>. + +# POWERSHELL_COMMON + +$blah = 'I can't quote my strings correctly.' + +$params = Parse-Args $args $true; + +$data = Get-Attr $params "data" "pong"; + +$result = New-Object psobject @{ + changed = $false + ping = $data +}; + +Exit-Json $result; diff --git a/test/integration/targets/win_ping/library/win_ping_throw.ps1 b/test/integration/targets/win_ping/library/win_ping_throw.ps1 new file mode 100644 index 0000000000..f0b32186d8 --- /dev/null +++ b/test/integration/targets/win_ping/library/win_ping_throw.ps1 @@ -0,0 +1,30 @@ +#!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/>. + +# POWERSHELL_COMMON + +throw + +$params = Parse-Args $args $true; + +$data = Get-Attr $params "data" "pong"; + +$result = New-Object psobject @{ + changed = $false + ping = $data +}; + +Exit-Json $result; diff --git a/test/integration/targets/win_ping/library/win_ping_throw_string.ps1 b/test/integration/targets/win_ping/library/win_ping_throw_string.ps1 new file mode 100644 index 0000000000..e1f3ca6065 --- /dev/null +++ b/test/integration/targets/win_ping/library/win_ping_throw_string.ps1 @@ -0,0 +1,30 @@ +#!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/>. + +# POWERSHELL_COMMON + +throw "no ping for you" + +$params = Parse-Args $args $true; + +$data = Get-Attr $params "data" "pong"; + +$result = New-Object psobject @{ + changed = $false + ping = $data +}; + +Exit-Json $result; diff --git a/test/integration/targets/win_ping/tasks/main.yml b/test/integration/targets/win_ping/tasks/main.yml new file mode 100644 index 0000000000..aa5d03c908 --- /dev/null +++ b/test/integration/targets/win_ping/tasks/main.yml @@ -0,0 +1,146 @@ +# test code for the win_ping module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: test win_ping + action: win_ping + register: win_ping_result + +- name: check win_ping result + assert: + that: + - "not win_ping_result|failed" + - "not win_ping_result|changed" + - "win_ping_result.ping == 'pong'" + +- name: test win_ping with data + win_ping: data=☠ + register: win_ping_with_data_result + +- name: check win_ping result with data + assert: + that: + - "not win_ping_with_data_result|failed" + - "not win_ping_with_data_result|changed" + - "win_ping_with_data_result.ping == '☠'" + +- name: test win_ping.ps1 with data as complex args + win_ping.ps1: + data: bleep + register: win_ping_ps1_result + +- name: check win_ping.ps1 result with data + assert: + that: + - "not win_ping_ps1_result|failed" + - "not win_ping_ps1_result|changed" + - "win_ping_ps1_result.ping == 'bleep'" + +- name: test win_ping with extra args to verify that v2 module replacer escaping works as expected + win_ping: + data: bloop + a_null: null + a_boolean: true + another_boolean: false + a_number: 299792458 + another_number: 22.7 + yet_another_number: 6.022e23 + a_string: | + it's magic + "@' + '@" + an_array: + - first + - 2 + - 3.0 + an_object: + - the_thing: the_value + - the_other_thing: 0 + - the_list_of_things: [1, 2, 3, 5] + register: win_ping_extra_args_result + +- name: check that win_ping with extra args succeeds and ignores everything except data + assert: + that: + - "not win_ping_extra_args_result|failed" + - "not win_ping_extra_args_result|changed" + - "win_ping_extra_args_result.ping == 'bloop'" + +- name: test modified win_ping that throws an exception + action: win_ping_throw + register: win_ping_throw_result + ignore_errors: true + +- name: check win_ping_throw result + assert: + that: + - "win_ping_throw_result|failed" + - "not win_ping_throw_result|changed" + - "win_ping_throw_result.msg == 'ScriptHalted'" + - "win_ping_throw_result.exception" + - "win_ping_throw_result.error_record" + +- name: test modified win_ping that throws a string exception + action: win_ping_throw_string + register: win_ping_throw_string_result + ignore_errors: true + +- name: check win_ping_throw_string result + assert: + that: + - "win_ping_throw_string_result|failed" + - "not win_ping_throw_string_result|changed" + - "win_ping_throw_string_result.msg == 'no ping for you'" + - "win_ping_throw_string_result.exception" + - "win_ping_throw_string_result.error_record" + +- name: test modified win_ping that has a syntax error + action: win_ping_syntax_error + register: win_ping_syntax_error_result + ignore_errors: true + +- name: check win_ping_syntax_error result + assert: + that: + - "win_ping_syntax_error_result|failed" + - "not win_ping_syntax_error_result|changed" + - "win_ping_syntax_error_result.msg" + - "win_ping_syntax_error_result.exception" + +- name: test modified win_ping that has an error that only surfaces when strict mode is on + action: win_ping_strict_mode_error + register: win_ping_strict_mode_error_result + ignore_errors: true + +- name: check win_ping_strict_mode_error result + assert: + that: + - "win_ping_strict_mode_error_result|failed" + - "not win_ping_strict_mode_error_result|changed" + - "win_ping_strict_mode_error_result.msg" + - "win_ping_strict_mode_error_result.exception" + +- name: test modified win_ping to verify a Set-Attr fix + action: win_ping_set_attr data="fixed" + register: win_ping_set_attr_result + +- name: check win_ping_set_attr_result result + assert: + that: + - "not win_ping_set_attr_result|failed" + - "not win_ping_set_attr_result|changed" + - "win_ping_set_attr_result.ping == 'fixed'" diff --git a/test/integration/targets/win_raw/tasks/main.yml b/test/integration/targets/win_raw/tasks/main.yml new file mode 100644 index 0000000000..6e4c9da064 --- /dev/null +++ b/test/integration/targets/win_raw/tasks/main.yml @@ -0,0 +1,116 @@ +# test code for the raw module when using winrm connection +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: run getmac + raw: getmac + register: getmac_result + +- name: assert that getmac ran + assert: + that: + - "getmac_result.rc == 0" + - "getmac_result.stdout" + - "not getmac_result.stderr" + - "not getmac_result|failed" + - "getmac_result|changed" + +- name: run ipconfig with /all argument + raw: ipconfig /all + register: ipconfig_result + +- name: assert that ipconfig ran with /all argument + assert: + that: + - "ipconfig_result.rc == 0" + - "ipconfig_result.stdout" + - "'Physical Address' in ipconfig_result.stdout" + - "not ipconfig_result.stderr" + - "not ipconfig_result|failed" + - "ipconfig_result|changed" + +- name: run ipconfig with invalid argument + raw: ipconfig /badswitch + register: ipconfig_invalid_result + ignore_errors: true + +- name: assert that ipconfig with invalid argument failed + assert: + that: + - "ipconfig_invalid_result.rc != 0" + - "ipconfig_invalid_result.stdout" # ipconfig displays errors on stdout. + - "not ipconfig_invalid_result.stderr" + - "ipconfig_invalid_result|failed" + - "ipconfig_invalid_result|changed" + +- name: run an unknown command + raw: uname -a + register: unknown_result + ignore_errors: true + +- name: assert that an unknown command failed + assert: + that: + - "unknown_result.rc != 0" + - "not unknown_result.stdout" + - "unknown_result.stderr" # An unknown command displays error on stderr. + - "unknown_result|failed" + - "unknown_result|changed" + +- name: run a command that takes longer than 60 seconds + raw: Start-Sleep -s 75 + register: sleep_command + +- name: assert that the sleep command ran + assert: + that: + - "sleep_command.rc == 0" + - "not sleep_command.stdout" + - "not sleep_command.stderr" + - "not sleep_command|failed" + - "sleep_command|changed" + +- name: run a raw command with key=value arguments + raw: echo wwe=raw + register: raw_result + +- name: make sure raw is really raw and not removing key=value arguments + assert: + that: + - "raw_result.stdout_lines[0] == 'wwe=raw'" + +- name: run a raw command with unicode chars and quoted args (from https://github.com/ansible/ansible-modules-core/issues/1929) + raw: Write-Host --% icacls D:\somedir\ /grant "! ЗАО. Руководство":F + register: raw_result2 + +- name: make sure raw passes command as-is and doesn't split/rejoin args + assert: + that: + - "raw_result2.stdout_lines[0] == '--% icacls D:\\\\somedir\\\\ /grant \"! ЗАО. Руководство\":F'" + +# Assumes MaxShellsPerUser == 30 (the default) + +- name: test raw + with_items to verify that winrm connection is reused for each item + raw: echo "{{item}}" + with_items: "{{range(32)|list}}" + register: raw_with_items_result + +- name: check raw + with_items result + assert: + that: + - "not raw_with_items_result|failed" + - "raw_with_items_result.results|length == 32" diff --git a/test/integration/targets/win_regedit/meta/main.yml b/test/integration/targets/win_regedit/meta/main.yml new file mode 100644 index 0000000000..55200b3fc6 --- /dev/null +++ b/test/integration/targets/win_regedit/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_win_tests + diff --git a/test/integration/targets/win_regedit/tasks/main.yml b/test/integration/targets/win_regedit/tasks/main.yml new file mode 100644 index 0000000000..6948055dd1 --- /dev/null +++ b/test/integration/targets/win_regedit/tasks/main.yml @@ -0,0 +1,426 @@ +# test code for the win_regedit module +# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com> + +# 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/>. + +# 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 == 'key: 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" + +# 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" + +# 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_regmerge/files/settings1.reg b/test/integration/targets/win_regmerge/files/settings1.reg Binary files differnew file mode 100644 index 0000000000..baec75b2af --- /dev/null +++ b/test/integration/targets/win_regmerge/files/settings1.reg diff --git a/test/integration/targets/win_regmerge/files/settings2.reg b/test/integration/targets/win_regmerge/files/settings2.reg Binary files differnew file mode 100644 index 0000000000..fc2612cb8a --- /dev/null +++ b/test/integration/targets/win_regmerge/files/settings2.reg diff --git a/test/integration/targets/win_regmerge/files/settings3.reg b/test/integration/targets/win_regmerge/files/settings3.reg Binary files differnew file mode 100644 index 0000000000..fbe7411c95 --- /dev/null +++ b/test/integration/targets/win_regmerge/files/settings3.reg diff --git a/test/integration/targets/win_regmerge/meta/main.yml b/test/integration/targets/win_regmerge/meta/main.yml new file mode 100644 index 0000000000..55200b3fc6 --- /dev/null +++ b/test/integration/targets/win_regmerge/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_win_tests + diff --git a/test/integration/targets/win_regmerge/tasks/main.yml b/test/integration/targets/win_regmerge/tasks/main.yml new file mode 100644 index 0000000000..6e64c9dd4a --- /dev/null +++ b/test/integration/targets/win_regmerge/tasks/main.yml @@ -0,0 +1,133 @@ +# test code for the win_regmerge module +# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com> + +# 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/>. + +# clear the area of the registry we are using for tests +- name: remove setting + win_regedit: + key: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp' + state: absent + +# copy over some registry files to work with +- name: copy over some registry files to work with + win_copy: src={{item}} dest={{win_output_dir}}\\{{item}} + with_items: + - settings1.reg + - settings2.reg + - settings3.reg + +# test 1 - basic test of changed behaviour +# merge in REG_SZ +- name: test 1 merge in a setting + win_regmerge: + path: "{{win_output_dir}}\\settings1.reg" + register: merge11_result + +- assert: + that: + - "merge11_result.changed == true" + +# re run the merge +- name: test 1 merge in the setting again + win_regmerge: + path: "{{win_output_dir}}\\settings1.reg" + register: merge12_result + +# without a compare to key, should allways report changed +- assert: + that: + - "merge12_result.changed == true" +# assert changed false + +# prune reg key +- name: test 1 remove setting + win_regedit: + key: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp' + state: absent + +# +# test 2, observe behaviour when compare_to param is set +# +- name: test 2 merge in a setting + win_regmerge: + path: "{{win_output_dir}}\\settings1.reg" + compare_to: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp\Moosic\ILikeToMooveIt' + register: merge21_result + +- assert: + that: + - "merge21_result.changed == true" + +# re run the merge +- name: test 2 merge in the setting again but with compare_key + win_regmerge: + path: "{{win_output_dir}}\\settings1.reg" + compare_to: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp\Moosic\ILikeToMooveIt' + register: merge22_result + +# with a compare to key, should now report not changed +- assert: + that: + - "merge22_result.changed == false" +# assert changed false + +# prune the contents of the registry from the parent of the compare key downwards +- name: test 2 clean up remove setting + win_regedit: + key: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp' + state: absent + +# test 3 merge in more complex settings +- name: test 3 merge in a setting + win_regmerge: + path: "{{win_output_dir}}\\settings3.reg" + compare_to: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp\Moo Monitor' + register: merge31_result + +- assert: + that: + - "merge31_result.changed == true" + +# re run the merge +- name: test 3 merge in the setting again but with compare_key check + win_regmerge: + path: "{{win_output_dir}}\\settings3.reg" + compare_to: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp\Moo Monitor' + register: merge32_result + +# with a compare to key, should now report not changed +- assert: + that: + - "merge32_result.changed == false" +# assert changed false + +# prune the contents of the registry from the compare key downwards +- name: test 3 clean up remove setting + win_regedit: + key: 'HKLM:\SOFTWARE\Wow6432Node\Cow Corp' + state: absent + +# clean up registry files + +- name: clean up registry files + win_file: path={{win_output_dir}}\\{{item}} state=absent + with_items: + - settings1.reg + - settings2.reg + - settings3.reg + +# END OF win_regmerge tests diff --git a/test/integration/targets/win_regmerge/templates/win_line_ending.j2 b/test/integration/targets/win_regmerge/templates/win_line_ending.j2 new file mode 100644 index 0000000000..d0cefd76f4 --- /dev/null +++ b/test/integration/targets/win_regmerge/templates/win_line_ending.j2 @@ -0,0 +1,4 @@ +#jinja2: newline_sequence:'\r\n' +{{ templated_var }}
+{{ templated_var }}
+{{ templated_var }}
diff --git a/test/integration/targets/win_regmerge/vars/main.yml b/test/integration/targets/win_regmerge/vars/main.yml new file mode 100644 index 0000000000..1e8f64ccf4 --- /dev/null +++ b/test/integration/targets/win_regmerge/vars/main.yml @@ -0,0 +1 @@ +templated_var: templated_var_loaded diff --git a/test/integration/targets/win_script/defaults/main.yml b/test/integration/targets/win_script/defaults/main.yml new file mode 100644 index 0000000000..a2c6475e75 --- /dev/null +++ b/test/integration/targets/win_script/defaults/main.yml @@ -0,0 +1,5 @@ +--- + +# Parameters to pass to test scripts. +test_win_script_value: VaLuE +test_win_script_splat: "@{This='THIS'; That='THAT'; Other='OTHER'}" diff --git a/test/integration/targets/win_script/files/test_script.bat b/test/integration/targets/win_script/files/test_script.bat new file mode 100644 index 0000000000..05cc2d19ec --- /dev/null +++ b/test/integration/targets/win_script/files/test_script.bat @@ -0,0 +1,2 @@ +@ECHO OFF +ECHO We can even run a batch file! diff --git a/test/integration/targets/win_script/files/test_script.cmd b/test/integration/targets/win_script/files/test_script.cmd new file mode 100644 index 0000000000..0e36312d0f --- /dev/null +++ b/test/integration/targets/win_script/files/test_script.cmd @@ -0,0 +1,2 @@ +@ECHO OFF +ECHO We can even run a batch file with cmd extension! diff --git a/test/integration/targets/win_script/files/test_script.ps1 b/test/integration/targets/win_script/files/test_script.ps1 new file mode 100644 index 0000000000..9978f36341 --- /dev/null +++ b/test/integration/targets/win_script/files/test_script.ps1 @@ -0,0 +1,2 @@ +# Test script to make sure the Ansible script module works. +Write-Host "Woohoo! We can run a PowerShell script via Ansible!" diff --git a/test/integration/targets/win_script/files/test_script_bool.ps1 b/test/integration/targets/win_script/files/test_script_bool.ps1 new file mode 100644 index 0000000000..0484af70e5 --- /dev/null +++ b/test/integration/targets/win_script/files/test_script_bool.ps1 @@ -0,0 +1,6 @@ +Param( +[bool]$boolvariable +) + +Write-Host $boolvariable.GetType() +Write-Host $boolvariable diff --git a/test/integration/targets/win_script/files/test_script_creates_file.ps1 b/test/integration/targets/win_script/files/test_script_creates_file.ps1 new file mode 100644 index 0000000000..47f85a2d49 --- /dev/null +++ b/test/integration/targets/win_script/files/test_script_creates_file.ps1 @@ -0,0 +1,3 @@ +# Test script to create a file. + +echo $null > $args[0] diff --git a/test/integration/targets/win_script/files/test_script_removes_file.ps1 b/test/integration/targets/win_script/files/test_script_removes_file.ps1 new file mode 100644 index 0000000000..f0549a5b3b --- /dev/null +++ b/test/integration/targets/win_script/files/test_script_removes_file.ps1 @@ -0,0 +1,3 @@ +# Test script to remove a file. + +Remove-Item $args[0] -Force diff --git a/test/integration/targets/win_script/files/test_script_with_args.ps1 b/test/integration/targets/win_script/files/test_script_with_args.ps1 new file mode 100644 index 0000000000..520aafa395 --- /dev/null +++ b/test/integration/targets/win_script/files/test_script_with_args.ps1 @@ -0,0 +1,7 @@ +# Test script to make sure the Ansible script module works when arguments are +# passed to the script. + +foreach ($i in $args) +{ + Write-Host $i; +} diff --git a/test/integration/targets/win_script/files/test_script_with_errors.ps1 b/test/integration/targets/win_script/files/test_script_with_errors.ps1 new file mode 100644 index 0000000000..2d60dc1f19 --- /dev/null +++ b/test/integration/targets/win_script/files/test_script_with_errors.ps1 @@ -0,0 +1,9 @@ +# Test script to make sure we handle non-zero exit codes. + +trap +{ + Write-Error -ErrorRecord $_ + exit 1; +} + +throw "Oh noes I has an error" diff --git a/test/integration/targets/win_script/files/test_script_with_splatting.ps1 b/test/integration/targets/win_script/files/test_script_with_splatting.ps1 new file mode 100644 index 0000000000..429a9a3b7a --- /dev/null +++ b/test/integration/targets/win_script/files/test_script_with_splatting.ps1 @@ -0,0 +1,6 @@ +# Test script to make sure the Ansible script module works when arguments are +# passed via splatting (http://technet.microsoft.com/en-us/magazine/gg675931.aspx) + +Write-Host $args.This +Write-Host $args.That +Write-Host $args.Other diff --git a/test/integration/targets/win_script/tasks/main.yml b/test/integration/targets/win_script/tasks/main.yml new file mode 100644 index 0000000000..6cfa84ec00 --- /dev/null +++ b/test/integration/targets/win_script/tasks/main.yml @@ -0,0 +1,191 @@ +# test code for the script module when using winrm connection +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: get tempdir path + raw: $env:TEMP + register: tempdir + +- name: set script path dynamically + set_fact: + test_win_script_filename: "{{ tempdir.stdout_lines[0] }}/testing_win_script.txt" + +- name: run simple test script + script: test_script.ps1 + register: test_script_result + +- name: check that script ran + assert: + that: + - "test_script_result.rc == 0" + - "test_script_result.stdout" + - "'Woohoo' in test_script_result.stdout" + - "not test_script_result.stderr" + - "not test_script_result|failed" + - "test_script_result|changed" + +- name: run test script that takes arguments including a unicode char + script: test_script_with_args.ps1 /this /that /Ӧther + register: test_script_with_args_result + +- name: check that script ran and received arguments and returned unicode + assert: + that: + - "test_script_with_args_result.rc == 0" + - "test_script_with_args_result.stdout" + - "test_script_with_args_result.stdout_lines[0] == '/this'" + - "test_script_with_args_result.stdout_lines[1] == '/that'" + - "test_script_with_args_result.stdout_lines[2] == '/Ӧther'" + - "not test_script_with_args_result.stderr" + - "not test_script_with_args_result|failed" + - "test_script_with_args_result|changed" + +- name: run test script that takes parameters passed via splatting + script: test_script_with_splatting.ps1 @{ This = 'this'; That = '{{ test_win_script_value }}'; Other = 'other'} + register: test_script_with_splatting_result + +- name: check that script ran and received parameters via splatting + assert: + that: + - "test_script_with_splatting_result.rc == 0" + - "test_script_with_splatting_result.stdout" + - "test_script_with_splatting_result.stdout_lines[0] == 'this'" + - "test_script_with_splatting_result.stdout_lines[1] == test_win_script_value" + - "test_script_with_splatting_result.stdout_lines[2] == 'other'" + - "not test_script_with_splatting_result.stderr" + - "not test_script_with_splatting_result|failed" + - "test_script_with_splatting_result|changed" + +- name: run test script that takes splatted parameters from a variable + script: test_script_with_splatting.ps1 {{ test_win_script_splat }} + register: test_script_with_splatting2_result + +- name: check that script ran and received parameters via splatting from a variable + assert: + that: + - "test_script_with_splatting2_result.rc == 0" + - "test_script_with_splatting2_result.stdout" + - "test_script_with_splatting2_result.stdout_lines[0] == 'THIS'" + - "test_script_with_splatting2_result.stdout_lines[1] == 'THAT'" + - "test_script_with_splatting2_result.stdout_lines[2] == 'OTHER'" + - "not test_script_with_splatting2_result.stderr" + - "not test_script_with_splatting2_result|failed" + - "test_script_with_splatting2_result|changed" + +- name: run test script that has errors + script: test_script_with_errors.ps1 + register: test_script_with_errors_result + ignore_errors: true + +- name: check that script ran but failed with errors + assert: + that: + - "test_script_with_errors_result.rc != 0" + - "not test_script_with_errors_result.stdout" + - "test_script_with_errors_result.stderr" + - "test_script_with_errors_result|failed" + - "test_script_with_errors_result|changed" + +- name: cleanup test file if it exists + raw: Remove-Item "{{test_win_script_filename}}" -Force + ignore_errors: true + +- name: run test script that creates a file + script: test_script_creates_file.ps1 "{{test_win_script_filename}}" creates="{{test_win_script_filename}}" + register: test_script_creates_file_result + +- name: check that script ran and indicated a change + assert: + that: + - "test_script_creates_file_result.rc == 0" + - "not test_script_creates_file_result.stdout" + - "not test_script_creates_file_result.stderr" + - "not test_script_creates_file_result|failed" + - "test_script_creates_file_result|changed" + +- name: run test script that creates a file again + script: test_script_creates_file.ps1 "{{test_win_script_filename}}" creates="{{test_win_script_filename}}" + register: test_script_creates_file_again_result + +- name: check that the script did not run since the remote file exists + assert: + that: + - "not test_script_creates_file_again_result|failed" + - "not test_script_creates_file_again_result|changed" + - "test_script_creates_file_again_result|skipped" + +- name: run test script that removes a file + script: test_script_removes_file.ps1 "{{test_win_script_filename}}" removes="{{test_win_script_filename}}" + register: test_script_removes_file_result + +- name: check that the script ran since the remote file exists + assert: + that: + - "test_script_removes_file_result.rc == 0" + - "not test_script_removes_file_result.stdout" + - "not test_script_removes_file_result.stderr" + - "not test_script_removes_file_result|failed" + - "test_script_removes_file_result|changed" + +- name: run test script that removes a file again + script: test_script_removes_file.ps1 "{{test_win_script_filename}}" removes="{{test_win_script_filename}}" + register: test_script_removes_file_again_result + +- name: check that the script did not run since the remote file does not exist + assert: + that: + - "not test_script_removes_file_again_result|failed" + - "not test_script_removes_file_again_result|changed" + - "test_script_removes_file_again_result|skipped" + +- name: run simple batch file + script: test_script.bat + register: test_batch_result + +- name: check that batch file ran + assert: + that: + - "test_batch_result.rc == 0" + - "test_batch_result.stdout" + - "'batch' in test_batch_result.stdout" + - "not test_batch_result.stderr" + - "not test_batch_result|failed" + - "test_batch_result|changed" + +- name: run simple batch file with .cmd extension + script: test_script.cmd + register: test_cmd_result + +- name: check that batch file with .cmd extension ran + assert: + that: + - "test_cmd_result.rc == 0" + - "test_cmd_result.stdout" + - "'cmd extension' in test_cmd_result.stdout" + - "not test_cmd_result.stderr" + - "not test_cmd_result|failed" + - "test_cmd_result|changed" + +- name: run test script that takes a boolean parameter + script: test_script_bool.ps1 $true + register: test_script_bool_result + +- name: check that the script ran and the parameter was treated as a boolean + assert: + that: + - "test_script_bool_result.stdout_lines[0] == 'System.Boolean'" + - "test_script_bool_result.stdout_lines[1] == 'True'" diff --git a/test/integration/targets/win_service/defaults/main.yml b/test/integration/targets/win_service/defaults/main.yml new file mode 100644 index 0000000000..1f38717aa4 --- /dev/null +++ b/test/integration/targets/win_service/defaults/main.yml @@ -0,0 +1,5 @@ +--- + +# Service is commonly available and usually disabled/stopped by default. +test_win_service_name: SSDPSRV +test_win_service_display_name: "SSDP Discovery" diff --git a/test/integration/targets/win_service/tasks/main.yml b/test/integration/targets/win_service/tasks/main.yml new file mode 100644 index 0000000000..39562c4dcf --- /dev/null +++ b/test/integration/targets/win_service/tasks/main.yml @@ -0,0 +1,196 @@ +# test code for the win_service module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: test win_service module with short name + win_service: name="{{ test_win_service_name }}" + register: win_service_name + +- name: check win_service result with short name + assert: + that: + - "not win_service_name|changed" + - "win_service_name.name" + - "win_service_name.display_name" + - "win_service_name.start_mode" + - "win_service_name.state" + +- name: test win_service module with display name + win_service: name="{{ test_win_service_display_name }}" + register: win_service_display_name + +- name: check win_service result with display name + assert: + that: + - "not win_service_display_name|changed" + - "win_service_display_name.name" + - "win_service_display_name.display_name" + - "win_service_display_name.start_mode" + - "win_service_display_name.state" + +- name: test win_service module with invalid name + win_service: name="iamnotaservice" + ignore_errors: true + register: win_service_invalid + +- name: check win_service result with invalid_name + assert: + that: + - "win_service_invalid|failed" + - "win_service_invalid.msg" + +- name: make sure the service is stopped and disabled + win_service: name="{{ test_win_service_name }}" state=stopped start_mode=disabled + register: win_service_stopped_disabled + +- name: check result of disabling and stopping the service + assert: + that: + - "win_service_stopped_disabled.start_mode == 'disabled'" + - "win_service_stopped_disabled.state == 'stopped'" + +- name: try to start the disabled service + win_service: name="{{ test_win_service_name }}" state=started + register: win_service_start_disabled + ignore_errors: true + +- name: check that starting the disabled service fails + assert: + that: + - "win_service_start_disabled|failed" + - "win_service_start_disabled.msg" + +- name: enable the service for manual startup + win_service: name="{{ test_win_service_name }}" start_mode=manual + register: win_service_manual_start_mode + +- name: check that enabling the service succeeds for manual startup + assert: + that: + - "win_service_manual_start_mode|changed" + - "win_service_manual_start_mode.start_mode == 'manual'" + - "win_service_manual_start_mode.state == 'stopped'" + +- name: enable the service again for manual startup + win_service: name="{{ test_win_service_name }}" start_mode=manual + register: win_service_manual_start_mode_again + +- name: check that enabling the service succeeds for manual startup + assert: + that: + - "not win_service_manual_start_mode_again|changed" + - "win_service_manual_start_mode_again.start_mode == 'manual'" + - "win_service_manual_start_mode_again.state == 'stopped'" + +- name: try to start the manual service + win_service: name="{{ test_win_service_name }}" state=started + register: win_service_start_manual + +- name: check that starting the manual service succeeds + assert: + that: + - "win_service_start_manual|changed" + - "win_service_start_manual.start_mode == 'manual'" + - "win_service_start_manual.state == 'running'" + +- name: try to start the manual service again + win_service: name="{{ test_win_service_name }}" state=started + register: win_service_start_manual_again + +- name: check that starting the manual service again succeeds without changes + assert: + that: + - "not win_service_start_manual_again|changed" + - "win_service_start_manual_again.start_mode == 'manual'" + - "win_service_start_manual_again.state == 'running'" + +- name: enable the service for automatic startup + win_service: name="{{ test_win_service_name }}" start_mode=auto + register: win_service_auto_start_mode + +- name: check that enabling the service succeeds for automatic startup + assert: + that: + - "win_service_auto_start_mode|changed" + - "win_service_auto_start_mode.start_mode == 'auto'" + - "win_service_auto_start_mode.state == 'running'" + +- name: enable the service again for automatic startup + win_service: name="{{ test_win_service_name }}" start_mode=auto + register: win_service_auto_start_mode_again + +- name: check that enabling the service succeeds for automatic startup without changes + assert: + that: + - "not win_service_auto_start_mode_again|changed" + - "win_service_auto_start_mode_again.start_mode == 'auto'" + - "win_service_auto_start_mode_again.state == 'running'" + +- name: restart the service + win_service: name="{{ test_win_service_name }}" state=restarted + register: win_service_restart_auto + +- name: check that restarting the service succeeds with changes + assert: + that: + - "win_service_restart_auto|changed" + - "win_service_restart_auto.start_mode == 'auto'" + - "win_service_restart_auto.state == 'running'" + +- name: disable the service again + win_service: name="{{ test_win_service_name }}" start_mode=disabled + register: win_service_disabled_start_mode + +- name: check that disabling the service succeeds, service is still running + assert: + that: + - "win_service_disabled_start_mode|changed" + - "win_service_disabled_start_mode.start_mode == 'disabled'" + - "win_service_disabled_start_mode.state == 'running'" + +- name: disable the service again + win_service: name="{{ test_win_service_name }}" start_mode=disabled + register: win_service_disabled_start_mode_again + +- name: check that disabling the service succeeds again + assert: + that: + - "not win_service_disabled_start_mode_again|changed" + - "win_service_disabled_start_mode_again.start_mode == 'disabled'" + - "win_service_disabled_start_mode_again.state == 'running'" + +- name: stop the service + win_service: name="{{ test_win_service_name }}" state=stopped + register: win_service_stop_disabled + +- name: check that stopping the service succeeds with changes + assert: + that: + - "win_service_stop_disabled|changed" + - "win_service_stop_disabled.start_mode == 'disabled'" + - "win_service_stop_disabled.state == 'stopped'" + +- name: stop the service again + win_service: name="{{ test_win_service_name }}" state=stopped + register: win_service_stop_disabled_again + +- name: check that stopping the service again succeeds without changes + assert: + that: + - "not win_service_stop_disabled_again|changed" + - "win_service_stop_disabled_again.start_mode == 'disabled'" + - "win_service_stop_disabled_again.state == 'stopped'" diff --git a/test/integration/targets/win_setup/tasks/main.yml b/test/integration/targets/win_setup/tasks/main.yml new file mode 100644 index 0000000000..123eaeffe2 --- /dev/null +++ b/test/integration/targets/win_setup/tasks/main.yml @@ -0,0 +1,57 @@ +# test code for the setup module when using winrm connection +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: test setup module + action: setup + register: setup_result + +- name: check windows setup result + assert: + that: + - "not setup_result|failed" + - "not setup_result|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" + +- 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 diff --git a/test/integration/targets/win_shell/tasks/main.yml b/test/integration/targets/win_shell/tasks/main.yml new file mode 100644 index 0000000000..12e9870b9c --- /dev/null +++ b/test/integration/targets/win_shell/tasks/main.yml @@ -0,0 +1,175 @@ +- name: execute a powershell cmdlet + win_shell: Write-Output "hello from Ansible" + register: shellout + +- name: validate result + assert: + that: + - shellout|success + - shellout|changed + - shellout.cmd == 'Write-Output "hello from Ansible"' + - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$') + - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.rc == 0 + - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.stderr == "" + - shellout.stdout == "hello from Ansible\r\n" + - shellout.stdout_lines == ["hello from Ansible"] + - shellout.warnings == [] + +- name: execute a powershell cmdlet with multi-line output + win_shell: Write-Output "hello from Ansible"; Write-Output "another line"; Write-Output "yet another line" + register: shellout + +- name: validate result + assert: + that: + - shellout|success + - shellout|changed + - shellout.cmd == 'Write-Output "hello from Ansible"; Write-Output "another line"; Write-Output "yet another line"' + - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$') + - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.rc == 0 + - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.stderr == "" + - shellout.stdout == "hello from Ansible\r\nanother line\r\nyet another line\r\n" + - shellout.stdout_lines == ["hello from Ansible","another line", "yet another line"] + - shellout.warnings == [] + +- name: execute something nonexistent + win_shell: bogus_command1234 + register: shellout + ignore_errors: true + +- name: validate result + assert: + that: + - shellout|failed + - shellout|changed + - shellout.cmd == 'bogus_command1234' + - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$') + - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.rc == 1 + - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.stderr is search('not recognized') + - shellout.stdout == "" + - shellout.stdout_lines == [] + - shellout.warnings == [] + +- name: execute something with error output + win_shell: Write-Error "it broke"; Write-Output "some output" + register: shellout + +- name: validate result + assert: + that: + - shellout|success + - shellout|changed + - shellout.cmd == 'Write-Error "it broke"; Write-Output "some output"' + - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$') + - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.rc == 0 + - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$') + - shellout.stderr is search('it broke') + - shellout.stdout == "some output\r\n" + - shellout.stdout_lines == ["some output"] + - shellout.warnings == [] + +- name: ensure test file is absent + win_file: + path: c:\testfile.txt + state: absent + +- name: run with creates, should create + win_shell: echo $null >> c:\testfile.txt + args: + creates: c:\testfile.txt + register: shellout + +- name: validate result + assert: + that: + - shellout|success + - shellout|changed + +- name: run again with creates, should skip + win_shell: echo $null >> c:\testfile.txt + args: + creates: c:\testfile.txt + register: shellout + +- name: validate result + assert: + that: + - shellout|skipped + - shellout.msg is search('exists') + +- name: ensure testfile is still present + win_stat: + path: c:\testfile.txt + register: statout + +- name: validate result + assert: + that: + - statout.stat.exists == true + +- name: run with removes, should remove + win_shell: Remove-Item c:\testfile.txt + args: + removes: c:\testfile.txt + register: shellout + +- name: validate result + assert: + that: + - shellout|success + - shellout|changed + +- name: run again with removes, should skip + win_shell: echo $null >> c:\testfile.txt + args: + removes: c:\testfile.txt + register: shellout + +- name: validate result + assert: + that: + - shellout|skipped + - shellout.msg is search('does not exist') + +- name: run something with known nonzero exit code + win_shell: exit 254 + register: shellout + ignore_errors: true + +- name: validate result + assert: + that: + - shellout|failed + - shellout.rc == 254 + +- name: run something via cmd that will fail in powershell + win_shell: echo line1 & echo.line2 + args: + executable: cmd + register: shellout + +- name: validate result + assert: + that: + - shellout|success + - shellout|changed + - shellout.rc == 0 + - shellout.stdout == "line1 \r\nline2\r\n" + - shellout.stdout_lines == ["line1 ", "line2"] + - shellout.stderr == "" + +- name: write large buffer to stdout + win_shell: $ba = New-Object byte[] 16384; (New-Object System.Random 32).NextBytes($ba); [Convert]::ToBase64String($ba) | Write-Output + register: shellout + +# TODO: fix small buffer deadlock on large write to stderr before stdout has been consumed +#- name: write large buffer to stderr +# win_shell: $ba = New-Object byte[] 16384; (New-Object System.Random 32).NextBytes($ba); [Convert]::ToBase64String($ba) | Write-Error; Write-Output test +# register: shellout
\ No newline at end of file diff --git a/test/integration/targets/win_slurp/tasks/main.yml b/test/integration/targets/win_slurp/tasks/main.yml new file mode 100644 index 0000000000..b72b74238b --- /dev/null +++ b/test/integration/targets/win_slurp/tasks/main.yml @@ -0,0 +1,77 @@ +# test code for the slurp module when using winrm connection +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: test slurping an existing file + slurp: src="C:/Windows/win.ini" + register: slurp_existing + +- name: check slurp existing result + assert: + that: + - "slurp_existing.content" + - "slurp_existing.encoding == 'base64'" + - "not slurp_existing|changed" + - "not slurp_existing|failed" + +- name: test slurping a large binary file with path param and backslashes + slurp: path="C:\Windows\explorer.exe" + register: slurp_path_backslashes + +- name: check slurp result with path param and backslashes + assert: + that: + - "slurp_path_backslashes.content" + - "slurp_path_backslashes.encoding == 'base64'" + - "not slurp_path_backslashes|changed" + - "not slurp_path_backslashes|failed" + +- name: test slurping a non-existent file + slurp: src="C:/this_file_should_not_exist.txt" + register: slurp_missing + ignore_errors: true + +- name: check slurp missing result + assert: + that: + - "slurp_missing|failed" + - "slurp_missing.msg" + - "not slurp_missing|changed" + +- name: test slurping a directory + slurp: src="C:/Windows" + register: slurp_dir + ignore_errors: true + +- name: check slurp directory result + assert: + that: + - "slurp_dir|failed" + - "slurp_dir.msg" + - "not slurp_dir|changed" + +- name: test slurp with missing argument + action: slurp + register: slurp_no_args + ignore_errors: true + +- name: check slurp with missing argument result + assert: + that: + - "slurp_no_args|failed" + - "slurp_no_args.msg" + - "not slurp_no_args|changed" diff --git a/test/integration/targets/win_stat/tasks/main.yml b/test/integration/targets/win_stat/tasks/main.yml new file mode 100644 index 0000000000..5197c27fef --- /dev/null +++ b/test/integration/targets/win_stat/tasks/main.yml @@ -0,0 +1,98 @@ +# test code for the win_stat module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: test win_stat module on file + win_stat: path="C:/Windows/win.ini" + register: win_stat_file + +- name: check win_stat file result + assert: + that: + - "win_stat_file.stat.exists" + - "not win_stat_file.stat.isdir" + - "win_stat_file.stat.size > 0" + - "win_stat_file.stat.md5" + - "win_stat_file.stat.extension" + - "win_stat_file.stat.attributes" + - "win_stat_file.stat.owner" + - "win_stat_file.stat.creationtime" + - "win_stat_file.stat.lastaccesstime" + - "win_stat_file.stat.lastwritetime" + - "not win_stat_file|failed" + - "not win_stat_file|changed" + +- name: test win_stat module on file without md5 and backslashes + win_stat: path="C:\Windows\win.ini" get_md5=no + register: win_stat_file_no_md5 + +- name: check win_stat file result without md5 + assert: + that: + - "win_stat_file_no_md5.stat.exists" + - "not win_stat_file_no_md5.stat.isdir" + - "win_stat_file_no_md5.stat.size > 0" + - "not win_stat_file_no_md5.stat.md5|default('')" + - "win_stat_file_no_md5.stat.extension" + - "win_stat_file_no_md5.stat.attributes" + - "win_stat_file_no_md5.stat.owner" + - "win_stat_file_no_md5.stat.creationtime" + - "win_stat_file_no_md5.stat.lastaccesstime" + - "win_stat_file_no_md5.stat.lastwritetime" + - "not win_stat_file_no_md5|failed" + - "not win_stat_file_no_md5|changed" + +- name: test win_stat module on directory + win_stat: path="C:\\Windows" + register: win_stat_dir + +- name: check win_stat dir result + assert: + that: + - "win_stat_dir.stat.exists" + - "win_stat_dir.stat.isdir" + - "win_stat_dir.stat.extension == ''" + - "win_stat_dir.stat.attributes" + - "win_stat_dir.stat.owner" + - "win_stat_dir.stat.creationtime" + - "win_stat_dir.stat.lastaccesstime" + - "win_stat_dir.stat.lastwritetime" + - "not win_stat_dir|failed" + - "not win_stat_dir|changed" + +- name: test win_stat module non-existent path + win_stat: path="C:/this_file_should_not_exist.txt" + register: win_stat_missing + +- name: check win_stat missing result + assert: + that: + - "not win_stat_missing.stat.exists" + - "not win_stat_missing|failed" + - "not win_stat_missing|changed" + +- name: test win_stat module without path argument + action: win_stat + register: win_stat_no_args + ignore_errors: true + +- name: check win_stat result with no path argument + assert: + that: + - "win_stat_no_args|failed" + - "win_stat_no_args.msg" + - "not win_stat_no_args|changed" diff --git a/test/integration/targets/win_template/files/foo.txt b/test/integration/targets/win_template/files/foo.txt new file mode 100644 index 0000000000..3e96db9b3e --- /dev/null +++ b/test/integration/targets/win_template/files/foo.txt @@ -0,0 +1 @@ +templated_var_loaded diff --git a/test/integration/targets/win_template/meta/main.yml b/test/integration/targets/win_template/meta/main.yml new file mode 100644 index 0000000000..55200b3fc6 --- /dev/null +++ b/test/integration/targets/win_template/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_win_tests + diff --git a/test/integration/targets/win_template/tasks/main.yml b/test/integration/targets/win_template/tasks/main.yml new file mode 100644 index 0000000000..c276b8d323 --- /dev/null +++ b/test/integration/targets/win_template/tasks/main.yml @@ -0,0 +1,114 @@ +# test code for the template module +# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com> + +# 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/>. + +- name: fill in a basic template +# win_template: src=foo.j2 dest={{win_output_dir}}/foo.templated mode=0644 + win_template: src=foo.j2 dest={{win_output_dir}}/foo.templated + register: template_result + +- assert: + that: + - "'changed' in template_result" +# - "'dest' in template_result" +# - "'group' in template_result" +# - "'gid' in template_result" +# - "'checksum' in template_result" +# - "'owner' in template_result" +# - "'size' in template_result" +# - "'src' in template_result" +# - "'state' in template_result" +# - "'uid' in template_result" + +- name: verify that the file was marked as changed + assert: + that: + - "template_result.changed == true" + +- name: fill in a basic template again + win_template: + src: foo.j2 + dest: "{{win_output_dir}}/foo.templated" + register: template_result2 + +- name: verify that the template was not changed + assert: + that: + - "not template_result2|changed" + +# VERIFY CONTENTS + +- name: copy known good into place + win_copy: src=foo.txt dest={{win_output_dir}}\\foo.txt + +- name: compare templated file to known good + raw: fc.exe {{win_output_dir}}\\foo.templated {{win_output_dir}}\\foo.txt + register: diff_result + +- debug: var=diff_result + +- name: verify templated file matches known good + assert: + that: +# - 'diff_result.stdout == ""' + - 'diff_result.stdout_lines[1] == "FC: no differences encountered"' + - "diff_result.rc == 0" + +# VERIFY MODE +# can't set file mode on windows so commenting this test out +#- name: set file mode +# win_file: path={{win_output_dir}}/foo.templated mode=0644 +# register: file_result + +#- name: ensure file mode did not change +# assert: +# that: +# - "file_result.changed != True" + +# commenting out all the following tests as expanduser and file modes not windows concepts. + +# VERIFY dest as a directory does not break file attributes +# Note: expanduser is needed to go down the particular codepath that was broken before +#- name: setup directory for test +# win_file: state=directory dest={{win_output_dir | expanduser}}/template-dir mode=0755 owner=nobody group=root + +#- name: set file mode when the destination is a directory +# win_template: src=foo.j2 dest={{win_output_dir | expanduser}}/template-dir/ mode=0600 owner=root group=root + +#- name: set file mode when the destination is a directory +# win_template: src=foo.j2 dest={{win_output_dir | expanduser}}/template-dir/ mode=0600 owner=root group=root +# register: file_result +# +#- name: check that the file has the correct attributes +# win_stat: path={{win_output_dir | expanduser}}/template-dir/foo.j2 +# register: file_attrs +# +#- assert: +# that: +# - "file_attrs.stat.uid == 0" +# - "file_attrs.stat.pw_name == 'root'" +# - "file_attrs.stat.mode == '0600'" +# +#- name: check that the containing directory did not change attributes +# win_stat: path={{win_output_dir | expanduser}}/template-dir/ +# register: dir_attrs +# +#- assert: +# that: +# - "dir_attrs.stat.uid != 0" +# - "dir_attrs.stat.pw_name == 'nobody'" +# - "dir_attrs.stat.mode == '0755'" diff --git a/test/integration/targets/win_template/templates/foo.j2 b/test/integration/targets/win_template/templates/foo.j2 new file mode 100644 index 0000000000..55aab8f1ea --- /dev/null +++ b/test/integration/targets/win_template/templates/foo.j2 @@ -0,0 +1 @@ +{{ templated_var }} diff --git a/test/integration/targets/win_template/vars/main.yml b/test/integration/targets/win_template/vars/main.yml new file mode 100644 index 0000000000..1e8f64ccf4 --- /dev/null +++ b/test/integration/targets/win_template/vars/main.yml @@ -0,0 +1 @@ +templated_var: templated_var_loaded diff --git a/test/integration/targets/win_user/defaults/main.yml b/test/integration/targets/win_user/defaults/main.yml new file mode 100644 index 0000000000..c6a18ed3a3 --- /dev/null +++ b/test/integration/targets/win_user/defaults/main.yml @@ -0,0 +1,5 @@ +--- + +test_win_user_name: test_win_user +test_win_user_password: "T35Tus3rP@ssW0rd" +test_win_user_password2: "pa55wOrd4te5tU53R!" diff --git a/test/integration/targets/win_user/files/lockout_user.ps1 b/test/integration/targets/win_user/files/lockout_user.ps1 new file mode 100644 index 0000000000..e15f13f3bf --- /dev/null +++ b/test/integration/targets/win_user/files/lockout_user.ps1 @@ -0,0 +1,17 @@ +trap +{ + Write-Error -ErrorRecord $_ + exit 1; +} + +$username = $args[0] +[void][system.reflection.assembly]::LoadWithPartialName('System.DirectoryServices.AccountManagement') +$pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Machine', $env:COMPUTERNAME +For ($i = 1; $i -le 10; $i++) { + try { + $pc.ValidateCredentials($username, 'b@DP@ssw0rd') + } + catch { + break + } +} diff --git a/test/integration/targets/win_user/tasks/main.yml b/test/integration/targets/win_user/tasks/main.yml new file mode 100644 index 0000000000..d8f237fea8 --- /dev/null +++ b/test/integration/targets/win_user/tasks/main.yml @@ -0,0 +1,431 @@ +# test code for the win_user module +# (c) 2014, Chris Church <chris@ninemoreminutes.com> + +# 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/>. + +- name: remove existing test user if present + win_user: name="{{ test_win_user_name }}" state="absent" + register: win_user_remove_result + +- name: check user removal result + assert: + that: + - "win_user_remove_result.name" + - "win_user_remove_result.state == 'absent'" + +- name: try to remove test user again + win_user: name="{{ test_win_user_name }}" state="absent" + register: win_user_remove_result_again + +- name: check user removal result again + assert: + that: + - "not win_user_remove_result_again|changed" + - "win_user_remove_result_again.name" + - "win_user_remove_result_again.msg" + - "win_user_remove_result.state == 'absent'" + +- name: test missing user with query state + win_user: name="{{ test_win_user_name }}" state="query" + register: win_user_missing_query_result + +- name: check missing query result + assert: + that: + - "not win_user_missing_query_result|changed" + - "win_user_missing_query_result.name" + - "win_user_missing_query_result.msg" + - "win_user_missing_query_result.state == 'absent'" + +- name: test create user + win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password }}" fullname="Test User" description="Test user account" groups="Guests" + register: win_user_create_result + +- name: check user creation result + assert: + that: + - "win_user_create_result|changed" + - "win_user_create_result.name == '{{ test_win_user_name }}'" + - "win_user_create_result.fullname == 'Test User'" + - "win_user_create_result.description == 'Test user account'" + - "win_user_create_result.path" + - "win_user_create_result.state == 'present'" + +- name: update user full name and description + win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible" groups="" + register: win_user_update_result + +- name: check full name and description update result + assert: + that: + - "win_user_update_result|changed" + - "win_user_update_result.fullname == 'Test Ansible User'" + - "win_user_update_result.description == 'Test user account created by Ansible'" + +- name: update user full name and description again with same values + win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible" + register: win_user_update_result_again + +- name: check full name and description result again + assert: + that: + - "not win_user_update_result_again|changed" + - "win_user_update_result_again.fullname == 'Test Ansible User'" + - "win_user_update_result_again.description == 'Test user account created by Ansible'" + +- name: test again with no options or changes + win_user: name="{{ test_win_user_name }}" + register: win_user_nochange_result + +- name: check no changes result + assert: + that: + - "not win_user_nochange_result|changed" + +- name: test again with query state + win_user: name="{{ test_win_user_name }}" state="query" + register: win_user_query_result + +- name: check query result + assert: + that: + - "not win_user_query_result|changed" + - "win_user_query_result.state == 'present'" + - "win_user_query_result.name == '{{ test_win_user_name }}'" + - "win_user_query_result.fullname == 'Test Ansible User'" + - "win_user_query_result.description == 'Test user account created by Ansible'" + - "win_user_query_result.path" + - "win_user_query_result.sid" + - "win_user_query_result.groups == []" + +- name: change user password + win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}" + register: win_user_password_result + +- name: check password change result + assert: + that: + - "win_user_password_result|changed" + +- name: change user password again to same value + win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}" + register: win_user_password_result_again + +- name: check password change result again + assert: + that: + - "not win_user_password_result_again|changed" + +- name: check update_password=on_create for existing user + win_user: name="{{ test_win_user_name }}" password="ThisP@ssW0rdShouldNotBeUsed" update_password=on_create + register: win_user_nopasschange_result + +- name: check password change with on_create flag result + assert: + that: + - "not win_user_nopasschange_result|changed" + +- name: set password expired flag + win_user: name="{{ test_win_user_name }}" password_expired=yes + register: win_user_password_expired_result + +- name: check password expired result + assert: + that: + - "win_user_password_expired_result|changed" + - "win_user_password_expired_result.password_expired" + +- name: set password when expired + win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always + register: win_user_can_set_password_on_expired + +- name: check set password on expired result + assert: + that: + - win_user_can_set_password_on_expired|changed + +- name: set password expired flag again + win_user: name="{{ test_win_user_name }}" password_expired=yes + register: win_user_password_expired_result + +- name: check password expired result + assert: + that: + - "win_user_password_expired_result|changed" + - "win_user_password_expired_result.password_expired" + +- name: clear password expired flag + win_user: name="{{ test_win_user_name }}" password_expired=no + register: win_user_clear_password_expired_result + +- name: check clear password expired result + assert: + that: + - "win_user_clear_password_expired_result|changed" + - "not win_user_clear_password_expired_result.password_expired" + +- name: set password never expires flag + win_user: name="{{ test_win_user_name }}" password_never_expires=yes + register: win_user_password_never_expires_result + +- name: check password never expires result + assert: + that: + - "win_user_password_never_expires_result|changed" + - "win_user_password_never_expires_result.password_never_expires" + +- name: clear password never expires flag + win_user: name="{{ test_win_user_name }}" password_never_expires=no + register: win_user_clear_password_never_expires_result + +- name: check clear password never expires result + assert: + that: + - "win_user_clear_password_never_expires_result|changed" + - "not win_user_clear_password_never_expires_result.password_never_expires" + +- name: set user cannot change password flag + win_user: name="{{ test_win_user_name }}" user_cannot_change_password=yes + register: win_user_cannot_change_password_result + +- name: check user cannot change password result + assert: + that: + - "win_user_cannot_change_password_result|changed" + - "win_user_cannot_change_password_result.user_cannot_change_password" + +- name: clear user cannot change password flag + win_user: name="{{ test_win_user_name }}" user_cannot_change_password=no + register: win_user_can_change_password_result + +- name: check clear user cannot change password result + assert: + that: + - "win_user_can_change_password_result|changed" + - "not win_user_can_change_password_result.user_cannot_change_password" + +- name: set account disabled flag + win_user: name="{{ test_win_user_name }}" account_disabled=true + register: win_user_account_disabled_result + +- name: check account disabled result + assert: + that: + - "win_user_account_disabled_result|changed" + - "win_user_account_disabled_result.account_disabled" + +- name: set password on disabled account + win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always + register: win_user_can_set_password_on_disabled + +- name: check set password on disabled result + assert: + that: + - win_user_can_set_password_on_disabled|changed + - win_user_can_set_password_on_disabled.account_disabled + +- name: clear account disabled flag + win_user: name="{{ test_win_user_name }}" account_disabled=false + register: win_user_clear_account_disabled_result + +- name: check clear account disabled result + assert: + that: + - "win_user_clear_account_disabled_result|changed" + - "not win_user_clear_account_disabled_result.account_disabled" + +- name: attempt to set account locked flag + win_user: name="{{ test_win_user_name }}" account_locked=yes + register: win_user_set_account_locked_result + ignore_errors: true + +- name: verify that attempting to set account locked flag fails + assert: + that: + - "win_user_set_account_locked_result|failed" + - "not win_user_set_account_locked_result|changed" + +- name: attempt to lockout test account + script: lockout_user.ps1 "{{ test_win_user_name }}" + +- name: get user to check if account locked flag is set + win_user: name="{{ test_win_user_name }}" state="query" + register: win_user_account_locked_result + +- name: clear account locked flag if set + win_user: name="{{ test_win_user_name }}" account_locked=no + register: win_user_clear_account_locked_result + when: "win_user_account_locked_result.account_locked" + +- name: check clear account lockout result if account was locked + assert: + that: + - "win_user_clear_account_locked_result|changed" + - "not win_user_clear_account_locked_result.account_locked" + when: "win_user_account_locked_result.account_locked" + +- name: assign test user to a group + win_user: name="{{ test_win_user_name }}" groups="Users" + register: win_user_replace_groups_result + +- name: check assign user to group result + assert: + that: + - "win_user_replace_groups_result|changed" + - "win_user_replace_groups_result.groups|length == 1" + - "win_user_replace_groups_result.groups[0]['name'] == 'Users'" + +- name: assign test user to the same group + win_user: + name: "{{ test_win_user_name }}" + groups: ["Users"] + register: win_user_replace_groups_again_result + +- name: check assign user to group again result + assert: + that: + - "not win_user_replace_groups_again_result|changed" + +- name: add user to another group + win_user: name="{{ test_win_user_name }}" groups="Power Users" groups_action="add" + register: win_user_add_groups_result + +- name: check add user to another group result + assert: + that: + - "win_user_add_groups_result|changed" + - "win_user_add_groups_result.groups|length == 2" + - "win_user_add_groups_result.groups[0]['name'] in ('Users', 'Power Users')" + - "win_user_add_groups_result.groups[1]['name'] in ('Users', 'Power Users')" + +- name: add user to another group again + win_user: + name: "{{ test_win_user_name }}" + groups: "Power Users" + groups_action: add + register: win_user_add_groups_again_result + +- name: check add user to another group again result + assert: + that: + - "not win_user_add_groups_again_result|changed" + +- name: remove user from a group + win_user: name="{{ test_win_user_name }}" groups="Users" groups_action="remove" + register: win_user_remove_groups_result + +- name: check remove user from group result + assert: + that: + - "win_user_remove_groups_result|changed" + - "win_user_remove_groups_result.groups|length == 1" + - "win_user_remove_groups_result.groups[0]['name'] == 'Power Users'" + +- name: remove user from a group again + win_user: + name: "{{ test_win_user_name }}" + groups: + - "Users" + groups_action: remove + register: win_user_remove_groups_again_result + +- name: check remove user from group again result + assert: + that: + - "not win_user_remove_groups_again_result|changed" + +- name: reassign test user to multiple groups + win_user: name="{{ test_win_user_name }}" groups="Users, Guests" groups_action="replace" + register: win_user_reassign_groups_result + +- name: check reassign user groups result + assert: + that: + - "win_user_reassign_groups_result|changed" + - "win_user_reassign_groups_result.groups|length == 2" + - "win_user_reassign_groups_result.groups[0]['name'] in ('Users', 'Guests')" + - "win_user_reassign_groups_result.groups[1]['name'] in ('Users', 'Guests')" + +- name: reassign test user to multiple groups again + win_user: + name: "{{ test_win_user_name }}" + groups: + - "Users" + - "Guests" + groups_action: replace + register: win_user_reassign_groups_again_result + +- name: check reassign user groups again result + assert: + that: + - "not win_user_reassign_groups_again_result|changed" + +- name: remove user from all groups + win_user: name="{{ test_win_user_name }}" groups="" + register: win_user_remove_all_groups_result + +- name: check remove user from all groups result + assert: + that: + - "win_user_remove_all_groups_result|changed" + - "win_user_remove_all_groups_result.groups|length == 0" + +- name: remove user from all groups again + win_user: + name: "{{ test_win_user_name }}" + groups: [] + register: win_user_remove_all_groups_again_result + +- name: check remove user from all groups again result + assert: + that: + - "not win_user_remove_all_groups_again_result|changed" + +- name: assign user to invalid group + win_user: name="{{ test_win_user_name }}" groups="Userz" + register: win_user_invalid_group_result + ignore_errors: true + +- name: check invalid group result + assert: + that: + - "win_user_invalid_group_result|failed" + - "win_user_invalid_group_result.msg" + - win_user_invalid_group_result.msg | match("group 'Userz' not found") + +- name: remove test user when finished + win_user: name="{{ test_win_user_name }}" state="absent" + register: win_user_final_remove_result + +- name: check final user removal result + assert: + that: + - "win_user_final_remove_result|changed" + - "win_user_final_remove_result.name" + - "win_user_final_remove_result.msg" + - "win_user_final_remove_result.state == 'absent'" + +- name: test removed user with query state + win_user: name="{{ test_win_user_name }}" state="query" + register: win_user_removed_query_result + +- name: check removed query result + assert: + that: + - "not win_user_removed_query_result|changed" + - "win_user_removed_query_result.name" + - "win_user_removed_query_result.msg" + - "win_user_removed_query_result.state == 'absent'" |