使用vars_prompt和with_sequence的Ansible循环

时间:2019-01-02 10:52:50

标签: ansible

我有一个问题,我们可以使用vars_prompt传递一系列输入吗? 我们可以实现with_sequence

示例: 从下面的剧本中,我可以传递多个端口号,并用“,”分隔。

prompt: Please enter the port name: 0/1,0/2,0/3,0/4,0/5

但是当我想传递某个范围内的端口输入时。

prompt: Please enter the port name: 0/1-0/5

我们是否可以选择如何运行,是否可以与嵌套循环一起使用

- hosts: localhost
  gather_facts: no
  vars_prompt:
  - name: port_name
    prompt: Please enter the port name
    private: no

  tasks:
  - add_host:
      name: "{{port_name}}"
      groups: dynamically_created_hosts
    with_items: "{{port_name.split(',')}}" 
  - name: Change port speed
    port_speed_change:
      switch_ip: "{{ip_address}}"
      user: "{{user}}"
      password: "{{password}}"
      checkmode: "{{ansible_check_mode}}"
      name: "{{items}}"
      speed: "{{port_speed}}"

1 个答案:

答案 0 :(得分:0)

我认为直接使用库是不可能的,但是,您可以通过多种方式实现目标,一种方式是使用列表和循环。

请考虑输入中的两个元素:

I1/S1-I2/S2

I=Interface S=Subport

为实现此目的而没有错误,必须运行3个循环:

  1. I1/S1 to I1/S_Max的列表中添加元素
  2. 添加I_middle/0 to I_middle/S_Max中的中间元素
  3. 添加最后一个元素I2/0 to I2/S2

首先收集port_name变量,尊重输入字符串的sinxtax确实很重要:

- name: port_name
  prompt: Please enter port name (format X/Y-X/Z, e.g 0/1-0/5)
  private: no

创建第一个循环:

####1st cycle, first port first sub_loop
#1st sub_loop, first entry subport to maximum subport
    - set_fact: port_sub_loop={{port_sub_loop|default([]) | union([item]) }}
      with_sequence: start="{{ S1 }}" end="{{ S_MAX }}"

    - name: Add first elements (first interface, first sub_loop)
      set_fact: ports="{{ ports|default([]) | union([item.0+'/'+item.1]) }}"
      with_nested:
        - "{{ I1 }}"
        - "{{ port_sub_loop }}"

第二个块很棘手,因为它必须在I1 >= I2 -2情况下转义,因此不能在循环中使用when条件,因此我决定将block与{{1} }:

rescue

最后一个####2nd cycle, middle elements, subports are from 0 to S_MAX... There is a rescue because you cannot add a condition "with_sequence", in case I1 >= I2 -2 it will continue with rescue #Set port interfaces loop ignoring first and last port - name: run middle loop block: - set_fact: port_interfaces_middle={{port_interfaces_middle|default([]) | union([item]) }} with_sequence: start="{{ I1|int + 1 }}" end="{{ I2|int - 1 }}" #Set complete port sub_interfaces loop from 0 to S_MAX - set_fact: port_sub={{port_sub|default([]) | union([item]) }} with_sequence: start="0" end="{{ S_MAX }}" # - name: Add middle elements (next ports starting from subport 0) - set_fact: ports="{{ ports|default([]) | union([item.0+'/'+item.1]) }}" with_nested: - "{{ port_interfaces_middle }}" - "{{ port_sub }}" rescue: - debug: msg='Not executed middle block' 的最后一部分添加元素:

I2

最终脚本

#Set last interface sub_loop, from 0 to S2
    - set_fact: port_sub_last={{port_sub_last|default([]) | union([item]) }}
      with_sequence: start="0" end="{{ S2 }}"

    - name: Add last elements (from last_interface)
      set_fact: ports="{{ ports|default([]) | union([item.0+'/'+item.1]) }}"
      with_nested:
        - "{{ I2 }}"
        - "{{ port_sub_last }}"

我不添加 vars_prompt: - name: port_name prompt: Please enter port name (format X/Y-X/Z, e.g 0/1-0/5) private: no tasks: #Get first interface - set_fact: I1={{ port_name | regex_search("^\d+") | int }} #Get second interface - set_fact: I2={{ port_name | regex_search("\-\d+") | regex_replace('^\-', '') | int }} #Get first sub_interface - set_fact: S1={{ port_name | regex_search("\d+\-") | regex_replace('\-$', '') | int }} #Get second sub_interface - set_fact: S2={{ port_name | regex_search("\d+$") | int }} #Set highest/lowest subinterface value - set_fact: S_MAX="{{ S1 if (S1 >= S2) else S2 }}" - set_fact: S_MIN="{{ S1 if (S1 <= S2) else S2 }}" ####1st cycle, first port first sub_loop #1st sub_loop, first entry subport to maximum subport - set_fact: port_sub_loop={{port_sub_loop|default([]) | union([item]) }} with_sequence: start="{{ S1 }}" end="{{ S_MAX }}" - name: Add first elements (first interface, first sub_loop) set_fact: ports="{{ ports|default([]) | union([item.0+'/'+item.1]) }}" with_nested: - "{{ I1 }}" - "{{ port_sub_loop }}" ####2nd cycle, middle elements, subports are from 0 to S_MAX... There is a rescue because you cannot add a condition "with_sequence", in case I1 >= I2 -2 it will continue with rescue #Set port interfaces loop ignoring first and last port - name: run middle loop block: - set_fact: port_interfaces_middle={{port_interfaces_middle|default([]) | union([item]) }} with_sequence: start="{{ I1|int + 1 }}" end="{{ I2|int - 1 }}" #Set complete port sub_interfaces loop from 0 to S_MAX - set_fact: port_sub={{port_sub|default([]) | union([item]) }} with_sequence: start="0" end="{{ S_MAX }}" # - name: Add middle elements (next ports starting from subport 0) - set_fact: ports="{{ ports|default([]) | union([item.0+'/'+item.1]) }}" with_nested: - "{{ port_interfaces_middle }}" - "{{ port_sub }}" rescue: - debug: msg='Not executed middle block' ####3rd cycle, last port until last element #Set last interface sub_loop, from 0 to S2 - set_fact: port_sub_last={{port_sub_last|default([]) | union([item]) }} with_sequence: start="0" end="{{ S2 }}" - name: Add last elements (from last_interface) set_fact: ports="{{ ports|default([]) | union([item.0+'/'+item.1]) }}" with_nested: - "{{ I2 }}" - "{{ port_sub_last }}" - debug: msg="{{ ports }}" ,因为它必须是本地库,我不知道您如何使用它。

致谢