Search code examples
ansible

Restructure data using Ansible


I am trying to use the set_fact module to create a new variable based on data from another variable. I have tried the groupby and lists_mergeby filters with no success.

How can I, from this list:

"myVms": [
        {
            "SubscriptionId": "564aba40-77683-4426-84ac-d195769c826c",
            "VirtualMachine": "K606WS625"
        },
        {
            "SubscriptionId": "564aba40-77683-4426-84ac-d195769c826c",
            "VirtualMachine": "K606WS626"
        },
        {
            "SubscriptionId": "564aba40-77683-4426-84ac-d195769c826c",
            "VirtualMachine": "K606WS812"
        },
        {
            "SubscriptionId": "564aba40-77683-4426-84ac-d195769c826c",
            "VirtualMachine": "K606WS817"
        }
]

Turn it into a new list with a structure like the following?

"myVmsModified": [
    {
        "SubscriptionId": "564aba40-77683-4426-84ac-d195769c826c",
        "MyBeautifulVms": [
            "K606WS817",
            "K606WS812",
            "K606WS626",
            "K606WS625"
        ]
    }
]

Solution

  • The filter lists_mergeby can append lists. Convert the attributes VirtualMachine to lists

     myVmsModified: "{{ myVms | json_query('[].{SubscriptionId: SubscriptionId,
                                                VirtualMachine: [VirtualMachine]}') }}"
    

    gives

      myVmsModified:
        - SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c
          VirtualMachine: [K606WS625]
        - SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c
          VirtualMachine: [K606WS626]
        - SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c
          VirtualMachine: [K606WS812]
        - SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c
          VirtualMachine: [K606WS817]
    

    The filter is designed to merge two or more lists. If you want to merge items in a single list merge it into an empty list

      myVmsModified: "{{ [myVms | json_query('[].{SubscriptionId: SubscriptionId,
                                                  VirtualMachine: [VirtualMachine]}'), []] |
                         community.general.lists_mergeby('SubscriptionId', list_merge='append') }}"
    

    gives what you want

      myVmsModified:
        - SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c
          VirtualMachine: [K606WS625, K606WS626, K606WS812, K606WS817]
    

    • Example of a complete playbook for testing
    - hosts: localhost
    
      vars:
    
        myVms:
          - {SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c, VirtualMachine: K606WS625}
          - {SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c, VirtualMachine: K606WS626}
          - {SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c, VirtualMachine: K606WS812}
          - {SubscriptionId: 564aba40-77683-4426-84ac-d195769c826c, VirtualMachine: K606WS817}
    
        myVmsModified: "{{ myVms | json_query('[].{SubscriptionId: SubscriptionId,
                                                   VirtualMachine: [VirtualMachine]}') }}"
        myVmsModifie2: "{{ [myVms | json_query('[].{SubscriptionId: SubscriptionId,
                                                    VirtualMachine: [VirtualMachine]}'), []] |
                           community.general.lists_mergeby('SubscriptionId', list_merge='append') }}"
    
      tasks:
    
        - debug:
            var: myVmsModified | to_yaml
        - debug:
            var: myVmsModifie2 | to_yaml
    
    • Replace the attribute(s) if you want to
      target:
        - before: 'VirtualMachine'
          after: 'MyBeautifulVms'
      myVmsModified: "{{ [myVms | json_query('[].{SubscriptionId: SubscriptionId,
                                                  VirtualMachine: [VirtualMachine]}'), []] |
                         community.general.lists_mergeby('SubscriptionId', list_merge='append') |
                         community.general.replace_keys(target=target) }}"