Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何用Ansible循环浏览这本词典?_Ansible_Ansible 2.x - Fatal编程技术网

如何用Ansible循环浏览这本词典?

如何用Ansible循环浏览这本词典?,ansible,ansible-2.x,Ansible,Ansible 2.x,假设我有这本字典 war_files: server1: - file1.war - file2.war server2: - file1.war - file2.war - file3.war 现在我只想循环每个项(键),然后循环键中的每个项(值)。是我干的 - name: Loop over the dictionary debug: msg="Key={{ item.key }} value={{ item.value }}" with_dict: "

假设我有这本字典

war_files:
  server1:
  - file1.war
  - file2.war
  server2:
  - file1.war
  - file2.war
  - file3.war
现在我只想循环每个项(键),然后循环键中的每个项(值)。是我干的

- name: Loop over the dictionary
  debug: msg="Key={{ item.key }} value={{ item.value }}"
  with_dict: "{{ war_files }}"
我明白了。这当然是正确的,但不是我想要的

ok: [localhost] => (item={'value': [u'file1.war', u'file2.war'], 'key': u'server1'}) => {
    "item": {
        "key": "server1", 
        "value": [
            "file1.war", 
            "file2.war"
        ]
    }, 
    "msg": "Server=server1, WAR=[u'file1.war', u'file2.war']"
}
ok: [localhost] => (item={'value': [u'file1.war', u'file2.war', u'file3.war'], 'key': u'server2'}) => {
    "item": {
        "key": "server2", 
        "value": [
            "file1.war", 
            "file2.war", 
            "file3.war"
        ]
    }, 
    "msg": "Server=server2, WAR=[u'file1.war', u'file2.war', u'file3.war']"
}
我想得到一个输出,上面写着

"msg": "Server=server1, WAR=file1.war"
"msg": "Server=server1, WAR=file2.war"
"msg": "Server=server2, WAR=file1.war"
"msg": "Server=server2, WAR=file2.war"
"msg": "Server=server2, WAR=file3.war"
那么,我如何编写一个任务来迭代字典,让它遍历每个键,然后遍历每个键中的项呢?本质上,我有一个嵌套数组,并希望对其进行迭代?


编辑:在撰写此答案时,Ansible 2.6尚未发布。请阅读@tmoschou提供的答案,因为它更好


好吧,我找不到一个非常简单的方法来做这件事,但是,用一点金甲2,我们可以实现这样的目标:

/tmp ❯❯❯ cat example.yml
---
- hosts: 127.0.0.1
  vars:
    war_files:
      server1:
      - file1.war
      - file2.war
      server2:
      - file1.war
      - file2.war
      - file3.war
  tasks:
  - set_fact:
      war_files_list_of_dicts: |
          {% set res = [] -%}
          {% for key in war_files.keys() -%}
             {% for value in war_files[key] -%}
              {% set ignored = res.extend([{'Server': key, 'WAR':value}]) -%}
             {%- endfor %}
          {%- endfor %}
          {{ res }}

  - name: let's debug the crap out of this
    debug: var=war_files_list_of_dicts

  - name: Servers and their WARs!!!
    debug:
       msg: "Server={{ item.Server }}, WAR={{ item.WAR }}"
    with_items: "{{ war_files_list_of_dicts }}"
并且,当运行剧本时:

/tmp ❯❯❯ ansible-playbook example.yml
 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [127.0.0.1] ***************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [set_fact] ****************************************************************
ok: [127.0.0.1]

TASK [let's debug the crap out of this] ****************************************
ok: [127.0.0.1] => {
    "war_files_list_of_dicts": [
        {
            "Server": "server1", 
            "WAR": "file1.war"
        }, 
        {
            "Server": "server1", 
            "WAR": "file2.war"
        }, 
        {
            "Server": "server2", 
            "WAR": "file1.war"
        }, 
        {
            "Server": "server2", 
            "WAR": "file2.war"
        }, 
        {
            "Server": "server2", 
            "WAR": "file3.war"
        }
    ]
}

TASK [Servers and their WARs!!!] ***********************************************
ok: [127.0.0.1] => (item={'WAR': u'file1.war', 'Server': u'server1'}) => {
    "item": {
        "Server": "server1", 
        "WAR": "file1.war"
    }, 
    "msg": "Server=server1, WAR=file1.war"
}
ok: [127.0.0.1] => (item={'WAR': u'file2.war', 'Server': u'server1'}) => {
    "item": {
        "Server": "server1", 
        "WAR": "file2.war"
    }, 
    "msg": "Server=server1, WAR=file2.war"
}
ok: [127.0.0.1] => (item={'WAR': u'file1.war', 'Server': u'server2'}) => {
    "item": {
        "Server": "server2", 
        "WAR": "file1.war"
    }, 
    "msg": "Server=server2, WAR=file1.war"
}
ok: [127.0.0.1] => (item={'WAR': u'file2.war', 'Server': u'server2'}) => {
    "item": {
        "Server": "server2", 
        "WAR": "file2.war"
    }, 
    "msg": "Server=server2, WAR=file2.war"
}
ok: [127.0.0.1] => (item={'WAR': u'file3.war', 'Server': u'server2'}) => {
    "item": {
        "Server": "server2", 
        "WAR": "file3.war"
    }, 
    "msg": "Server=server2, WAR=file3.war"
}

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=4    changed=0    unreachable=0    failed=0   

现在Ansible允许这样做

- name: add several users
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }
怎么样

