summaryrefslogtreecommitdiff
path: root/test/integration/targets
diff options
context:
space:
mode:
authorMatt Clay <matt@mystile.com>2016-10-13 10:03:19 -0700
committerJohn R Barker <john@johnrbarker.com>2016-10-13 18:03:19 +0100
commitc2ec86cb78f3c43bc5f2484d1888571e27225702 (patch)
tree43602995d1b5b009de1e1d4a7bc1a835f60204b7 /test/integration/targets
parent9182619fef4151d04d28b30b8a6f33e469560f5f (diff)
downloadansible-c2ec86cb78f3c43bc5f2484d1888571e27225702.tar.gz
Migrate Windows CI roles to test targets. (#18005)
Diffstat (limited to 'test/integration/targets')
-rw-r--r--test/integration/targets/prepare_win_tests/meta/main.yml3
-rw-r--r--test/integration/targets/prepare_win_tests/tasks/main.yml30
-rw-r--r--test/integration/targets/win_async_wrapper/library/async_test.ps157
-rw-r--r--test/integration/targets/win_async_wrapper/tasks/main.yml189
-rw-r--r--test/integration/targets/win_command/tasks/main.yml134
-rw-r--r--test/integration/targets/win_copy/files/empty.txt0
-rw-r--r--test/integration/targets/win_copy/files/foo.txt1
-rw-r--r--test/integration/targets/win_copy/files/subdir/bar.txt1
-rw-r--r--test/integration/targets/win_copy/files/subdir/subdir2/baz.txt1
-rw-r--r--test/integration/targets/win_copy/files/subdir/subdir2/subdir3/subdir4/qux.txt1
-rw-r--r--test/integration/targets/win_copy/meta/main.yml3
-rw-r--r--test/integration/targets/win_copy/tasks/main.yml296
-rw-r--r--test/integration/targets/win_feature/defaults/main.yml4
-rw-r--r--test/integration/targets/win_feature/tasks/main.yml149
-rw-r--r--test/integration/targets/win_fetch/tasks/main.yml167
-rw-r--r--test/integration/targets/win_file/files/foo.txt1
-rw-r--r--test/integration/targets/win_file/files/foobar/directory/fileC0
-rw-r--r--test/integration/targets/win_file/files/foobar/directory/fileD0
-rw-r--r--test/integration/targets/win_file/files/foobar/fileA1
-rw-r--r--test/integration/targets/win_file/files/foobar/fileB0
-rw-r--r--test/integration/targets/win_file/meta/main.yml3
-rw-r--r--test/integration/targets/win_file/tasks/main.yml494
-rw-r--r--test/integration/targets/win_get_url/defaults/main.yml6
-rw-r--r--test/integration/targets/win_get_url/tasks/main.yml105
-rw-r--r--test/integration/targets/win_group/defaults/main.yml4
-rw-r--r--test/integration/targets/win_group/tasks/main.yml101
-rw-r--r--test/integration/targets/win_lineinfile/files/test.txt5
-rw-r--r--test/integration/targets/win_lineinfile/files/test_quoting.txt0
-rw-r--r--test/integration/targets/win_lineinfile/files/testempty.txt0
-rw-r--r--test/integration/targets/win_lineinfile/files/testnoeof.txt2
-rw-r--r--test/integration/targets/win_lineinfile/meta/main.yml3
-rw-r--r--test/integration/targets/win_lineinfile/tasks/main.yml641
-rw-r--r--test/integration/targets/win_msi/defaults/main.yml6
-rw-r--r--test/integration/targets/win_msi/tasks/main.yml70
-rw-r--r--test/integration/targets/win_package/defaults/main.yml6
-rw-r--r--test/integration/targets/win_package/tasks/main.yml81
-rw-r--r--test/integration/targets/win_ping/library/win_ping_set_attr.ps131
-rw-r--r--test/integration/targets/win_ping/library/win_ping_strict_mode_error.ps130
-rw-r--r--test/integration/targets/win_ping/library/win_ping_syntax_error.ps130
-rw-r--r--test/integration/targets/win_ping/library/win_ping_throw.ps130
-rw-r--r--test/integration/targets/win_ping/library/win_ping_throw_string.ps130
-rw-r--r--test/integration/targets/win_ping/tasks/main.yml146
-rw-r--r--test/integration/targets/win_raw/tasks/main.yml116
-rw-r--r--test/integration/targets/win_regedit/meta/main.yml3
-rw-r--r--test/integration/targets/win_regedit/tasks/main.yml426
-rw-r--r--test/integration/targets/win_regmerge/files/settings1.regbin0 -> 374 bytes
-rw-r--r--test/integration/targets/win_regmerge/files/settings2.regbin0 -> 760 bytes
-rw-r--r--test/integration/targets/win_regmerge/files/settings3.regbin0 -> 1926 bytes
-rw-r--r--test/integration/targets/win_regmerge/meta/main.yml3
-rw-r--r--test/integration/targets/win_regmerge/tasks/main.yml133
-rw-r--r--test/integration/targets/win_regmerge/templates/win_line_ending.j24
-rw-r--r--test/integration/targets/win_regmerge/vars/main.yml1
-rw-r--r--test/integration/targets/win_script/defaults/main.yml5
-rw-r--r--test/integration/targets/win_script/files/test_script.bat2
-rw-r--r--test/integration/targets/win_script/files/test_script.cmd2
-rw-r--r--test/integration/targets/win_script/files/test_script.ps12
-rw-r--r--test/integration/targets/win_script/files/test_script_bool.ps16
-rw-r--r--test/integration/targets/win_script/files/test_script_creates_file.ps13
-rw-r--r--test/integration/targets/win_script/files/test_script_removes_file.ps13
-rw-r--r--test/integration/targets/win_script/files/test_script_with_args.ps17
-rw-r--r--test/integration/targets/win_script/files/test_script_with_errors.ps19
-rw-r--r--test/integration/targets/win_script/files/test_script_with_splatting.ps16
-rw-r--r--test/integration/targets/win_script/tasks/main.yml191
-rw-r--r--test/integration/targets/win_service/defaults/main.yml5
-rw-r--r--test/integration/targets/win_service/tasks/main.yml196
-rw-r--r--test/integration/targets/win_setup/tasks/main.yml57
-rw-r--r--test/integration/targets/win_shell/tasks/main.yml175
-rw-r--r--test/integration/targets/win_slurp/tasks/main.yml77
-rw-r--r--test/integration/targets/win_stat/tasks/main.yml98
-rw-r--r--test/integration/targets/win_template/files/foo.txt1
-rw-r--r--test/integration/targets/win_template/meta/main.yml3
-rw-r--r--test/integration/targets/win_template/tasks/main.yml114
-rw-r--r--test/integration/targets/win_template/templates/foo.j21
-rw-r--r--test/integration/targets/win_template/vars/main.yml1
-rw-r--r--test/integration/targets/win_user/defaults/main.yml5
-rw-r--r--test/integration/targets/win_user/files/lockout_user.ps117
-rw-r--r--test/integration/targets/win_user/tasks/main.yml431
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
new file mode 100644
index 0000000000..baec75b2af
--- /dev/null
+++ b/test/integration/targets/win_regmerge/files/settings1.reg
Binary files differ
diff --git a/test/integration/targets/win_regmerge/files/settings2.reg b/test/integration/targets/win_regmerge/files/settings2.reg
new file mode 100644
index 0000000000..fc2612cb8a
--- /dev/null
+++ b/test/integration/targets/win_regmerge/files/settings2.reg
Binary files differ
diff --git a/test/integration/targets/win_regmerge/files/settings3.reg b/test/integration/targets/win_regmerge/files/settings3.reg
new file mode 100644
index 0000000000..fbe7411c95
--- /dev/null
+++ b/test/integration/targets/win_regmerge/files/settings3.reg
Binary files differ
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'"