Survey vars prevent other vars in templates to be expanded

Hello all,

I’m not sure what’s going on here, would you mind to take a look pleases:

https://gist.github.com/AndrewSav/bc6c717c3a14922a6bb292fb70a4cec4

For some reason if the expression includes a variable that comes from awx survey other variables in the template do not get expanded.

Any possible explanation for it? Also I would appreciated if some one could reproduce.

Create a template, point it to the play, create an inventory with localhost only and use it. Then create a survey with a single text parameter named input_variable make it required and provided a default value. Add extra_variable: extravalue to the extra variables field of the template and launch. Confirm on survey prompt. Observe the result.

This is on awx 14.

If anyone has trouble reproducing this, happy to post some screenshots too.

Cheers,
Andrew

I’m a bit confused. It seems to be working. In your play.yml if extra_variable is defined then new2 gets the value testvalue, otherwise it would get the value nope. You then echo out new2 and the value, as expected, is testvalue. This shows that extra_variable is defined. Therefore, the job template variables are flowing through to the ansible playbook, along with the survey variables.

Please include screenshots for clarity.

Chris, look at the new1. In new1 test variable is not expanded. Why?
I upgraded to awx 15 in the meanwhile.

Cheers,
Andrew

Weird, I put some screenshots in the message but they disappeared. Let me try again.

https://drive.google.com/file/d/1TjRpW7aRGz3Vls62dQwytY8yhvFPXPFA/view?usp=drivesdk

https://drive.google.com/file/d/1TCAaX3VaByt8EQdj1CAx9VolHSEZ1RtN/view?usp=drivesdk

https://drive.google.com/file/d/1gPmpPdSUp2hbIrI6OTctLLh1hqtOUZaE/view?usp=drivesdk

https://drive.google.com/file/d/1Oqq5MbEMAc4stPi153mLC1Dac8YFNPV9/view?usp=drivesdk

https://drive.google.com/file/d/1keTHnA87HPhlWLBWS4OKI3B94h7luQSN/view?usp=drivesdk

I would like to clarify here, what my problem is. new2 and new3 are working this is not a problem, this is just to demonstrate that non-survey variables do not prevent expansion of other variables.
new1 is the one exhibiting the problem. We are trying to expand test variable supplied in playbook. It is not a survey variable. But presents of input_variable, which is a survey variable prevent the test variable from being expanded as new1 case shows.

It is possible, that I have wrong expectations here, but I’m having trouble using surveys because of that, since they seem to prevent other variables in the template to be expanded. I would appreciate some insight?

Is it working as intended? If yes why and how to workaround then?

Cheers,
Andrew

Guys, if anything is still unclear, please ask for clarification, I’m happy to explain. I’d like to get some insight into this one. Is there a better place/avenue to address this?

Can I get some help, please?

Andrew,

Can you do it this way instead? As far as I can tell it works and accomplishes the same thing.

https://gist.github.com/jakemcdermott/14896eb4eec91dab55db3a54d27e7868#file-play-yaml-L14-L22

And if for some reason you absolutely must do a nested expand, set an intermediate decision variable in your playbook beforehand and use that. This should do what you’re trying to accomplish in the example you provided.

https://gist.github.com/jakemcdermott/afe8c438dd6a8f4ca7f1c356a124eadb#file-play2-yaml-L10-L20

Hello Jake,

Thank you for your response. Now when we have established that minimal example indeed does not work as presented by me, let me give you a more realistic example, that also does not work. Here it is:

  • name: select execution method for shell script
    set_fact:
    vm_shell: >-
    {{
    ‘/bin/wget’ if os_type == ‘linux’ else
    ‘c:\windows\system32\windowspowershell\v1.0\powershell.exe’ if os_type == ‘windows’
    }}
    vm_shell_args: >-
    {{
    ‘-O - {{ url }} | bash -s {{ args }}’ if os_type == ‘linux’ and not debug else
    ‘-O - {{ url }} 2> {{ debug }}_curl.log | bash -s {{ args }} > {{ debug }}_script.log 2>&1’ if os_type == ‘linux’ and debug else
    ‘-command “curl.exe -L {{ url }} -o ./script.ps1; ./script.ps1 {{ args }}”’ if os_type == ‘windows’ and not debug else
    ‘-command “curl.exe -L {{ url }} -o ./script.ps1 *> {{ debug }}_curl.log; ./script.ps1 {{ args }} *> {{ debug }}_script.log”’ if os_type == ‘windows’ and debug
    }}
    delegate_to: localhost
  • name: “run shell script {{ url | urlsplit(‘path’) | basename }}”

