---
- 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
我从交换机收集输出
我想遍历“客户”列表,并检查“ services.sap”中是否列出了“ inventory_hostname”
我认为我可以通过以下方法做到这一点:
when: inventory_hostname in item.1.sap
如果以上检查为真,则我想在事实3和第一个任务的标准输出之间进行正则表达式比较,如果第一个任务的标准输出中不存在正则表达式,则会引发失败:
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做到这一点? 我在做什么错了?
只是要确保我的意图明确:
/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 ^这里\ n“
}
答案 0 :(得分:1)
这里有几个问题。
首先,您的剧本在语法上无效:它根本不会运行。它将失败并显示错误:
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
希望这足以指导您正确的方向。让我知道是否可以澄清任何事情。
答案 1 :(得分:0)
感谢幼虫。经过一番挣扎,我得以通过以下比赛实现自己的目标。 我还必须更改failed_when语法。
- hosts: leaf-1
gather_facts: no
tags: [ verify ]
vars_files:
- ../Step2-config/roles/services_config/vars/main.yml
tasks:
- name: collect the vlan databse
raw: "show vlan brief"
register: vlan_db
- debug:
var: vlan_db.stdout
var: inventory_hostname, vlan_db
- name: compare vlan_id(.*)Ports against the vlan_db
set_fact:
fact1: "{{ item.1.vlan_id }}"
fact2: "{{ item.0.name }}"
fact3: "{{ item.1.sap[inventory_hostname] | join('.*')}}"
when: "inventory_hostname in item.1.sap"
failed_when: not vlan_db.stdout_lines is regex(fact1 + '.*' + fact2 + '.*' + fact3)
with_subelements:
- "{{ customers }}"
- services