Is it possible to set a fact of an array in Ansibl

2019-03-08 10:41发布

Is it possible to set a fact containing an array in ansible using set_fact? What's the correct syntax for it?

标签: ansible
5条回答
啃猪蹄的小仙女
2楼-- · 2019-03-08 10:47

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.

查看更多
狗以群分
3楼-- · 2019-03-08 10:57

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"
            }
        }
    ]
}
查看更多
The star\"
4楼-- · 2019-03-08 10:59

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"
}
查看更多
Animai°情兽
5楼-- · 2019-03-08 11:02

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   
查看更多
劳资没心,怎么记你
6楼-- · 2019-03-08 11:05

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

查看更多
登录 后发表回答