vmware_vm_shell:
hostname: “{{ vsphere_server }}”
username: “{{ vsphere_username }}”
password: “{{ vsphere_password }}”
validate_certs: no
datacenter: “{{ vmware_datacentre }}”
folder: “{{ vmware_folder }}”
vm_id: “{{ vmware_vmname }}”
vm_username: “{{ provisioning_user }}”
vm_password: “{{ provisioning_password.value }}”
vm_shell: “{{ vm_shell }}”
vm_shell_args: “{{ vm_shell_args }}”
wait_for_process: “{{ wait_for_process }}”
delegate_to: localhost
no_log: true

In this example os_type is derived from an input variable, although it is not input variable itself:

  • set_fact:
    os_type: “{{ templates[vmware_template_name].os_type }}”
    delegate_to: localhost

Now, vmware_template_name is input variable, and tempates are defined similar to this in the defaults folder of the role:

templates:
centos-8-base:
scripts:

Now with this example, the variable {{ url }} above does not get expanded just as well.

Do I understand correctly, that in order to make the above work, I need to write 4 additional set_fact tasks? I would like to avoid it if possible, because they make the play output difficult to read, spitting out intermediate steps information that are only there to work around the expansion bug?

Is there a better way to accomplish what I want without writing many additional set tasks? Your examples are all based on using the when condition, and I cannot figure out how I can combine those tasks in a single set_fact, because it’s the conditions themselves that are different.

Would love to get some more input on the above, thank you in advance,
Andrew

Please let me know if the question is not clear, or if I need to provide more information.

I’m still interested in an answer

I’m wondering if anyone can help with the above. Please let me know if you think that it’s my fault that I’m not getting an answer, and I’ll try to improve what you think needs improving - just let me know.

This is still an open question.

If anyone could help with this, would be awesome!

https://docs.ansible.com/ansible-tower/3.2.6/html/installandreference/release_notes.html#ansible-tower-version-3-2-4

ALLOW_JINJA_IN_EXTRA_VARS is causing you issues. You can work around or disable the protection. You can recreate on the command line using the below extra vars.

extra_variable: extravalue
!unsafe ‘input_variable’: !unsafe ‘inputvalue’

Hello Chris,

thank you for chiming in. I have already seen this variable ALLOW_JINJA_IN_EXTRA_VARS, and the always setting does solve this issue. However, it’s quite apparent that this is not a solution, since, according to the link you gave “the always option is deprecated, and will be removed in a future Tower release”. Full quote below.

I cannot use the deprecated option, since this is going to be removed in a future Tower release, and I need the solution to keep working in foreseeable future. The other two option “template” (the default) and “never” (recommended) do not solve the original problem.

Could you please advise if there is a longer term solution here? It also quite possible that I’m missing something, so please do not hesitate to point that out. Thank you for your continuing help.

Andrew

From the quoted link:

  • Fixed Tower to disable usage of Jinja templates in launch-time variables for security reasons (CVE-2018-1104). This release introduces the ALLOW_JINJA_IN_EXTRA_VARS configuration parameter for Tower. This parameter has three values: template to allow usage of Jinja saved directly on a job template definition (the default), never to disable all Jinja usage (recommended), and always to always allow Jinja (strongly discouraged, but an option for prior compatibility). Note that the always option is deprecated, and will be removed in a future Tower release.

I’m not sure of all the nuances of Ansible when a jinja variable is “tainted” (marked unsafe). I tried converting your inline if statement to a when: statement and it behaved in a more sane manner. I’d ask on the ansible mailing list or IRC.

Thank you, Chris, that makes sense, I’ll keep investigating on the ansible side. Still, if their answer is “it works this way because ”, after depreciating always this situation will remain without a solution. Do you think it may be possible NOT deprecate it?

Andrew

Thank you everyone for the help, to close this off, the main issues was with me trying to nest the curly brackets, which did not work because the expression would need to be run via templating engine again, and the sensitive variable prevented that.

I was helped by fowerysong (Paul Arthur) on the IRC.

The way to write my first example so that it works is: https://gist.github.com/AndrewSav/e0fa0c45e395c9b14027ed8598c6248a and the way to write my second example that it works is: https://gist.github.com/AndrewSav/7a63dcd98080753338be26481bf8feb5

Once again, everyone involved, thank you for help resolving this.

Andrew