首页 > 解决方案 > JSON 操作 - 过滤器和行内联

问题描述

我专注于 Ansible 将一些 F5 集成到 devops 管道中,到目前为止一切都很好,除了一件事。

如果我使用以下代码将一些 vlan 分配给来宾:

- name: Assign VLANS to vCMP Guest 
  bigip_vcmp_guest:
    name: "{{ item.vcmp_name }}"
    vlans: "{{ item.vcmp_vlans }}"
    provider: "{{ var_provider }}"
  delegate_to: localhost
  loop: "{{ vcmp }}"
  when: vcmp is defined

它会替换所有的 vlan,并且只保留新添加的。

所以我决定从这个配置中收集 vlan 信息,将其复制到一个文件中,附加列表,然后重新推送所有 vlan。这是我为此建立的角色:

- name: Create F5 VLAN File
  file:
    dest: ./roles/facts/vars/f5vlans.yml
    state: touch
  delegate_to: localhost
  when: facts_vcmp_vlan is defined
- name: Create VLAN List
  lineinfile:
    dest: ./roles/facts/vars/f5vlans.yml
    line: "vlan_list:"
    insertafter: EOF
  delegate_to: localhost
  when: facts_vcmp_vlan is defined
- name: Collect BIG-IP vCMP facts
  bigip_device_facts:
    gather_subset:
      - vcmp-guests
    provider: "{{ var_provider }}"
  delegate_to: localhost
  register: gathered_vlans
  when: facts_vcmp_vlan is defined
- name: Debug
  debug:
    msg: "{{ gathered_vlans }}"
- name: Appened Existing VLANs to List
  lineinfile:
    dest: ./roles/facts/vars/f5vlans.yml
    line: "- {{ item.vcmp_guests }} "
    insertafter: EOF
  delegate_to: localhost
  with_items: "{{ gathered_vlans }}"
  when: facts_vcmp_vlan is defined
ok: [device] => {
    "msg": {
        "changed": false,
        "failed": false,
        "queried": true,
        "vcmp_guests": [
                        {
                "allowed_slots": [
                    0
                ],
                "assigned_slots": [
                    0
                ],
                "boot_priority": 65535,
                "cores_per_slot": 2,
                "full_path": "name1",
                "hostname": "value",
                "hotfix_image": "value",
                "initial_image": "value",
                "mgmt_address": "subnet/24",
                "mgmt_network": "IP",
                "mgmt_route": "value",
                "min_number_of_slots": 1,
                "name": "name1",
                "number_of_slots": 1,
                "ssl_mode": "value",
                "state": "value",
                "virtual_disk": "value",
                "vlans": [
                    "vlan100",
                    "vlan101",
                    "vlan102"
                ]
            },
                        {
                "allowed_slots": [
                    0
                ],
                "assigned_slots": [
                    0
                ],
                "boot_priority": 65535,
                "cores_per_slot": 2,
                "full_path": "name2",
                "hostname": "value",
                "hotfix_image": "value",
                "initial_image": "value",
                "mgmt_address": "subnet/24",
                "mgmt_network": "IP",
                "mgmt_route": "value",
                "min_number_of_slots": 1,
                "name": "name2",
                "number_of_slots": 1,
                "ssl_mode": "value",
                "state": "value",
                "virtual_disk": "value",
                "vlans": [
                    "vlan200",
                    "vlan201",
                    "vlan202"
                ]
            },
            {
                "allowed_slots": [
                    0
                ],
                "assigned_slots": [
                    0
                ],
                "boot_priority": 65535,
                "cores_per_slot": 2,
                "full_path": "name3",
                "hostname": "value",
                "hotfix_image": "value",
                "initial_image": "value",
                "mgmt_address": "subnet/24",
                "mgmt_network": "IP",
                "mgmt_route": "value",
                "min_number_of_slots": 1,
                "name": "name3",
                "number_of_slots": 1,
                "ssl_mode": "value",
                "state": "value",
                "virtual_disk": "value",
                "vlans": [
                    "vlan300",
                    "vlan301",
                    "vlan302"
                ]
            }
        ]
    }
}

我的目标是仅使用分配给name: name2的 vlan。所以在我的文件后面加上:

标签: ansible

解决方案


您可以为此使用json_queryJMESPath查询语言

您甚至不需要在这里循环,因为 Ansible 可以将列表转储为带有过滤器的 YAML,例如to_nice_yaml. 而且,......老实说,你甚至不需要一个临时文件,如果这是你在这里实现的(更多关于答案的结尾)。

鉴于剧本:

