Is it possible to set a fact containing an array in ansible using set_fact
? What's the correct syntax for it?
问题:
回答1:
Indeed it is. You need to quote the entire array though:
- name: set fact
set_fact: foo="[ 'one', 'two', 'three']"
- name: debug
debug: msg={{ item }}
with_items: foo
The above tasks should generate the following output:
TASK: [set fact] **************************************************************
ok: [localhost]
TASK: [debug] *****************************************************************
ok: [localhost] => (item=one) => {
"item": "one",
"msg": "one"
}
ok: [localhost] => (item=two) => {
"item": "two",
"msg": "two"
}
ok: [localhost] => (item=three) => {
"item": "three",
"msg": "three"
}
回答2:
Yes, this is possible. As mentioned in another answer, you can set an array using double quotes, like so:
- name: set foo fact to an array
set_fact: foo="[ 'one', 'two', 'three' ]"
However, I thought I'd create another answer to indicate that it's also possible to add to an existing array, like so:
- name: add items to foo array fact
set_fact: foo="{{foo}} + [ 'four' ]"
Combining these and adding debugging as a playbook (which I'm calling facts.yml
) like so:
---
- name: test playbook
gather_facts: false
hosts: localhost
tasks:
- name: set foo fact to an array
set_fact: foo="[ 'one', 'two', 'three' ]"
- debug: var=foo
- name: add items to foo array fact
set_fact: foo="{{foo}} + [ 'four' ]"
- debug: var=foo
Produces (via ansible-playbook facts.yml
) the following:
PLAY [test playbook] **********************************************************
TASK: [set foo fact to an array] **********************************************
ok: [localhost]
TASK: [debug var=foo] *********************************************************
ok: [localhost] => {
"foo": [
"one",
"two",
"three"
]
}
TASK: [add items to foo array fact] *******************************************
ok: [localhost]
TASK: [debug var=foo] *********************************************************
ok: [localhost] => {
"foo": [
"one",
"two",
"three",
"four"
]
}
PLAY RECAP ********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
回答3:
Adding to the already given answers I would like to show you a different way to
define a list with set_fact
using the regular YAML syntax instead of the
custom format which Ansible core folks like to use in their docs. This
custom format, like in this case, has shown lead to confusion.
Consider this example:
- name: 'Set the foo variable to a static list using the YAML syntax'
set_fact:
foo:
- 'one'
- 'two'
- 'three'
Straight forward, right? Just as you would do in any normal YAML document. So why not use it in Ansible YAML tasks file too?
About the combination of lists mentioned by @lindes-hw. There is more than one way to do this. The following examples use Jinja2 syntax to define the list:
- name: 'Set the foo variable to a combined static list using the Jinja2 syntax'
set_fact:
foo: '{{ [ "one" ] + [ "two", "three" ] }}'
- name: 'Set the foo variable to a combined static list using the Jinja2 syntax and Jinja2 filters'
set_fact:
foo: '{{ [ "one" ] | union([ "two", "three" ]) }}'
The second example uses the union
filter. Refer to the set theory filters in the Ansible docs.
回答4:
I had a similar requirement to create list of server objects based on list of IP addresses.
vars:
server_ips: one,two,three
tasks:
- name: build items list
set_fact:
foo: "{{foo|default([]) + [{'ip': {'addr': item, 'type': 'V4'}}] }}"
with_items: "{{server_ips.split(',')}}"
- debug:
msg: "{{ foo }}"
Gives following output
TASK [setup] *******************************************************************
ok: [localhost]
TASK [build items list] ********************************************************
ok: [localhost] => (item=one)
ok: [localhost] => (item=two)
ok: [localhost] => (item=three)
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
{
"ip": {
"addr": "one",
"type": "V4"
}
},
{
"ip": {
"addr": "two",
"type": "V4"
}
},
{
"ip": {
"addr": "three",
"type": "V4"
}
}
]
}
回答5:
I don't know if the functionality changed --- it possibly did in 2.5 --- but it looks to me like this code
with_items: foo
in the example doesn't work any more you have to use
with_items: "{{ foo }}"
I'm using Ansible 2.5.2. I was getting this (incorrect) output:
ok:[localhost] => (item=None) => {
"msg":"foo"
}
I found the updated syntax in the docs here:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#with-items