【问题标题】:Append a string to a List in Ansible将字符串附加到 Ansible 中的列表
【发布时间】:2022-05-05 13:48:34
【问题描述】:

我正在尝试将字符串附加到 ansible 中的列表,所以基本上我将构建一个有效负载以删除 F5 GTM 网络设备中的一些拓扑记录。

我能够创建一个列表,其中包括相应拓扑记录的所有输出。对于输出的每一行,我需要附加一个字符串“删除”。

- name: Lookup Topology Records  
  bigip_command:
    user: admin
    password: password
    server: gtm.abc.com
    commands: "list gtm topology | grep -i '{{ item }}'"
    warn: no
    validate_certs: no
  register: topology_info
  delegate_to: localhost
  loop: "{{ gtm_pool }}"
  
- debug: var=topology_info
 
- name: Sanitize the Topology records of the Pool
  set_fact:
    clean_topology_info: "{{ clean_topology_info | default ([]) + item.stdout_lines  }}"
  loop: "{{ topology_info.results }}"
  
- debug: var=clean_topology_info
 
 
- name: Sanitized Topology Info
  vars:
    topology_item: "{{ item }}"
   set_fact:
     sanitized_topology_info: "{{ sanitized_topology_info | default ([]) + topology_item }}"
  loop: "{{ clean_topology_info }}"
  
- name: Build payload to delete the Topology Record
  set_fact:
    topology_payload: "{{ topology_payload | default([]) + ['delete'] + item }}"
  loop: "{{ clean_topology_info }}"
  
- debug: var=topology_payload

------------------------------------------------------------
Debug outputs(stdout_lines) as below :-

"gtm_pool": [
        "test-poo1", 
        "test-pool2"
    ]

debug of "topology_info" :-

"stdout_lines": [
                    [
                        "gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/test-pool1 {", 
                        "gtm topology ldns: subnet 10.8.22.0/24 server: pool /Common/test-pool1 {"
                    ]
                ]

