Home > Back-end >  Merge/Combine top level of dictionary
Merge/Combine top level of dictionary

Time:11-08

I am trying to create dictionary out of the servers stored in different env variables in ansible.

What i currently have is:

env_loadbalancer_vservers2: "{{ hostvars[inventory_hostname] | dict2items | selectattr('key', 'match', 'env_.*_loadbalancer_vservers(?![_.])') | list | items2dict }} "

Which will:

  1. get all variables in ansible for a specific host,
  2. change dict to items type
  3. as we can easily access now key value I will match only keys I want using regex
  4. Change it back to list
  5. Back to dict

problem is that output looks like this:

{
     "env_decision_manager_loadbalancer_vservers": {
         "decision_central": {
             "ip_or_dns": "ip",
             "port": "port",
             "protocol": "SSL",
             "ssl": true,
             "timeout": 600,
         }
     },
     "env_ftp_loadbalancer_vservers": {
         "ftp_1": {
             "ip_or_dns": "ip",
             "port": "port",
             "protocol": "FTP",
             "ssl": false,
             "timeout": 9010,
         }
     },
     "env_jboss_loadbalancer_vservers": {
         "jboss": {
             "ip_or_dns": "ip",
             "port": "port",
             "protocol": "SSL",
             "ssl": true,
             "timeout": 600,
         }
         "jboss_adm": {
             "ip_or_dns": "som_other_ip",
             "port": "rando_number",
             "protocol": "SSL",
             "ssl": true,
             "timeout": 86410,
         }
     }

While my desired output should look like:

{
         "decision_central": {
             "ip_or_dns": "ip",
             "port": "port",
             "protocol": "SSL",
             "ssl": true,
             "timeout": 600,
         },
         "ftp_1": {
             "ip_or_dns": "ip",
             "port": "port",
             "protocol": "FTP",
             "ssl": false,
             "timeout": 9010,
         },
         "jboss": {
             "ip_or_dns": "ip",
             "port": "port",
             "protocol": "SSL",
             "ssl": true,
             "timeout": 600,
         },
         "jboss_adm": {
             "ip_or_dns": "som_other_ip",
             "port": "rando_number",
             "protocol": "SSL",
             "ssl": true,
             "timeout": 86410,
         }

So practically I need to remove "Top-level key tier" and merge their values. I've spent quite a time on this solution without any good progress and I would be happy for any advice :)

PS. The solution should be "clean" without any custom modules or actual tasks, the best idea would just add some functions to the filter pipeline mentioned above that will result in the correct format of dict

Thank you :)

CodePudding user response:

Select the attribute value

  regexp: 'env_.*_loadbalancer_vservers(?![_.])'
  l1: "{{ hostvars[inventory_hostname]|
          dict2items|
          selectattr('key', 'match', regexp)|
          map(attribute='value')|
          list }}"

gives the list

  l1:
  - decision_central:
      ip_or_dns: ip
      port: port
      protocol: SSL
      ssl: true
      timeout: 600
  - ftp_1: null
      ip_or_dns: IP
      port: port
      protocol: FTP
      ssl: false
      timeout: 9010
  - jboss:
      ip_or_dns: ip
      port: port
      protocol: SSL
      ssl: true
      timeout: 600
    jboss_adm:
      ip_or_dns: som_other_ip
      port: rando_number
      protocol: SSL
      ssl: true
      timeout: 86410

Combine the items of the list

  d1: "{{ {}|combine(l1) }}"

gives the dictionary you're looking for

  d1:
    decision_central:
      ip_or_dns: ip
      port: port
      protocol: SSL
      ssl: true
      timeout: 600
    ftp_1:
      ip_or_dns: ip
      port: port
      protocol: FTP
      ssl: false
      timeout: 9010
    jboss:
      ip_or_dns: ip
      port: port
      protocol: SSL
      ssl: true
      timeout: 600
    jboss_adm:
      ip_or_dns: som_other_ip
      port: rando_number
      protocol: SSL
      ssl: true
      timeout: 86410
  • Related