HiveBrain v1.2.0
Get Started
← Back to all entries
patternyamlMinor

Add item(s) to yaml array only if defined (ansible)

Submitted by: @import:stackexchange-devops··
0
Viewed 0 times
itemansiblearrayyamlonlydefinedadd

Problem

How do I write a yaml file such that it defines an array with a list of values, and it skips those values from being added to the yaml array if the given value is undefined?

Specifically, I'm trying to define an array of IP addresses to which I want a service (sshd) to bind to, including the ipv4 and ipv6 addresses. If there is both an ipv4 & ipv6 address, then the array should contain both values. If there is only an ipv4 address or only an ipv6 address, then it should contain one of those values.

This doesn't work, as it will produce an error "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'address'"}

ssh_listen_to:
      - "{{ ansible_default_ipv4.address }}"
      - "{{ ansible_default_ipv6.address }}"


This also doesn't work, as it will end-up adding a line ListenAddress with no argument, that breaks the sshd server (this may be a shortsighted design of my ansible role, but that's out-of-scope in this question).

ssh_listen_to:
      - "{{ ansible_default_ipv4.address | default('') }}"
      - "{{ ansible_default_ipv6.address | default('') }}"


How can I update the above yaml block such that it will skip adding the values to the array if the value isn't defined? Note that this is being done in my playbook's vars: section, so no tasks-based solutions please.

Solution

Create the list in Jinja2 and convert it, e.g.
- hosts: localhost
gather_facts: true
tasks:
- set_fact:
ssh_listen_to: "{{ _ssh_listen_to|from_yaml }}"
vars:
_ssh_listen_to: |
{% if ansible_default_ipv4.address is defined %}
- {{ ansible_default_ipv4.address }}
{% endif %}
{% if ansible_default_ipv6.address is defined %}
- {{ ansible_default_ipv6.address }}
{% endif %}
- debug:
var: ssh_listen_to|type_debug
- debug:
var: ssh_listen_to


gives
TASK [debug] ****
ok: [localhost] =>
ssh_listen_to|type_debug: list

TASK [debug] ****
ok: [localhost] =>
ssh_listen_to:
- 10.1.0.27


If you put the name of the variables into the list, e.g.
vars_addr:
- default_ipv4
- default_ipv6


the task below gives the same result
- set_fact:
ssh_listen_to: "{{ vars_addr|
map('extract', ansible_facts, 'address')|
select('defined')|
list }}"

Context

StackExchange DevOps Q#13564, answer score: 1

Revisions (0)

No revisions yet.