summaryrefslogtreecommitdiffstats
path: root/test/integration/targets/delegate_to
diff options
context:
space:
mode:
Diffstat (limited to 'test/integration/targets/delegate_to')
-rw-r--r--test/integration/targets/delegate_to/aliases4
-rw-r--r--test/integration/targets/delegate_to/connection_plugins/fakelocal.py76
-rw-r--r--test/integration/targets/delegate_to/delegate_and_nolog.yml8
-rw-r--r--test/integration/targets/delegate_to/delegate_facts_block.yml25
-rw-r--r--test/integration/targets/delegate_to/delegate_facts_loop.yml40
-rw-r--r--test/integration/targets/delegate_to/delegate_local_from_root.yml10
-rw-r--r--test/integration/targets/delegate_to/delegate_to_lookup_context.yml4
-rw-r--r--test/integration/targets/delegate_to/delegate_vars_hanldling.yml58
-rw-r--r--test/integration/targets/delegate_to/delegate_with_fact_from_delegate_host.yml18
-rw-r--r--test/integration/targets/delegate_to/discovery_applied.yml8
-rw-r--r--test/integration/targets/delegate_to/files/testfile1
-rw-r--r--test/integration/targets/delegate_to/has_hostvars.yml64
-rw-r--r--test/integration/targets/delegate_to/inventory17
-rw-r--r--test/integration/targets/delegate_to/inventory_interpreters5
-rw-r--r--test/integration/targets/delegate_to/library/detect_interpreter.py18
-rw-r--r--test/integration/targets/delegate_to/resolve_vars.yml16
-rw-r--r--test/integration/targets/delegate_to/roles/delegate_to_lookup_context/tasks/main.yml5
-rw-r--r--test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/one.j21
-rw-r--r--test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/two.j21
-rw-r--r--test/integration/targets/delegate_to/roles/test_template/templates/foo.j23
-rwxr-xr-xtest/integration/targets/delegate_to/runme.sh78
-rw-r--r--test/integration/targets/delegate_to/test_delegate_to.yml82
-rw-r--r--test/integration/targets/delegate_to/test_delegate_to_lookup_context.yml12
-rw-r--r--test/integration/targets/delegate_to/test_delegate_to_loop_caching.yml45
-rw-r--r--test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml73
-rw-r--r--test/integration/targets/delegate_to/test_loop_control.yml16
-rw-r--r--test/integration/targets/delegate_to/verify_interpreter.yml47
27 files changed, 735 insertions, 0 deletions
diff --git a/test/integration/targets/delegate_to/aliases b/test/integration/targets/delegate_to/aliases
new file mode 100644
index 0000000..cb931dc
--- /dev/null
+++ b/test/integration/targets/delegate_to/aliases
@@ -0,0 +1,4 @@
+shippable/posix/group5
+needs/ssh
+needs/root # only on macOS and FreeBSD to configure network interfaces
+context/controller
diff --git a/test/integration/targets/delegate_to/connection_plugins/fakelocal.py b/test/integration/targets/delegate_to/connection_plugins/fakelocal.py
new file mode 100644
index 0000000..59ddcf0
--- /dev/null
+++ b/test/integration/targets/delegate_to/connection_plugins/fakelocal.py
@@ -0,0 +1,76 @@
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+DOCUMENTATION = '''
+ connection: fakelocal
+ short_description: dont execute anything
+ description:
+ - This connection plugin just verifies parameters passed in
+ author: ansible (@core)
+ version_added: histerical
+ options:
+ password:
+ description: Authentication password for the C(remote_user). Can be supplied as CLI option.
+ vars:
+ - name: ansible_password
+ remote_user:
+ description:
+ - User name with which to login to the remote server, normally set by the remote_user keyword.
+ ini:
+ - section: defaults
+ key: remote_user
+ vars:
+ - name: ansible_user
+'''
+
+from ansible.errors import AnsibleConnectionFailure
+from ansible.plugins.connection import ConnectionBase
+from ansible.utils.display import Display
+
+display = Display()
+
+
+class Connection(ConnectionBase):
+ ''' Local based connections '''
+
+ transport = 'fakelocal'
+ has_pipelining = True
+
+ def __init__(self, *args, **kwargs):
+
+ super(Connection, self).__init__(*args, **kwargs)
+ self.cwd = None
+
+ def _connect(self):
+ ''' verify '''
+
+ if self.get_option('remote_user') == 'invaliduser' and self.get_option('password') == 'badpassword':
+ raise AnsibleConnectionFailure('Got invaliduser and badpassword')
+
+ if not self._connected:
+ display.vvv(u"ESTABLISH FAKELOCAL CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self._play_context.remote_addr)
+ self._connected = True
+ return self
+
+ def exec_command(self, cmd, in_data=None, sudoable=True):
+ ''' run a command on the local host '''
+
+ super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
+
+ return 0, '{"msg": "ALL IS GOOD"}', ''
+
+ def put_file(self, in_path, out_path):
+ ''' transfer a file from local to local '''
+
+ super(Connection, self).put_file(in_path, out_path)
+
+ def fetch_file(self, in_path, out_path):
+ ''' fetch a file from local to local -- for compatibility '''
+
+ super(Connection, self).fetch_file(in_path, out_path)
+
+ def close(self):
+ ''' terminate the connection; nothing to do here '''
+ self._connected = False
diff --git a/test/integration/targets/delegate_to/delegate_and_nolog.yml b/test/integration/targets/delegate_to/delegate_and_nolog.yml
new file mode 100644
index 0000000..d8ed64f
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_and_nolog.yml
@@ -0,0 +1,8 @@
+- hosts: testhost
+ gather_facts: false
+ tasks:
+ - name: no log filtering caused delegation to fail https://github.com/ansible/ansible/issues/43026
+ become: False
+ no_log: true
+ debug:
+ delegate_to: localhost
diff --git a/test/integration/targets/delegate_to/delegate_facts_block.yml b/test/integration/targets/delegate_to/delegate_facts_block.yml
new file mode 100644
index 0000000..2edfeb4
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_facts_block.yml
@@ -0,0 +1,25 @@
+- hosts: testhost
+ gather_facts: false
+ tasks:
+ - name: set var to delegated host directly
+ set_fact: qq1=333
+ delegate_facts: true
+ delegate_to: localhost
+
+ - name: ensure qq1 exists in localhost but not in testhost
+ assert:
+ that:
+ - qq1 is undefined
+ - "'qq1' in hostvars['localhost']"
+
+ - name: set var to delegated host via inheritance
+ block:
+ - set_fact: qq2=333
+ delegate_facts: true
+ delegate_to: localhost
+
+ - name: ensure qq2 exists in localhost but not in testhost
+ assert:
+ that:
+ - qq2 is undefined
+ - "'qq2' in hostvars['localhost']"
diff --git a/test/integration/targets/delegate_to/delegate_facts_loop.yml b/test/integration/targets/delegate_to/delegate_facts_loop.yml
new file mode 100644
index 0000000..b05c406
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_facts_loop.yml
@@ -0,0 +1,40 @@
+- hosts: localhost
+ gather_facts: no
+ tasks:
+ - set_fact:
+ test: 123
+ delegate_to: "{{ item }}"
+ delegate_facts: true
+ loop: "{{ groups['all'] | difference(['localhost']) }}"
+
+ - name: ensure we didnt create it on current host
+ assert:
+ that:
+ - test is undefined
+
+ - name: ensure facts get created
+ assert:
+ that:
+ - "'test' in hostvars[item]"
+ - hostvars[item]['test'] == 123
+ loop: "{{ groups['all'] | difference(['localhost'])}}"
+
+
+- name: test that we don't polute whole group with one value
+ hosts: localhost
+ gather_facts: no
+ vars:
+ cluster_name: bleh
+ tasks:
+ - name: construct different fact per host in loop
+ set_fact:
+ vm_name: "{{ cluster_name }}-{{item}}"
+ delegate_to: "{{ item }}"
+ delegate_facts: True
+ with_items: "{{ groups['all'] }}"
+
+ - name: ensure the fact is personalized for each host
+ assert:
+ that:
+ - hostvars[item]['vm_name'].endswith(item)
+ loop: "{{ groups['all'] }}"
diff --git a/test/integration/targets/delegate_to/delegate_local_from_root.yml b/test/integration/targets/delegate_to/delegate_local_from_root.yml
new file mode 100644
index 0000000..c9be4ff
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_local_from_root.yml
@@ -0,0 +1,10 @@
+- name: handle case from issue 72541
+ hosts: testhost
+ gather_facts: false
+ remote_user: root
+ tasks:
+ - name: ensure we copy w/o errors due to remote user not being overriden
+ copy:
+ src: testfile
+ dest: "{{ playbook_dir }}"
+ delegate_to: localhost
diff --git a/test/integration/targets/delegate_to/delegate_to_lookup_context.yml b/test/integration/targets/delegate_to/delegate_to_lookup_context.yml
new file mode 100644
index 0000000..83e24bc
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_to_lookup_context.yml
@@ -0,0 +1,4 @@
+- hosts: localhost
+ gather_facts: false
+ roles:
+ - delegate_to_lookup_context
diff --git a/test/integration/targets/delegate_to/delegate_vars_hanldling.yml b/test/integration/targets/delegate_to/delegate_vars_hanldling.yml
new file mode 100644
index 0000000..6ac64e9
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_vars_hanldling.yml
@@ -0,0 +1,58 @@
+- name: setup delegated hsot
+ hosts: localhost
+ gather_facts: false
+ tasks:
+ - add_host:
+ name: delegatetome
+ ansible_host: 127.0.0.4
+
+- name: ensure we dont use orig host vars if delegated one does not define them
+ hosts: testhost
+ gather_facts: false
+ connection: local
+ tasks:
+ - name: force current host to use winrm
+ set_fact:
+ ansible_connection: winrm
+
+ - name: this should fail (missing winrm or unreachable)
+ ping:
+ ignore_errors: true
+ ignore_unreachable: true
+ register: orig
+
+ - name: ensure prev failed
+ assert:
+ that:
+ - orig is failed or orig is unreachable
+
+ - name: this will only fail if we take orig host ansible_connection instead of defaults
+ ping:
+ delegate_to: delegatetome
+
+
+- name: ensure plugin specific vars are properly used
+ hosts: testhost
+ gather_facts: false
+ tasks:
+ - name: set unusable ssh args
+ set_fact:
+ ansible_host: 127.0.0.1
+ ansible_connection: ssh
+ ansible_ssh_common_args: 'MEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'
+ ansible_connection_timeout: 5
+
+ - name: fail to ping with bad args
+ ping:
+ register: bad_args_ping
+ ignore_unreachable: true
+
+ - debug: var=bad_args_ping
+ - name: ensure prev failed
+ assert:
+ that:
+ - bad_args_ping is failed or bad_args_ping is unreachable
+
+ - name: this should work by ignoring the bad ags for orig host
+ ping:
+ delegate_to: delegatetome
diff --git a/test/integration/targets/delegate_to/delegate_with_fact_from_delegate_host.yml b/test/integration/targets/delegate_to/delegate_with_fact_from_delegate_host.yml
new file mode 100644
index 0000000..1670398
--- /dev/null
+++ b/test/integration/targets/delegate_to/delegate_with_fact_from_delegate_host.yml
@@ -0,0 +1,18 @@
+- name: ensure we can use fact on delegated host for connection info
+ hosts: localhost
+ gather_facts: no
+ tasks:
+ - add_host: name=f31 bogus_user=notme ansible_connection=ssh ansible_host=4.2.2.2
+
+ - name: if not overriding with delegated host info, will not be unreachable
+ ping:
+ timeout: 5
+ delegate_to: f31
+ ignore_errors: true
+ ignore_unreachable: true
+ register: delping
+
+ - name: ensure that the expected happened
+ assert:
+ that:
+ - delping is failed
diff --git a/test/integration/targets/delegate_to/discovery_applied.yml b/test/integration/targets/delegate_to/discovery_applied.yml
new file mode 100644
index 0000000..fafe664
--- /dev/null
+++ b/test/integration/targets/delegate_to/discovery_applied.yml
@@ -0,0 +1,8 @@
+- hosts: testhost
+ gather_facts: no
+ tasks:
+ - command: ls
+ delegate_to: "{{ item }}"
+ with_items:
+ - localhost
+ - "{{ inventory_hostname }}"
diff --git a/test/integration/targets/delegate_to/files/testfile b/test/integration/targets/delegate_to/files/testfile
new file mode 100644
index 0000000..492bafc
--- /dev/null
+++ b/test/integration/targets/delegate_to/files/testfile
@@ -0,0 +1 @@
+nothing special
diff --git a/test/integration/targets/delegate_to/has_hostvars.yml b/test/integration/targets/delegate_to/has_hostvars.yml
new file mode 100644
index 0000000..9e8926b
--- /dev/null
+++ b/test/integration/targets/delegate_to/has_hostvars.yml
@@ -0,0 +1,64 @@
+- name: ensure delegated host has hostvars available for resolving connection
+ hosts: testhost
+ gather_facts: false
+ tasks:
+
+ - name: ensure delegated host uses current host as inventory_hostname
+ assert:
+ that:
+ - inventory_hostname == ansible_delegated_vars['testhost5']['inventory_hostname']
+ delegate_to: testhost5
+
+ - name: Set info on inventory_hostname
+ set_fact:
+ login: invaliduser
+ mypass: badpassword
+
+ - name: test fakelocal
+ command: ls
+ ignore_unreachable: True
+ ignore_errors: True
+ remote_user: "{{ login }}"
+ vars:
+ ansible_password: "{{ mypass }}"
+ ansible_connection: fakelocal
+ register: badlogin
+
+ - name: ensure we skipped do to unreachable and not templating error
+ assert:
+ that:
+ - badlogin is unreachable
+
+ - name: delegate but try to use inventory_hostname data directly
+ command: ls
+ delegate_to: testhost5
+ ignore_unreachable: True
+ ignore_errors: True
+ remote_user: "{{ login }}"
+ vars:
+ ansible_password: "{{ mypass }}"
+ register: badlogin
+
+ - name: ensure we skipped do to unreachable and not templating error
+ assert:
+ that:
+ - badlogin is not unreachable
+ - badlogin is failed
+ - "'undefined' in badlogin['msg']"
+
+ - name: delegate ls to testhost5 as it uses ssh while testhost is local, but use vars from testhost
+ command: ls
+ remote_user: "{{ hostvars[inventory_hostname]['login'] }}"
+ delegate_to: testhost5
+ ignore_unreachable: True
+ ignore_errors: True
+ vars:
+ ansible_password: "{{ hostvars[inventory_hostname]['mypass'] }}"
+ register: badlogin
+
+ - name: ensure we skipped do to unreachable and not templating error
+ assert:
+ that:
+ - badlogin is unreachable
+ - badlogin is not failed
+ - "'undefined' not in badlogin['msg']"
diff --git a/test/integration/targets/delegate_to/inventory b/test/integration/targets/delegate_to/inventory
new file mode 100644
index 0000000..ebc3325
--- /dev/null
+++ b/test/integration/targets/delegate_to/inventory
@@ -0,0 +1,17 @@
+[local]
+testhost ansible_connection=local
+testhost2 ansible_connection=local
+testhost3 ansible_ssh_host=127.0.0.3
+testhost4 ansible_ssh_host=127.0.0.4
+testhost5 ansible_connection=fakelocal
+
+[all:vars]
+ansible_python_interpreter="{{ ansible_playbook_python }}"
+
+[delegated_vars]
+testhost6 myhost=127.0.0.3
+testhost7 myhost=127.0.0.4
+
+[delegated_vars:vars]
+ansible_host={{myhost}}
+ansible_connection=ssh
diff --git a/test/integration/targets/delegate_to/inventory_interpreters b/test/integration/targets/delegate_to/inventory_interpreters
new file mode 100644
index 0000000..4c202ca
--- /dev/null
+++ b/test/integration/targets/delegate_to/inventory_interpreters
@@ -0,0 +1,5 @@
+testhost ansible_python_interpreter=firstpython
+testhost2 ansible_python_interpreter=secondpython
+
+[all:vars]
+ansible_connection=local
diff --git a/test/integration/targets/delegate_to/library/detect_interpreter.py b/test/integration/targets/delegate_to/library/detect_interpreter.py
new file mode 100644
index 0000000..1f40167
--- /dev/null
+++ b/test/integration/targets/delegate_to/library/detect_interpreter.py
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import sys
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(argument_spec={})
+ module.exit_json(**dict(found=sys.executable))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/delegate_to/resolve_vars.yml b/test/integration/targets/delegate_to/resolve_vars.yml
new file mode 100644
index 0000000..898c0b0
--- /dev/null
+++ b/test/integration/targets/delegate_to/resolve_vars.yml
@@ -0,0 +1,16 @@
+---
+- name: though we test for 'vars' this is only for backwards compatibility and the 'vars' variable will be deprecated and removed in the future
+ hosts: localhost
+ gather_facts: no
+ tasks:
+ - add_host:
+ name: host1
+ ansible_connection: local
+
+- hosts: localhost
+ gather_facts: no
+ vars:
+ server_name: host1
+ tasks:
+ - command: echo should delegate to host1 with local connection
+ delegate_to: "{{ vars['server_name'] }}"
diff --git a/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/tasks/main.yml b/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/tasks/main.yml
new file mode 100644
index 0000000..2b14c55
--- /dev/null
+++ b/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/tasks/main.yml
@@ -0,0 +1,5 @@
+- name: sends SQL template files to mysql host(s)
+ debug:
+ msg: "{{ item }}"
+ with_fileglob: ../templates/*.j2
+ delegate_to: localhost
diff --git a/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/one.j2 b/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/one.j2
new file mode 100644
index 0000000..1fad51f
--- /dev/null
+++ b/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/one.j2
@@ -0,0 +1 @@
+{{ inventory_hostname }}
diff --git a/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/two.j2 b/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/two.j2
new file mode 100644
index 0000000..1fad51f
--- /dev/null
+++ b/test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/two.j2
@@ -0,0 +1 @@
+{{ inventory_hostname }}
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 0000000..22187f9
--- /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 0000000..1bdf27c
--- /dev/null
+++ b/test/integration/targets/delegate_to/runme.sh
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+
+set -eux
+
+platform="$(uname)"
+
+function setup() {
+ if [[ "${platform}" == "FreeBSD" ]] || [[ "${platform}" == "Darwin" ]]; then
+ ifconfig lo0
+
+ existing=$(ifconfig lo0 | grep '^[[:blank:]]inet 127\.0\.0\. ' || true)
+
+ echo "${existing}"
+
+ for i in 3 4 254; do
+ ip="127.0.0.${i}"
+
+ if [[ "${existing}" != *"${ip}"* ]]; then
+ ifconfig lo0 alias "${ip}" up
+ fi
+ done
+
+ ifconfig lo0
+ fi
+}
+
+function teardown() {
+ if [[ "${platform}" == "FreeBSD" ]] || [[ "${platform}" == "Darwin" ]]; then
+ for i in 3 4 254; do
+ ip="127.0.0.${i}"
+
+ if [[ "${existing}" != *"${ip}"* ]]; then
+ ifconfig lo0 -alias "${ip}"
+ fi
+ done
+
+ ifconfig lo0
+ fi
+}
+
+setup
+
+trap teardown EXIT
+
+ANSIBLE_SSH_ARGS='-C -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null' \
+ ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook test_delegate_to.yml -i inventory -v "$@"
+
+# this test is not doing what it says it does, also relies on var that should not be available
+#ansible-playbook test_loop_control.yml -v "$@"
+
+ansible-playbook test_delegate_to_loop_randomness.yml -i inventory -v "$@"
+
+ansible-playbook delegate_and_nolog.yml -i inventory -v "$@"
+
+ansible-playbook delegate_facts_block.yml -i inventory -v "$@"
+
+ansible-playbook test_delegate_to_loop_caching.yml -i inventory -v "$@"
+
+# ensure we are using correct settings when delegating
+ANSIBLE_TIMEOUT=3 ansible-playbook delegate_vars_hanldling.yml -i inventory -v "$@"
+
+ansible-playbook has_hostvars.yml -i inventory -v "$@"
+
+# test ansible_x_interpreter
+# python
+source virtualenv.sh
+(
+cd "${OUTPUT_DIR}"/venv/bin
+ln -s python firstpython
+ln -s python secondpython
+)
+ansible-playbook verify_interpreter.yml -i inventory_interpreters -v "$@"
+ansible-playbook discovery_applied.yml -i inventory -v "$@"
+ansible-playbook resolve_vars.yml -i inventory -v "$@"
+ansible-playbook test_delegate_to_lookup_context.yml -i inventory -v "$@"
+ansible-playbook delegate_local_from_root.yml -i inventory -v "$@" -e 'ansible_user=root'
+ansible-playbook delegate_with_fact_from_delegate_host.yml "$@"
+ansible-playbook delegate_facts_loop.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 0000000..dcfa9d0
--- /dev/null
+++ b/test/integration/targets/delegate_to/test_delegate_to.yml
@@ -0,0 +1,82 @@
+- 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
+
+ - debug: var=setup_results
+
+ - 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
+
+
+- name: verify delegation with per host vars
+ hosts: testhost6
+ gather_facts: yes
+ tasks:
+ - debug: msg={{ansible_facts['env']}}
+
+ - name: ensure normal facts still work as expected
+ assert:
+ that:
+ - '"127.0.0.3" in ansible_facts["env"]["SSH_CONNECTION"]'
+
+ - name: Test delegate_to with other host defined using same named var
+ setup:
+ register: setup_results
+ delegate_to: testhost7
+
+ - debug: msg={{setup_results.ansible_facts.ansible_env}}
+
+ - name: verify ssh plugin resolves variable for ansible_host correctly
+ assert:
+ that:
+ - '"127.0.0.4" in setup_results.ansible_facts.ansible_env["SSH_CONNECTION"]'
diff --git a/test/integration/targets/delegate_to/test_delegate_to_lookup_context.yml b/test/integration/targets/delegate_to/test_delegate_to_lookup_context.yml
new file mode 100644
index 0000000..ae1bb28
--- /dev/null
+++ b/test/integration/targets/delegate_to/test_delegate_to_lookup_context.yml
@@ -0,0 +1,12 @@
+- hosts: localhost
+ gather_facts: false
+ vars:
+ verbosity: "{{ '' if not ansible_verbosity else '-' ~ ('v' * ansible_verbosity) }}"
+ tasks:
+ - command: ansible-playbook {{ verbosity }} delegate_to_lookup_context.yml
+ register: result
+
+ - assert:
+ that:
+ - >
+ '[WARNING]: Unable to find' not in result.stderr
diff --git a/test/integration/targets/delegate_to/test_delegate_to_loop_caching.yml b/test/integration/targets/delegate_to/test_delegate_to_loop_caching.yml
new file mode 100644
index 0000000..6ea08f7
--- /dev/null
+++ b/test/integration/targets/delegate_to/test_delegate_to_loop_caching.yml
@@ -0,0 +1,45 @@
+- hosts: testhost,testhost2
+ gather_facts: false
+ vars:
+ delegate_to_host: "localhost"
+ tasks:
+ - set_fact:
+ gandalf:
+ shout: 'You shall not pass!'
+ when: inventory_hostname == 'testhost'
+
+ - set_fact:
+ gandalf:
+ speak: 'Run you fools!'
+ when: inventory_hostname == 'testhost2'
+
+ - name: works correctly
+ debug: var=item
+ delegate_to: localhost
+ with_dict: "{{ gandalf }}"
+ register: result1
+
+ - name: shows same item for all hosts
+ debug: var=item
+ delegate_to: "{{ delegate_to_host }}"
+ with_dict: "{{ gandalf }}"
+ register: result2
+
+ - debug:
+ var: result2.results[0].item.value
+
+ - assert:
+ that:
+ - result1.results[0].item.value == 'You shall not pass!'
+ - result2.results[0].item.value == 'You shall not pass!'
+ when: inventory_hostname == 'testhost'
+
+ - assert:
+ that:
+ - result1.results[0].item.value == 'Run you fools!'
+ - result2.results[0].item.value == 'Run you fools!'
+ when: inventory_hostname == 'testhost2'
+
+ - assert:
+ that:
+ - _ansible_loop_cache is undefined
diff --git a/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml b/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml
new file mode 100644
index 0000000..81033a1
--- /dev/null
+++ b/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml
@@ -0,0 +1,73 @@
+---
+- name: Integration tests for #28231
+ hosts: localhost
+ gather_facts: false
+ tasks:
+ - name: Add some test hosts
+ add_host:
+ name: "foo{{item}}"
+ groups: foo
+ ansible_connection: local
+ ansible_python_interpreter: "{{ ansible_playbook_python }}"
+ loop: "{{ range(10)|list }}"
+
+ # We expect all of the next 3 runs to succeeed
+ # this is done multiple times to increase randomness
+ - assert:
+ that:
+ - item in ansible_delegated_vars
+ delegate_to: "{{ item }}"
+ loop:
+ - "{{ groups.foo|random }}"
+ ignore_errors: true
+ register: result1
+
+ - assert:
+ that:
+ - item in ansible_delegated_vars
+ delegate_to: "{{ item }}"
+ loop:
+ - "{{ groups.foo|random }}"
+ ignore_errors: true
+ register: result2
+
+ - assert:
+ that:
+ - item in ansible_delegated_vars
+ delegate_to: "{{ item }}"
+ loop:
+ - "{{ groups.foo|random }}"
+ ignore_errors: true
+ register: result3
+
+ - debug:
+ var: result1
+
+ - debug:
+ var: result2
+
+ - debug:
+ var: result3
+
+ - name: Ensure all of the 3 asserts were successful
+ assert:
+ that:
+ - results is all
+ vars:
+ results:
+ - "{{ (result1.results|first) is successful }}"
+ - "{{ (result2.results|first) is successful }}"
+ - "{{ (result3.results|first) is successful }}"
+
+ - name: Set delegate
+ set_fact:
+ _delegate: '{{ groups.foo[0] }}'
+
+ - command: "true"
+ delegate_to: "{{ _delegate }}"
+ register: result
+
+ - assert:
+ that:
+ - result.stdout is defined
+ - result.results is undefined
diff --git a/test/integration/targets/delegate_to/test_loop_control.yml b/test/integration/targets/delegate_to/test_loop_control.yml
new file mode 100644
index 0000000..61e9304
--- /dev/null
+++ b/test/integration/targets/delegate_to/test_loop_control.yml
@@ -0,0 +1,16 @@
+- hosts: localhost
+ gather_facts: no
+ tasks:
+ - name: Test delegate_to with loop_control
+ ping:
+ delegate_to: "{{ item }}"
+ with_items:
+ - localhost
+ loop_control:
+ label: "{{ item }}"
+ register: out
+
+ - name: Check if delegated_host was templated properly
+ assert:
+ that:
+ - out.results[0]['_ansible_delegated_vars']['ansible_delegated_host'] == 'localhost'
diff --git a/test/integration/targets/delegate_to/verify_interpreter.yml b/test/integration/targets/delegate_to/verify_interpreter.yml
new file mode 100644
index 0000000..63c60a4
--- /dev/null
+++ b/test/integration/targets/delegate_to/verify_interpreter.yml
@@ -0,0 +1,47 @@
+- name: ensure they are different
+ hosts: localhost
+ tasks:
+ - name: dont game me
+ assert:
+ msg: 'expected different values but got ((hostvars["testhost"]["ansible_python_interpreter"]}} and {{hostvars["testhost2"]["ansible_python_interpreter"]}}'
+ that:
+ - hostvars["testhost"]["ansible_python_interpreter"] != hostvars["testhost2"]["ansible_python_interpreter"]
+
+- name: no delegation
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: detect interpreter used by each host
+ detect_interpreter:
+ register: baseline
+
+ - name: verify it
+ assert:
+ msg: 'expected {{ansible_python_interpreter}} but got {{baseline.found|basename}}'
+ that:
+ - baseline.found|basename == ansible_python_interpreter
+
+- name: actual test
+ hosts: testhost
+ gather_facts: false
+ tasks:
+ - name: original host
+ detect_interpreter:
+ register: found
+
+ - name: verify it orig host
+ assert:
+ msg: 'expected {{ansible_python_interpreter}} but got {{found.found|basename}}'
+ that:
+ - found.found|basename == ansible_python_interpreter
+
+ - name: delegated host
+ detect_interpreter:
+ register: found2
+ delegate_to: testhost2
+
+ - name: verify it delegated
+ assert:
+ msg: 'expected {{hostvars["testhost2"]["ansible_python_interpreter"]}} but got {{found2.found|basename}}'
+ that:
+ - found2.found|basename == hostvars["testhost2"]["ansible_python_interpreter"]