我正在尝试取消挂载所有挂载点,除非它们属于当前列表的一部分:
excluded: ['home', 'cdrom', 'tmpfs', 'sys', 'run', 'dev', 'root']
仅限 fstab 的设备示例:
- /dev/mapper/vgroot-local_home
- devtmpfs
- tmpfs
/dev/mapper/vgroot-local_home
应排除在卸载之外,因为子字符串 home
存在于数组中,对于 devtmpfs
也一样> 子字符串tmpfs
。对于 tmpfs,我们有一个完美的匹配。目标是检查设备。
检查完所有Ansible filters后和 Jinja2 documentation ,我没有找到解决这个问题的方法。所有 Ansible 事实均已收集。
- name: Ensure the mountpoint is on the excluded list
ansible.posix.mount:
path: '{{ mount.device }}'
state: unmounted
when: {{ ??? }}
with_items: '{{ ??? }}'
become: true
tags: mountpoints
最佳答案
为了测试 Jinja 中的字符串是否包含子字符串,我们使用 in
测试,就像 Python 一样:
"somestring" in somevariable
在您的情况下,您想要检查给定字符串是否包含排除
列表中的任何子字符串。从概念上讲,我们想要的是类似 Python 表达式的东西
if any(x in mount.device for x in excluded)
使用 Jinja 过滤器,我们需要稍微颠倒我们的逻辑。我们
可以使用 select
过滤器从
给定目标字符串中包含的排除
列表(例如
mount.device
)像这样:
excluded|select('in', item)
如果item
与excluded
列表中的任何内容匹配,则上面的内容
表达式将产生一个非空列表(其计算结果为true
当在 bool 上下文中使用时)。
在剧本中使用,它看起来像这样:
- hosts: localhost
gather_facts: false
vars:
excluded: ['home', 'cdrom', 'tmpfs', 'sys', 'run', 'dev', 'root']
mounts:
- /dev/mapper/vgroot-local_home
- devtmpfs
- tmpfs
- something/else
tasks:
- debug:
msg: "unmount {{ item }}"
when: not excluded|select('in', item)
loop: "{{ mounts }}"
上面的剧本产生输出:
TASK [debug] *******************************************************************
skipping: [localhost] => (item=/dev/mapper/vgroot-local_home)
skipping: [localhost] => (item=devtmpfs)
skipping: [localhost] => (item=tmpfs)
ok: [localhost] => (item=something/else) => {
"msg": "unmount something/else"
}
也就是说,当当前循环项包含一个时,它会跳过任务
排除
列表中的子字符串。
假设您的目标是“卸载除以下文件系统之外的所有文件系统”
其中设备名称包含排除
列表中的子字符串”,
你可能会写:
- name: Unmount filesystems that aren't excluded
ansible.posix.mount:
path: '{{ mount.device }}'
state: unmounted
when: not excluded|select('in', item.device)
loop: "{{ ansible_mounts }}"
become: true
tags: mountpoints
关于ansible - Ansible 和/或 Jinja2 中的子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72346000/