Ansible-检查列表中的元素在另一个字典中是否没有相同的值

时间:2020-10-08 16:21:49

标签: ansible

我正在使用列表,列表字典等,但我对此一无所知。

从功能上讲,我试图了解输入列表中的安装是否都安装在其他设备上。

因此在输入中,我有一个在变量中定义的安装列表,即:

mounts:
   - '/' 
   - '/home'
   - '/foo'

诸如此类的事实

"ansible_mounts": [
    {
        "device": "/device1",
        "mount": "/"
    },
    {
        "device": "/device1",
        "mount": "/home"
    },
    {
        "device": "/device2",
        "mount": "/boot"
    },
    {
        "device": "/device2",
        "mount": "/bar"
    },
    {
        "device": "/device3",
        "mount": "/foo"
    }
]

因此,我需要构建一个在此示例中失败的任务,因为'/''/home'都安装在'/device1'上(并且我们并不关心'/bar''/device2'一样安装在'/boot'上,因为'/bar'不在输入列表中。

我想出了以下元素:一个以设备为键,所有相关的坐骑为值的字典:

"filesystems_by_device": {
    "/device1": [
        "/",
        "/home"
    ],
    "/device2": [
        "/boot",
        "/bar"
    ],
    "/device3": [
        "/foo"
    ]
}

还有一个以mount为键,设备为值的字典(它确实可以是单个值而不是列表):

"filesystems_by_mount": {
    "/": [
        "/device1"
    ],
    "/home": [
        "/device1"
    ],
    "/boot": [
        "/device2"
    ],
    "/bar": [
        "/device2"
    ],
    "/foo": [
        "/device3"
    ]
}

我不知道如何混合这些数据来构建适当的任务。我已经尝试了几种解决方案,进行了很多测试,但是现在我需要重新审视这个问题。我迷失了这种语法。

任何帮助表示赞赏

注意:这可以轻松地以静态方式完成,也可以通过相应模块调用的bash脚本轻松完成,但是我真的想避免这种情况,并保持这种“动态”的方式进行

2 个答案:

答案 0 :(得分:1)

您有安装列表。这个有length个X挂接,您要检查。

您有一本字典,其中安装点为键,而相应的设备为值。

从那里,为每个安装点提取设备列表的值(如果是单个字符串,会更容易...),将它们放在展平的列表中,使该列表唯一,并获取其长度。如果此列表的长度与安装点的长度不同,则您将使任务失败。

一个例子总是比漫长的演讲更好:

- name: Fail if my mounts are not on separate devices
  vars:
    mount_num: "{{ mounts | length }}"
    mount_devices: "{{ mounts | map('extract', filesystems_by_mount) | list | flatten | unique }}"
    device_num: "{{ mount_devices | length }}"
  fail:
    msg: "Two or more mount are on the same device"
  when: mount_num != device_num

答案 1 :(得分:1)

Q:“输入列表中的安装都安装在不同的设备上...失败,因为'/'和'/ home'都安装在'/ device1'上。”

A:下面的任务

    - assert:
        that: my_mounts|intersect(mounts)|length <= 1
        fail_msg: "[ERR] Too many mounts {{ my_mounts }} on {{ item.0 }}"
      loop: "{{ ansible_mounts|groupby('device') }}"
      vars:
        my_mounts: "{{ item.1|map(attribute='mount')|list }}"

给予(删节)

failed: ...

  ansible_loop_var: item
  assertion: my_mounts|intersect(mounts)|length <= 1
  evaluated_to: false
  item:
  - /device1
  - - device: /device1
      mount: /
    - device: /device1
      mount: /home
  msg: '[ERR] Too many mounts [''/'', ''/home''] on /device1'

  ansible_loop_var: item
  item:
  - /device2
  - - device: /device2
      mount: /boot
    - device: /device2
      mount: /bar
  msg: All assertions passed

  ansible_loop_var: item
  item:
  - /device3
  - - device: /device3
      mount: /foo
  msg: All assertions passed
相关问题