summaryrefslogtreecommitdiffstats
path: root/test/integration/targets
diff options
context:
space:
mode:
authorMatt Clay <matt@mystile.com>2016-10-12 23:57:53 +0200
committerGitHub <noreply@github.com>2016-10-12 23:57:53 +0200
commit80a5c70ad795f3cd1e6e3edde7077a8dfd65470b (patch)
tree50ab0ad670d2631fa32cad47019d9a970ed81596 /test/integration/targets
parentOnly dispkay failure to use cryptography at a higher verbosity (diff)
downloadansible-80a5c70ad795f3cd1e6e3edde7077a8dfd65470b.tar.xz
ansible-80a5c70ad795f3cd1e6e3edde7077a8dfd65470b.zip
Split integration tests out from Makefile. (#17976)
Diffstat (limited to 'test/integration/targets')
-rwxr-xr-xtest/integration/targets/args/runme.sh12
-rwxr-xr-xtest/integration/targets/async_extra_data/runme.sh9
-rw-r--r--test/integration/targets/async_extra_data/test_async.yml10
-rw-r--r--test/integration/targets/binary_modules/Makefile14
-rw-r--r--test/integration/targets/binary_modules/download_binary_modules.yml21
-rw-r--r--test/integration/targets/binary_modules/library/.gitignore1
-rw-r--r--test/integration/targets/binary_modules/library/helloworld.go89
-rw-r--r--test/integration/targets/binary_modules/roles/test_binary_modules/tasks/main.yml54
-rwxr-xr-xtest/integration/targets/binary_modules/test.sh8
-rw-r--r--test/integration/targets/binary_modules/test_binary_modules.yml6
-rwxr-xr-xtest/integration/targets/binary_modules_posix/runme.sh6
-rwxr-xr-xtest/integration/targets/binary_modules_winrm/runme.sh6
-rw-r--r--test/integration/targets/blocks/fail.yml2
-rw-r--r--test/integration/targets/blocks/main.yml103
-rw-r--r--test/integration/targets/blocks/nested_fail.yml3
-rw-r--r--test/integration/targets/blocks/nested_nested_fail.yml3
-rwxr-xr-xtest/integration/targets/blocks/runme.sh20
-rw-r--r--test/integration/targets/check_mode/check_mode.yml6
-rw-r--r--test/integration/targets/check_mode/roles/test_always_run/meta/main.yml18
-rw-r--r--test/integration/targets/check_mode/roles/test_always_run/tasks/main.yml29
-rw-r--r--test/integration/targets/check_mode/roles/test_check_mode/files/foo.txt1
-rw-r--r--test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml50
-rw-r--r--test/integration/targets/check_mode/roles/test_check_mode/templates/foo.j21
-rw-r--r--test/integration/targets/check_mode/roles/test_check_mode/vars/main.yml1
-rwxr-xr-xtest/integration/targets/check_mode/runme.sh5
-rwxr-xr-xtest/integration/targets/connection/test.sh10
-rw-r--r--test/integration/targets/connection/test_connection.yml40
l---------test/integration/targets/connection_chroot/runme.sh1
-rw-r--r--test/integration/targets/connection_chroot/test_connection.inventory6
l---------test/integration/targets/connection_docker/runme.sh1
-rw-r--r--test/integration/targets/connection_docker/test_connection.inventory6
l---------test/integration/targets/connection_jail/runme.sh1
-rw-r--r--test/integration/targets/connection_jail/test_connection.inventory7
l---------test/integration/targets/connection_libvirt_lxc/runme.sh1
-rw-r--r--test/integration/targets/connection_libvirt_lxc/test_connection.inventory6
l---------test/integration/targets/connection_local/runme.sh1
-rw-r--r--test/integration/targets/connection_local/test_connection.inventory6
l---------test/integration/targets/connection_lxc/runme.sh1
-rw-r--r--test/integration/targets/connection_lxc/test_connection.inventory17
l---------test/integration/targets/connection_lxd/runme.sh1
-rw-r--r--test/integration/targets/connection_lxd/test_connection.inventory6
l---------test/integration/targets/connection_paramiko_ssh/runme.sh1
-rw-r--r--test/integration/targets/connection_paramiko_ssh/test_connection.inventory6
-rwxr-xr-xtest/integration/targets/connection_posix/test.sh18
l---------test/integration/targets/connection_ssh/runme.sh1
-rw-r--r--test/integration/targets/connection_ssh/test_connection.inventory6
-rwxr-xr-xtest/integration/targets/connection_winrm/runme.sh12
-rw-r--r--test/integration/targets/delegate_to/roles/test_template/templates/foo.j23
-rwxr-xr-xtest/integration/targets/delegate_to/runme.sh5
-rw-r--r--test/integration/targets/delegate_to/test_delegate_to.yml56
-rwxr-xr-xtest/integration/targets/environment/runme.sh5
-rw-r--r--test/integration/targets/environment/test_environment.yml66
-rwxr-xr-xtest/integration/targets/gathering_facts/runme.sh5
-rw-r--r--test/integration/targets/gathering_facts/test_gathering_facts.yml133
-rw-r--r--test/integration/targets/group_by/inventory.group_by6
-rwxr-xr-xtest/integration/targets/group_by/runme.sh5
-rw-r--r--test/integration/targets/group_by/test_group_by.yml127
-rw-r--r--test/integration/targets/handlers/inventory.handlers6
-rw-r--r--test/integration/targets/handlers/roles/test_force_handlers/handlers/main.yml2
-rw-r--r--test/integration/targets/handlers/roles/test_force_handlers/tasks/main.yml26
-rw-r--r--test/integration/targets/handlers/roles/test_handlers/handlers/main.yml5
-rw-r--r--test/integration/targets/handlers/roles/test_handlers/meta/main.yml2
-rw-r--r--test/integration/targets/handlers/roles/test_handlers/tasks/main.yml52
-rw-r--r--test/integration/targets/handlers/roles/test_handlers_meta/handlers/main.yml7
-rw-r--r--test/integration/targets/handlers/roles/test_handlers_meta/tasks/main.yml41
-rwxr-xr-xtest/integration/targets/handlers/runme.sh36
-rw-r--r--test/integration/targets/handlers/test_force_handlers.yml30
-rw-r--r--test/integration/targets/handlers/test_handlers.yml26
-rw-r--r--test/integration/targets/hash/roles/test_hash_behavior/defaults/main.yml21
-rw-r--r--test/integration/targets/hash/roles/test_hash_behavior/meta/main.yml18
-rw-r--r--test/integration/targets/hash/roles/test_hash_behavior/tasks/main.yml42
-rw-r--r--test/integration/targets/hash/roles/test_hash_behavior/vars/main.yml21
-rwxr-xr-xtest/integration/targets/hash/runme.sh8
-rw-r--r--test/integration/targets/hash/test_hash.yml20
-rw-r--r--test/integration/targets/hash/vars/test_hash_vars.yml3
-rw-r--r--test/integration/targets/hosts_field/inventory.hosts_field1
-rwxr-xr-xtest/integration/targets/hosts_field/runme.sh49
-rw-r--r--test/integration/targets/hosts_field/test_hosts_field.json1
-rw-r--r--test/integration/targets/hosts_field/test_hosts_field.yml62
-rw-r--r--test/integration/targets/includes/roles/test_includes/handlers/main.yml2
-rw-r--r--test/integration/targets/includes/roles/test_includes/handlers/more_handlers.yml14
-rw-r--r--test/integration/targets/includes/roles/test_includes/tasks/empty.yml0
-rw-r--r--test/integration/targets/includes/roles/test_includes/tasks/included_task1.yml10
-rw-r--r--test/integration/targets/includes/roles/test_includes/tasks/main.yml84
-rw-r--r--test/integration/targets/includes/roles/test_includes/tasks/not_a_role_task.yml4
-rwxr-xr-xtest/integration/targets/includes/runme.sh5
-rw-r--r--test/integration/targets/includes/test_includes.yml3
-rw-r--r--test/integration/targets/includes/test_includes2.yml22
-rw-r--r--test/integration/targets/includes/test_includes3.yml7
-rw-r--r--test/integration/targets/includes/test_includes4.yml2
-rw-r--r--test/integration/targets/lookup_paths/play.yml64
-rw-r--r--test/integration/targets/lookup_paths/roles/showfile/tasks/main.yml2
-rwxr-xr-xtest/integration/targets/lookup_paths/runme.sh5
-rw-r--r--test/integration/targets/lookup_paths/testplay.yml19
-rw-r--r--test/integration/targets/lookup_properties/lookup.ini24
-rw-r--r--test/integration/targets/lookup_properties/lookup.properties5
-rwxr-xr-xtest/integration/targets/lookup_properties/runme.sh5
-rw-r--r--test/integration/targets/lookup_properties/test_lookup_properties.yml40
-rw-r--r--test/integration/targets/no_log/no_log_local.yml66
-rwxr-xr-xtest/integration/targets/no_log/runme.sh9
-rw-r--r--test/integration/targets/parsing/bad_parsing.yml12
-rw-r--r--test/integration/targets/parsing/good_parsing.yml9
-rw-r--r--test/integration/targets/parsing/roles/test_bad_parsing/tasks/main.yml60
-rw-r--r--test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario1.yml5
-rw-r--r--test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario2.yml5
-rw-r--r--test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario3.yml5
-rw-r--r--test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario4.yml5
-rw-r--r--test/integration/targets/parsing/roles/test_bad_parsing/vars/main.yml2
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml204
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include.yml1
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml1
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_nested.yml2
-rw-r--r--test/integration/targets/parsing/roles/test_good_parsing/vars/main.yml2
-rwxr-xr-xtest/integration/targets/parsing/runme.sh6
-rwxr-xr-xtest/integration/targets/pull_limit_inventory/runme.sh10
-rwxr-xr-xtest/integration/targets/pull_no_127/runme.sh11
-rwxr-xr-xtest/integration/targets/pull_run/runme.sh10
-rwxr-xr-xtest/integration/targets/tags/runme.sh37
-rw-r--r--test/integration/targets/tags/test_tags.yml23
-rwxr-xr-xtest/integration/targets/templating_settings/runme.sh5
-rw-r--r--test/integration/targets/templating_settings/test_templating_settings.yml16
-rw-r--r--test/integration/targets/test_infra/inventory.local2
-rwxr-xr-xtest/integration/targets/test_infra/runme.sh23
-rw-r--r--test/integration/targets/test_infra/test_test_infra.yml26
-rwxr-xr-xtest/integration/targets/unicode/runme.sh7
-rwxr-xr-xtest/integration/targets/unicode/unicode-test-script7
-rw-r--r--test/integration/targets/unicode/unicode.yml149
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence/meta/main.yml4
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence/tasks/main.yml10
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_dep/defaults/main.yml5
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_dep/tasks/main.yml14
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_dep/vars/main.yml4
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_inven_override/tasks/main.yml5
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role1/defaults/main.yml5
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role1/meta/main.yml2
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role1/tasks/main.yml14
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role1/vars/main.yml4
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role2/defaults/main.yml5
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role2/tasks/main.yml14
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role2/vars/main.yml5
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role3/defaults/main.yml7
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role3/tasks/main.yml14
-rw-r--r--test/integration/targets/var_precedence/roles/test_var_precedence_role3/vars/main.yml3
-rwxr-xr-xtest/integration/targets/var_precedence/runme.sh7
-rw-r--r--test/integration/targets/var_precedence/test_var_precedence.yml45
-rw-r--r--test/integration/targets/var_precedence/vars/test_var_precedence.yml5
-rw-r--r--test/integration/targets/vault/roles/test_vault/tasks/main.yml10
-rw-r--r--test/integration/targets/vault/roles/test_vault/vars/main.yml9
-rw-r--r--test/integration/targets/vault/roles/test_vault_embedded/tasks/main.yml14
-rw-r--r--test/integration/targets/vault/roles/test_vault_embedded/vars/main.yml17
-rwxr-xr-xtest/integration/targets/vault/runme.sh10
-rw-r--r--test/integration/targets/vault/test_vault.yml6
-rw-r--r--test/integration/targets/vault/test_vault_embedded.yml4
-rw-r--r--test/integration/targets/vault/vault-password1
-rw-r--r--test/integration/targets/vault/vault-secret.txt6
155 files changed, 2809 insertions, 0 deletions
diff --git a/test/integration/targets/args/runme.sh b/test/integration/targets/args/runme.sh
new file mode 100755
index 0000000000..af1c31d79b
--- /dev/null
+++ b/test/integration/targets/args/runme.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -eu
+
+echo "arg[#]: $#"
+echo "arg[0]: $0"
+
+i=0
+for arg in "$@"; do
+ i=$((i+1))
+ echo "arg[$i]: ${arg}"
+done
diff --git a/test/integration/targets/async_extra_data/runme.sh b/test/integration/targets/async_extra_data/runme.sh
new file mode 100755
index 0000000000..bdc3b4209d
--- /dev/null
+++ b/test/integration/targets/async_extra_data/runme.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# Verify that extra data before module JSON output during async call is ignored.
+ANSIBLE_DEBUG=0 LC_ALL=bogus ansible-playbook test_async.yml -i localhost, -e ansible_connection=ssh -v "$@"
+# Verify that the warning exists by examining debug output.
+ANSIBLE_DEBUG=1 LC_ALL=bogus ansible-playbook test_async.yml -i localhost, -e ansible_connection=ssh -v "$@" \
+ | grep 'bash: warning: setlocale: LC_ALL: cannot change locale (bogus)' > /dev/null
diff --git a/test/integration/targets/async_extra_data/test_async.yml b/test/integration/targets/async_extra_data/test_async.yml
new file mode 100644
index 0000000000..e54ffd3d47
--- /dev/null
+++ b/test/integration/targets/async_extra_data/test_async.yml
@@ -0,0 +1,10 @@
+- hosts: localhost
+ gather_facts: false
+ tasks:
+ # make sure non-JSON data before module output is ignored
+ - name: async ping with invalid locale via ssh
+ ping:
+ async: 10
+ poll: 1
+ register: result
+ - debug: var=result
diff --git a/test/integration/targets/binary_modules/Makefile b/test/integration/targets/binary_modules/Makefile
new file mode 100644
index 0000000000..d6b791730f
--- /dev/null
+++ b/test/integration/targets/binary_modules/Makefile
@@ -0,0 +1,14 @@
+.PHONY: all clean
+
+all:
+ # Compiled versions of these binary modules are available at the url below.
+ # This avoids a dependency on go and keeps the binaries out of our git repository.
+ # https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_binary_modules/
+ cd library; \
+ GOOS=linux GOARCH=amd64 go build -o helloworld_linux helloworld.go; \
+ GOOS=windows GOARCH=amd64 go build -o helloworld_win32nt.exe helloworld.go; \
+ GOOS=darwin GOARCH=amd64 go build -o helloworld_darwin helloworld.go; \
+ GOOS=freebsd GOARCH=amd64 go build -o helloworld_freebsd helloworld.go
+
+clean:
+ rm -f library/helloworld_*
diff --git a/test/integration/targets/binary_modules/download_binary_modules.yml b/test/integration/targets/binary_modules/download_binary_modules.yml
new file mode 100644
index 0000000000..456ddb4a79
--- /dev/null
+++ b/test/integration/targets/binary_modules/download_binary_modules.yml
@@ -0,0 +1,21 @@
+- hosts: testhost_binary_modules
+ tasks:
+ - debug: var=ansible_system
+
+ - name: set module filename (POSIX)
+ set_fact:
+ module_filename: "helloworld_{{ ansible_system | lower }}"
+ when: ansible_system != 'Win32NT'
+
+ - name: set module filename (Win32NT)
+ set_fact:
+ module_filename: "helloworld_{{ ansible_system | lower }}.exe"
+ when: ansible_system == 'Win32NT'
+
+ - name: download binary module
+ tags: test_binary_modules
+ local_action:
+ module: get_url
+ url: "https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_binary_modules/{{ module_filename }}"
+ dest: "{{ playbook_dir }}/library/{{ module_filename }}"
+ mode: 0755
diff --git a/test/integration/targets/binary_modules/library/.gitignore b/test/integration/targets/binary_modules/library/.gitignore
new file mode 100644
index 0000000000..d034a06ac7
--- /dev/null
+++ b/test/integration/targets/binary_modules/library/.gitignore
@@ -0,0 +1 @@
+helloworld_*
diff --git a/test/integration/targets/binary_modules/library/helloworld.go b/test/integration/targets/binary_modules/library/helloworld.go
new file mode 100644
index 0000000000..a4c16b20e5
--- /dev/null
+++ b/test/integration/targets/binary_modules/library/helloworld.go
@@ -0,0 +1,89 @@
+// 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/>.
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+type ModuleArgs struct {
+ Name string
+}
+
+type Response struct {
+ Msg string `json:"msg"`
+ Changed bool `json:"changed"`
+ Failed bool `json:"failed"`
+}
+
+func ExitJson(responseBody Response) {
+ returnResponse(responseBody)
+}
+
+func FailJson(responseBody Response) {
+ responseBody.Failed = true
+ returnResponse(responseBody)
+}
+
+func returnResponse(responseBody Response) {
+ var response []byte
+ var err error
+ response, err = json.Marshal(responseBody)
+ if err != nil {
+ response, _ = json.Marshal(Response{Msg: "Invalid response object"})
+ }
+ fmt.Println(string(response))
+ if responseBody.Failed {
+ os.Exit(1)
+ } else {
+ os.Exit(0)
+ }
+}
+
+func main() {
+ var response Response
+
+ if len(os.Args) != 2 {
+ response.Msg = "No argument file provided"
+ FailJson(response)
+ }
+
+ argsFile := os.Args[1]
+
+ text, err := ioutil.ReadFile(argsFile)
+ if err != nil {
+ response.Msg = "Could not read configuration file: " + argsFile
+ FailJson(response)
+ }
+
+ var moduleArgs ModuleArgs
+ err = json.Unmarshal(text, &moduleArgs)
+ if err != nil {
+ response.Msg = "Configuration file not valid JSON: " + argsFile
+ FailJson(response)
+ }
+
+ var name string = "World"
+ if moduleArgs.Name != "" {
+ name = moduleArgs.Name
+ }
+
+ response.Msg = "Hello, " + name + "!"
+ ExitJson(response)
+}
diff --git a/test/integration/targets/binary_modules/roles/test_binary_modules/tasks/main.yml b/test/integration/targets/binary_modules/roles/test_binary_modules/tasks/main.yml
new file mode 100644
index 0000000000..e7139dbf37
--- /dev/null
+++ b/test/integration/targets/binary_modules/roles/test_binary_modules/tasks/main.yml
@@ -0,0 +1,54 @@
+- debug: var=ansible_system
+
+- name: ping
+ ping:
+ when: ansible_system != 'Win32NT'
+
+- name: win_ping
+ win_ping:
+ when: ansible_system == 'Win32NT'
+
+- name: Hello, World!
+ action: "helloworld_{{ ansible_system|lower }}"
+ register: hello_world
+
+- assert:
+ that:
+ - 'hello_world.msg == "Hello, World!"'
+
+- name: Hello, Ansible!
+ action: "helloworld_{{ ansible_system|lower }}"
+ args:
+ name: Ansible
+ register: hello_ansible
+
+- assert:
+ that:
+ - 'hello_ansible.msg == "Hello, Ansible!"'
+
+- name: Async Hello, World!
+ action: "helloworld_{{ ansible_system|lower }}"
+ async: 10
+ poll: 1
+ when: ansible_system != 'Win32NT'
+ register: async_hello_world
+
+- assert:
+ that:
+ - 'async_hello_world.msg == "Hello, World!"'
+ when: not async_hello_world|skipped
+
+- name: Async Hello, Ansible!
+ action: "helloworld_{{ ansible_system|lower }}"
+ args:
+ name: Ansible
+ async: 10
+ poll: 1
+ when: ansible_system != 'Win32NT'
+ register: async_hello_ansible
+
+- assert:
+ that:
+ - 'async_hello_ansible.msg == "Hello, Ansible!"'
+ when: not async_hello_ansible|skipped
+
diff --git a/test/integration/targets/binary_modules/test.sh b/test/integration/targets/binary_modules/test.sh
new file mode 100755
index 0000000000..7f046670f7
--- /dev/null
+++ b/test/integration/targets/binary_modules/test.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -eux
+
+[ -f "${INVENTORY}" ]
+
+ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook download_binary_modules.yml -i "${INVENTORY}" -v "$@"
+ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook test_binary_modules.yml -i "${INVENTORY}" -v "$@"
diff --git a/test/integration/targets/binary_modules/test_binary_modules.yml b/test/integration/targets/binary_modules/test_binary_modules.yml
new file mode 100644
index 0000000000..e5fd341cf2
--- /dev/null
+++ b/test/integration/targets/binary_modules/test_binary_modules.yml
@@ -0,0 +1,6 @@
+- hosts: testhost_binary_modules
+ roles:
+ - role: test_binary_modules
+ tags:
+ - test_binary_modules
+
diff --git a/test/integration/targets/binary_modules_posix/runme.sh b/test/integration/targets/binary_modules_posix/runme.sh
new file mode 100755
index 0000000000..670477d186
--- /dev/null
+++ b/test/integration/targets/binary_modules_posix/runme.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -eux
+
+cd ../binary_modules
+INVENTORY=../../inventory ./test.sh "$@"
diff --git a/test/integration/targets/binary_modules_winrm/runme.sh b/test/integration/targets/binary_modules_winrm/runme.sh
new file mode 100755
index 0000000000..f182c2d66f
--- /dev/null
+++ b/test/integration/targets/binary_modules_winrm/runme.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -eux
+
+cd ../binary_modules
+INVENTORY=../../inventory.winrm ./test.sh "$@"
diff --git a/test/integration/targets/blocks/fail.yml b/test/integration/targets/blocks/fail.yml
new file mode 100644
index 0000000000..ae94655136
--- /dev/null
+++ b/test/integration/targets/blocks/fail.yml
@@ -0,0 +1,2 @@
+- name: EXPECTED FAILURE
+ fail: msg="{{msg}}"
diff --git a/test/integration/targets/blocks/main.yml b/test/integration/targets/blocks/main.yml
new file mode 100644
index 0000000000..a80a62b753
--- /dev/null
+++ b/test/integration/targets/blocks/main.yml
@@ -0,0 +1,103 @@
+- name: simple block test
+ hosts: localhost
+ gather_facts: yes
+ strategy: "{{test_strategy|default('linear')}}"
+ vars:
+ block_tasks_run: false
+ block_rescue_run: false
+ block_always_run: false
+ nested_block_always_run: false
+ tasks_run_after_failure: false
+ rescue_run_after_failure: false
+ always_run_after_failure: false
+ tasks:
+ - block:
+ - name: set block tasks run flag
+ set_fact:
+ block_tasks_run: true
+ - name: EXPECTED FAILURE fail in tasks
+ fail:
+ - name: tasks flag should not be set after failure
+ set_fact:
+ tasks_run_after_failure: true
+ rescue:
+ - name: set block rescue run flag
+ set_fact:
+ block_rescue_run: true
+ - name: EXPECTED FAILURE fail in rescue
+ fail:
+ - name: tasks flag should not be set after failure in rescue
+ set_fact:
+ rescue_run_after_failure: true
+ always:
+ - name: set block always run flag
+ set_fact:
+ block_always_run: true
+ #- block:
+ # - meta: noop
+ # always:
+ # - name: set nested block always run flag
+ # set_fact:
+ # nested_block_always_run: true
+ # - name: fail in always
+ # fail:
+ # - name: tasks flag should not be set after failure in always
+ # set_fact:
+ # always_run_after_failure: true
+ - meta: clear_host_errors
+
+ post_tasks:
+ - assert:
+ that:
+ - block_tasks_run
+ - block_rescue_run
+ - block_always_run
+ #- nested_block_always_run
+ - not tasks_run_after_failure
+ - not rescue_run_after_failure
+ - not always_run_after_failure
+ - debug: msg="TEST COMPLETE"
+
+- name: block with includes
+ hosts: localhost
+ gather_facts: yes
+ strategy: "{{test_strategy|default('linear')}}"
+ vars:
+ rescue_run_after_include_fail: false
+ always_run_after_include_fail_in_rescue: false
+ tasks_run_after_failure: false
+ rescue_run_after_failure: false
+ always_run_after_failure: false
+ tasks:
+ - block:
+ - name: include fail.yml in tasks
+ include: fail.yml
+ args:
+ msg: "failed from tasks"
+ - name: tasks flag should not be set after failure
+ set_fact:
+ tasks_run_after_failure: true
+ rescue:
+ - set_fact:
+ rescue_run_after_include_fail: true
+ - name: include fail.yml in rescue
+ include: fail.yml
+ args:
+ msg: "failed from rescue"
+ - name: flag should not be set after failure in rescue
+ set_fact:
+ rescue_run_after_failure: true
+ always:
+ - set_fact:
+ always_run_after_include_fail_in_rescue: true
+ - meta: clear_host_errors
+
+ post_tasks:
+ - assert:
+ that:
+ - rescue_run_after_include_fail
+ - always_run_after_include_fail_in_rescue
+ - not tasks_run_after_failure
+ - not rescue_run_after_failure
+ - not always_run_after_failure
+ - debug: msg="TEST COMPLETE"
diff --git a/test/integration/targets/blocks/nested_fail.yml b/test/integration/targets/blocks/nested_fail.yml
new file mode 100644
index 0000000000..31ae870e37
--- /dev/null
+++ b/test/integration/targets/blocks/nested_fail.yml
@@ -0,0 +1,3 @@
+- include: fail.yml
+ args:
+ msg: "nested {{msg}}"
diff --git a/test/integration/targets/blocks/nested_nested_fail.yml b/test/integration/targets/blocks/nested_nested_fail.yml
new file mode 100644
index 0000000000..e9a050fb98
--- /dev/null
+++ b/test/integration/targets/blocks/nested_nested_fail.yml
@@ -0,0 +1,3 @@
+- include: nested_fail.yml
+ args:
+ msg: "nested {{msg}}"
diff --git a/test/integration/targets/blocks/runme.sh b/test/integration/targets/blocks/runme.sh
new file mode 100755
index 0000000000..dd15a10083
--- /dev/null
+++ b/test/integration/targets/blocks/runme.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# remove old output log
+rm -f block_test.out
+# run the test and check to make sure the right number of completions was logged
+ansible-playbook -vv main.yml -i ../../inventory "$@" | tee block_test.out
+env python -c \
+ 'import sys, re; sys.stdout.write(re.sub("\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]", "", sys.stdin.read()))' \
+ <block_test.out >block_test_wo_colors.out
+[ "$(grep -c 'TEST COMPLETE' block_test.out)" = "$(egrep '^[0-9]+ plays in' block_test_wo_colors.out | cut -f1 -d' ')" ]
+# cleanup the output log again, to make sure the test is clean
+rm -f block_test.out block_test_wo_colors.out
+# run test with free strategy and again count the completions
+ansible-playbook -vv main.yml -i ../../inventory -e test_strategy=free "$@" | tee block_test.out
+env python -c \
+ 'import sys, re; sys.stdout.write(re.sub("\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]", "", sys.stdin.read()))' \
+ <block_test.out >block_test_wo_colors.out
+[ "$(grep -c 'TEST COMPLETE' block_test.out)" = "$(egrep '^[0-9]+ plays in' block_test_wo_colors.out | cut -f1 -d' ')" ]
diff --git a/test/integration/targets/check_mode/check_mode.yml b/test/integration/targets/check_mode/check_mode.yml
new file mode 100644
index 0000000000..0f4fde4da0
--- /dev/null
+++ b/test/integration/targets/check_mode/check_mode.yml
@@ -0,0 +1,6 @@
+- hosts: testhost
+ vars:
+ - output_dir: .
+ roles:
+ - { role: test_always_run, tags: test_always_run }
+ - { role: test_check_mode, tags: test_check_mode }
diff --git a/test/integration/targets/check_mode/roles/test_always_run/meta/main.yml b/test/integration/targets/check_mode/roles/test_always_run/meta/main.yml
new file mode 100644
index 0000000000..b7cb12f7b6
--- /dev/null
+++ b/test/integration/targets/check_mode/roles/test_always_run/meta/main.yml
@@ -0,0 +1,18 @@
+# test code for the always_run option
+# (c) 2014, James Cammarata <jcammarata@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/>.
+
diff --git a/test/integration/targets/check_mode/roles/test_always_run/tasks/main.yml b/test/integration/targets/check_mode/roles/test_always_run/tasks/main.yml
new file mode 100644
index 0000000000..eb27785ad6
--- /dev/null
+++ b/test/integration/targets/check_mode/roles/test_always_run/tasks/main.yml
@@ -0,0 +1,29 @@
+# test code for the always_run option
+# (c) 2014, James Cammarata <jcammarata@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: run a command while in check mode
+ shell: echo "running"
+ check_mode: no
+ register: result
+
+- name: assert that the command was run
+ assert:
+ that:
+ - "result.changed == true"
+ - "result.stdout == 'running'"
+ - "result.rc == 0"
diff --git a/test/integration/targets/check_mode/roles/test_check_mode/files/foo.txt b/test/integration/targets/check_mode/roles/test_check_mode/files/foo.txt
new file mode 100644
index 0000000000..3e96db9b3e
--- /dev/null
+++ b/test/integration/targets/check_mode/roles/test_check_mode/files/foo.txt
@@ -0,0 +1 @@
+templated_var_loaded
diff --git a/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml b/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml
new file mode 100644
index 0000000000..637e9e193c
--- /dev/null
+++ b/test/integration/targets/check_mode/roles/test_check_mode/tasks/main.yml
@@ -0,0 +1,50 @@
+# 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 in check mode
+ template: src=foo.j2 dest={{output_dir}}/checkmode_foo.templated mode=0644
+ register: template_result
+
+- name: check whether file exists
+ stat: path={{output_dir}}/checkmode_foo.templated
+ register: foo
+
+- name: verify that the file was marked as changed in check mode
+ assert:
+ that:
+ - "template_result|changed"
+ - "not foo.stat.exists"
+
+- name: Actually create the file, disable check mode
+ template: src=foo.j2 dest={{output_dir}}/checkmode_foo.templated2 mode=0644
+ check_mode: no
+ register: checkmode_disabled
+
+- name: fill in template with new content
+ template: src=foo.j2 dest={{output_dir}}/checkmode_foo.templated2 mode=0644
+ register: template_result2
+
+- name: remove templated file
+ file: path={{output_dir}}/checkmode_foo.templated2 state=absent
+ check_mode: no
+
+- name: verify that the file was not changed
+ assert:
+ that:
+ - "checkmode_disabled|changed"
+ - "not template_result2|changed"
diff --git a/test/integration/targets/check_mode/roles/test_check_mode/templates/foo.j2 b/test/integration/targets/check_mode/roles/test_check_mode/templates/foo.j2
new file mode 100644
index 0000000000..55aab8f1ea
--- /dev/null
+++ b/test/integration/targets/check_mode/roles/test_check_mode/templates/foo.j2
@@ -0,0 +1 @@
+{{ templated_var }}
diff --git a/test/integration/targets/check_mode/roles/test_check_mode/vars/main.yml b/test/integration/targets/check_mode/roles/test_check_mode/vars/main.yml
new file mode 100644
index 0000000000..1e8f64ccf4
--- /dev/null
+++ b/test/integration/targets/check_mode/roles/test_check_mode/vars/main.yml
@@ -0,0 +1 @@
+templated_var: templated_var_loaded
diff --git a/test/integration/targets/check_mode/runme.sh b/test/integration/targets/check_mode/runme.sh
new file mode 100755
index 0000000000..184ecb7c27
--- /dev/null
+++ b/test/integration/targets/check_mode/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook check_mode.yml -i ../../inventory -v --check "$@"
diff --git a/test/integration/targets/connection/test.sh b/test/integration/targets/connection/test.sh
new file mode 100755
index 0000000000..4e7aa8dda1
--- /dev/null
+++ b/test/integration/targets/connection/test.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -eux
+
+[ -f "${INVENTORY}" ]
+
+# Run connection tests with both the default and C locale.
+
+ ansible-playbook test_connection.yml -i "${INVENTORY}" "$@"
+LC_ALL=C LANG=C ansible-playbook test_connection.yml -i "${INVENTORY}" "$@"
diff --git a/test/integration/targets/connection/test_connection.yml b/test/integration/targets/connection/test_connection.yml
new file mode 100644
index 0000000000..2f0a98ccdf
--- /dev/null
+++ b/test/integration/targets/connection/test_connection.yml
@@ -0,0 +1,40 @@
+- hosts: "{{ hosts }}"
+ gather_facts: no
+ serial: 1
+ tasks:
+
+ ### raw with unicode arg and output
+
+ - name: raw with unicode arg and output
+ raw: echo 汉语
+ register: command
+ - name: check output of raw with unicode arg and output
+ assert:
+ that:
+ - "'汉语' in command.stdout"
+ - command | changed # as of 2.2, raw should default to changed: true for consistency w/ shell/command/script modules
+
+ ### copy local file with unicode filename and content
+
+ - name: create local file with unicode filename and content
+ local_action: lineinfile dest={{ local_tmp }}-汉语/汉语.txt create=true line=汉语
+ - name: remove remote file with unicode filename and content
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语/汉语.txt state=absent"
+ - name: create remote directory with unicode name
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=directory"
+ - name: copy local file with unicode filename and content
+ action: "{{ action_prefix }}copy src={{ local_tmp }}-汉语/汉语.txt dest={{ remote_tmp }}-汉语/汉语.txt"
+
+ ### fetch remote file with unicode filename and content
+
+ - name: remove local file with unicode filename and content
+ local_action: file path={{ local_tmp }}-汉语/汉语.txt state=absent
+ - name: fetch remote file with unicode filename and content
+ fetch: src={{ remote_tmp }}-汉语/汉语.txt dest={{ local_tmp }}-汉语/汉语.txt fail_on_missing=true validate_checksum=true flat=true
+
+ ### remove local and remote temp files
+
+ - name: remove local temp file
+ local_action: file path={{ local_tmp }}-汉语 state=absent
+ - name: remove remote temp file
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=absent"
diff --git a/test/integration/targets/connection_chroot/runme.sh b/test/integration/targets/connection_chroot/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_chroot/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_chroot/test_connection.inventory b/test/integration/targets/connection_chroot/test_connection.inventory
new file mode 100644
index 0000000000..9e0302c7d0
--- /dev/null
+++ b/test/integration/targets/connection_chroot/test_connection.inventory
@@ -0,0 +1,6 @@
+[chroot]
+chroot-pipelining ansible_ssh_pipelining=true
+chroot-no-pipelining ansible_ssh_pipelining=false
+[chroot:vars]
+ansible_host=/
+ansible_connection=chroot
diff --git a/test/integration/targets/connection_docker/runme.sh b/test/integration/targets/connection_docker/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_docker/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_docker/test_connection.inventory b/test/integration/targets/connection_docker/test_connection.inventory
new file mode 100644
index 0000000000..42940ac3b7
--- /dev/null
+++ b/test/integration/targets/connection_docker/test_connection.inventory
@@ -0,0 +1,6 @@
+[docker]
+docker-pipelining ansible_ssh_pipelining=true
+docker-no-pipelining ansible_ssh_pipelining=false
+[docker:vars]
+ansible_host=ubuntu-latest
+ansible_connection=docker
diff --git a/test/integration/targets/connection_jail/runme.sh b/test/integration/targets/connection_jail/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_jail/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_jail/test_connection.inventory b/test/integration/targets/connection_jail/test_connection.inventory
new file mode 100644
index 0000000000..a525c72f43
--- /dev/null
+++ b/test/integration/targets/connection_jail/test_connection.inventory
@@ -0,0 +1,7 @@
+[jail]
+jail-pipelining ansible_ssh_pipelining=true
+jail-no-pipelining ansible_ssh_pipelining=false
+[jail:vars]
+ansible_host=freebsd_10_2
+ansible_connection=jail
+ansible_python_interpreter=/usr/local/bin/python
diff --git a/test/integration/targets/connection_libvirt_lxc/runme.sh b/test/integration/targets/connection_libvirt_lxc/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_libvirt_lxc/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_libvirt_lxc/test_connection.inventory b/test/integration/targets/connection_libvirt_lxc/test_connection.inventory
new file mode 100644
index 0000000000..ff98a25542
--- /dev/null
+++ b/test/integration/targets/connection_libvirt_lxc/test_connection.inventory
@@ -0,0 +1,6 @@
+[libvirt_lxc]
+libvirt_lxc-pipelining ansible_ssh_pipelining=true
+libvirt_lxc-no-pipelining ansible_ssh_pipelining=false
+[libvirt_lxc:vars]
+ansible_host=lv-ubuntu-wily-amd64
+ansible_connection=libvirt_lxc
diff --git a/test/integration/targets/connection_local/runme.sh b/test/integration/targets/connection_local/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_local/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_local/test_connection.inventory b/test/integration/targets/connection_local/test_connection.inventory
new file mode 100644
index 0000000000..7178291040
--- /dev/null
+++ b/test/integration/targets/connection_local/test_connection.inventory
@@ -0,0 +1,6 @@
+[local]
+local-pipelining ansible_ssh_pipelining=true
+local-no-pipelining ansible_ssh_pipelining=false
+[local:vars]
+ansible_host=localhost
+ansible_connection=local
diff --git a/test/integration/targets/connection_lxc/runme.sh b/test/integration/targets/connection_lxc/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_lxc/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_lxc/test_connection.inventory b/test/integration/targets/connection_lxc/test_connection.inventory
new file mode 100644
index 0000000000..8737a9e8f9
--- /dev/null
+++ b/test/integration/targets/connection_lxc/test_connection.inventory
@@ -0,0 +1,17 @@
+[lxc]
+lxc-pipelining ansible_ssh_pipelining=true
+lxc-no-pipelining ansible_ssh_pipelining=false
+[lxc:vars]
+# 1. install lxc
+# 2. install python2-lxc
+# $ pip install git+https://github.com/lxc/python2-lxc.git
+# 3. create container:
+# $ sudo lxc-create -t download -n centos-7-amd64 -- -d centos -r 7 -a amd64
+# 4. start container:
+# $ sudo lxc-start -n centos-7-amd64 -d
+# 5. run test:
+# $ sudo -E make test_connection_lxc
+# 6. stop container
+# $ sudo lxc-stop -n centos-7-amd64
+ansible_host=centos-7-amd64
+ansible_connection=lxc
diff --git a/test/integration/targets/connection_lxd/runme.sh b/test/integration/targets/connection_lxd/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_lxd/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_lxd/test_connection.inventory b/test/integration/targets/connection_lxd/test_connection.inventory
new file mode 100644
index 0000000000..9c5998eced
--- /dev/null
+++ b/test/integration/targets/connection_lxd/test_connection.inventory
@@ -0,0 +1,6 @@
+[lxd]
+lxd-pipelining ansible_ssh_pipelining=true
+lxd-no-pipelining ansible_ssh_pipelining=false
+[lxd:vars]
+ansible_host=centos-7-amd64
+ansible_connection=lxd
diff --git a/test/integration/targets/connection_paramiko_ssh/runme.sh b/test/integration/targets/connection_paramiko_ssh/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_paramiko_ssh/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_paramiko_ssh/test_connection.inventory b/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
new file mode 100644
index 0000000000..8c430f0d0f
--- /dev/null
+++ b/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
@@ -0,0 +1,6 @@
+[paramiko_ssh]
+paramiko_ssh-pipelining ansible_ssh_pipelining=true
+paramiko_ssh-no-pipelining ansible_ssh_pipelining=false
+[paramiko_ssh:vars]
+ansible_host=localhost
+ansible_connection=paramiko_ssh
diff --git a/test/integration/targets/connection_posix/test.sh b/test/integration/targets/connection_posix/test.sh
new file mode 100755
index 0000000000..e133ad74a6
--- /dev/null
+++ b/test/integration/targets/connection_posix/test.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# Connection tests for POSIX platforms use this script by linking to it from the appropriate 'connection_' target dir.
+# The name of the inventory group to test is extracted from the directory name following the 'connection_' prefix.
+
+group=$(python -c \
+ "from os import path; print(path.basename(path.abspath(path.dirname('$0'))).replace('connection_', ''))")
+
+cd ../connection
+
+INVENTORY="../connection_${group}/test_connection.inventory" ./test.sh \
+ -e hosts="${group}" \
+ -e action_prefix= \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=/tmp/ansible-remote \
+ "$@"
diff --git a/test/integration/targets/connection_ssh/runme.sh b/test/integration/targets/connection_ssh/runme.sh
new file mode 120000
index 0000000000..70aa5dbdba
--- /dev/null
+++ b/test/integration/targets/connection_ssh/runme.sh
@@ -0,0 +1 @@
+../connection_posix/test.sh \ No newline at end of file
diff --git a/test/integration/targets/connection_ssh/test_connection.inventory b/test/integration/targets/connection_ssh/test_connection.inventory
new file mode 100644
index 0000000000..0f0ad23ebb
--- /dev/null
+++ b/test/integration/targets/connection_ssh/test_connection.inventory
@@ -0,0 +1,6 @@
+[ssh]
+ssh-pipelining ansible_ssh_pipelining=true
+ssh-no-pipelining ansible_ssh_pipelining=false
+[ssh:vars]
+ansible_host=localhost
+ansible_connection=ssh
diff --git a/test/integration/targets/connection_winrm/runme.sh b/test/integration/targets/connection_winrm/runme.sh
new file mode 100755
index 0000000000..05afcc83b4
--- /dev/null
+++ b/test/integration/targets/connection_winrm/runme.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -eux
+
+cd ../connection
+
+INVENTORY=../../inventory.winrm ./test.sh \
+ -e hosts=winrm \
+ -e action_prefix=win_ \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=c:/windows/temp/ansible-remote \
+ "$@"
diff --git a/test/integration/targets/delegate_to/roles/test_template/templates/foo.j2 b/test/integration/targets/delegate_to/roles/test_template/templates/foo.j2
new file mode 100644
index 0000000000..22187f9130
--- /dev/null
+++ b/test/integration/targets/delegate_to/roles/test_template/templates/foo.j2
@@ -0,0 +1,3 @@
+{{ templated_var }}
+
+{{ templated_dict | to_nice_json }}
diff --git a/test/integration/targets/delegate_to/runme.sh b/test/integration/targets/delegate_to/runme.sh
new file mode 100755
index 0000000000..782ec0902e
--- /dev/null
+++ b/test/integration/targets/delegate_to/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook test_delegate_to.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/delegate_to/test_delegate_to.yml b/test/integration/targets/delegate_to/test_delegate_to.yml
new file mode 100644
index 0000000000..d75857cc6c
--- /dev/null
+++ b/test/integration/targets/delegate_to/test_delegate_to.yml
@@ -0,0 +1,56 @@
+- hosts: testhost3
+ vars:
+ - template_role: ./roles/test_template
+ - output_dir: "{{ playbook_dir }}"
+ - templated_var: foo
+ - templated_dict: { 'hello': 'world' }
+ tasks:
+ - name: Test no delegate_to
+ setup:
+ register: setup_results
+
+ - assert:
+ that:
+ - '"127.0.0.3" in setup_results.ansible_facts.ansible_env["SSH_CONNECTION"]'
+
+ - name: Test delegate_to with host in inventory
+ setup:
+ register: setup_results
+ delegate_to: testhost4
+
+ - assert:
+ that:
+ - '"127.0.0.4" in setup_results.ansible_facts.ansible_env["SSH_CONNECTION"]'
+
+ - name: Test delegate_to with host not in inventory
+ setup:
+ register: setup_results
+ delegate_to: 127.0.0.254
+
+ - assert:
+ that:
+ - '"127.0.0.254" in setup_results.ansible_facts.ansible_env["SSH_CONNECTION"]'
+#
+# Smoketest some other modules do not error as a canary
+#
+ - name: Test file works with delegate_to and a host in inventory
+ file: path={{ output_dir }}/foo.txt mode=0644 state=touch
+ delegate_to: testhost4
+
+ - name: Test file works with delegate_to and a host not in inventory
+ file: path={{ output_dir }}/tmp.txt mode=0644 state=touch
+ delegate_to: 127.0.0.254
+
+ - name: Test template works with delegate_to and a host in inventory
+ template: src={{ template_role }}/templates/foo.j2 dest={{ output_dir }}/foo.txt
+ delegate_to: testhost4
+
+ - name: Test template works with delegate_to and a host not in inventory
+ template: src={{ template_role }}/templates/foo.j2 dest={{ output_dir }}/foo.txt
+ delegate_to: 127.0.0.254
+
+ - name: remove test file
+ file: path={{ output_dir }}/foo.txt state=absent
+
+ - name: remove test file
+ file: path={{ output_dir }}/tmp.txt state=absent
diff --git a/test/integration/targets/environment/runme.sh b/test/integration/targets/environment/runme.sh
new file mode 100755
index 0000000000..c556a17c9d
--- /dev/null
+++ b/test/integration/targets/environment/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_environment.yml -i ../../inventory "$@"
diff --git a/test/integration/targets/environment/test_environment.yml b/test/integration/targets/environment/test_environment.yml
new file mode 100644
index 0000000000..e72224ba76
--- /dev/null
+++ b/test/integration/targets/environment/test_environment.yml
@@ -0,0 +1,66 @@
+- hosts: testhost
+ vars:
+ - test1:
+ key1: val1
+ tasks:
+ - name: check that envvar does not exist
+ shell: echo $key1
+ register: test_env
+
+ - name: assert no val in stdout
+ assert:
+ that:
+ - '"val1" not in test_env.stdout_lines'
+
+ - name: check that envvar does exist
+ shell: echo $key1
+ environment: "{{test1}}"
+ register: test_env2
+
+ - name: assert val1 in stdout
+ assert:
+ that:
+ - '"val1" in test_env2.stdout_lines'
+
+- hosts: testhost
+ vars:
+ - test1:
+ key1: val1
+ - test2:
+ key1: not1
+ other1: val2
+ environment: "{{test1}}"
+ tasks:
+ - name: check that play envvar does exist
+ shell: echo $key1
+ register: test_env3
+
+ - name: assert val1 in stdout
+ assert:
+ that:
+ - '"val1" in test_env3.stdout_lines'
+
+ - name: check that task envvar does exist
+ shell: echo $key1; echo $other1
+ register: test_env4
+ environment: "{{test2}}"
+
+ - name: assert all vars appear as expected
+ assert:
+ that:
+ - '"val1" not in test_env4.stdout_lines'
+ - '"not1" in test_env4.stdout_lines'
+ - '"val2" in test_env4.stdout_lines'
+
+ - block:
+ - name: check that task envvar does exist in block
+ shell: echo $key1; echo $other1
+ register: test_env5
+
+ - name: assert all vars appear as expected in block
+ assert:
+ that:
+ - '"val1" not in test_env5.stdout_lines'
+ - '"not1" in test_env5.stdout_lines'
+ - '"val2" in test_env5.stdout_lines'
+ environment: "{{test2}}"
diff --git a/test/integration/targets/gathering_facts/runme.sh b/test/integration/targets/gathering_facts/runme.sh
new file mode 100755
index 0000000000..925910b226
--- /dev/null
+++ b/test/integration/targets/gathering_facts/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/gathering_facts/test_gathering_facts.yml b/test/integration/targets/gathering_facts/test_gathering_facts.yml
new file mode 100644
index 0000000000..ed3fa841ba
--- /dev/null
+++ b/test/integration/targets/gathering_facts/test_gathering_facts.yml
@@ -0,0 +1,133 @@
+---
+
+- hosts: facthost0
+ tags: [ 'fact_min' ]
+ connection: local
+ gather_subset: "all"
+ gather_facts: yes
+ tasks:
+ - setup:
+ register: facts
+ - debug: var=facts
+ - name: Test that retrieving all facts works
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" != "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" != "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" != "UNDEF_VIRT"'
+
+- hosts: facthost1
+ tags: [ 'fact_min' ]
+ connection: local
+ gather_subset: "!all"
+ gather_facts: yes
+ tasks:
+ - name: Test that only retrieving minimal facts work
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" == "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" == "UNDEF_VIRT"'
+
+- hosts: facthost2
+ tags: [ 'fact_network' ]
+ connection: local
+ gather_subset: "network"
+ gather_facts: yes
+ tasks:
+ - name: Test that retrieving network facts work
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" != "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" == "UNDEF_VIRT"'
+
+- hosts: facthost3
+ tags: [ 'fact_hardware' ]
+ connection: local
+ gather_subset: "hardware"
+ gather_facts: yes
+ tasks:
+ - name: Test that retrieving hardware facts work
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" == "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" != "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" == "UNDEF_VIRT"'
+
+- hosts: facthost4
+ tags: [ 'fact_virtual' ]
+ connection: local
+ gather_subset: "virtual"
+ gather_facts: yes
+ tasks:
+ - name: Test that retrieving virtualization facts work
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" == "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" != "UNDEF_VIRT"'
+
+- hosts: facthost5
+ tags: [ 'fact_comma_string' ]
+ connection: local
+ gather_subset: "virtual,network"
+ gather_facts: yes
+ tasks:
+ - name: Test that retrieving virtualization and network as a string works
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" != "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" != "UNDEF_VIRT"'
+
+- hosts: facthost6
+ tags: [ 'fact_yaml_list' ]
+ connection: local
+ gather_subset:
+ - virtual
+ - network
+ gather_facts: yes
+ tasks:
+ - name: Test that retrieving virtualization and network as a string works
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" != "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" != "UNDEF_VIRT"'
+
+- hosts: facthost7
+ tags: [ 'fact_negation' ]
+ connection: local
+ gather_subset: "!hardware"
+ gather_facts: yes
+ tasks:
+ - name: Test that negation of fact subsets work
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" != "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" != "UNDEF_VIRT"'
+
+- hosts: facthost8
+ tags: [ 'fact_mixed_negation_addition' ]
+ connection: local
+ gather_subset: "!hardware,network"
+ gather_facts: yes
+ tasks:
+ - name: Test that negation and additional subsets work together
+ assert:
+ that:
+ - '"{{ ansible_user_id|default("UNDEF_MIN") }}" != "UNDEF_MIN"'
+ - '"{{ ansible_interfaces|default("UNDEF_NET") }}" != "UNDEF_NET"'
+ - '"{{ ansible_mounts|default("UNDEF_HW") }}" == "UNDEF_HW"'
+ - '"{{ ansible_virtualization_role|default("UNDEF_VIRT") }}" == "UNDEF_VIRT"'
+
diff --git a/test/integration/targets/group_by/inventory.group_by b/test/integration/targets/group_by/inventory.group_by
new file mode 100644
index 0000000000..d8d285dee5
--- /dev/null
+++ b/test/integration/targets/group_by/inventory.group_by
@@ -0,0 +1,6 @@
+[lamini]
+alpaca genus=vicugna
+llama genus=lama
+
+[lamini:vars]
+ansible_connection=local
diff --git a/test/integration/targets/group_by/runme.sh b/test/integration/targets/group_by/runme.sh
new file mode 100755
index 0000000000..c6f6841e5c
--- /dev/null
+++ b/test/integration/targets/group_by/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_group_by.yml -i inventory.group_by -v "$@"
diff --git a/test/integration/targets/group_by/test_group_by.yml b/test/integration/targets/group_by/test_group_by.yml
new file mode 100644
index 0000000000..87d1809e8d
--- /dev/null
+++ b/test/integration/targets/group_by/test_group_by.yml
@@ -0,0 +1,127 @@
+# test code for the group_by module
+# (c) 2014, 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: Create overall groups
+ hosts: lamini
+ gather_facts: false
+ tasks:
+ - debug: var=genus
+ - name: group by genus
+ group_by: key={{ genus }}
+
+ - name: group by first three letters of genus with key in quotes
+ group_by: key="{{ genus | truncate(3, true, '') }}"
+
+ - name: group by first two letters of genus with key not in quotes
+ group_by: key={{ genus | truncate(2, true, '') }}
+
+ - name: group by genus in uppercase using complex args
+ group_by: { key: "{{ genus | upper() }}" }
+
+- name: Vicunga group validation
+ hosts: vicugna
+ gather_facts: false
+ tasks:
+ - name: verify that only the alpaca is in this group
+ assert: { that: "inventory_hostname == 'alpaca'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_vicugna=true
+
+- name: Lama group validation
+ hosts: lama
+ gather_facts: false
+ tasks:
+ - name: verify that only the llama is in this group
+ assert: { that: "inventory_hostname == 'llama'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_lama=true
+
+- name: Vic group validation
+ hosts: vic
+ gather_facts: false
+ tasks:
+ - name: verify that only the alpaca is in this group
+ assert: { that: "inventory_hostname == 'alpaca'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_vic=true
+
+- name: Lam group validation
+ hosts: lam
+ gather_facts: false
+ tasks:
+ - name: verify that only the llama is in this group
+ assert: { that: "inventory_hostname == 'llama'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_lam=true
+
+- name: Vi group validation
+ hosts: vi
+ gather_facts: false
+ tasks:
+ - name: verify that only the alpaca is in this group
+ assert: { that: "inventory_hostname == 'alpaca'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_vi=true
+
+- name: La group validation
+ hosts: la
+ gather_facts: false
+ tasks:
+ - name: verify that only the llama is in this group
+ assert: { that: "inventory_hostname == 'llama'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_la=true
+
+- name: VICUGNA group validation
+ hosts: VICUGNA
+ gather_facts: false
+ tasks:
+ - name: verify that only the alpaca is in this group
+ assert: { that: "inventory_hostname == 'alpaca'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_VICUGNA=true
+
+- name: LAMA group validation
+ hosts: LAMA
+ gather_facts: false
+ tasks:
+ - name: verify that only the llama is in this group
+ assert: { that: "inventory_hostname == 'llama'" }
+ - name: set a fact to check that we ran this play
+ set_fact: genus_LAMA=true
+
+- name: genus group validation (expect skipped)
+ hosts: 'genus'
+ gather_facts: false
+ tasks:
+ - name: no hosts should match this group
+ fail: msg="should never get here"
+
+- name: alpaca validation of groups
+ hosts: alpaca
+ gather_facts: false
+ tasks:
+ - name: check that alpaca matched all four groups
+ assert: { that: ["genus_vicugna", "genus_vic", "genus_vi", "genus_VICUGNA"] }
+
+- name: llama validation of groups
+ hosts: llama
+ gather_facts: false
+ tasks:
+ - name: check that llama matched all four groups
+ assert: { that: ["genus_lama", "genus_lam", "genus_la", "genus_LAMA"] }
diff --git a/test/integration/targets/handlers/inventory.handlers b/test/integration/targets/handlers/inventory.handlers
new file mode 100644
index 0000000000..905026f12e
--- /dev/null
+++ b/test/integration/targets/handlers/inventory.handlers
@@ -0,0 +1,6 @@
+[testgroup]
+A
+B
+C
+D
+E
diff --git a/test/integration/targets/handlers/roles/test_force_handlers/handlers/main.yml b/test/integration/targets/handlers/roles/test_force_handlers/handlers/main.yml
new file mode 100644
index 0000000000..2cfb1ef710
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_force_handlers/handlers/main.yml
@@ -0,0 +1,2 @@
+- name: echoing handler
+ command: echo CALLED_HANDLER_{{ inventory_hostname }} \ No newline at end of file
diff --git a/test/integration/targets/handlers/roles/test_force_handlers/tasks/main.yml b/test/integration/targets/handlers/roles/test_force_handlers/tasks/main.yml
new file mode 100644
index 0000000000..ea01660ba7
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_force_handlers/tasks/main.yml
@@ -0,0 +1,26 @@
+---
+
+# We notify for A and B, and hosts B and C fail.
+# When forcing, we expect A and B to run handlers
+# When not forcing, we expect only B to run handlers
+
+- name: notify the handler for host A and B
+ shell: echo
+ notify:
+ - echoing handler
+ when: inventory_hostname == 'A' or inventory_hostname == 'B'
+
+- name: EXPECTED FAILURE fail task for all
+ fail: msg="Fail All"
+ when: fail_all is defined and fail_all
+
+- name: EXPECTED FAILURE fail task for A
+ fail: msg="Fail A"
+ when: inventory_hostname == 'A'
+
+- name: EXPECTED FAILURE fail task for C
+ fail: msg="Fail C"
+ when: inventory_hostname == 'C'
+
+- name: echo after A and C have failed
+ command: echo CALLED_TASK_{{ inventory_hostname }} \ No newline at end of file
diff --git a/test/integration/targets/handlers/roles/test_handlers/handlers/main.yml b/test/integration/targets/handlers/roles/test_handlers/handlers/main.yml
new file mode 100644
index 0000000000..b8ee48b5c8
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_handlers/handlers/main.yml
@@ -0,0 +1,5 @@
+- name: set handler fact
+ set_fact:
+ handler_called: True
+- name: test handler
+ debug: msg="handler called"
diff --git a/test/integration/targets/handlers/roles/test_handlers/meta/main.yml b/test/integration/targets/handlers/roles/test_handlers/meta/main.yml
new file mode 100644
index 0000000000..74d2c33354
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_handlers/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies: []
+
diff --git a/test/integration/targets/handlers/roles/test_handlers/tasks/main.yml b/test/integration/targets/handlers/roles/test_handlers/tasks/main.yml
new file mode 100644
index 0000000000..1c1d819269
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_handlers/tasks/main.yml
@@ -0,0 +1,52 @@
+# test code for the async keyword
+# (c) 2014, James Tanner <tanner.jc@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: reset handler_called variable to false for all hosts
+ set_fact:
+ handler_called: False
+ tags: scenario1
+
+- name: notify the handler for host A only
+ shell: echo
+ notify:
+ - set handler fact
+ when: inventory_hostname == 'A'
+ tags: scenario1
+
+- name: force handler execution now
+ meta: "flush_handlers"
+ tags: scenario1
+
+- debug: var=handler_called
+ tags: scenario1
+
+- name: validate the handler only ran on one host
+ assert:
+ that:
+ - "inventory_hostname == 'A' and handler_called == True or handler_called == False"
+ tags: scenario1
+
+- name: 'test notify with loop'
+ debug: msg='a task'
+ changed_when: item == 1
+ notify: test handler
+ with_items:
+ - 1
+ - 2
+ tags: scenario2
diff --git a/test/integration/targets/handlers/roles/test_handlers_meta/handlers/main.yml b/test/integration/targets/handlers/roles/test_handlers_meta/handlers/main.yml
new file mode 100644
index 0000000000..634e6eca2a
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_handlers_meta/handlers/main.yml
@@ -0,0 +1,7 @@
+- name: set_handler_fact_1
+ set_fact:
+ handler1_called: True
+
+- name: set_handler_fact_2
+ set_fact:
+ handler2_called: True
diff --git a/test/integration/targets/handlers/roles/test_handlers_meta/tasks/main.yml b/test/integration/targets/handlers/roles/test_handlers_meta/tasks/main.yml
new file mode 100644
index 0000000000..047b61ce88
--- /dev/null
+++ b/test/integration/targets/handlers/roles/test_handlers_meta/tasks/main.yml
@@ -0,0 +1,41 @@
+# test code for the async keyword
+# (c) 2014, James Tanner <tanner.jc@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: notify the first handler
+ shell: echo
+ notify:
+ - set_handler_fact_1
+
+- name: force handler execution now
+ meta: "flush_handlers"
+
+- name: assert handler1 ran and not handler2
+ assert:
+ that:
+ - "handler1_called is defined"
+ - "handler2_called is not defined"
+
+- name: reset handler1_called
+ set_fact:
+ handler1_called: False
+
+- name: notify the second handler
+ shell: echo
+ notify:
+ - set_handler_fact_2
+
diff --git a/test/integration/targets/handlers/runme.sh b/test/integration/targets/handlers/runme.sh
new file mode 100755
index 0000000000..48dfd8368b
--- /dev/null
+++ b/test/integration/targets/handlers/runme.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_handlers.yml -i inventory.handlers -v "$@" --tags scenario1
+
+[ "$(ansible-playbook test_handlers.yml -i inventory.handlers -v "$@" --tags scenario2 -l A \
+| egrep -o 'RUNNING HANDLER \[test_handlers : .*?]')" = "RUNNING HANDLER [test_handlers : test handler]" ]
+
+# Not forcing, should only run on successful host
+[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags normal \
+| egrep -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_B" ]
+
+# Forcing from command line
+[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags normal --force-handlers \
+| egrep -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_A CALLED_HANDLER_B" ]
+
+# Forcing from command line, should only run later tasks on unfailed hosts
+[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags normal --force-handlers \
+| egrep -o CALLED_TASK_. | sort | uniq | xargs)" = "CALLED_TASK_B CALLED_TASK_D CALLED_TASK_E" ]
+
+# Forcing from command line, should call handlers even if all hosts fail
+[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags normal --force-handlers -e fail_all=yes \
+| egrep -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_A CALLED_HANDLER_B" ]
+
+# Forcing from ansible.cfg
+[ "$(ANSIBLE_FORCE_HANDLERS=true ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags normal \
+| egrep -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_A CALLED_HANDLER_B" ]
+
+# Forcing true in play
+[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags force_true_in_play \
+| egrep -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_A CALLED_HANDLER_B" ]
+
+# Forcing false in play, which overrides command line
+[ "$(ansible-playbook test_force_handlers.yml -i inventory.handlers -v "$@" --tags force_false_in_play --force-handlers \
+| egrep -o CALLED_HANDLER_. | sort | uniq | xargs)" = "CALLED_HANDLER_B" ]
diff --git a/test/integration/targets/handlers/test_force_handlers.yml b/test/integration/targets/handlers/test_force_handlers.yml
new file mode 100644
index 0000000000..f7cadbd86d
--- /dev/null
+++ b/test/integration/targets/handlers/test_force_handlers.yml
@@ -0,0 +1,30 @@
+---
+
+- name: test force handlers (default)
+ tags: normal
+ hosts: testgroup
+ gather_facts: False
+ connection: local
+ roles:
+ - { role: test_force_handlers }
+ tasks:
+ - debug: msg="you should see this with --tags=normal"
+
+- name: test force handlers (set to true)
+ tags: force_true_in_play
+ hosts: testgroup
+ gather_facts: False
+ connection: local
+ force_handlers: True
+ roles:
+ - { role: test_force_handlers, tags: force_true_in_play }
+
+
+- name: test force handlers (set to false)
+ tags: force_false_in_play
+ hosts: testgroup
+ gather_facts: False
+ connection: local
+ force_handlers: False
+ roles:
+ - { role: test_force_handlers, tags: force_false_in_play }
diff --git a/test/integration/targets/handlers/test_handlers.yml b/test/integration/targets/handlers/test_handlers.yml
new file mode 100644
index 0000000000..dafa9ceebe
--- /dev/null
+++ b/test/integration/targets/handlers/test_handlers.yml
@@ -0,0 +1,26 @@
+---
+- name: run handlers
+ hosts: A
+ gather_facts: False
+ connection: local
+ roles:
+ - { role: test_handlers_meta, tags: ['scenario1'] }
+
+- name: verify final handler was run
+ hosts: A
+ gather_facts: False
+ connection: local
+ tasks:
+ - name: verify handler2 ran
+ assert:
+ that:
+ - "not hostvars[inventory_hostname]['handler1_called']"
+ - "'handler2_called' in hostvars[inventory_hostname]"
+ tags: ['scenario1']
+
+- name: test handlers
+ hosts: testgroup
+ gather_facts: False
+ connection: local
+ roles:
+ - { role: test_handlers }
diff --git a/test/integration/targets/hash/roles/test_hash_behavior/defaults/main.yml b/test/integration/targets/hash/roles/test_hash_behavior/defaults/main.yml
new file mode 100644
index 0000000000..10cc09f31c
--- /dev/null
+++ b/test/integration/targets/hash/roles/test_hash_behavior/defaults/main.yml
@@ -0,0 +1,21 @@
+# test code for the hash variable behavior
+# (c) 2014, James Cammarata <jcammarata@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/>.
+
+---
+test_hash:
+ default_vars: "this is in role defaults/main.yml"
diff --git a/test/integration/targets/hash/roles/test_hash_behavior/meta/main.yml b/test/integration/targets/hash/roles/test_hash_behavior/meta/main.yml
new file mode 100644
index 0000000000..c3dcf7aaf9
--- /dev/null
+++ b/test/integration/targets/hash/roles/test_hash_behavior/meta/main.yml
@@ -0,0 +1,18 @@
+# test code for the hash variable behavior
+# (c) 2014, James Cammarata <jcammarata@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/>.
+
diff --git a/test/integration/targets/hash/roles/test_hash_behavior/tasks/main.yml b/test/integration/targets/hash/roles/test_hash_behavior/tasks/main.yml
new file mode 100644
index 0000000000..463141edd3
--- /dev/null
+++ b/test/integration/targets/hash/roles/test_hash_behavior/tasks/main.yml
@@ -0,0 +1,42 @@
+# test code for the hash variable behavior
+# (c) 2014, James Cammarata <jcammarata@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: get the hash behavior env setting
+ shell: env | grep ^ANSIBLE_HASH_BEHAVIOUR'=' | cut -f2- -d'='
+ register: hash_behavior
+ # This only works with the local connection. The way this test is run means the
+ connection: local
+ delegate_to: localhost
+
+
+- name: debug hash behavior result
+ debug: var=hash_behavior.stdout
+
+- name: assert hash behavior is merge or replace
+ assert:
+ that:
+ - "hash_behavior.stdout in ('merge', 'replace')"
+
+- name: debug test_hash var
+ debug: var=test_hash
+
+- name: assert the dictionary values match
+ assert:
+ that:
+ - "hash_behavior.stdout == 'merge' and test_hash == merged_hash or hash_behavior.stdout == 'replace' and test_hash == replaced_hash"
+
diff --git a/test/integration/targets/hash/roles/test_hash_behavior/vars/main.yml b/test/integration/targets/hash/roles/test_hash_behavior/vars/main.yml
new file mode 100644
index 0000000000..2068e9fbaf
--- /dev/null
+++ b/test/integration/targets/hash/roles/test_hash_behavior/vars/main.yml
@@ -0,0 +1,21 @@
+# test code for the hash variable behavior
+# (c) 2014, James Cammarata <jcammarata@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/>.
+
+---
+test_hash:
+ role_vars: "this is in role vars/main.yml"
diff --git a/test/integration/targets/hash/runme.sh b/test/integration/targets/hash/runme.sh
new file mode 100755
index 0000000000..9448e4e098
--- /dev/null
+++ b/test/integration/targets/hash/runme.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -eux
+
+JSON_ARG='{"test_hash":{"extra_args":"this is an extra arg"}}'
+
+ANSIBLE_HASH_BEHAVIOUR=replace ansible-playbook test_hash.yml -i ../../inventory -v "$@" -e "${JSON_ARG}"
+ANSIBLE_HASH_BEHAVIOUR=merge ansible-playbook test_hash.yml -i ../../inventory -v "$@" -e "${JSON_ARG}"
diff --git a/test/integration/targets/hash/test_hash.yml b/test/integration/targets/hash/test_hash.yml
new file mode 100644
index 0000000000..271563355b
--- /dev/null
+++ b/test/integration/targets/hash/test_hash.yml
@@ -0,0 +1,20 @@
+---
+- hosts: testhost
+ vars_files:
+ - vars/test_hash_vars.yml
+ vars:
+ test_hash:
+ playbook_vars: "this is a playbook variable"
+ replaced_hash:
+ extra_args: "this is an extra arg"
+ merged_hash:
+ default_vars: "this is in role defaults/main.yml"
+ extra_args: "this is an extra arg"
+ group_vars_all: "this is in group_vars/all"
+ host_vars_testhost: "this is in host_vars/testhost"
+ playbook_vars: "this is a playbook variable"
+ role_argument: "this is a role argument variable"
+ role_vars: "this is in role vars/main.yml"
+ vars_file: "this is in a vars_file"
+ roles:
+ - { role: test_hash_behavior, test_hash: {'role_argument':'this is a role argument variable'} }
diff --git a/test/integration/targets/hash/vars/test_hash_vars.yml b/test/integration/targets/hash/vars/test_hash_vars.yml
new file mode 100644
index 0000000000..e25f8576c3
--- /dev/null
+++ b/test/integration/targets/hash/vars/test_hash_vars.yml
@@ -0,0 +1,3 @@
+---
+test_hash:
+ vars_file: "this is in a vars_file"
diff --git a/test/integration/targets/hosts_field/inventory.hosts_field b/test/integration/targets/hosts_field/inventory.hosts_field
new file mode 100644
index 0000000000..81efd478f8
--- /dev/null
+++ b/test/integration/targets/hosts_field/inventory.hosts_field
@@ -0,0 +1 @@
+42 ansible_host=127.0.0.42 ansible_connection=local
diff --git a/test/integration/targets/hosts_field/runme.sh b/test/integration/targets/hosts_field/runme.sh
new file mode 100755
index 0000000000..1291933c5b
--- /dev/null
+++ b/test/integration/targets/hosts_field/runme.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# Hosts in playbook has a list of strings consisting solely of digits
+ansible-playbook test_hosts_field.yml -i inventory.hosts_field -e 'target_kv=42' \
+ -e '{ "target_json_cli": "42", "target_json_cli_list": ["42", "localhost"] }' -e "@test_hosts_field.json" \
+ -t string_digit_host_in_list -v "$@" | tee test_hosts_field.out
+grep 'Running on 42' test_hosts_field.out 2>&1
+test "$(grep -c 'ok=1' test_hosts_field.out)" = 1
+
+# Hosts taken from kv extra_var on the CLI
+ansible-playbook test_hosts_field.yml -i inventory.hosts_field -e 'target_kv=42' \
+ -e '{ "target_json_cli": "42", "target_json_cli_list": ["42", "localhost"] }' -e "@test_hosts_field.json" \
+ -t hosts_from_kv_string -v "$@" | tee test_hosts_field.out
+grep 'Running on 42' test_hosts_field.out 2>&1
+test "$(grep -c 'ok=1' test_hosts_field.out)" = 1
+
+# hosts is taken from an all digit json extra_vars string on the CLI
+ansible-playbook test_hosts_field.yml -i inventory.hosts_field -e 'target_kv=42' \
+ -e '{ "target_json_cli": "42", "target_json_cli_list": ["42", "localhost"] }' -e "@test_hosts_field.json" \
+ -t hosts_from_cli_json_string -v "$@" | tee test_hosts_field.out
+grep 'Running on 42' test_hosts_field.out 2>&1
+test "$(grep -c 'ok=1' test_hosts_field.out)" = 1
+
+# hosts is taken from a json list in extra_vars on the CLI
+ansible-playbook test_hosts_field.yml -i inventory.hosts_field -e 'target_kv=42' \
+ -e '{ "target_json_cli": "42", "target_json_cli_list": ["42", "localhost"] }' -e "@test_hosts_field.json" \
+ -t hosts_from_cli_json_list -v "$@" | tee test_hosts_field.out
+grep 'Running on 42' test_hosts_field.out 2>&1
+grep 'Running on localhost' test_hosts_field.out 2>&1
+test "$(grep -c 'ok=1' test_hosts_field.out)" = 2
+
+# hosts is taken from a json string in an extra_vars file
+ansible-playbook test_hosts_field.yml -i inventory.hosts_field -e 'target_kv=42' \
+ -e '{ "target_json_cli": "42", "target_json_cli_list": ["42", "localhost"] }' -e "@test_hosts_field.json" \
+ -t hosts_from_json_file_string -v "$@" | tee test_hosts_field.out
+grep 'Running on 42' test_hosts_field.out 2>&1
+test "$(grep -c 'ok=1' test_hosts_field.out)" = 1
+
+# hosts is taken from a json list in an extra_vars file
+ansible-playbook test_hosts_field.yml -i inventory.hosts_field -e 'target_kv=42' \
+ -e '{ "target_json_cli": "42", "target_json_cli_list": ["42", "localhost"] }' -e "@test_hosts_field.json" \
+ -t hosts_from_json_file_list -v "$@" | tee test_hosts_field.out
+grep 'Running on 42' test_hosts_field.out 2>&1
+grep 'Running on localhost' test_hosts_field.out 2>&1
+test "$(grep -c 'ok=1' test_hosts_field.out)" = 2
+
+rm test_hosts_field.out
diff --git a/test/integration/targets/hosts_field/test_hosts_field.json b/test/integration/targets/hosts_field/test_hosts_field.json
new file mode 100644
index 0000000000..2687556093
--- /dev/null
+++ b/test/integration/targets/hosts_field/test_hosts_field.json
@@ -0,0 +1 @@
+{ "target_json_file": "42", "target_json_file_list": ["42", "localhost"] }
diff --git a/test/integration/targets/hosts_field/test_hosts_field.yml b/test/integration/targets/hosts_field/test_hosts_field.yml
new file mode 100644
index 0000000000..568d702503
--- /dev/null
+++ b/test/integration/targets/hosts_field/test_hosts_field.yml
@@ -0,0 +1,62 @@
+---
+#- name: Host in playbook is an integer
+# hosts: 42
+# tags: numeric_host
+# tasks:
+# - command: echo 'Running on {{ inventory_hostname }}'
+
+#- name: Host in playbook is a string of digits
+# hosts: "42"
+# tags: string_digit_host
+# tasks:
+# - command: echo 'Running on {{ inventory_hostname }}'
+
+#- name: Host in playbook is a list of integer
+# hosts:
+# - 42
+# tags: numeric_host_in_list
+# tasks:
+# - command: echo 'Running on {{ inventory_hostname }}'
+
+- name: Host in playbook is a list of strings of digits
+ hosts:
+ - "42"
+ gather_facts: False
+ tags: string_digit_host_in_list
+ tasks:
+ - command: echo 'Running on {{ inventory_hostname }}'
+
+- name: Hosts taken from kv extra_var on the CLI
+ hosts: "{{ target_kv }}"
+ gather_facts: False
+ tags: hosts_from_kv_string
+ tasks:
+ - command: echo 'Running on {{ inventory_hostname }}'
+
+- name: Hosts taken from a json string on the CLI
+ hosts: "{{ target_json_cli }}"
+ gather_facts: False
+ tags: hosts_from_cli_json_string
+ tasks:
+ - command: echo 'Running on {{ inventory_hostname }}'
+
+- name: Hosts taken from a json list on the CLI
+ hosts: "{{ target_json_cli_list }}"
+ gather_facts: False
+ tags: hosts_from_cli_json_list
+ tasks:
+ - command: echo 'Running on {{ inventory_hostname }}'
+
+- name: Hosts is taken from a json string in an extra_vars file
+ hosts: "{{ target_json_file }}"
+ gather_facts: False
+ tags: hosts_from_json_file_string
+ tasks:
+ - command: echo 'Running on {{ inventory_hostname }}'
+
+- name: Hosts is taken from a json list in an extra_vars file
+ hosts: "{{ target_json_file_list }}"
+ gather_facts: False
+ tags: hosts_from_json_file_list
+ tasks:
+ - command: echo 'Running on {{ inventory_hostname }}'
diff --git a/test/integration/targets/includes/roles/test_includes/handlers/main.yml b/test/integration/targets/includes/roles/test_includes/handlers/main.yml
new file mode 100644
index 0000000000..25e7d3886f
--- /dev/null
+++ b/test/integration/targets/includes/roles/test_includes/handlers/main.yml
@@ -0,0 +1,2 @@
+- include: more_handlers.yml
+
diff --git a/test/integration/targets/includes/roles/test_includes/handlers/more_handlers.yml b/test/integration/targets/includes/roles/test_includes/handlers/more_handlers.yml
new file mode 100644
index 0000000000..947ede8d91
--- /dev/null
+++ b/test/integration/targets/includes/roles/test_includes/handlers/more_handlers.yml
@@ -0,0 +1,14 @@
+- name: included_handler
+ set_fact:
+ ca: 4001
+ cb: 4002
+ cc: 4003
+
+- name: verify_handler
+ assert:
+ that:
+ - "ca == 4001"
+ - "cb == 4002"
+ - "cc == 4003"
+
+
diff --git a/test/integration/targets/includes/roles/test_includes/tasks/empty.yml b/test/integration/targets/includes/roles/test_includes/tasks/empty.yml
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/integration/targets/includes/roles/test_includes/tasks/empty.yml
diff --git a/test/integration/targets/includes/roles/test_includes/tasks/included_task1.yml b/test/integration/targets/includes/roles/test_includes/tasks/included_task1.yml
new file mode 100644
index 0000000000..8fe79a1cb7
--- /dev/null
+++ b/test/integration/targets/includes/roles/test_includes/tasks/included_task1.yml
@@ -0,0 +1,10 @@
+- set_fact:
+ ca: "{{ a }}"
+- debug: var=ca
+- set_fact:
+ cb: "{{b}}"
+- debug: var=cb
+- set_fact:
+ cc: "{{ c }}"
+- debug: var=cc
+
diff --git a/test/integration/targets/includes/roles/test_includes/tasks/main.yml b/test/integration/targets/includes/roles/test_includes/tasks/main.yml
new file mode 100644
index 0000000000..33aefe8959
--- /dev/null
+++ b/test/integration/targets/includes/roles/test_includes/tasks/main.yml
@@ -0,0 +1,84 @@
+# test code for the ping module
+# (c) 2014, James Cammarata <jcammarata@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/>.
+
+
+- include: included_task1.yml a=1 b=2 c=3
+
+- name: verify non-variable include params
+ assert:
+ that:
+ - "ca == '1'"
+ - "cb == '2'"
+ - "cc == '3'"
+
+- set_fact:
+ a: 101
+ b: 102
+ c: 103
+
+- include: included_task1.yml a={{a}} b={{b}} c=103
+
+- name: verify variable include params
+ assert:
+ that:
+ - "ca == 101"
+ - "cb == 102"
+ - "cc == 103"
+
+# Test that strings are not turned into numbers
+- set_fact:
+ a: "101"
+ b: "102"
+ c: "103"
+
+- include: included_task1.yml a={{a}} b={{b}} c=103
+
+- name: verify variable include params
+ assert:
+ that:
+ - "ca == '101'"
+ - "cb == '102'"
+ - "cc == '103'"
+
+# now try long form includes
+
+- include: included_task1.yml
+ vars:
+ a: 201
+ b: 202
+ c: 203
+
+- debug: var=a
+- debug: var=b
+- debug: var=c
+
+- name: verify long-form include params
+ assert:
+ that:
+ - "ca == 201"
+ - "cb == 202"
+ - "cc == 203"
+
+- name: test handlers with includes
+ shell: echo 1
+ notify:
+ # both these via a handler include
+ - included_handler
+ - verify_handler
+
+
diff --git a/test/integration/targets/includes/roles/test_includes/tasks/not_a_role_task.yml b/test/integration/targets/includes/roles/test_includes/tasks/not_a_role_task.yml
new file mode 100644
index 0000000000..862b051ce5
--- /dev/null
+++ b/test/integration/targets/includes/roles/test_includes/tasks/not_a_role_task.yml
@@ -0,0 +1,4 @@
+- set_fact:
+ ca: 33000
+ cb: 33001
+ cc: 33002
diff --git a/test/integration/targets/includes/runme.sh b/test/integration/targets/includes/runme.sh
new file mode 100755
index 0000000000..dff40029b1
--- /dev/null
+++ b/test/integration/targets/includes/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_includes.yml -i ../../inventory "$@"
diff --git a/test/integration/targets/includes/test_includes.yml b/test/integration/targets/includes/test_includes.yml
new file mode 100644
index 0000000000..d7303880f1
--- /dev/null
+++ b/test/integration/targets/includes/test_includes.yml
@@ -0,0 +1,3 @@
+- include: test_includes2.yml parameter1=asdf parameter2=jkl
+
+- include: test_includes3.yml
diff --git a/test/integration/targets/includes/test_includes2.yml b/test/integration/targets/includes/test_includes2.yml
new file mode 100644
index 0000000000..1b15682d70
--- /dev/null
+++ b/test/integration/targets/includes/test_includes2.yml
@@ -0,0 +1,22 @@
+
+- name: verify playbook includes can take parameters
+ hosts: testhost
+ tasks:
+ - assert:
+ that:
+ - "parameter1 == 'asdf'"
+ - "parameter2 == 'jkl'"
+
+- name: verify task include logic
+ hosts: testhost
+ gather_facts: True
+ roles:
+ - { role: test_includes, tags: test_includes }
+ tasks:
+ - include: roles/test_includes/tasks/not_a_role_task.yml
+ - include: roles/test_includes/tasks/empty.yml
+ - assert:
+ that:
+ - "ca == 33000"
+ - "cb == 33001"
+ - "cc == 33002"
diff --git a/test/integration/targets/includes/test_includes3.yml b/test/integration/targets/includes/test_includes3.yml
new file mode 100644
index 0000000000..012ee20568
--- /dev/null
+++ b/test/integration/targets/includes/test_includes3.yml
@@ -0,0 +1,7 @@
+---
+- hosts: localhost
+ tasks:
+ - include: test_includes4.yml
+ with_items: ["a"]
+ loop_control:
+ loop_var: r
diff --git a/test/integration/targets/includes/test_includes4.yml b/test/integration/targets/includes/test_includes4.yml
new file mode 100644
index 0000000000..bee906bdfb
--- /dev/null
+++ b/test/integration/targets/includes/test_includes4.yml
@@ -0,0 +1,2 @@
+- set_fact:
+ p: 1
diff --git a/test/integration/targets/lookup_paths/play.yml b/test/integration/targets/lookup_paths/play.yml
new file mode 100644
index 0000000000..26a9ce10b9
--- /dev/null
+++ b/test/integration/targets/lookup_paths/play.yml
@@ -0,0 +1,64 @@
+- name: setup state
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ tasks:
+ - file: path={{playbook_dir}}/files state=directory
+ - file: path={{playbook_dir}}/roles/showfile/files state=directory
+ - copy: dest={{playbook_dir}}/roles/showfile/files/testfile content='in role files'
+ - copy: dest={{playbook_dir}}/roles/showfile/tasks/testfile content='in role tasks'
+ - copy: dest={{playbook_dir}}/roles/showfile/testfile content='in role'
+ - copy: dest={{playbook_dir}}/files/testfile content='in files'
+ - copy: dest={{playbook_dir}}/testfile content='in local'
+ - set_fact: role_out="in role files" play_out="in files" stage='setup'
+
+- include: testplay.yml
+
+- name: remove from role/files
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ tasks:
+ - file: path={{playbook_dir}}/roles/showfile/files/testfile state=absent
+ - set_fact: role_out="in role tasks" play_out="in files" stage='remove 1'
+
+- include: testplay.yml
+
+- name: remove from role/tasks
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ tasks:
+ - file: path={{playbook_dir}}/roles/showfile/tasks/testfile state=absent
+ - set_fact: role_out="in files" play_out="in files" stage='remote 2'
+
+- include: testplay.yml
+
+- name: remove from role dir
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ tasks:
+ - file: path={{playbook_dir}}/roles/showfile/testfile state=absent
+ - set_fact: role_out="in files" play_out="in files" stage='remove 3'
+
+- include: testplay.yml
+
+- name: remove from play/files
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ tasks:
+ - file: path={{playbook_dir}}/files/testfile state=absent
+ - set_fact: role_out="in local" play_out="in local" stage='remove 4'
+
+- include: testplay.yml
+
+- name: cleanup
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ tasks:
+ - file: path={{playbook_dir}}/testfile state=absent
+ - file: path={{playbook_dir}}/files state=absent
+ - file: path={{playbook_dir}}/roles/showfile/files state=absent
diff --git a/test/integration/targets/lookup_paths/roles/showfile/tasks/main.yml b/test/integration/targets/lookup_paths/roles/showfile/tasks/main.yml
new file mode 100644
index 0000000000..1b3805798d
--- /dev/null
+++ b/test/integration/targets/lookup_paths/roles/showfile/tasks/main.yml
@@ -0,0 +1,2 @@
+- name: relative to role
+ set_fact: role_result="{{lookup('file', 'testfile')}}"
diff --git a/test/integration/targets/lookup_paths/runme.sh b/test/integration/targets/lookup_paths/runme.sh
new file mode 100755
index 0000000000..754150b4c7
--- /dev/null
+++ b/test/integration/targets/lookup_paths/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook play.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/lookup_paths/testplay.yml b/test/integration/targets/lookup_paths/testplay.yml
new file mode 100644
index 0000000000..8bf4be2c08
--- /dev/null
+++ b/test/integration/targets/lookup_paths/testplay.yml
@@ -0,0 +1,19 @@
+- name: test initial state
+ hosts: testhost
+ connection: local
+ gather_facts: false
+ roles:
+ - showfile
+ tasks:
+ - name: from play
+ set_fact: play_result="{{lookup('file', 'testfile')}}"
+
+ - name: output output {{stage}}
+ debug: msg="play> {{play_out}}, role> {{role_out}}"
+
+ - name: verify that result match expected
+ assert:
+ that:
+ - 'play_result == play_out'
+ - 'role_result == role_out'
+
diff --git a/test/integration/targets/lookup_properties/lookup.ini b/test/integration/targets/lookup_properties/lookup.ini
new file mode 100644
index 0000000000..16500fd899
--- /dev/null
+++ b/test/integration/targets/lookup_properties/lookup.ini
@@ -0,0 +1,24 @@
+[global]
+# A comment
+value1=Text associated with value1 and global section
+value2=Same for value2 and global section
+value.dot=Properties with dot
+field.with.space = another space
+
+[section1]
+value1=section1/value1
+value2=section1/value2
+
+[value_section]
+value1=1
+value2=2
+value3=3
+other1=4
+other2=5
+
+[other_section]
+value1=1
+value2=2
+value3=3
+other1=4
+other2=5
diff --git a/test/integration/targets/lookup_properties/lookup.properties b/test/integration/targets/lookup_properties/lookup.properties
new file mode 100644
index 0000000000..f388d8cfbf
--- /dev/null
+++ b/test/integration/targets/lookup_properties/lookup.properties
@@ -0,0 +1,5 @@
+# A comment
+value1=Text associated with value1
+value2=Same for value2
+value.dot=Properties with dot
+field.with.space = another space
diff --git a/test/integration/targets/lookup_properties/runme.sh b/test/integration/targets/lookup_properties/runme.sh
new file mode 100755
index 0000000000..71a507de42
--- /dev/null
+++ b/test/integration/targets/lookup_properties/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_lookup_properties.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/lookup_properties/test_lookup_properties.yml b/test/integration/targets/lookup_properties/test_lookup_properties.yml
new file mode 100644
index 0000000000..4d22ce642c
--- /dev/null
+++ b/test/integration/targets/lookup_properties/test_lookup_properties.yml
@@ -0,0 +1,40 @@
+---
+- name: "Lookup test"
+ hosts: "localhost"
+# connection: local
+ tasks:
+ - name: "read properties value"
+ set_fact:
+ test1: "{{lookup('ini', 'value1 type=properties file=lookup.properties')}}"
+ test2: "{{lookup('ini', 'value2 type=properties file=lookup.properties')}}"
+ test_dot: "{{lookup('ini', 'value.dot type=properties file=lookup.properties')}}"
+ field_with_space: "{{lookup('ini', 'field.with.space type=properties file=lookup.properties')}}"
+ - debug: var={{item}}
+ with_items: [ 'test1', 'test2', 'test_dot', 'field_with_space' ]
+ - name: "read ini value"
+ set_fact:
+ value1_global: "{{lookup('ini', 'value1 section=global file=lookup.ini')}}"
+ value2_global: "{{lookup('ini', 'value2 section=global file=lookup.ini')}}"
+ value1_section1: "{{lookup('ini', 'value1 section=section1 file=lookup.ini')}}"
+ - debug: var={{item}}
+ with_items: [ 'value1_global', 'value2_global', 'value1_section1' ]
+ - name: "read ini value with section and regexp"
+ set_fact:
+ value_section: "{{lookup('ini', 'value[1-2] section=value_section file=lookup.ini re=true')}}"
+ other_section: "{{lookup('ini', 'other[1-2] section=other_section file=lookup.ini re=true')}}"
+ - debug: var={{item}}
+ with_items: [ 'value_section', 'other_section' ]
+ - name: "Reading unknown value"
+ set_fact:
+ unknown: "{{lookup('ini', 'value2 default=unknown section=section1 file=lookup.ini')}}"
+ - debug: var=unknown
+ - name: "Looping over section section1"
+ debug: msg="{{item}}"
+ with_ini: value[1-2] section=section1 file=lookup.ini re=true
+ - name: "Looping over section value_section"
+ debug: msg="{{item}}"
+ with_ini: value[1-2] section=value_section file=lookup.ini re=true
+ - debug: msg="{{item}}"
+ with_ini: value[1-2] section=section1 file=lookup.ini re=true
+ register: _
+ - debug: var=_
diff --git a/test/integration/targets/no_log/no_log_local.yml b/test/integration/targets/no_log/no_log_local.yml
new file mode 100644
index 0000000000..87d76ff082
--- /dev/null
+++ b/test/integration/targets/no_log/no_log_local.yml
@@ -0,0 +1,66 @@
+# TODO: test against real connection plugins to ensure they're not leaking module args
+
+- name: normal play
+ hosts: testhost
+ gather_facts: no
+ tasks:
+ - name: args should be logged in the absence of no_log
+ shell: echo "LOG_ME_TASK_SUCCEEDED"
+
+ - name: failed args should be logged in the absence of no_log
+ shell: echo "LOG_ME_TASK_FAILED"
+ failed_when: true
+ ignore_errors: true
+
+ - name: item args should be logged in the absence of no_log
+ shell: echo {{ item }}
+ with_items: [ "LOG_ME_ITEM", "LOG_ME_SKIPPED", "LOG_ME_ITEM_FAILED" ]
+ when: item != "LOG_ME_SKIPPED"
+ failed_when: item == "LOG_ME_ITEM_FAILED"
+ ignore_errors: true
+
+ - name: args should not be logged when task-level no_log set
+ shell: echo "DO_NOT_LOG_TASK_SUCCEEDED"
+ no_log: true
+
+ - name: failed args should not be logged when task-level no_log set
+ shell: echo "DO_NOT_LOG_TASK_FAILED"
+ no_log: true
+ failed_when: true
+ ignore_errors: true
+
+ - name: skipped task args should be suppressed with no_log
+ shell: echo "DO_NOT_LOG_TASK_SKIPPED"
+ no_log: true
+ when: false
+
+ - name: items args should be suppressed with no_log in every state
+ shell: echo {{ item }}
+ no_log: true
+ with_items: [ "DO_NOT_LOG_ITEM", "DO_NOT_LOG_ITEM_SKIPPED", "DO_NOT_LOG_ITEM_FAILED" ]
+ when: item != "DO_NOT_LOG_ITEM_SKIPPED"
+ failed_when: item == "DO_NOT_LOG_ITEM_FAILED"
+ ignore_errors: yes
+
+ - name: async task args should suppressed with no_log
+ async: 10
+ poll: 1
+ shell: echo "DO_NOT_LOG_ASYNC_TASK_SUCCEEDED"
+ no_log: true
+
+- name: play-level no_log set
+ hosts: testhost
+ gather_facts: no
+ no_log: true
+ tasks:
+ - name: args should not be logged when play-level no_log set
+ shell: echo "DO_NOT_LOG_PLAY"
+
+ - name: args should not be logged when both play- and task-level no_log set
+ shell: echo "DO_NOT_LOG_TASK_AND_PLAY"
+ no_log: true
+
+ - name: args should be logged when task-level no_log overrides play-level
+ shell: echo "LOG_ME_OVERRIDE"
+ no_log: false
+
diff --git a/test/integration/targets/no_log/runme.sh b/test/integration/targets/no_log/runme.sh
new file mode 100755
index 0000000000..e20bb08c4f
--- /dev/null
+++ b/test/integration/targets/no_log/runme.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# This test expects 7 loggable vars and 0 non-loggable ones.
+# If either mismatches it fails, run the ansible-playbook command to debug.
+
+[ "$(ansible-playbook no_log_local.yml -i ../../inventory -vvvvv "$@" | awk \
+'BEGIN { logme = 0; nolog = 0; } /LOG_ME/ { logme += 1;} /DO_NOT_LOG/ { nolog += 1;} END { printf "%d/%d", logme, nolog; }')" = "26/0" ]
diff --git a/test/integration/targets/parsing/bad_parsing.yml b/test/integration/targets/parsing/bad_parsing.yml
new file mode 100644
index 0000000000..110b2903ec
--- /dev/null
+++ b/test/integration/targets/parsing/bad_parsing.yml
@@ -0,0 +1,12 @@
+- hosts: testhost
+
+ # the following commands should all parse fine and execute fine
+ # and represent quoting scenarios that should be legit
+
+ gather_facts: False
+
+ roles:
+
+ # this one has a lot of things that should fail, see makefile for operation w/ tags
+
+ - { role: test_bad_parsing }
diff --git a/test/integration/targets/parsing/good_parsing.yml b/test/integration/targets/parsing/good_parsing.yml
new file mode 100644
index 0000000000..8fc8d88ec9
--- /dev/null
+++ b/test/integration/targets/parsing/good_parsing.yml
@@ -0,0 +1,9 @@
+- hosts: testhost
+
+ # the following commands should all parse fine and execute fine
+ # and represent quoting scenarios that should be legit
+
+ gather_facts: False
+
+ roles:
+ - { role: test_good_parsing, tags: test_good_parsing }
diff --git a/test/integration/targets/parsing/roles/test_bad_parsing/tasks/main.yml b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/main.yml
new file mode 100644
index 0000000000..da8ad3d25b
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/main.yml
@@ -0,0 +1,60 @@
+# test code for the ping module
+# (c) 2014, Michael DeHaan <michael@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/>.
+
+# the following tests all raise errors, to use them in a Makefile, we run them with different flags, as
+# otherwise ansible stops at the first one and we want to ensure STOP conditions for each
+
+- set_fact:
+ test_file: "{{ output_dir }}/ansible_test_file" # FIXME, use set tempdir
+ test_input: "owner=test"
+ bad_var: "{{ output_dir }}' owner=test"
+ chdir: "mom chdir=/tmp"
+ tags: common
+
+- file: name={{test_file}} state=touch
+ tags: common
+
+- name: remove touched file
+ file: name={{test_file}} state=absent
+ tags: common
+
+- name: include test that we cannot insert arguments
+ include: scenario1.yml
+ tags: scenario1
+
+- name: include test that we cannot duplicate arguments
+ include: scenario2.yml
+ tags: scenario2
+
+- name: include test that we can't do this for the shell module
+ include: scenario3.yml
+ tags: scenario3
+
+- name: include test that we can't go all Little Bobby Droptables on a quoted var to add more
+ include: scenario4.yml
+ tags: scenario4
+
+- name: test that a missing/malformed jinja2 filter fails
+ debug: msg="{{output_dir|badfiltername}}"
+ tags: scenario5
+ register: filter_fail
+ ignore_errors: yes
+
+- assert:
+ that:
+ - filter_fail|failed
diff --git a/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario1.yml b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario1.yml
new file mode 100644
index 0000000000..dab20be749
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario1.yml
@@ -0,0 +1,5 @@
+- name: test that we cannot insert arguments
+ file: path={{ test_file }} {{ test_input }}
+ failed_when: False # ignore the module, just test the parser
+ tags: scenario1
+
diff --git a/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario2.yml b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario2.yml
new file mode 100644
index 0000000000..4f14f81b23
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario2.yml
@@ -0,0 +1,5 @@
+- name: test that we cannot duplicate arguments
+ file: path={{ test_file }} owner=test2 {{ test_input }}
+ failed_when: False # ignore the module, just test the parser
+ tags: scenario2
+
diff --git a/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario3.yml b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario3.yml
new file mode 100644
index 0000000000..cd4da7baba
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario3.yml
@@ -0,0 +1,5 @@
+- name: test that we can't do this for the shell module
+ shell: echo hi {{ chdir }}
+ failed_when: False
+ tags: scenario3
+
diff --git a/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario4.yml b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario4.yml
new file mode 100644
index 0000000000..9ed1eae0b5
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_bad_parsing/tasks/scenario4.yml
@@ -0,0 +1,5 @@
+- name: test that we can't go all Little Bobby Droptables on a quoted var to add more
+ file: "name={{ bad_var }}"
+ failed_when: False
+ tags: scenario4
+
diff --git a/test/integration/targets/parsing/roles/test_bad_parsing/vars/main.yml b/test/integration/targets/parsing/roles/test_bad_parsing/vars/main.yml
new file mode 100644
index 0000000000..1aaeac7730
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_bad_parsing/vars/main.yml
@@ -0,0 +1,2 @@
+---
+output_dir: .
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml b/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml
new file mode 100644
index 0000000000..418b6d4040
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_good_parsing/tasks/main.yml
@@ -0,0 +1,204 @@
+# test code for the ping module
+# (c) 2014, Michael DeHaan <michael@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/>.
+
+# various tests of things that should not cause parsing problems
+
+- set_fact:
+ test_input: "a=1 a=2 a=3"
+
+- set_fact:
+ multi_line: |
+ echo old
+ echo mcdonald
+ echo had
+ echo a
+ echo farm
+
+- shell: echo "dog"
+ register: result
+
+- assert:
+ that:
+ result.cmd == 'echo "dog"'
+
+- shell: echo 'dog'
+ register: result
+
+- assert:
+ that:
+ result.cmd == 'echo \'dog\''
+
+- name: a quoted argument is not sent to the shell module as anything but a string parameter
+ shell: echo 'dog' 'executable=/usr/bin/python'
+ register: result
+
+- debug: var=result.cmd
+
+- assert:
+ that:
+ result.cmd == "echo 'dog' 'executable=/usr/bin/python'"
+
+- name: it is valid to pass multiple key=value arguments because the shell doesn't check key=value arguments
+ shell: echo quackquack=here quackquack=everywhere
+ register: result
+
+- assert:
+ that:
+ result.cmd == 'echo quackquack=here quackquack=everywhere'
+
+- name: the same is true with quoting
+ shell: echo "quackquack=here quackquack=everywhere"
+ register: result
+
+- assert:
+ that:
+ result.cmd == 'echo "quackquack=here quackquack=everywhere"'
+
+- name: the same is true with quoting (B)
+ shell: echo "quackquack=here" "quackquack=everywhere"
+ register: result
+
+- name: the same is true with quoting (C)
+ shell: echo "quackquack=here" 'quackquack=everywhere'
+ register: result
+
+- name: the same is true with quoting (D)
+ shell: echo "quackquack=here" 'quackquack=everywhere'
+ register: result
+
+- name: the same is true with quoting (E)
+ shell: echo {{ test_input }}
+ register: result
+
+- assert:
+ that:
+ result.cmd == "echo a=1 a=2 a=3"
+
+- name: more shell duplicates
+ shell: echo foo=bar foo=bar
+ register: result
+
+- assert:
+ that:
+ result.cmd == "echo foo=bar foo=bar"
+
+- name: raw duplicates, noop
+ raw: env true foo=bar foo=bar
+
+- name: multi-line inline shell commands (should use script module but hey) are a thing
+ shell: "{{ multi_line }}"
+ register: result
+
+- debug: var=result
+
+- assert:
+ that:
+ result.stdout_lines == [ 'old', 'mcdonald', 'had', 'a', 'farm' ]
+
+- name: passing same arg to shell command is legit
+ shell: echo foo --arg=a --arg=b
+ failed_when: False # just catch the exit code, parse error is what I care about, but should register and compare result
+ register: result
+
+- assert:
+ that:
+ # command shouldn't end in spaces, amend test once fixed
+ - result.cmd == "echo foo --arg=a --arg=b"
+
+- name: test includes with params
+ include: test_include.yml fact_name=include_params param="{{ test_input }}"
+
+- name: assert the include set the correct fact for the param
+ assert:
+ that:
+ - include_params == test_input
+
+- name: test includes with quoted params
+ include: test_include.yml fact_name=double_quoted_param param="this is a param with double quotes"
+
+- name: assert the include set the correct fact for the double quoted param
+ assert:
+ that:
+ - double_quoted_param == "this is a param with double quotes"
+
+- name: test includes with single quoted params
+ include: test_include.yml fact_name=single_quoted_param param='this is a param with single quotes'
+
+- name: assert the include set the correct fact for the single quoted param
+ assert:
+ that:
+ - single_quoted_param == "this is a param with single quotes"
+
+- name: test includes with quoted params in complex args
+ include: test_include.yml
+ vars:
+ fact_name: complex_param
+ param: "this is a param in a complex arg with double quotes"
+
+- name: assert the include set the correct fact for the params in complex args
+ assert:
+ that:
+ - complex_param == "this is a param in a complex arg with double quotes"
+
+- name: test variable module name
+ action: "{{ variable_module_name }} msg='this should be debugged'"
+ register: result
+
+- name: assert the task with variable module name ran
+ assert:
+ that:
+ - result.msg == "this should be debugged"
+
+- name: test conditional includes
+ include: test_include_conditional.yml
+ when: false
+
+- name: assert the nested include from test_include_conditional was not set
+ assert:
+ that:
+ - nested_include_var is undefined
+
+- name: test omit in complex args
+ set_fact:
+ foo: bar
+ spam: "{{ omit }}"
+ should_not_omit: "prefix{{ omit }}"
+
+- assert:
+ that:
+ - foo == 'bar'
+ - spam is undefined
+ - should_not_omit is defined
+
+- name: test omit in module args
+ set_fact: >
+ yo=whatsup
+ eggs="{{ omit }}"
+ default_omitted="{{ not_exists|default(omit) }}"
+ should_not_omit_1="prefix{{ omit }}"
+ should_not_omit_2="{{ omit }}suffix"
+ should_not_omit_3="__omit_place_holder__afb6b9bc3d20bfeaa00a1b23a5930f89"
+
+- assert:
+ that:
+ - yo == 'whatsup'
+ - eggs is undefined
+ - default_omitted is undefined
+ - should_not_omit_1 is defined
+ - should_not_omit_2 is defined
+ - should_not_omit_3 == "__omit_place_holder__afb6b9bc3d20bfeaa00a1b23a5930f89"
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include.yml b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include.yml
new file mode 100644
index 0000000000..4ba5035805
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include.yml
@@ -0,0 +1 @@
+- set_fact: "{{fact_name}}='{{param}}'"
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml
new file mode 100644
index 0000000000..070888dad3
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_conditional.yml
@@ -0,0 +1 @@
+- include: test_include_nested.yml
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_nested.yml b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_nested.yml
new file mode 100644
index 0000000000..f1f6fcc465
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_good_parsing/tasks/test_include_nested.yml
@@ -0,0 +1,2 @@
+- name: set the nested include fact
+ set_fact: nested_include_var=1
diff --git a/test/integration/targets/parsing/roles/test_good_parsing/vars/main.yml b/test/integration/targets/parsing/roles/test_good_parsing/vars/main.yml
new file mode 100644
index 0000000000..ea7a0b846e
--- /dev/null
+++ b/test/integration/targets/parsing/roles/test_good_parsing/vars/main.yml
@@ -0,0 +1,2 @@
+---
+variable_module_name: debug
diff --git a/test/integration/targets/parsing/runme.sh b/test/integration/targets/parsing/runme.sh
new file mode 100755
index 0000000000..022ce4cf39
--- /dev/null
+++ b/test/integration/targets/parsing/runme.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook bad_parsing.yml -i ../../inventory -vvv "$@" --tags prepare,common,scenario5
+ansible-playbook good_parsing.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/pull_limit_inventory/runme.sh b/test/integration/targets/pull_limit_inventory/runme.sh
new file mode 100755
index 0000000000..74b2fe625f
--- /dev/null
+++ b/test/integration/targets/pull_limit_inventory/runme.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# http://unix.stackexchange.com/questions/30091/fix-or-alternative-for-mktemp-in-os-x
+MYTMPDIR=$(shell mktemp -d 2>/dev/null || mktemp -d -t 'ansible-testing-XXXXXXXXXX')
+trap 'rm -rf "${MYTMPDIR}"' EXIT
+
+# test for https://github.com/ansible/ansible/issues/13688
+ansible-pull -d "${MYTMPDIR}" -U https://github.com/ansible-test-robinro/pull-integration-test "$@"
diff --git a/test/integration/targets/pull_no_127/runme.sh b/test/integration/targets/pull_no_127/runme.sh
new file mode 100755
index 0000000000..cdb8e057a4
--- /dev/null
+++ b/test/integration/targets/pull_no_127/runme.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# http://unix.stackexchange.com/questions/30091/fix-or-alternative-for-mktemp-in-os-x
+MYTMPDIR=$(shell mktemp -d 2>/dev/null || mktemp -d -t 'ansible-testing-XXXXXXXXXX')
+trap 'rm -rf "${MYTMPDIR}"' EXIT
+
+# test for https://github.com/ansible/ansible/issues/13681
+ansible-pull -d "${MYTMPDIR}" -U https://github.com/ansible-test-robinro/pull-integration-test "$@" \
+ | grep -v '127\.0\.0\.1'
diff --git a/test/integration/targets/pull_run/runme.sh b/test/integration/targets/pull_run/runme.sh
new file mode 100755
index 0000000000..854698b2fc
--- /dev/null
+++ b/test/integration/targets/pull_run/runme.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# http://unix.stackexchange.com/questions/30091/fix-or-alternative-for-mktemp-in-os-x
+MYTMPDIR=$(shell mktemp -d 2>/dev/null || mktemp -d -t 'ansible-testing-XXXXXXXXXX')
+trap 'rm -rf "${MYTMPDIR}"' EXIT
+
+ansible-pull -d "${MYTMPDIR}" -U https://github.com/ansible-test-robinro/pull-integration-test "$@" \
+ | grep MAGICKEYWORD
diff --git a/test/integration/targets/tags/runme.sh b/test/integration/targets/tags/runme.sh
new file mode 100755
index 0000000000..d1f26c41d0
--- /dev/null
+++ b/test/integration/targets/tags/runme.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+set -eu
+
+# Using set -x for this test causes the Shippable console to stop receiving updates and the job to time out for OS X.
+# Once that issue is resolved the set -x option can be added above.
+
+# Run these using en_US.UTF-8 because list-tasks is a user output function and so it tailors its output to the
+# user's locale. For unicode tags, this means replacing non-ascii chars with "?"
+
+COMMAND=(ansible-playbook -i ../../inventory test_tags.yml -v --list-tasks)
+
+export LC_ALL=en_US.UTF-8
+
+# Run everything by default
+[ "$("${COMMAND[@]}" | grep -F Task_with | xargs)" = \
+"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: []" ]
+
+# Run the exact tags, and always
+[ "$("${COMMAND[@]}" --tags tag | grep -F Task_with | xargs)" = \
+"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always]" ]
+
+# Skip one tag
+[ "$("${COMMAND[@]}" --skip-tags tag | grep -F Task_with | xargs)" = \
+"Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: []" ]
+
+# Skip a unicode tag
+[ "$("${COMMAND[@]}" --skip-tags 'くらとみ' | grep -F Task_with | xargs)" = \
+"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: []" ]
+
+# Run just a unicode tag and always
+[ "$("${COMMAND[@]}" --tags 'くらとみ' | grep -F Task_with | xargs)" = \
+"Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ]" ]
+
+# Run a tag from a list of tags and always
+[ "$("${COMMAND[@]}" --tags café | grep -F Task_with | xargs)" = \
+"Task_with_always_tag TAGS: [always] Task_with_list_of_tags TAGS: [café, press]" ]
diff --git a/test/integration/targets/tags/test_tags.yml b/test/integration/targets/tags/test_tags.yml
new file mode 100644
index 0000000000..d450de7b39
--- /dev/null
+++ b/test/integration/targets/tags/test_tags.yml
@@ -0,0 +1,23 @@
+---
+- name: verify tags work as expected
+ hosts: localhost
+ gather_facts: False
+ connection: local
+ tasks:
+ - name: Task_with_tag
+ debug: msg=
+ tags: tag
+ - name: Task_with_always_tag
+ debug: msg=
+ tags: always
+ - name: Task_with_unicode_tag
+ debug: msg=
+ tags: くらとみ
+ - name: Task_with_list_of_tags
+ debug: msg=
+ tags:
+ - café
+ - press
+ - name: Task_without_tag
+ debug: msg=
+
diff --git a/test/integration/targets/templating_settings/runme.sh b/test/integration/targets/templating_settings/runme.sh
new file mode 100755
index 0000000000..4af73bfd94
--- /dev/null
+++ b/test/integration/targets/templating_settings/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_templating_settings.yml -i ../../inventory -v "$@"
diff --git a/test/integration/targets/templating_settings/test_templating_settings.yml b/test/integration/targets/templating_settings/test_templating_settings.yml
new file mode 100644
index 0000000000..524b869e63
--- /dev/null
+++ b/test/integration/targets/templating_settings/test_templating_settings.yml
@@ -0,0 +1,16 @@
+---
+- name: 'Test templating in name'
+ hosts: localhost
+ connection: local
+ vars:
+ a_list:
+ - 'part'
+ - 'of a'
+ - 'name'
+
+ tasks:
+ # Note: this only tests that we do not traceback. It doesn't test that the
+ # name goes through templating correctly
+ - name: 'Task: {{ a_list | to_json }}'
+ debug: msg='{{ a_list | to_json }}'
+
diff --git a/test/integration/targets/test_infra/inventory.local b/test/integration/targets/test_infra/inventory.local
new file mode 100644
index 0000000000..2baa1f88fb
--- /dev/null
+++ b/test/integration/targets/test_infra/inventory.local
@@ -0,0 +1,2 @@
+testhost ansible_connection=local
+
diff --git a/test/integration/targets/test_infra/runme.sh b/test/integration/targets/test_infra/runme.sh
new file mode 100755
index 0000000000..b5932868e2
--- /dev/null
+++ b/test/integration/targets/test_infra/runme.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -ux
+
+# ensure fail/assert work locally and can stop execution with non-zero exit code
+PB_OUT=$(ansible-playbook -i inventory.local test_test_infra.yml)
+APB_RC=$?
+echo "$PB_OUT"
+echo "rc was $APB_RC (must be non-zero)"
+[ $$APB_RC -ne 0 ]
+echo "ensure playbook output shows assert/fail works (True)"
+echo "$PB_OUT" | grep -F "fail works (True)" || exit 1
+echo "$PB_OUT" | grep -F "assert works (True)" || exit 1
+
+# ensure we work using all specified test args, overridden inventory, etc
+PB_OUT=$(ansible-playbook -i ../../inventory test_test_infra.yml "$@")
+APB_RC=$?
+echo "$PB_OUT"
+echo "rc was $APB_RC (must be non-zero)"
+[ $$APB_RC -ne 0 ]
+echo "ensure playbook output shows assert/fail works (True)"
+echo "$PB_OUT" | grep -F "fail works (True)" || exit 1
+echo "$PB_OUT" | grep -F "assert works (True)" || exit 1
diff --git a/test/integration/targets/test_infra/test_test_infra.yml b/test/integration/targets/test_infra/test_test_infra.yml
new file mode 100644
index 0000000000..13c570530a
--- /dev/null
+++ b/test/integration/targets/test_infra/test_test_infra.yml
@@ -0,0 +1,26 @@
+- hosts: testhost
+ gather_facts: no
+ tags:
+ - always
+ tasks:
+ - name: ensure fail action produces a failing result
+ fail:
+ ignore_errors: yes
+ register: fail_out
+
+ - debug:
+ msg: fail works ({{ fail_out.failed }})
+
+ - name: ensure assert produces a failing result
+ assert:
+ that: false
+ ignore_errors: yes
+ register: assert_out
+
+ - debug:
+ msg: assert works ({{ assert_out.failed }})
+
+ - name: EXPECTED FAILURE ensure fail action stops execution
+ fail:
+ msg: fail actually failed (this is expected)
+
diff --git a/test/integration/targets/unicode/runme.sh b/test/integration/targets/unicode/runme.sh
new file mode 100755
index 0000000000..0182093f41
--- /dev/null
+++ b/test/integration/targets/unicode/runme.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook unicode.yml -i ../../inventory -v -e 'extra_var=café' "$@"
+# Test the start-at-task flag #9571
+ansible-playbook unicode.yml -i ../../inventory -v --start-at-task '*¶' -e 'start_at_task=True' "$@"
diff --git a/test/integration/targets/unicode/unicode-test-script b/test/integration/targets/unicode/unicode-test-script
new file mode 100755
index 0000000000..340f2a9f5b
--- /dev/null
+++ b/test/integration/targets/unicode/unicode-test-script
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+echo "Non-ascii arguments:"
+echo $@
+
+echo "Non-ascii Env var:"
+echo $option
diff --git a/test/integration/targets/unicode/unicode.yml b/test/integration/targets/unicode/unicode.yml
new file mode 100644
index 0000000000..b22415a45d
--- /dev/null
+++ b/test/integration/targets/unicode/unicode.yml
@@ -0,0 +1,149 @@
+---
+- name: 'A play with unicode: ¢ £ ¤ ¥'
+ hosts: localhost
+ connection: local
+ vars:
+ test_var: 'Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ'
+ hostnames:
+ - 'host-ϬϭϮϯϰ'
+ - 'host-fóöbär'
+ - 'host-ΙΚΛΜΝΞ'
+ - 'host-στυφχψ'
+ - 'host-ϬϭϮϯϰϱ'
+
+ tasks:
+ - name: 'A task name with unicode: è é ê ë'
+ debug: msg='hi there'
+
+ - name: 'A task with unicode parameters'
+ debug: var=test_var
+
+ # € ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ž ‘ ’ “ ” • – — ˜ ™ š › œ ž Ÿ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ®'
+
+ - name: 'A task using with_items containing unicode'
+ debug: msg='{{item}}'
+ with_items:
+ - '¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö ×'
+ - 'Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ Ā'
+ - 'ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ'
+
+ - add_host:
+ name: '{{item}}'
+ groups: 'ĪīĬĭ'
+ ansible_ssh_host: 127.0.0.1
+ ansible_connection: local
+ with_items: "{{ hostnames }}"
+
+ - name: 'A task with unicode extra vars'
+ debug: var=extra_var
+
+ - name: 'A task with unicode host vars'
+ debug: var=unicode_host_var
+
+ - name: 'A task with unicode shell parameters'
+ shell: echo '¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö ×'
+ register: output
+
+ - name: 'Assert that the unicode was echoed'
+ assert:
+ that:
+ - "'¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö ×' in output.stdout_lines"
+
+ - name: Run raw with non-ascii options
+ raw: "/bin/echo Zażółć gęślą jaźń"
+ register: results
+
+ - name: Check that raw output the right thing
+ assert:
+ that:
+ - "'Zażółć gęślą jaźń' in results.stdout_lines"
+
+ - name: Run a script with non-ascii options and environment
+ script: unicode-test-script --option "Zażółć gęślą jaźń"
+ environment:
+ option: Zażółć
+ register: results
+
+ - name: Check that script output includes the nonascii arguments and environment values
+ assert:
+ that:
+ - "'--option Zażółć gęślą jaźń' in results.stdout_lines"
+ - "'Zażółć' in results.stdout_lines"
+
+ - name: Ping with non-ascii environment variable and option
+ ping:
+ data: "Zażółć gęślą jaźń"
+ environment:
+ option: Zażółć
+ register: results
+
+ - name: Check that ping with non-ascii data was correct
+ assert:
+ that:
+ - "'Zażółć gęślą jaźń' == results.ping"
+
+ - name: Command that echos a non-ascii env var
+ command: "echo $option"
+ environment:
+ option: Zażółć
+ register: results
+
+ - name: Check that a non-ascii env var was passed to the command module
+ assert:
+ that:
+ - "'Zażółć' in results.stdout_lines"
+
+ - name: Clean a temp directory
+ file:
+ path: /var/tmp/ansible_test_unicode_get_put
+ state: absent
+
+ - name: Create a temp directory
+ file:
+ path: /var/tmp/ansible_test_unicode_get_put
+ state: directory
+
+ - name: Create a file with a non-ascii filename
+ file:
+ path: /var/tmp/ansible_test_unicode_get_put/Zażółć
+ state: touch
+ delegate_to: localhost
+
+ - name: Put with unicode filename
+ copy:
+ src: /var/tmp/ansible_test_unicode_get_put/Zażółć
+ dest: /var/tmp/ansible_test_unicode_get_put/Zażółć2
+
+ - name: Fetch with unicode filename
+ fetch:
+ src: /var/tmp/ansible_test_unicode_get_put/Zażółć2
+ dest: /var/tmp/ansible_test_unicode_get_put/
+
+ - name: Clean a temp directory
+ file:
+ path: /var/tmp/ansible_test_unicode_get_put
+ state: absent
+
+- name: 'A play for hosts in group: ĪīĬĭ'
+ hosts: 'ĪīĬĭ'
+ gather_facts: true
+ tasks:
+ - debug: msg='Unicode is a good thing ™'
+ - debug: msg=АБВГД
+
+# Run this test by adding to the CLI: -e start_at_task=True --start-at-task '*¶'
+- name: 'Show that we can skip to unicode named tasks'
+ hosts: localhost
+ gather_facts: false
+ vars:
+ flag: 'original'
+ start_at_task: False
+ tasks:
+ - name: 'Override flag var'
+ set_fact: flag='new'
+
+ - name: 'A unicode task at the end of the playbook: ¶'
+ assert:
+ that:
+ - 'flag == "original"'
+ when: start_at_task|bool
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence/meta/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence/meta/main.yml
new file mode 100644
index 0000000000..423b94e31c
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence/meta/main.yml
@@ -0,0 +1,4 @@
+dependencies:
+ - { role: test_var_precedence_role1, param_var: "param_var_role1" }
+ - { role: test_var_precedence_role2, param_var: "param_var_role2" }
+ - { role: test_var_precedence_role3, param_var: "param_var_role3" }
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence/tasks/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence/tasks/main.yml
new file mode 100644
index 0000000000..7850e6b646
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence/tasks/main.yml
@@ -0,0 +1,10 @@
+- debug: var=extra_var
+- debug: var=vars_var
+- debug: var=vars_files_var
+- debug: var=vars_files_var_role
+- assert:
+ that:
+ - 'extra_var == "extra_var"'
+ - 'vars_var == "vars_var"'
+ - 'vars_files_var == "vars_files_var"'
+ - 'vars_files_var_role == "vars_files_var_role3"'
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_dep/defaults/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_dep/defaults/main.yml
new file mode 100644
index 0000000000..dda4224c35
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_dep/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+# should be overridden by vars_files in the main play
+vars_files_var: "BAD!"
+# should be seen in role1 (no override)
+defaults_file_var_role1: "defaults_file_var_role1"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_dep/tasks/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_dep/tasks/main.yml
new file mode 100644
index 0000000000..2f8e17096b
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_dep/tasks/main.yml
@@ -0,0 +1,14 @@
+- debug: var=extra_var
+- debug: var=param_var
+- debug: var=vars_var
+- debug: var=vars_files_var
+- debug: var=vars_files_var_role
+- debug: var=defaults_file_var_role1
+- assert:
+ that:
+ - 'extra_var == "extra_var"'
+ - 'param_var == "param_var_role1"'
+ - 'vars_var == "vars_var"'
+ - 'vars_files_var == "vars_files_var"'
+ - 'vars_files_var_role == "vars_files_var_dep"'
+ - 'defaults_file_var_role1 == "defaults_file_var_role1"'
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_dep/vars/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_dep/vars/main.yml
new file mode 100644
index 0000000000..a69efad537
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_dep/vars/main.yml
@@ -0,0 +1,4 @@
+---
+# should override the global vars_files_var since it's local to the role
+# but will be set to the value in the last role included which defines it
+vars_files_var_role: "vars_files_var_dep"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_inven_override/tasks/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_inven_override/tasks/main.yml
new file mode 100644
index 0000000000..942ae4ec05
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_inven_override/tasks/main.yml
@@ -0,0 +1,5 @@
+---
+- debug: var=foo
+- assert:
+ that:
+ - 'foo == "bar"'
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role1/defaults/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/defaults/main.yml
new file mode 100644
index 0000000000..dda4224c35
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+# should be overridden by vars_files in the main play
+vars_files_var: "BAD!"
+# should be seen in role1 (no override)
+defaults_file_var_role1: "defaults_file_var_role1"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role1/meta/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/meta/main.yml
new file mode 100644
index 0000000000..c8b410b59c
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - test_var_precedence_dep
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role1/tasks/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/tasks/main.yml
new file mode 100644
index 0000000000..95b2a0bb5a
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/tasks/main.yml
@@ -0,0 +1,14 @@
+- debug: var=extra_var
+- debug: var=param_var
+- debug: var=vars_var
+- debug: var=vars_files_var
+- debug: var=vars_files_var_role
+- debug: var=defaults_file_var_role1
+- assert:
+ that:
+ - 'extra_var == "extra_var"'
+ - 'param_var == "param_var_role1"'
+ - 'vars_var == "vars_var"'
+ - 'vars_files_var == "vars_files_var"'
+ - 'vars_files_var_role == "vars_files_var_role1"'
+ - 'defaults_file_var_role1 == "defaults_file_var_role1"'
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role1/vars/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/vars/main.yml
new file mode 100644
index 0000000000..2f7613d30a
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role1/vars/main.yml
@@ -0,0 +1,4 @@
+---
+# should override the global vars_files_var since it's local to the role
+# but will be set to the value in the last role included which defines it
+vars_files_var_role: "vars_files_var_role1"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role2/defaults/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role2/defaults/main.yml
new file mode 100644
index 0000000000..8ed63ced96
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role2/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+# should be overridden by vars_files in the main play
+vars_files_var: "BAD!"
+# should be overridden by the vars file in role2
+defaults_file_var_role2: "BAD!"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role2/tasks/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role2/tasks/main.yml
new file mode 100644
index 0000000000..a862389cd3
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role2/tasks/main.yml
@@ -0,0 +1,14 @@
+- debug: var=extra_var
+- debug: var=param_var
+- debug: var=vars_var
+- debug: var=vars_files_var
+- debug: var=vars_files_var_role
+- debug: var=defaults_file_var_role1
+- assert:
+ that:
+ - 'extra_var == "extra_var"'
+ - 'param_var == "param_var_role2"'
+ - 'vars_var == "vars_var"'
+ - 'vars_files_var == "vars_files_var"'
+ - 'vars_files_var_role == "vars_files_var_role2"'
+ - 'defaults_file_var_role2 == "overridden by role vars"'
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role2/vars/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role2/vars/main.yml
new file mode 100644
index 0000000000..483c5ea245
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role2/vars/main.yml
@@ -0,0 +1,5 @@
+---
+# should override the global vars_files_var since it's local to the role
+vars_files_var_role: "vars_files_var_role2"
+# should override the value in defaults/main.yml for role 2
+defaults_file_var_role2: "overridden by role vars"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role3/defaults/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role3/defaults/main.yml
new file mode 100644
index 0000000000..763b0d508e
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role3/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+# should be overridden by vars_files in the main play
+vars_files_var: "BAD!"
+# should override the defaults var for role 1 and 2
+defaults_file_var: "last one wins"
+# should be overridden from the inventory value
+defaults_file_var_role3: "BAD!"
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role3/tasks/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role3/tasks/main.yml
new file mode 100644
index 0000000000..12346ecdc8
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role3/tasks/main.yml
@@ -0,0 +1,14 @@
+- debug: var=extra_var
+- debug: var=param_var
+- debug: var=vars_var
+- debug: var=vars_files_var
+- debug: var=vars_files_var_role
+- debug: var=defaults_file_var_role1
+- assert:
+ that:
+ - 'extra_var == "extra_var"'
+ - 'param_var == "param_var_role3"'
+ - 'vars_var == "vars_var"'
+ - 'vars_files_var == "vars_files_var"'
+ - 'vars_files_var_role == "vars_files_var_role3"'
+ - 'defaults_file_var_role3 == "overridden from inventory"'
diff --git a/test/integration/targets/var_precedence/roles/test_var_precedence_role3/vars/main.yml b/test/integration/targets/var_precedence/roles/test_var_precedence_role3/vars/main.yml
new file mode 100644
index 0000000000..3cfb1b1c68
--- /dev/null
+++ b/test/integration/targets/var_precedence/roles/test_var_precedence_role3/vars/main.yml
@@ -0,0 +1,3 @@
+---
+# should override the global vars_files_var since it's local to the role
+vars_files_var_role: "vars_files_var_role3"
diff --git a/test/integration/targets/var_precedence/runme.sh b/test/integration/targets/var_precedence/runme.sh
new file mode 100755
index 0000000000..454c35333e
--- /dev/null
+++ b/test/integration/targets/var_precedence/runme.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_var_precedence.yml -i ../../inventory -v "$@" \
+ -e 'extra_var=extra_var' \
+ -e 'extra_var_override=extra_var_override'
diff --git a/test/integration/targets/var_precedence/test_var_precedence.yml b/test/integration/targets/var_precedence/test_var_precedence.yml
new file mode 100644
index 0000000000..df09914158
--- /dev/null
+++ b/test/integration/targets/var_precedence/test_var_precedence.yml
@@ -0,0 +1,45 @@
+---
+- hosts: testhost
+ vars:
+ - ansible_hostname: "BAD!"
+ - vars_var: "vars_var"
+ - param_var: "BAD!"
+ - vars_files_var: "BAD!"
+ - extra_var_override_once_removed: "{{ extra_var_override }}"
+ - from_inventory_once_removed: "{{ inven_var | default('BAD!') }}"
+ vars_files:
+ - vars/test_var_precedence.yml
+ roles:
+ - { role: test_var_precedence, param_var: "param_var" }
+ tasks:
+ - name: register a result
+ command: echo 'BAD!'
+ register: registered_var
+ - name: use set_fact to override the registered_var
+ set_fact: registered_var="this is from set_fact"
+ - debug: var=extra_var
+ - debug: var=extra_var_override_once_removed
+ - debug: var=vars_var
+ - debug: var=vars_files_var
+ - debug: var=vars_files_var_role
+ - debug: var=registered_var
+ - debug: var=from_inventory_once_removed
+ - assert:
+ that: item
+ with_items:
+ - 'extra_var == "extra_var"'
+ - 'extra_var_override == "extra_var_override"'
+ - 'extra_var_override_once_removed == "extra_var_override"'
+ - 'vars_var == "vars_var"'
+ - 'vars_files_var == "vars_files_var"'
+ - 'vars_files_var_role == "vars_files_var_role3"'
+ - 'registered_var == "this is from set_fact"'
+ - 'from_inventory_once_removed == "inventory_var"'
+
+- hosts: inven_overridehosts
+ vars_files:
+ - "test_var_precedence.yml"
+ roles:
+ - role: test_var_precedence_inven_override
+ foo: bar
+
diff --git a/test/integration/targets/var_precedence/vars/test_var_precedence.yml b/test/integration/targets/var_precedence/vars/test_var_precedence.yml
new file mode 100644
index 0000000000..19d65cba3e
--- /dev/null
+++ b/test/integration/targets/var_precedence/vars/test_var_precedence.yml
@@ -0,0 +1,5 @@
+---
+extra_var: "BAD!"
+role_var: "BAD!"
+vars_files_var: "vars_files_var"
+vars_files_var_role: "should be overridden by roles"
diff --git a/test/integration/targets/vault/roles/test_vault/tasks/main.yml b/test/integration/targets/vault/roles/test_vault/tasks/main.yml
new file mode 100644
index 0000000000..2c18e41815
--- /dev/null
+++ b/test/integration/targets/vault/roles/test_vault/tasks/main.yml
@@ -0,0 +1,10 @@
+
+- assert:
+ that:
+ - 'secret_var == "secret"'
+
+
+- copy: src=vault-secret.txt dest={{output_dir}}/secret.txt
+
+- name: cleanup decrypted file
+ file: path={{ output_dir }}/secret.txt state=absent
diff --git a/test/integration/targets/vault/roles/test_vault/vars/main.yml b/test/integration/targets/vault/roles/test_vault/vars/main.yml
new file mode 100644
index 0000000000..cfac107aed
--- /dev/null
+++ b/test/integration/targets/vault/roles/test_vault/vars/main.yml
@@ -0,0 +1,9 @@
+$ANSIBLE_VAULT;1.1;AES256
+31626536666232643662346539623662393436386162643439643434656231343435653936343235
+6139346364396166336636383734333430373763336434310a303137623539653939336132626234
+64613232396532313731313935333433353330666466646663303233323331636234326464643166
+6538653264636166370a613161313064653566323037393962643032353230396536313865326362
+34396262303130326632623162623230346238633932393938393766313036643835613936356233
+33323730373331386337353339613165373064323134343930333031623036326164353534646631
+31313963666234623731316238656233396638643331306231373539643039383434373035306233
+30386230363730643561
diff --git a/test/integration/targets/vault/roles/test_vault_embedded/tasks/main.yml b/test/integration/targets/vault/roles/test_vault_embedded/tasks/main.yml
new file mode 100644
index 0000000000..4dda2acbcd
--- /dev/null
+++ b/test/integration/targets/vault/roles/test_vault_embedded/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+- name: Assert that a embedded vault of a string with no newline works
+ assert:
+ that:
+ - '"{{ vault_encrypted_one_line_var }}" == "Setec Astronomy"'
+
+- name: Assert that a multi line embedded vault works, including new line
+ assert:
+ that:
+ - vault_encrypted_var == "Setec Astronomy\n"
+
+# TODO: add a expected fail here
+# - debug: var=vault_encrypted_one_line_var_with_embedded_template
+
diff --git a/test/integration/targets/vault/roles/test_vault_embedded/vars/main.yml b/test/integration/targets/vault/roles/test_vault_embedded/vars/main.yml
new file mode 100644
index 0000000000..e9c568eac1
--- /dev/null
+++ b/test/integration/targets/vault/roles/test_vault_embedded/vars/main.yml
@@ -0,0 +1,17 @@
+# If you use normal 'ansible-vault create' or edit, files always have at least one new line
+# so c&p from a vault encrypted that wasn't specifically created sans new line ends up with one.
+# (specifically created, as in 'echo -n "just one line" > my_secret.yml'
+vault_encrypted_var: !vault-encrypted |
+ $ANSIBLE_VAULT;1.1;AES256
+ 66386439653236336462626566653063336164663966303231363934653561363964363833313662
+ 6431626536303530376336343832656537303632313433360a626438346336353331386135323734
+ 62656361653630373231613662633962316233633936396165386439616533353965373339616234
+ 3430613539666330390a313736323265656432366236633330313963326365653937323833366536
+ 34623731376664623134383463316265643436343438623266623965636363326136
+vault_encrypted_one_line_var: !vault-encrypted |
+ $ANSIBLE_VAULT;1.1;AES256
+ 33363965326261303234626463623963633531343539616138316433353830356566396130353436
+ 3562643163366231316662386565383735653432386435610a306664636137376132643732393835
+ 63383038383730306639353234326630666539346233376330303938323639306661313032396437
+ 6233623062366136310a633866373936313238333730653739323461656662303864663666653563
+ 3138
diff --git a/test/integration/targets/vault/runme.sh b/test/integration/targets/vault/runme.sh
new file mode 100755
index 0000000000..a78ee4d4b2
--- /dev/null
+++ b/test/integration/targets/vault/runme.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_vault.yml -i ../../inventory -v "$@" --vault-password-file vault-password --list-tasks
+ansible-playbook test_vault.yml -i ../../inventory -v "$@" --vault-password-file vault-password --list-hosts
+ansible-playbook test_vault.yml -i ../../inventory -v "$@" --vault-password-file vault-password --syntax-check
+ansible-playbook test_vault.yml -i ../../inventory -v "$@" --vault-password-file vault-password
+ansible-playbook test_vault_embedded.yml -i ../../inventory -v "$@" --vault-password-file vault-password --syntax-check
+ansible-playbook test_vault_embedded.yml -i ../../inventory -v "$@" --vault-password-file vault-password
diff --git a/test/integration/targets/vault/test_vault.yml b/test/integration/targets/vault/test_vault.yml
new file mode 100644
index 0000000000..7f8ed11570
--- /dev/null
+++ b/test/integration/targets/vault/test_vault.yml
@@ -0,0 +1,6 @@
+- hosts: testhost
+ gather_facts: False
+ vars:
+ - output_dir: .
+ roles:
+ - { role: test_vault, tags: test_vault}
diff --git a/test/integration/targets/vault/test_vault_embedded.yml b/test/integration/targets/vault/test_vault_embedded.yml
new file mode 100644
index 0000000000..ee9739f8bb
--- /dev/null
+++ b/test/integration/targets/vault/test_vault_embedded.yml
@@ -0,0 +1,4 @@
+- hosts: testhost
+ gather_facts: False
+ roles:
+ - { role: test_vault_embedded, tags: test_vault_embedded}
diff --git a/test/integration/targets/vault/vault-password b/test/integration/targets/vault/vault-password
new file mode 100644
index 0000000000..969739294d
--- /dev/null
+++ b/test/integration/targets/vault/vault-password
@@ -0,0 +1 @@
+test-vault-password
diff --git a/test/integration/targets/vault/vault-secret.txt b/test/integration/targets/vault/vault-secret.txt
new file mode 100644
index 0000000000..b6bc9bfb17
--- /dev/null
+++ b/test/integration/targets/vault/vault-secret.txt
@@ -0,0 +1,6 @@
+$ANSIBLE_VAULT;1.1;AES256
+39303432393062643236616234306333383838333662386165616633303735336537613337396337
+6662666233356462326631653161663663363166323338320a653131656636666339633863346530
+32326238646631653133643936306666643065393038386234343736663239363665613963343661
+3230353633643361650a363034323631613864326438396665343237383566336339323837326464
+3930