From 8a754e0858d922e955e71b253c139e071ecec432 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 18:04:21 +0200 Subject: Adding upstream version 2.14.3. Signed-off-by: Daniel Baumann --- test/integration/targets/delegate_to/aliases | 4 ++ .../delegate_to/connection_plugins/fakelocal.py | 76 ++++++++++++++++++++ .../targets/delegate_to/delegate_and_nolog.yml | 8 +++ .../targets/delegate_to/delegate_facts_block.yml | 25 +++++++ .../targets/delegate_to/delegate_facts_loop.yml | 40 +++++++++++ .../delegate_to/delegate_local_from_root.yml | 10 +++ .../delegate_to/delegate_to_lookup_context.yml | 4 ++ .../delegate_to/delegate_vars_hanldling.yml | 58 +++++++++++++++ .../delegate_with_fact_from_delegate_host.yml | 18 +++++ .../targets/delegate_to/discovery_applied.yml | 8 +++ .../integration/targets/delegate_to/files/testfile | 1 + .../targets/delegate_to/has_hostvars.yml | 64 +++++++++++++++++ test/integration/targets/delegate_to/inventory | 17 +++++ .../targets/delegate_to/inventory_interpreters | 5 ++ .../delegate_to/library/detect_interpreter.py | 18 +++++ .../targets/delegate_to/resolve_vars.yml | 16 +++++ .../delegate_to_lookup_context/tasks/main.yml | 5 ++ .../delegate_to_lookup_context/templates/one.j2 | 1 + .../delegate_to_lookup_context/templates/two.j2 | 1 + .../roles/test_template/templates/foo.j2 | 3 + test/integration/targets/delegate_to/runme.sh | 78 ++++++++++++++++++++ .../targets/delegate_to/test_delegate_to.yml | 82 ++++++++++++++++++++++ .../test_delegate_to_lookup_context.yml | 12 ++++ .../delegate_to/test_delegate_to_loop_caching.yml | 45 ++++++++++++ .../test_delegate_to_loop_randomness.yml | 73 +++++++++++++++++++ .../targets/delegate_to/test_loop_control.yml | 16 +++++ .../targets/delegate_to/verify_interpreter.yml | 47 +++++++++++++ 27 files changed, 735 insertions(+) create mode 100644 test/integration/targets/delegate_to/aliases create mode 100644 test/integration/targets/delegate_to/connection_plugins/fakelocal.py create mode 100644 test/integration/targets/delegate_to/delegate_and_nolog.yml create mode 100644 test/integration/targets/delegate_to/delegate_facts_block.yml create mode 100644 test/integration/targets/delegate_to/delegate_facts_loop.yml create mode 100644 test/integration/targets/delegate_to/delegate_local_from_root.yml create mode 100644 test/integration/targets/delegate_to/delegate_to_lookup_context.yml create mode 100644 test/integration/targets/delegate_to/delegate_vars_hanldling.yml create mode 100644 test/integration/targets/delegate_to/delegate_with_fact_from_delegate_host.yml create mode 100644 test/integration/targets/delegate_to/discovery_applied.yml create mode 100644 test/integration/targets/delegate_to/files/testfile create mode 100644 test/integration/targets/delegate_to/has_hostvars.yml create mode 100644 test/integration/targets/delegate_to/inventory create mode 100644 test/integration/targets/delegate_to/inventory_interpreters create mode 100644 test/integration/targets/delegate_to/library/detect_interpreter.py create mode 100644 test/integration/targets/delegate_to/resolve_vars.yml create mode 100644 test/integration/targets/delegate_to/roles/delegate_to_lookup_context/tasks/main.yml create mode 100644 test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/one.j2 create mode 100644 test/integration/targets/delegate_to/roles/delegate_to_lookup_context/templates/two.j2 create mode 100644 test/integration/targets/delegate_to/roles/test_template/templates/foo.j2 create mode 100755 test/integration/targets/delegate_to/runme.sh create mode 100644 test/integration/targets/delegate_to/test_delegate_to.yml create mode 100644 test/integration/targets/delegate_to/test_delegate_to_lookup_context.yml create mode 100644 test/integration/targets/delegate_to/test_delegate_to_loop_caching.yml create mode 100644 test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml create mode 100644 test/integration/targets/delegate_to/test_loop_control.yml create mode 100644 test/integration/targets/delegate_to/verify_interpreter.yml (limited to 'test/integration/targets/delegate_to') 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"] -- cgit v1.2.3