Hello,
I have a list of dicts, and I would like to add a (key, value) pair to each dict (ie. to each element of the list).
Typically, I have this list:
- port: 2000
release: trusty
- port: 2001
release: xenial
And I would like to create this one
- port: 2000
release: trusty
name: trusty-2000
- port: 2001
release: xenial
name: xenial-2001
Is it possible? I tried using the “map(‘combine’)” filter (see below) but do see how to compute a different value for each element.
This is probably something obvious that I’m missing.
Thank you!
$ cat list.yaml
- hosts: localhost
vars:
- containers:
- port: 2000
release: trusty
- port: 2001
release: xenial
- containers_with_name: “{{ containers | map(‘combine’, {‘name’: ‘TODO:release-port’ }) | list }}”
tasks:
- debug:
msg: “containers_with_name: {{ containers_with_name }}”
$ ansible-playbook list.yaml
[WARNING]: provided hosts list is empty, only localhost is available
PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
“msg”: “containers_with_name: [{u’release’: u’trusty’, u’port’: 2000, ‘name’: ‘TODO:release-port’}, {u’release’: u’xenial’, u’port’: 2001, ‘name’: ‘TODO:release-port’}]”
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
Try this. Its not exactly pretty, but it seems to do what you need.
$ cat listtest-playbook.yml
Hello,
thank you for your answer, and sorry for my late one.
Try this. Its not exactly pretty,
indeed
I’m growing increasingly frustrated by the many quirks and lack of expressibility of ansible’s dialect .
This would have been peanuts to write in python. I probably investigate how to write python module/filters in order to avoid jinja-ed yaml.
but it seems to do what you need.
Yes, thank you.
For my real use-case, I ended-up using with_subelements (see below), but I’ll recall how you use set_fact.
$ cat hosts
[jenkins_masters]
ald-1545-de
[jenkins_slaves_holders]
ald-1545-de
ald-1469-de
[jenkins_slaves_holders:vars]
jenkins_slaves=[{‘release’: ‘trusty’, ‘ssh_port’: 2000},{‘release’: ‘xenial’, ‘ssh_port’: 2001}]
$ cat main.yaml
let ansible know about each created container
add_host “bypasses the play host loop”: it will only be called from one host.
Let this host be “localhost”, for symmetry.
- hosts: localhost
tasks:
- add_host:
hostname: “{{ item.0.inventory_hostname_short }}-build-{{ item.1.release }}”
container_holder_inventory_hostname_short: “{{ item.0.inventory_hostname_short }}”
ansible_port: “{{ item.1.ssh_port }}”
ansible_host: “{{ item.0.ansible_host }}”
ansible_user: ‘root’
jenkins_master: “{{ groups[‘jenkins_masters’] | first | mandatory }}”
groups: ‘build,jenkinsslaves’
with_subelements:
- “{{ groups[‘jenkins_slaves_holders’] | map(‘extract’, hostvars) | list }}”
- jenkins_slaves
Thank you again!