【问题标题】:Create new list from two lists and create "helper" key to match 2 keys从两个列表创建新列表并创建 \"helper\" 键以匹配 2 个键
【发布时间】:2022-11-18 03:18:34
【问题描述】:

奇怪的标题,但问题很复杂。 (如果你知道更好的标题,请不要犹豫,更改标题)

我需要创建一个新列表,其中包含来自其他列表的更改键、来自键的子字符串以检查其他列表的键名称并将这些键子字符串与列表中的另一个键匹配。

我希望当我试图澄清我需要什么时,它会变得清晰。

第一个名为 ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist 的列表输出如下:

{
    "ansible_facts": {
        "ansible_net_virtual-systems": [
            {
                "vsys_zonelist": [
                    "L3_v0123_Zone1",
                    "L3_v0124_Zone2",
                    "L3_v0125_Zone3",
                    "L3_Trans_v0020_Zone4"  
                ]
            }
        ]
    }
}

第二个列表ansible_facts.ansible_net_routing_table

{
    "ansible_facts": {
        "ansible_net_routing_table": [
            {
                "virtual_router": "Internal",
                "destination": "10.12.123.0/24",
                "nexthop": "0.0.0.0",
                "metric": "10",
                "flags": "  Oi  ",
                "age": "3924798",
                "interface": "ae1.123",
                "route_table": "unicast"
            },
            {
                "virtual_router": "Internal",
                "destination": "10.12.124.0/24",
                "nexthop": "0.0.0.0",
                "metric": "10",
                "flags": "  Oi  ",
                "age": "3924798",
                "interface": "ae1.124",
                "route_table": "unicast"
            },
            {
                "virtual_router": "Internal",
                "destination": "10.12.125.0/24",
                "nexthop": "0.0.0.0",
                "metric": "10",
                "flags": "  Oi  ",
                "age": "3924798",
                "interface": "ae1.125",
                "route_table": "unicast"
            },
            {
                "virtual_router": "Internal",
                "destination": "10.12.20.0/24",
                "nexthop": "0.0.0.0",
                "metric": "10",
                "flags": "  Oi  ",
                "age": "3924798",
                "interface": "ae1.20",
                "route_table": "unicast"
            }
        ]
    }
}

现在我有了子串 v0123来自第一个列表和interface:ae1。123来自第二个列表。这意味着他们属于一起。我现在需要第二个列表中的 destination 用于每个匹配列表,并且还更改我从 ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist 获得的名称。

我需要的是:创建一个如下所示的列表:

"interface": "ae1.123"已经不需要了,只是一个匹配一切的帮手)

{
    "result_list": [
        {
            "name": "n-x-123-Zone1",
            "destination": "10.12.123.0/24"
        },
        {
            "name": "n-x-124-Zone2",
            "destination": "10.12.124.0/24"
        },
        {
            "name": "n-x-125-Zone3",
            "destination": "10.12.125.0/24"
        },
        {
            "name": "n-x-20-Zone4",
            "destination": "10.12.20.0/24"
        }
    ]
}

我尝试了很多不同的方法,但不知何故我无法让它工作,因为我所做的一切都没有帮助我创建我需要的列表。

我已经尝试过的一些输入:

- name: DEBUG list with split and loop
  ansible.builtin.debug:
    # creates
    # n-x-01-Name
    # but no list(!), just messages, but could be useful to create a loop
    msg: "n-x-{% if item.split('_')[1].startswith('Client') %}{{ item[3:100] }}{% else %}{{ item.split('_')[1] | regex_replace('v','') }}-{% endif %}{% if item.split('_')[2] is defined and item.split('_')[2].startswith('Trans') %}{{ item[3:50] }}{% elif item.split('_')[1].startswith('Clients')%}{% else %}{{ item[9:100] | default('') }}{% endif %}"
  loop: '{{ ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist }}'
  delegate_to: 127.0.0.1

- name: create extract_interface
  ansible.builtin.set_fact:
    # creates (also see next task) 
    # {
    #   {
    #     "interface": "ae1.123"
    #   },
    #   {
    #     "interface": "ae1.124"
    #   }
    # }
    extract_interface: "{{ ansible_facts.ansible_net_routing_table | map(attribute='interface') | map('community.general.dict_kv', 'interface') | list }}"
  delegate_to: 127.0.0.1

- name: create map_destination_to_interface
  ansible.builtin.set_fact:
    # {
    #   "ae1.123": "10.12.123.0/24",
    #   "ae1.124": "10.12.124.0/24"
    # }
    map_destination_to_interface: "{{ ansible_facts.ansible_net_routing_table | zip(extract_interface) | map('combine') | items2dict(key_name='interface', value_name='destination') }}"
  delegate_to: 127.0.0.1

也许有人可以理解需要什么。提前感谢大家!

