ansible - Ansible 嵌套循环和条件一起在同一个任务中
问题描述
---
- hosts: leaf-1, leaf-2
vars_files:
- /vars/all.yml
tasks:
- name: collect the vlan databse
raw: "show vlan brief"
register: vlan_db
- name: compare vlan_id(.*)Ports against the vlan_db
set_fact:
fact1: "{{ item.1.vlan_id }}"
fact2: "{{ item.1.sap.inventory_hostname | join(', ') }}"
fact3: "{{ fact1 }}(.*){{ fact2 }}"
failed_when: not vlan_db.stdout is regex(fact3)
when: inventory_hostname in item.1.sap
with_subelements:
- "{{ customers }}"
- services
我从开关收集输出
我想遍历“customer”列表并检查“inventory_hostname”是否列在“services.sap”中
我想我可以通过以下方式做到这一点:
when: inventory_hostname in item.1.sap
如果上述检查为真,我想在 fact3 和第一个任务的标准输出之间进行正则表达式比较,如果第一个任务的标准输出中不存在正则表达式,则引发失败:
set_fact: fact1: "{{ item.1.vlan_id }}" fact2: "{{ item.1.sap.inventory_hostname | join(', ') }}" fact3: "{{ fact1 }}(.*){{ fact2 }}" failed_when: not vlan_db.stdout is regex(fact3)
这就像嵌套循环和条件在一起。有没有办法用 Ansible 做到这一点?我做错了什么?
只是为了确保我的意图是明确的:
- 遍历客户列表中的项目
- 遍历每个客户的服务列表中的项目
- 检查 item.1.sap 是否有与 inventory_hostname 匹配的键
- 如果上述检查为真,请在上面的正则表达式模式和第一个任务的输出之间进行比较。
/vars/all.yml 看起来像这样:
customers:
- name: "cust-1"
l3_vni: "101"
services:
- vlan_id: "10"
vni: "1010"
gw: "10.0.0.254/24"
sap:
leaf-1: ["Eth3"]
leaf-2: ["Eth3"]
- vlan_id: "11"
vni: "1011"
gw: "10.0.1.254/24"
sap:
leaf-1: ["Eth3"]
leaf-2: ["Eth3"]
- name: "cust-2"
l3_vni: "102"
services:
- vlan_id: "20"
vni: "1020"
gw: "20.0.0.254/24"
sap:
leaf-3: ["Eth3", "Eth4"]
leaf-4: ["Eth3"]
- vlan_id: "21"
vni: "1021"
gw: "20.0.1.254/24"
sap:
leaf-3: ["Eth3"]
leaf-4: ["Eth3"]
```
a switch vlan database usually looks like this:
```
leaf-1#show vlan brief
VLAN Name Status Ports
---- -------------------------------- --------- ----------------------
1 default active Eth5
10 cust-1 active Eth3, Eth4
20 cust-2 active Eth1, Eth2
```
error log:
致命的:[leaf-1]:失败!=> { "msg": "该任务包含一个带有未定义变量的选项。错误是:'fact1' 未定义\n\n错误似乎在 '/vagrant/Ansible Folder Setup/NetAutHardWay/Step4-CICD/ vlan_test.yml':第 23 行,第 7 列,但可能\n位于文件中的其他位置,具体取决于确切的语法问题。\n\n违规行似乎是:\n\n\n - 名称:比较 vlan_id(.* )针对 vlan_db 的端口\n ^ here\n" }
解决方案
这里有几个问题。
首先,您的剧本在语法上是无效的:它根本无法运行。它将失败并出现以下错误:
ERROR! unexpected parameter type in action: <class 'ansible.parsing.yaml.objects.AnsibleSequence'>
这是因为 的内容set_fact
应该是字典,而不是列表:
- name: "compare vlan_id(.*)Ports against the vlan_db"
set_fact:
fact1: "{{ item.1.vlan_id }}"
fact2: "{{ item.1.sap.inventory_hostname | join(', ') }}"
fact3: "{{ fact1 }}(.*){{ fact2 }}"
failed_when: not vlan_db.stdout is regex(fact3)
when: inventory_hostname in item.1.sap
with_subelements:
- "{{ customers }}"
- services
但是,您在这里遇到了另一个问题:您的事实在任务运行之后才可用set_fact
,因此您正在检查的条件is regex(fact3)
永远不会正确匹配。如果要使用该表达式的值,则需要将该值公开为变量。
但在我们看之前,还有另一个问题:当你写:
fact2: "{{ item.1.sap.inventory_hostname | join(', ') }}"
sap
您正在字典中查找名为“inventory_hostname”的文字键。请记住,当您编写 时foo.bar.baz
,这实际上是 . 的简写foo["bar"]["baz"]
。你需要:
fact2: "{{ item.1.sap[inventory_hostname] | join(', ') }}"
所以,回到变量。如果您想fact3
在条件中使用 的值,有几种方法可以做到这一点。一种选择是在您的任务上使用一个vars
块,它会创建在任务期间存在的新变量。我在这里使用了一个debug
任务来演示正在发生的事情;set_fact
如果您需要在任务完成后保留部分或全部这些变量,您显然可以用任务替换它:
- name: "compare vlan_id(.*)Ports against the vlan_db"
debug:
msg:
- "{{ fact1 }}"
- "{{ fact2 }}"
- "{{ fact3 }}"
vars:
fact1: "{{ item.1.vlan_id }}"
fact2: "{{ item.1.sap[inventory_hostname] | join(', ') }}"
fact3: "{{ fact1 }}(.*){{ fact2 }}"
failed_when: not vlan_db.stdout is regex(fact3)
when: inventory_hostname in item.1.sap
with_subelements:
- "{{ customers }}"
- services
希望这足以为您指明正确的方向。让我知道我是否可以澄清任何事情。
推荐阅读
- python - 如何在熊猫中按函数获取平均值
- python - 现在获得UTC的非天真(感知)日期时间的最简单方法是什么?
- python - matplotlib:如何在 0 到 255 的绝对灰度上绘制图像
- java - Docker Image 未正确启动
- cplex - 如何获得每个节点上所有小数变量的界限
- python-3.x - Scrapy 无法使用 Python 3 发布二进制正文
- reactjs - 如何使用本机反应在选项卡之外导航?
- jenkins-pipeline - 推荐jFrog神器/包
- windows - RC 文件信息:语言中性
- python - 跳过 matplotlib 中连接的第一个和最后一个点