- hosts: localhost
  vars:
    war_files:
      server1:
      - file1.war
      - file2.war
      server2:
      - file1.war
      - file2.war
      - file3.war
  tasks:
    - name: Loop over subelements of the dictionary
      debug:
        msg: "Key={{ item.0.key }} value={{ item.1 }}"
      loop: "{{ war_files | dict2items | subelements('value') }}"
dict2items
子元素
过滤器将出现在Ansible 2.6中


仅供参考,如果您的目标不存在过滤器,您可以用python编写自己的过滤器,而不必求助于jinja2黑客。Ansible易于扩展;默认情况下,
filter\u plugins/*.py
中的过滤器会在您的角色/角色旁边搜索,并自动包括在内-有关详细信息,请参阅。

以下是我循环字典的首选方法:

input_data.yml包含以下内容:

----
input_data:
  item_1:
    id: 1
    info: "Info field number 1"
  item_2:
    id: 2
    info: "Info field number 2"
然后,我在游戏中使用keys()函数使用如上所述的数据结构,并使用with_items对数据进行迭代:

---
- hosts: localhost
  gather_facts: false
  connection: local
  tasks:
    - name: Include dictionary data
      include_vars:
        file: data.yml

    - name: Show info field from data.yml
      debug:
        msg: "Id: {{ input_data[item]['id'] }} - info: {{ input_data[item]['info'] }}"
      with_items: "{{ input_data.keys() | list }}"
上述剧本产生以下输出:

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

TASK [Include dictionary data] *********************************************
ok: [localhost]

TASK [Show info field from data.yml] ***************************************
ok: [localhost] => (item=item_2) => {
    "msg": "Id: 2 - info: Info field item 2"
}
ok: [localhost] => (item=item_3) => {
    "msg": "Id: 3 - info: Info field item 3"
}
ok: [localhost] => (item=item_1) => {
    "msg": "Id: 1 - info: Info field item 1"
}

PLAY RECAP *****************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0
口述2项 我发现自己想要迭代一组异构键及其相关值,并在任务中使用键-值对。
dict2items
过滤器是我发现的最不痛苦的方法。您可以在Ansible 2.6中找到

例句 示例任务
一种对我有效的方法是使用。注意,不应命名dict。只有键值对

-名称:ssh-config
线条填充:
dest:/etc/ssh/sshd\u config
regexp:“^#?\s*{{{item.key}}\s”
行:“{item.key}}{{item.value}”
国家:现在
用_dict:
登录比赛时间:“1米”
Permitrotlogin:“是”
PubkeyAuthentication:“是”
密码验证:“否”
PermistyPasswords:“不”
无知者:“是的”
议定书:2

谢谢!这就是我喜欢Chef而不是Ansible的地方,在这里我可以编写Ruby来迭代数据结构。本质上,这就是你在这里使用Python所做的,但是这种语法很难看。@ChrisF我写的是jinja2,不是Python。但是,是的,我同意你的观点。因此,木偶和厨师比Ansible更有优势。对不起,jinja2,不是Python。再次感谢!更好地使用tmoschou提到的
dict2items
子元素。这个解决方案也可以,但会增加很多复杂性。这是在字典列表上循环,而不是像问题所问的那样在字典的键上循环@因此,这不应是可接受的答案;)。答案可能不被接受,但我相信这是更好的方式。这根本不能解决问题。嵌套有三个层次,这才是真正的问题。另外,为了避免混淆,请尝试使用示例变量来证明您的答案解决了这个问题。这个答案解决了“字典列表”,这是一个非常基本的示例。OP询问的是一本“包含列表的词典词典”,这本词典有很大的不同。不,这个答案不是更好的方法,不,这不应该是被接受的答案。你根本上误解了原来的问题。好多了。您不必在所有情况下都使用
子元素
。尝试
loop:{{users | dict2items}}}
然后
msg:“Key={{item.Key}}value={{item.value}
来了解可能性是什么。请查看并注意,
是逐项计算的。使用ansible,我已经能够编写类似
{Accounts | dict2items}的表达式('key','in',SecuredAccounts)| map(attribute='value.Id')| list}
展开、筛选和提取所需的值。您能解释一下这是如何解决原始问题的吗?演示如何定义一个具有多个id和值的条目。我的答案直接针对问题的标题,因此我的答案对寻找答案的人很有帮助。
systemsetup:
  remotelogin: "On"
  timezone: "Europe/Oslo"
  usingnetworktime: "On"
  sleep: 0
  computersleep: 0
  displaysleep: 0
  harddisksleep: 0
  allowpowerbuttontosleepcomputer: "Off"
  wakeonnetworkaccess: "On"
  restartfreeze: "On"
  restartpowerfailure: "On"
---
- debug:
    msg: "KEY: {{ item.key }}, VALUE: {{ item.value }}"
  loop: "{{ systemsetup | dict2items }}"