【问题讨论】:

    标签: python ansible jinja2 ansible-facts


    【解决方案1】:

    你已经用 python 标记了这个问题,所以我将用 python 回答。

    一些字符串操作和几个循环可以提取您需要的内容。

    # not needed, but nice for printing out the result
    import json
    
    
    ansible_facts = {
        "ansible_facts": {
            "ansible_net_virtual-systems": [
                {
                    "vsys_zonelist": [
                        "L3_v0123_Zone1",
                        "L3_v0124_Zone2",
                        "L3_v0125_Zone3",
                        "L3_Trans_v0020_Zone4",
                    ]
                }
            ],
            "ansible_net_routing_table": [
                {
                    "virtual_router": "Internal",
                    "destination": "10.12.123.0/24",
                    "nexthop": "0.0.0.0",
                    "metric": "10",
                    "flags": "  Oi  ",
                    "age": "3924798",
                    "interface": "ae1.123",
                    "route_table": "unicast",
                },
                {
                    "virtual_router": "Internal",
                    "destination": "10.12.124.0/24",
                    "nexthop": "0.0.0.0",
                    "metric": "10",
                    "flags": "  Oi  ",
                    "age": "3924798",
                    "interface": "ae1.124",
                    "route_table": "unicast",
                },
                {
                    "virtual_router": "Internal",
                    "destination": "10.12.125.0/24",
                    "nexthop": "0.0.0.0",
                    "metric": "10",
                    "flags": "  Oi  ",
                    "age": "3924798",
                    "interface": "ae1.125",
                    "route_table": "unicast",
                },
                {
                    "virtual_router": "Internal",
                    "destination": "10.12.20.0/24",
                    "nexthop": "0.0.0.0",
                    "metric": "10",
                    "flags": "  Oi  ",
                    "age": "3924798",
                    "interface": "ae1.20",
                    "route_table": "unicast",
                },
            ],
        }
    }
    
    result = {"result_list": []}
    for vs in ansible_facts["ansible_facts"]["ansible_net_virtual-systems"][0]["vsys_zonelist"]:
        # work from the last element as that's the consistent part
        # turn to int to remove leading zeros
        vs_vers = int(vs.split("_")[-2].replace("v", ""))
        for nrt in ansible_facts["ansible_facts"]["ansible_net_routing_table"]:
            nrt_vers = int(nrt["interface"].split(".")[-1])
            # note that the 3rd octet of the destination IP address also seems to be the version
            # you can use that to compare as well, as such:
            # nrt_vers = int(nrt["destination"].split(".")[2])
            if nrt_vers == vs_vers:
                # work from the last element as that's the consistent part
                vs_zone = vs.split("_")[-1]
                # f-strings to turn it into the correct name
                vs_name = f"n-x-{vs_vers}-{vs_zone}"
                nrt_destination = nrt["destination"]
                result["result_list"].append({"name": vs_name, "destination": nrt_destination})
                # break to stop needless iteration
                break 
    
    
    print(json.dumps(result, indent=4))
    

    输出

    {
        "result_list": [
            {
                "name": "n-x-123-Zone1",
                "destination": "10.12.123.0/24"
            },
            {
                "name": "n-x-124-Zone2",
                "destination": "10.12.124.0/24"
            },
            {
                "name": "n-x-125-Zone3",
                "destination": "10.12.125.0/24"
            },
            {
                "name": "n-x-20-Zone4",
                "destination": "10.12.20.0/24"
            }
        ]
    }
    

    【讨论】:

    • 哇谢谢你!现在我需要以某种方式将它转换为 ansible 到 jinja2 :) 你已经知道如何做到这一点了吗?
    【解决方案2】:

    声明变量。压缩列表并创建结构

    lists: "{{ ansible_facts.ansible_net_routing_table|
               zip(ansible_facts['ansible_net_virtual-systems'][0].vsys_zonelist) }}"
    result_list_str: |
      {% for i in lists %}
      {% set arr=i.1|split('_') %}
      - destination: {{ i.0.destination }},
        name: n-x-{{ arr[-2][1:]|int }}-{{ arr[-1] }}
      {% endfor %}
    result_list: "{{ result_list_str|from_yaml }}"
    

    result_list:
      - destination: 10.12.123.0/24
        name: n-x-123-Zone1
      - destination: 10.12.124.0/24
        name: n-x-124-Zone2
      - destination: 10.12.125.0/24
        name: n-x-125-Zone3
      - destination: 10.12.20.0/24
        name: n-x-20-Zone4
    

    用于测试的完整剧本示例

    - hosts: localhost
    
      vars:
    
        ansible_facts:
          ansible_net_routing_table:
          - age: '3924798'
            destination: 10.12.123.0/24
            flags: '  Oi  '
            interface: ae1.123
            metric: '10'
            nexthop: 0.0.0.0
            route_table: unicast
            virtual_router: Internal
          - age: '3924798'
            destination: 10.12.124.0/24
            flags: '  Oi  '
            interface: ae1.124
            metric: '10'
            nexthop: 0.0.0.0
            route_table: unicast
            virtual_router: Internal
          - age: '3924798'
            destination: 10.12.125.0/24
            flags: '  Oi  '
            interface: ae1.125
            metric: '10'
            nexthop: 0.0.0.0
            route_table: unicast
            virtual_router: Internal
          - age: '3924798'
            destination: 10.12.20.0/24
            flags: '  Oi  '
            interface: ae1.20
            metric: '10'
            nexthop: 0.0.0.0
            route_table: unicast
            virtual_router: Internal
          ansible_net_virtual-systems:
          - vsys_zonelist:
            - L3_v0123_Zone1
            - L3_v0124_Zone2
            - L3_v0125_Zone3
            - L3_Trans_v0020_Zone4
    
        lists: "{{ ansible_facts.ansible_net_routing_table|
                   zip(ansible_facts['ansible_net_virtual-systems'][0].vsys_zonelist) }}"
        result_list_str: |
          {% for i in lists %}
          {% set arr=i.1|split('_') %}
          - destination: {{ i.0.destination }}
            name: n-x-{{ arr[-2][1:]|int }}-{{ arr[-1] }}
          {% endfor %}
        result_list: "{{ result_list_str|from_yaml }}"
    
      tasks:
    
        - debug:
            var: result_list
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多