如何在 ansible 剧本中有条件地向字典添加 key/value

How to add a key/value to a dict in an ansible playbook, conditional

假设我想在变量 test_var 存在时添加 InterestingVar 字典键和关联值(通过 -e in command line 传递),我该怎么做?

# ansible-playbook ./add_to_dict_on_condition.yml -i 127.0.0.1, -e env=test -e test_var=123
- hosts: localhost
  gather_facts: no
  vars:
    - tags:
        InterestingVar: "{{test_var}}" # How to omit this line if test_var == '' ?
        Name: xxx
        Env: "{{ env }}"

  tasks:
    - debug: var=tags

我测试了

 InterestingVar: "{{test_var|default(omit)}}

但我得到:

"InterestingVar": "__omit_place_holder__caca01e207397883640613b08e8ce3a8fbdd6"

而不是什么都没有。

任何帮助将不胜感激。

我用ansible 1.8

我唯一能想到的就是将字典与 Ansible 2.0 中引入的 set_fact task when your condition is met. This relies on the combine filter 相结合。

- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    - tags:
        Name: xxx
        Env: "{{ env }}"
    - optional_tags:
        InterestingVar: "{{ test_var }}"

  tasks:
    - name: combine tags
      set_fact:
        tags: "{{ tags | combine(optional_tags) }}"
      when: test_var is defined

    - name: debug tags
      debug: var=tags

输出以下内容然后 test_var 未定义:

vagrant@Test-02:~$ ansible-playbook -i "localhost," conditional_key.yml -e "env=test"

PLAY ***************************************************************************

TASK [combine tags] ************************************************************
skipping: [localhost]

TASK [debug tags] **************************************************************
ok: [localhost] => {
    "changed": false,
    "tags": {
        "Env": "test",
        "Name": "xxx"
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

定义时输出:

vagrant@Test-02:~$ ansible-playbook -i "localhost," conditional_key.yml -e "env=test" -e "test_var=123"

PLAY ***************************************************************************

TASK [combine tags] ************************************************************
ok: [localhost]

TASK [debug tags] **************************************************************
ok: [localhost] => {
    "changed": false,
    "tags": {
        "Env": "test",
        "InterestingVar": "123",
        "Name": "xxx"
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

如果您无法使用 2.0+,那么另一种选择可能是更改 Ansible's hash behaviour 以合并词典而不是通过设置覆盖它们:

hash_behaviour=merge

在你的 ansible.cfg.

有了这个你就可以使用这样的东西了:

- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    - tags:
        Name: xxx
        Env: "{{ env }}"
    - tags:
        InterestingVar: "{{ test_var }}"

  tasks:
    - name: debug tags
      debug: var=tags

在以下文件中定义您的变量:

vagrant@Test-01:~$ cat tags.yml
tags:
  Name: xxx
  Env: "{{ env }}"
vagrant@Test-01:~$ cat optional_tags.yml
tags:
  InterestingVar: "{{ test_var }}"

这将为您提供所需的输出,但您必须确保在未定义 test_var 时不包含 optional_vars.yml

vagrant@Test-01:~$ ansible-playbook -i "localhost," conditional_key.yml -e "env=test" -e "test_var=123" -e@tags.yml -e@optional_tags.yml

PLAY [localhost] **************************************************************

TASK: [debug tags] ************************************************************
ok: [localhost] => {
    "var": {
        "tags": {
            "Env": "test",
            "InterestingVar": "123",
            "Name": "xxx"
        }
    }
}

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

请注意,在使用此方法时,任何预期通过继承覆盖的字典现在都将合并字典,因此这对于覆盖其清单中内容的任何人来说可能不是那么有用。