Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TaskExecutor: update_vars (add magic vars) before post_validate #22156

Open
wants to merge 1 commit into
base: devel
from

Conversation

@fullyint
Copy link
Contributor

commented Mar 1, 2017

ISSUE TYPE
  • Bugfix Pull Request
COMPONENT NAME

TaskExecutor

ANSIBLE VERSION
ansible 2.3.0 (devel c26cac2a53) last updated 2017/03/01 10:55:21 (GMT -600)
  config file =
  configured module search path = Default w/o overrides
SUMMARY

Fixes #21639

Concept. Magic vars are not available for consumption (are undefined) in the explicit redefinition of other magic vars.

Example. Suppose a user's definition of ansible_become_pass includes ansible_user. Despite passing the --user CLI option, the definition below will produce 'ansible_user' is undefined.

ansible_become_pass: "{{ passwords[ansible_user] }}"

Proposed solution. This PR avoids the error by restoring the sequence of update_vars() executing before post_validate(), as existed prior to 479cbfc. This in unfamiliar code for me, so a team member familiar with TaskExecutor may want to review/confirm this revised execution sequence.

Aside: It appears good to keep the remote_addr update before the update_vars() so that the latter can add the ansible_ssh_host and ansible_host magic vars.

Steps to reproduce
Test playbook:

---
- name: No problem if NON-magic var is defined using magic var
  hosts: test # NOT localhost
  gather_facts: false
  vars:
    passwords: # normally in vault-encrypted file
      admin: strong_pass
    non_magic_var: "{{ passwords[ansible_user] }}"
  tasks:
    - debug: var=non_magic_var

- name: Failure when magic var is redefined using magic var
  hosts: test # NOT localhost
  gather_facts: false
  vars:
    passwords: # normally in vault-encrypted file
      admin: strong_pass
    ansible_become_pass: "{{ passwords[ansible_user] }}"
  tasks:
    - debug: var=ansible_become_pass

Test command:

ansible-playbook debug.yml -i hosts -u admin

Output from current devel:

PLAY [No problem if NON-magic var is defined using magic var] ******************

TASK [debug] *******************************************************************
ok: [test] => {
    "changed": false,
    "non_magic_var": "strong_pass"
}

PLAY [Failure when magic var is redefined using magic var] *********************

TASK [debug] *******************************************************************
fatal: [test]: FAILED! => {"failed": true, "msg": "the field 'become_pass' has an invalid value, which appears to include a variable that is undefined. The error was: 'ansible_user' is undefined"}
	to retry, use: --limit @/Users/philip/projects/ansible/ansible/debug.retry

PLAY RECAP *********************************************************************
test                       : ok=1    changed=0    unreachable=0    failed=1

Output after PR:

PLAY [No problem if NON-magic var is defined using magic var] ******************

TASK [debug] *******************************************************************
ok: [test] => {
    "changed": false,
    "non_magic_var": "strong_pass"
}

PLAY [Failure when magic var is redefined using magic var] *********************

TASK [debug] *******************************************************************
ok: [test] => {
    "ansible_become_pass": "strong_pass",
    "changed": false
}

PLAY RECAP *********************************************************************
test                       : ok=2    changed=0    unreachable=0    failed=0
TaskExecutor: update_vars (add magic vars) before post_validate
* Fixes #21639 - a failure of "'varname' is undefined" resulting from redefining
  a magic var with a value that includes another magic var.
* Avoids the error by restoring the sequence of `update_vars()` executing before
  `post_validate()`, as existed prior to 479cbfc.
self._play_context.post_validate(templar=templar)

# now that the play context is finalized, if the remote_addr is not set
# default to using the host's address field as the remote address

This comment has been minimized.

Copy link
@bcoca

bcoca Aug 17, 2017

Member

we cannot set remote_addr w/o post_validating first


# now that the play context is finalized, if the remote_addr is not set
# default to using the host's address field as the remote address
# if the remote_addr is not set, default to using the host's address field
if not self._play_context.remote_addr:
self._play_context.remote_addr = self._host.address

# We also add "magic" variables back into the variables dict to make sure
# a certain subset of variables exist.
self._play_context.update_vars(variables)

This comment has been minimized.

Copy link
@bcoca

bcoca Aug 17, 2017

Member

some of the magic vars rely on post_validate already being run to have the correct value

@bcoca

This comment has been minimized.

Copy link
Member

commented Nov 30, 2018

alternate fix #38861

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.