【问题标题】:ANSIBLE: Looping over complex dict using several variablesANSIBLE:使用多个变量循环复杂的字典
【发布时间】:2021-11-19 19:16:02
【问题描述】:

我希望能够确定多个主机上特定目录列表的平均大小。我首先在主机上找到我想要的目录,评估它们的大小并将结果放入一个不错的字典中:

  - name: find log dirs
    shell: "find / -type d -name 'log' 2>/dev/null | sort"
    register: log_list

  - name: evaluate dir sizes
    shell: "du -sk {{ item }} | awk '{ print $1 }'"
    register: folder_size 
    loop : "{{ log_list.stdout_lines }}"

  - name: build dict
    set_fact:
      folder_info: "{{ folder_info|default({}) | combine({item.item: {'path': item.item, 'size': item.stdout|int}}) }}"
    loop: "{{ folder_size.results }}"

回到 Ansible 控制器,我将所有这些 dicts 放在一个不错的大 dict 中,并放在一起 dirs 列表:

  - name: gather folder info
    set_fact:
      all_dirs: "{{ all_dirs|default([]) + hostvars[item].dir_list|unique }}"
      all_folder_info: "{{ all_folder_info|default({}) | combine({hostvars[item].inventory_hostname:hostvars[item].folder_info}) }}"
    loop: "{{ groups['backoffice'] }}"

调试 all_folder_info 给了我这样的东西:

TASK [debug] *******************************************************************
ok: [localhost] => {
    "all_folder_info": {
        "some.host.com": {
            "/some/directory/": {
                "path": "/some/directory",
                "size": 220
            },
            "/some/other/directory": {
                "path": "/some/other/directory",
                "size": 8
            },
            "/some/third/directory": {
                "path": "/some/third/directory",
                "size": 319404
            }
        },

我现在需要遍历这个巨大的字典来提取我想要的信息并对其进行数学运算,但我被困住了。我试过这样压缩,Ansible 说不能模板:

  - name: debug
    debug: 
      var: (all_folder_info[item.0].[item.1].size | sum) / (all_folder_info[item.0].[item.1].size | length)
    loop: "{{ groups['backoffice']|zip_longest(all_dirs|unique)|list }}"

这似乎充其量只是将两个列表放入键:值对中。我做错了什么?

【问题讨论】:

  • 我想了解你最后想要得到什么,如果我误解了,请告诉我。对于backoffice 组中的每个主机,您希望通过在all_folder_info[someHost] 中查找该主机来打印出平均目录大小。
  • 没错。所以我的直觉是我需要同时在 [someHost] 和 [someDir] 上循环来实现...

标签: python ansible yaml jinja2


【解决方案1】:

为了避免需要执行嵌套循环,我们可以使用过滤器来获取我们想要的单个主机的值。这个 sn-p 应该给你你想要的。

- debug:
    msg: "{{ item }} average size: {{ all_folder_info[item].values() | map(attribute='size') | sum / all_folder_info[item] | length }}"
  loop: "{{ groups['backoffice'] }}"

分解:

all_folder_info['some.host.com'] 现在是一个字典,但我更喜欢仅包含值的列表,以便我可以使用 map 过滤器来操作它。我发现你可以使用.values() 来返回一个没有键的值列表——all_folder_info['some.host.com'].values()

[
  {"path": "/some/directory", "size": 220},
  {"path": "/some/other/directory", "size": 8},
  {"path": "/some/third/directory", "size": 319404}
]

然后对其应用map 过滤器以仅提取size 属性——all_folder_info['some.host.com'].values() | map(attribute='size') | list

[220, 8, 319404]

由于列表仅包含整数,因此我们可以使用sum 过滤器对列表的总数求和。

【讨论】:

  • 谢谢!我之前一直在努力使用地图过滤器,而使用 .values() 则完全不同。但是,最终结果是每个主机的所有日志目录的平均值。你能想出一种我也可以循环“路径”值的方法吗?也许在某个时候:?
  • 您是说要在所有主机上显示/some/directory 的平均大小吗?如果是这样,当前的 all_folder_info 结构可能会很困难。也许如果 all_folder_info 的结构可以改变,那么路径就是关键。
  • 没错。你的意思是all_folder_info: [some_host: { path:size}] 形式的东西吗?
猜你喜欢
  • 1970-01-01
  • 2015-01-02
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多