"stdout_lines": [
                    [
                        "gtm topology ldns: subnet 0.0.0.0/0 server: pool /Common/test-pool2 {"
                    ]


debug of "clean_topology_info":-

"clean_topology_info": [
        [
                        "gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/test-pool1 {", 
                        "gtm topology ldns: subnet 10.8.22.0/24 server: pool /Common/test-pool1 {", 
        ], 
        [
            "gtm topology ldns: subnet 0.0.0.0/0 server: pool /Common/test-pool2 {",
        ]
    ]

debug of "sanitized_topology_info":-

"sanitized_topology_info": [
             "gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/test-pool1 {", 
                        "gtm topology ldns: subnet 10.8.22.0/24 server: pool /Common/test-pool1 {", 
           "gtm topology ldns: subnet 0.0.0.0/0 server: pool /Common/test-pool2 {"
        ]



debug of "topology_payload":-

"topology_payload": [
        "delete", 
        "gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/test-pool1 {", 
                        "gtm topology ldns: subnet 10.8.22.0/24 server: pool /Common/test-pool1 {",  
        "delete", 
       "gtm topology ldns: subnet 0.0.0.0/0 server: pool /Common/test-pool2 {"
    ]


Expected output of topology_payload should be like :-

Basically i need to append a string 'delete' infront of the each output.

"topology_payload": [ 
        "delete gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/test-pool1 {", 
                        "delete gtm topology ldns: subnet 10.8.22.0/24 server: pool /Common/test-pool1 {",  
       "delete gtm topology ldns: subnet 0.0.0.0/0 server: pool /Common/test-pool2 {"
    ]

topology_payload 的预期输出应该是这样的:-

基本上我需要在每个输出前面附加一个字符串“删除”。

topology_payload:
  - "delete gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/test-pool1"
  - "delete gtm topology ldns: subnet 10.8.22.0/24 server: pool /Common/test-pool1"
  - "delete gtm topology ldns: subnet 0.0.0.0/0 server: pool /Common/test-pool2"

【问题讨论】:

    标签: ansible


    【解决方案1】:

    问:“在每个项目前面添加一个字符串 'delete'。”

    A:这就是你looking for

    - hosts: localhost
      vars:
        info: ['a', 'b', 'c']
      tasks:
        - set_fact:
            payload: "{{ payload|default([]) + ['delete ' ~ item] }}"
          loop: "{{ info }}"
        - debug:
            var: payload
    

    给予(删节)

    payload:
      - delete a
      - delete b
      - delete c
    

    无需迭代也可以达到相同的结果(信用@Romain DEQUIDT)

    - hosts: localhost
      vars:
        info: ['a', 'b', 'c']
        payload: "{{ ['delete']|product(info)|map('join', ' ')|list }}"
      tasks:
        - debug:
            var: payload
    

    问:“在每个以'gtm topology' 开头的输出前添加一个字符串'delete'。”

    A:使用测试search

    - hosts: localhost
      gather_facts: false
      vars:
        info: ['a', 'gtm topology', 'c']
      tasks:
        - set_fact:
            payload: "{{ payload|default([]) + ['delete ' ~ item] }}"
          loop: "{{ info }}"
          when: item is search('^gtm topology')
        - debug:
            var: payload
    

    给予(删节)

    payload:
      - delete gtm topology
    

    不用迭代也能达到同样的效果

    - hosts: localhost
      vars:
        info: ['a', 'gtm topology', 'c']
        info_gtm_topology: "{{ info|select('search', '^gtm topology') }}"
        payload: "{{ ['delete']|product(info_gtm_topology)|map('join', ' ')|list }}"
      tasks:
        - debug:
            var: payload
    

    问:“除上述条件外,处理列表直到找到'test-pool1'。”

    A:使用测试search也可以找到最后一项的索引

      hosts: localhost
      vars:
        info: ['a', 'gtm topology 1', 'c', 'test-pool1', 'gtm topology 2', 'd']
        stop_regex: '.*pool1.*'
        stop_items: "{{ info|select('search', stop_regex) }}"
        stop_index: "{{ info.index(stop_items.0) }}"
      tasks:
        - set_fact:
            payload: "{{ payload|default([]) + ['delete ' ~ item] }}"
          loop: "{{ info[:stop_index|int] }}"
          when: item is search('^gtm topology')
        - debug:
            var: payload
    

    给予(删节)

    payload:
      - delete gtm topology 1
    

    不用迭代也能达到同样的效果

    - hosts: localhost
      vars:
        info: ['a', 'gtm topology 1', 'c', 'test-pool1', 'gtm topology 2', 'd']
        stop_regex: '.*pool1.*'
        stop_items: "{{ info|select('search', stop_regex) }}"
        stop_index: "{{ info.index(stop_items.0) }}"
        info_gtm_topology: "{{ info[:stop_index|int]|select('search', '^gtm topology') }}"
        payload: "{{ ['delete']|product(info_gtm_topology)|map('join', ' ')|list }}"
      tasks:
        - debug:
            var: payload
    

    附带说明,您可以创建自定义过滤器。见filter_plugins

    shell> cat filter_plugins/list_search.py 
    import re
    
    
    def list_search(l, x):
        r = re.compile(x)
        return list(filter(r.match, l))
    
    
    def list_index(l, x, *i):
        if len(i) == 0:
            return l.index(x) if x in l else -1
        elif len(i) == 1:
            return l.index(x, i[0]) if x in l[i[0]:] else -1
        else:
            return l.index(x, i[0], i[1]) if x in l[i[0]:i[1]] else -1
    
    
    class FilterModule(object):
        ''' Ansible filters for operating on lists '''
    
        def filters(self):
            return {
                'list_index': list_index,
                'list_search': list_search,
            }
    

    下面的戏

    - hosts: localhost
      vars:
        info: ['a', 'gtm topology 1', 'c', 'test-pool1', 'gtm topology 2', 'd']
        stop_regex: '.*pool1.*'
        stop_items: "{{ info|list_search(stop_regex) }}"
        stop_index: "{{ info|list_index(stop_items.0) }}"
        info_gtm_topology: "{{ info[:stop_index|int]|select('search', '^gtm topology') }}"
        payload: "{{ ['delete']|product(info_gtm_topology)|map('join', ' ')|list }}"
      tasks:
        - debug:
            var: payload
    

    给出相同的结果

    payload:
      - delete gtm topology 1
    

    【讨论】:

    • 嘿,非常感谢,它运行良好。我的错误是尝试使用其他变量进行循环。
    • 如何删除最后一个 {" ,我可以使用替换过滤器并尝试吗? "topology_payload": [ "delete gtm topology ldns: subnet 10.10.10.0/24 server: pool /Common/ test-pool1 {", "删除 gtm 拓扑 ldns: 子网 10.8.22.0/24 服务器: 池 /Common/test-pool1 {", "删除 gtm 拓扑 ldns: 子网 0.0.0.0/0 服务器: 池 /Common/test- pool2 {" ]
    • 最后一个“{”应该被删除吗?请更新问题并使其最小化。读起来很不错。
    • 对不起,我需要输出到 test-pool1 并且我不需要 {.供您参考“删除 gtm 拓扑 ldns:子网 10.10.10.0/24 服务器:池 /Common/test-pool1 {”
    • 好的让我试试,我们可以使用替换过滤器来实现同样的效果。谢谢!
    【解决方案2】:

    您可以使用product filter 为项目列表添加前缀或后缀:

    ---
    - hosts: localhost
      gather_facts: false
      vars:
          string: "prepend "
          list: ["value1", "value2", "value3"]
      tasks:
        - name: "prefix"
          set_fact:
              prefix_list: "{{ ["prefix_"] | product(list) | map('join') }}"
        - debug:
              msg: "{{ prefix_list }}"
        - name: "suffix"
          set_fact:
              suffix_list: "{{ list | product(["_suffix"]) | map('join') }}"
        - debug:
              msg: "{{ suffix_list }}"
    

    【讨论】:

    • 这是一个更优雅的解决方案,但需要将字符串放入列表中才能正常工作,即["prefix_"]
    【解决方案3】:

    您可以使用map filter 将函数应用于列表中的每个元素。将其与regex_replace 结合使用即可达到您想要的效果:

    ---
    - hosts: localhost
      gather_facts: false
      vars:
          string: "prepend "
          list: ["value1", "value2", "value3"]
      tasks:
        - name: "append string to each element in a list"
          set_fact:
              list: "{{ list | map('regex_replace', '(.*)', '{{ string }}\\1') | list }}"
        - debug:
              msg: "{{ list }}"
    

    【讨论】:

      猜你喜欢
      • 2018-09-13
      • 2012-12-05
      • 2012-09-14
      • 1970-01-01
      • 2016-07-03
      • 2020-06-20
      • 1970-01-01
      • 2012-07-12
      • 2011-01-04
      相关资源
      最近更新 更多