I would like to use variable servers.server1
in task without additional steps like step_var
.
How to substitute variables and add dictionaries to another dictionary outside of tasks in var file?
#var/main.yaml
common_parts_1:
storage:
type: nfs
value: 10GB
common_parts_2:
cpu:
cores: 2
memory:
value: 2GB
servers:
server1:
name: superPC
owner: John
"{{ common_parts_1 }}"
"{{ common_parts_2 }}"
Expected result:
servers:
server1:
name: superPC
owner: John
storage:
type: nfs
value: 10GB
cpu:
cores: 2
memory:
value: 2GB
I would like to use variable servers.server1
in task without additional steps like step_var
.
How to substitute variables and add dictionaries to another dictionary outside of tasks in var file?
#var/main.yaml
common_parts_1:
storage:
type: nfs
value: 10GB
common_parts_2:
cpu:
cores: 2
memory:
value: 2GB
servers:
server1:
name: superPC
owner: John
"{{ common_parts_1 }}"
"{{ common_parts_2 }}"
Expected result:
servers:
server1:
name: superPC
owner: John
storage:
type: nfs
value: 10GB
cpu:
cores: 2
memory:
value: 2GB
Share
Improve this question
edited Feb 17 at 8:11
phanaz
1,58111 silver badges22 bronze badges
asked Feb 16 at 19:29
KucharskyKucharsky
2651 gold badge5 silver badges21 bronze badges
2 Answers
Reset to default 2I see two simple ways to implement this
- Ansible's
combine
filter - YAML anchors and aliases
Ansible's combine
filter
# vars/vars1.yml
---
common_parts_1:
storage:
type: nfs
value: 10GB
common_parts_2:
cpu:
cores: 2
memory:
value: 2GB
servers_pre:
server1:
name: superPC
owner: John
servers:
server1: "{{ servers_pre.server1 | combine(common_parts_1) | combine(common_parts_2) }}"
First you do not define servers
but e.g. servers_pre
. Then you can define servers
by combining the data from the other variables, for this you can use the combine
filter of Ansible.
YAML anchors and aliases
# vars/vars2.yml
---
common_parts_1: &common_parts_1
storage:
type: nfs
value: 10GB
common_parts_2: &common_parts_2
cpu:
cores: 2
memory:
value: 2GB
servers:
server1:
name: superPC
owner: John
<<: [*common_parts_1, *common_parts_2]
server2:
name: nanoPC
owner: James
<<: *common_parts_2
This variant is based purely on YAML and uses YAML anchors and aliases. You do not only define the key common_parts_1
, but also define the data structure as an anchor using &common_parts_1
. You can then insert this data structure elsewhere using the alias *common_parts_1
.
To insert a data structures with an alias in a level on which you have already defined data, use <<:
followed by the alias (see server2
). If you want to insert several anchored data structures, define the aliases as a list (see server1
).
Difference between the two variants
Attention, the two variants are not identical.
If you have the same key in common_parts_1
and common_parts_2
: combine
(in the default configuration list_merge=replace
) overwrites the last occurrence of the key. Therefore, the order of the combine
variant should be chosen from the most general (left) to the most specific (right). The YAML variant acts slightly differently here.
Make your own tests to ensure that the result is as desired.
Put the dictionaries you want to combine into a list
servers:
server1: "{{ [common_parts_1, common_parts_2, server1] | combine }}"
gives what you want
servers:
server1:
cpu:
cores: 2
memory:
value: 2GB
name: superPC
owner: John
storage:
type: nfs
value: 10GB
As a side note: Combine all server_* with all common_parts_.*. For example, given the file var/main.yml
shell> cat var/main.yml
common_parts_1:
storage:
type: nfs
value: 10GB
common_parts_2:
cpu:
cores: 2
memory:
value: 2GB
server_1:
name: superPC
owner: John
server_2:
name: trashPC
owner: Jack
cpu:
cores: 1
memory:
value: 512MB
declare the below variables in the same file
common_parts: "{{ q('vars', *q('varnames', '^common_parts_.*$')) | combine }}"
servers_values: "{{ [common_parts] | product(q('vars', *q('varnames', '^server_.*$')))
| map('combine') }}"
servers_names: "{{ q('varnames', '^server_.*$') }}"
servers: "{{ dict(servers_names | zip(servers_values)) }}"
Then, the below play
- hosts: all
vars_files:
- var/main.yml
tasks:
- debug:
var: common_parts
- debug:
var: servers_names
- debug:
var: servers_values
- debug:
var: servers
gives
servers:
server_1:
cpu:
cores: 2
memory:
value: 2GB
name: superPC
owner: John
storage:
type: nfs
value: 10GB
server_2:
cpu:
cores: 1
memory:
value: 512MB
name: trashPC
owner: Jack
storage:
type: nfs
value: 10GB