- hosts: all
  gather_facts: no

  tasks:
    - blockinfile:
        dest: ./roles/facts/vars/f5vlans.yml
        block: >-
          {{ 
            gathered_vlans 
            | json_query('vcmp_guests[?name==`name2`].vlans []') 
            | to_nice_yaml 
          }}
      vars:
        gathered_vlans:
          changed: false
          failed: false
          queried: true
          vcmp_guests:
          - allowed_slots:
            - 0
            assigned_slots:
            - 0
            boot_priority: 65535
            cores_per_slot: 2
            full_path: name1
            hostname: value
            hotfix_image: value
            initial_image: value
            mgmt_address: subnet/24
            mgmt_network: IP
            mgmt_route: value
            min_number_of_slots: 1
            name: name1
            number_of_slots: 1
            ssl_mode: value
            state: value
            virtual_disk: value
            vlans:
            - vlan100
            - vlan101
            - vlan102
          - allowed_slots:
            - 0
            assigned_slots:
            - 0
            boot_priority: 65535
            cores_per_slot: 2
            full_path: name2
            hostname: value
            hotfix_image: value
            initial_image: value
            mgmt_address: subnet/24
            mgmt_network: IP
            mgmt_route: value
            min_number_of_slots: 1
            name: name2
            number_of_slots: 1
            ssl_mode: value
            state: value
            virtual_disk: value
            vlans:
            - vlan200
            - vlan201
            - vlan202
          - allowed_slots:
            - 0
            assigned_slots:
            - 0
            boot_priority: 65535
            cores_per_slot: 2
            full_path: name3
            hostname: value
            hotfix_image: value
            initial_image: value
            mgmt_address: subnet/24
            mgmt_network: IP
            mgmt_route: value
            min_number_of_slots: 1
            name: name3
            number_of_slots: 1
            ssl_mode: value
            state: value
            virtual_disk: value
            vlans:
            - vlan300
            - vlan301
            - vlan302

和文件角色/事实/vars/f5vlans.yml

- vlan-dummy-1
- vlan-dummy-2

这将在文件roles/facts/vars/f5vlans.yml中结束,其中包含:

- vlan-dummy-1
- vlan-dummy-2
# BEGIN ANSIBLE MANAGED BLOCK
- vlan200
- vlan201
- vlan202
# END ANSIBLE MANAGED BLOCK

没有临时文件,这个剧本,在vlan_to_add字典键中保存新的 VLAN:

- hosts: all
  gather_facts: no

  tasks:
    - debug:
        msg:
          vlan_list: >-
            {{ 
              vlan_to_add + gathered_vlans 
              | json_query('vcmp_guests[?name==`name2`].vlans []') 
            }}
      vars:
        vlan_to_add:
          - dummy-vlan-1
          - dummy-vlan-2
        gathered_vlans:
          changed: false
          failed: false
          queried: true
          vcmp_guests:
          - allowed_slots:
            - 0
            assigned_slots:
            - 0
            boot_priority: 65535
            cores_per_slot: 2
            full_path: name1
            hostname: value
            hotfix_image: value
            initial_image: value
            mgmt_address: subnet/24
            mgmt_network: IP
            mgmt_route: value
            min_number_of_slots: 1
            name: name1
            number_of_slots: 1
            ssl_mode: value
            state: value
            virtual_disk: value
            vlans:
            - vlan100
            - vlan101
            - vlan102
          - allowed_slots:
            - 0
            assigned_slots:
            - 0
            boot_priority: 65535
            cores_per_slot: 2
            full_path: name2
            hostname: value
            hotfix_image: value
            initial_image: value
            mgmt_address: subnet/24
            mgmt_network: IP
            mgmt_route: value
            min_number_of_slots: 1
            name: name2
            number_of_slots: 1
            ssl_mode: value
            state: value
            virtual_disk: value
            vlans:
            - vlan200
            - vlan201
            - vlan202
          - allowed_slots:
            - 0
            assigned_slots:
            - 0
            boot_priority: 65535
            cores_per_slot: 2
            full_path: name3
            hostname: value
            hotfix_image: value
            initial_image: value
            mgmt_address: subnet/24
            mgmt_network: IP
            mgmt_route: value
            min_number_of_slots: 1
            name: name3
            number_of_slots: 1
            ssl_mode: value
            state: value
            virtual_disk: value
            vlans:
            - vlan300
            - vlan301
            - vlan302

会产生:

PLAY [all] **********************************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "msg": {
        "vlan_list": [
            "dummy-vlan-1",
            "dummy-vlan-2",
            "vlan200",
            "vlan201",
            "vlan202"
        ]
    }
}

PLAY RECAP **********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

推荐阅读