首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不可用的嵌套循环和条件组合在同一个任务中。

不可用的嵌套循环和条件组合在同一个任务中。
EN

Stack Overflow用户
提问于 2019-12-06 11:02:55
回答 2查看 2.9K关注 0票数 1
代码语言:javascript
复制
---

    - 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"

  • )收集输出,我想循环遍历"customer“列表,并检查"inventory_hostname”是否在该

中列出。

我想我可以用以下方法来完成这个任务:when: inventory_hostname in item.1.sap

如果上面的检查为真,我希望在第一个任务的stdout和fact3之间进行regex比较,如果第一个任务的stdout中没有regex,则引发失败:

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做这件事?我做错什么了?

为了确保我的意图是明确的:

通过客户列表中的项目循环,通过每个customer

  • make中的服务列表中的项目来检查。1. has有一个与inventory_hostname

  • if匹配的键,上面的检查是真的,比较上面的regex模式和第一个任务的输出。

/vars/all.yml如下所示:

代码语言:javascript
复制
    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:

致命:叶-1:失败!=> { "msg":“任务包含一个带有未定义变量的选项。错误是:'fact1‘是未定义的\n\n,错误出现在’/迷走区/Ansible文件夹fact1第23行,第7列,但可能\n在文件的其他地方,这取决于确切的语法问题。\n\n,违规行似乎是:\n\n\n-名称:比较vlan_id(.*)端口和vlan_db\n ^ here\n“}

代码语言:javascript
复制
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-07 14:38:34

这里有几个问题。

首先,您的剧本在语法上是无效的:它根本无法运行。如果出现错误,它将失败:

代码语言:javascript
复制
ERROR! unexpected parameter type in action: <class 'ansible.parsing.yaml.objects.AnsibleSequence'>

这是因为set_fact的内容应该是字典,而不是列表:

代码语言:javascript
复制
- 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)的条件永远不会正确匹配。如果要使用该表达式的值,则需要将该值公开为变量。

但在我们看这个之前,还有另外一个问题:当你写:

代码语言:javascript
复制
fact2: "{{ item.1.sap.inventory_hostname | join(', ') }}"

您要在inventory_hostname字典中查找一个名为“sap”的文字键。请记住,当您编写foo.bar.baz时,这实际上是foo["bar"]["baz"]的缩写。相反,你需要:

代码语言:javascript
复制
fact2: "{{ item.1.sap[inventory_hostname] | join(', ') }}"

所以,回到变量。如果您想在条件中使用fact3的值,有几种方法可以做到这一点。一种选择是在任务上使用vars块,这将创建任务持续时间内存在的新变量。我在这里使用了一个debug任务来演示正在发生的事情;如果在任务完成后需要持久化一些或所有这些变量,显然可以用set_fact任务替换它:

代码语言:javascript
复制
    - 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
EN

Stack Overflow用户

发布于 2019-12-07 16:01:16

谢谢各位。经过一番努力,我才能用下面的游戏达到我的目标。我还必须更改failed_when语法。

代码语言:javascript
复制
- 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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59211880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档