Search code examples
ansiblejinja2

How to create a 'null' default in Ansible


I want 'lucy' to follow the user module creators' default behaviour which is to create and use a group matching the user name 'lucy'. However for 'frank' I want the primary group to be an existing one; gid 1003. So my hash looks like this:

lucy:
  comment: dog
frank:
  comment: cat
  group: 1003

And my task looks like this:

- name: Set up local unix user accounts
  user:
    name: "{{ item.key }}"
    comment: "{{ item.value.comment }}"
    group: "{{ item.value.group | default(undef) }}"
  loop: "{{ users|dict2items }}"

This doesn't work, as undef is not recognised. Nor is anything else I can think of. 'null', 'None' etc. all fail. '' creates an empty string which is not right either. I can't find out how to do it. Any ideas?


Solution

  • default(omit) is what you are looking for. For example,

    - name: Set up local Unix user accounts
      user:
        name: "{{ item.key }}"
        comment: "{{ item.value.comment }}"
        group: "{{ item.value.group | default(omit) }}"
      loop: "{{ users|dict2items }}"
    

    Comments

    Comment by Lucas Basquerotto: "... omit only works correctly when used directly in a module, it won't work in a set_fact ..."

    A: You're wrong. For example, default(omit) works both in set_fact and in the module. The first item in the list defaults to false with the result "VARIABLE IS NOT DEFINED!". The second item defaults to omit. Omitted parameter get_checksum defaults to true with the checksum in the results

    shell> cat pb.yml
    - hosts: localhost
      tasks:
        - set_fact:
            test:
              - "{{ gchk|default(false) }}"
              - "{{ gchk|default(omit) }}"
        - stat:
            path: /etc/passwd
            get_checksum: "{{ item }}"
          loop: "{{ test }}"
          register: result
        - debug:
            var: item.stat.checksum
          loop: "{{ result.results }}"
    

    gives

    shell> ansible-playbook pb.yml | grep item.stat.checksum
      item.stat.checksum: VARIABLE IS NOT DEFINED!
      item.stat.checksum: 7c73e9f589ca1f0a1372aa4cd6944feec459c4a8
    

    In addition to this, default(omit) works as expected also in some expressions. For example

        - debug:
            msg: "{{ {'a': item}|combine({'b': true}) }}"
          loop: "{{ test }}"
    

    gives

      msg:
        a: false
        b: true
    
      msg:
        b: true
    

    See the results without default values

    shell> ansible-playbook pb.yml -e "gchk={{ true|bool }}"
    

    It does not work when passing vars to a module (a template in my case ...). When using omit, the template gets the value of the placeholder instead.

    A: Of course, it doesn't work in this use case. For example,

    shell> cat pb.yml
    - hosts: localhost
      tasks:
        - debug:
            msg: |
              {{ var1 }}
              {{ var2 }}
          vars:
            var1: "{{ foo }}"
            var2: "{{ bar|default(omit) }}"
    

    gives

    shell> ansible-playbook pb.yml -e foo=123
      ...
      msg: |-
        123
        __omit_place_holder__73431d735cecaedbd9c4386e2ebc77ded8eaee51
    

    The goal is to omit a parameter in a module. The question says: I can think of. 'null', 'None' etc. all fail. '' creates an empty string which is not right either. I can't find out how to do it. Any ideas? This is not your use case. The title is misleading, perhaps? Set the default to None if you want to use null. Perhaps, this will do what you want.

          vars:
            var1: "{{ foo }}"
            var2: "{{ bar|default(None) }}"