Conditionally define variable in Ansible

2020-05-19 04:03发布

I want to conditionally define a variable in an Ansible playbook like this:

my_var: "{{ 'foo' if my_condition}}"

I would like the variable to remain undefined if the condition does not resolve to true.

Ansible gives the following error if I try to execute the code:

fatal: [foo.local] => {'msg': 'AnsibleUndefinedVariable: One or more undefined
                       variables: the inline if-expression on line 1 evaluated
                       to false and no else section was defined.', 'failed': True}

Why is this an error anyway?

The complete case looks like this:

{role: foo, my_var: "foo"}

If my_var is defined, the role does something special. In some cases, I don't want the role to do this. I could use when: condition, but then I would have to copy the whole role block. I could also use an extra bool variable, but I would like a solution without having to change the "interface" to the role.

Any ideas?

标签: ansible
4条回答
Deceive 欺骗
2楼-- · 2020-05-19 04:26

This code may help you to define a variable with condition.

- hosts: node1
  gather_facts: yes
  tasks:
   - name: Check File
     shell: ls -ld /etc/postfix/post-install
     register: result
     ignore_errors: yes

   - name: Define Variable
     set_fact:
         exists: "{{ result.stdout }}"
     when: result|success

   - name: Display Variable
     debug: msg="{{ exists }}"
     ignore_errors: yes

So here the exists will display only if the condition is true.

查看更多
放我归山
3楼-- · 2020-05-19 04:29

You could use something like this:

my_var: "{{ 'foo' if my_condition else '' }}"

The 'else' will happen if condition not match, and in this case will set a empty value for the variable. I think this is a short, readable and elegant solution.

查看更多
神经病院院长
4楼-- · 2020-05-19 04:40

My example, after https://stackoverflow.com/a/43403229/5025060:

vars:
    sudoGroup: "{{ 'sudo' if ansible_distribution == 'Ubuntu' else 'wheel' }}"

Because of the different sudo conventions used by Ubuntu versus other platforms, here I am telling Ansible to set a variable named sudoGroup to sudo if the platform is Ubuntu, otherwise set it to wheel.

Later in my playbook, I combine the variable with Ansible's user module to add either sudo or wheel to an account's secondary groups depending on the OS Ansible is running on:

- name: Add or update bob account
  user:
    name: bob
    uid: 3205
    groups: "{{ sudoGroup }}"
    append: yes

NOTES:

  • Double quotes around the {{ variable }} are required in the user: groups: definition above.
  • Once I define sudoGroup as above in my playbook's global vars: section, Ansible configures it at run time (based on ansible_distribution) for each target I define in my hosts: section.
查看更多
放我归山
5楼-- · 2020-05-19 04:48

I believe you're after the default(omit) filter. (Reference).

As per the example, mode will behave like it wasn't set at all for the first two items in the loop.

- name: touch files with an optional mode
  file:
    dest: "{{item.path}}"
    state: touch
    mode: "{{item.mode|default(omit)}}"
  loop:
    - path: /tmp/foo
    - path: /tmp/bar
    - path: /tmp/baz
      mode: "0444"
查看更多
登录 后发表回答