用列表建立字典/哈希

时间:2019-05-05 03:08:08

标签: ansible

我正在尝试构建字典,但无法掌握jinja2如何对变量进行插值。

我想将数组中的特定项目(例如item [0])设置为特定的键值字典项目。

- set_fact: 
    nodes: 
      - node1
      - node2 

- set_fact:
    list_one: 
      - f-one
      - f-two 

- set_fact: 
    list_two:
      - n-one
      - n-two

我想要什么:

- set_fact: 
    **node_dict:
      node1:
        labels:
          f-one: n-one
      node2:
        labels: 
          f-two: n-two**  

我跑步时:

- name: check loop1
  debug:
   msg: '{{item[0]}} - {{item[1]}} - {{ item[2]}} '
  with_nested:
    - '{{ nodes }}'
    - '{{ list_one }}'
    - '{{ list_two }}'

item变量可用。但是要这样做:

- set_fact: 
    final:
      '{{item[0]}}':
        labels:
          "{{item[1] }}" : "{{item[2]}}"
    with_nested:
      - '{{ nodes }}'
      - '{{ list_one }}'
      - '{{ list_two }}'

导致错误。

有人可以解释为什么吗?我如何最终得到理想的结果?

2 个答案:

答案 0 :(得分:0)

一种选择是创建标签列表,然后组合字典。下面的游戏

- hosts: localhost
  vars:
    nodes: 
      - node1
      - node2 
    list_one: 
      - f-one
      - f-two 
    list_two:
      - n-one
      - n-two
    node_dict: {}
    my_labels: []
  tasks:
    - set_fact:
        my_labels: "{{ my_labels + [ {list_one[my_idx]:list_two[my_idx]} ] }}"
      loop: "{{ nodes }}"
      loop_control:
        index_var: my_idx
    - set_fact:
        node_dict: "{{ node_dict | combine({item:{'labels':my_labels[my_idx]}}) }}"
      loop: "{{ nodes }}"
      loop_control:
        index_var: my_idx
     - debug:
         var: node_dict

给予:

"node_dict": {
    "node1": {
        "labels": {
            "f-one": "n-one"
        }
    }, 
    "node2": {
        "labels": {
            "f-two": "n-two"
        }
    }
}

答案 1 :(得分:0)

  1. 尽管上面的最后一段代码不满足您的要求,但这是完全有效的:运行它时没有出现任何错误。
  2. 您现在正在使用它,set_fact在每个循环上都覆盖您的final变量。要将元素添加到像您尝试执行的dict一样,您需要将var初始化为一个空dict,并使用您为每次迭代计算的值combine对其进行初始化。由于计算的值本身就是字典,因此如果必须在字典的深处编写表达式,则需要使用recursive=True
  3. 如果我考虑到您的原始数据和预期结果,则希望将每个列表的 Nth 元素关联在一起。这不是nested所做的(在nodes上有一个子循环,在list_one上有一个子循环,在list_two上循环...)。在您的情况下,您只需要遍历列表长度的索引,并将相同索引的元素组合在一起。我的看法如下。
---
- name: test for SO
  hosts: localhost

  vars:
    nodes:
      - node1
      - node2
    list_one:
      - f-one
      - f-two
    list_two:
      - n-one
      - n-two

  tasks:
    - name: Make my config
      set_fact:
        final: >-
          {{
            final
            | default({})
            | combine ({
                nodes[item]: {
                  'labels': {
                    list_one[item]: list_two[item]
                  }
                }
              }, recursive=True)
          }}
      loop: "{{ range(nodes | length) | list }}"

    - name: debug
      debug:
        var: final

给出以下结果

$ ansible-playbook test.yml 

PLAY [test for SO] ******************************************************************

TASK [Gathering Facts] **************************************************************
ok: [localhost]

TASK [Make my config] ***************************************************************
ok: [localhost] => (item=0)
ok: [localhost] => (item=1)

TASK [debug] ************************************************************************
ok: [localhost] => {
    "final": {
        "node1": {
            "labels": {
                "f-one": "n-one"
            }
        },
        "node2": {
            "labels": {
                "f-two": "n-two"
            }
        }
    }
}

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

编辑:使用zip filter(今天我(重新)发现reading an other contribution)可以得到相同的结果。

    - name: Make my config
       set_fact:
         final: >-
           {{
             final
             | default({})
             | combine ({
                 item.0: {
                   'labels': {
                     item.1: item.2
                   }
                 }
               }, recursive=True)
           }}
       loop: "{{ nodes | zip(list_one, list_two) | list }}"