Ansible - omit parameter in list of dictionary

Viewed 147

I know about the omit filter but I'm not able to get to work when it's in a list of dictionaries.

I want it so that if for example, the published_port variable is not defined then the publish parameter is omitted

- name: test
  community.docker.docker_swarm_service:
    name: myservice
    image: alpine
    publish:
      - published_port: "{{ published_port | default(omit) }}"
        target_port: "{{ target_port | default(omit) }}"

The error I get is: "missing required arguments: published_port, target_port found in publish". I know it's something to do with it being a list but not sure how to get around this issue.

1 Answers

This happens because, when your two variables are both undefined, you end up creating a list with one empty element. But what you should really do in this case is to omit the whole published parameter.

You can achieve this thanks to a inline if expression, assessing if both variables are undefined, ending up omitting the whole parameter.

Here would be an example playbook:

- hosts: localhost
  gather_facts: no

  tasks:
    - set_fact: 
        docker: 
          name: myservice
          image: alpine
          publish: >- 
            {{ 
              [{
                'published_port': published_port | default(omit), 
                'target_port': target_port | default(omit)
              }]
              if published_port is defined or target_port is defined else omit 
            }}

    - debug:
        var: docker

Mind that I am defining neither published_port nor target_port in this playbook.

  • Now, if I run it like that, I will get the recap:
    PLAY [localhost] **************************************************************************************************
    
    TASK [set_fact] ***************************************************************************************************
    ok: [localhost]
    
    TASK [debug] ******************************************************************************************************
    ok: [localhost] => 
      docker:
        image: alpine
        name: myservice
    
    PLAY RECAP ********************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
  • If I run it adding -e 'published_port=42', I will get the recap:
    PLAY [localhost] **************************************************************************************************
    
    TASK [set_fact] ***************************************************************************************************
    ok: [localhost]
    
    TASK [debug] ******************************************************************************************************
    ok: [localhost] => 
      docker:
        image: alpine
        name: myservice
        publish:
        - published_port: '42'
    
    PLAY RECAP ********************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
  • If I run it adding -e 'target_port=43', I will get the recap:
    PLAY [localhost] **************************************************************************************************
    
    TASK [set_fact] ***************************************************************************************************
    ok: [localhost]
    
    TASK [debug] ******************************************************************************************************
    ok: [localhost] => 
      docker:
        image: alpine
        name: myservice
        publish:
        - target_port: '43'
    
    PLAY RECAP ********************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
  • And, finally, if I run it adding -e 'published_port=42 target_port=43', I will get the recap:
    PLAY [localhost] **************************************************************************************************
    
    TASK [set_fact] ***************************************************************************************************
    ok: [localhost]
    
    TASK [debug] ******************************************************************************************************
    ok: [localhost] => 
      docker:
        image: alpine
        name: myservice
        publish:
        - published_port: '42'
          target_port: '43'
    
    PLAY RECAP ********************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    

Which fixes your issue.

Related