Home > Blockchain >  Create a list from a dictionary cycle
Create a list from a dictionary cycle

Time:07-12

I would like to create a list with this dict


{
    "v3bf33-srv01": "eu-west0-a",
    "v3bf33-srv02": "eu-west0-a",
    "v3bf33-srv03": "eu-west0-a",
    "v3bf33-srv04": "eu-west0-b",
    "v3bf33-srv05": "eu-west0-b",
    "v3bf33-srv06": "eu-west0-b",
    "v3bf33-srv07": "eu-west0-c",
    "v3bf33-srv08": "eu-west0-c",
    "v3bf33-srv09": "eu-west0-c",
}

I would like to create a list, so, if a user ask 5 servers, cycle through servers of each value: eu-west0-a, eu-west0-b, eu-west0-c, then, eu-west0-a, eu-west0-b.

The result should be a list containing only the server name.

E.g.:

- v3bf33-srv01    #eu-west0-a
- v3bf33-srv04    #eu-west0-b
- v3bf33-srv07    #eu-west0-c
- v3bf33-srv02    #eu-west0-a
- v3bf33-srv05    #eu-west0-b

CodePudding user response:

Given the simplified data for testing

servers:
  srv01: a
  srv02: a
  srv03: a
  srv04: b
  srv05: b
  srv06: b
  srv07: c
  srv08: c
  srv09: c

Create a matrix of the keys

arr: "{{ servers|dict2items|
                 groupby('value')|
                 map(attribute=1)|
                 map('map', attribute='key')|
                 list }}"

gives

arr:
  - [srv01, srv02, srv03]
  - [srv04, srv05, srv06]
  - [srv07, srv08, srv09]

Transpose the matrix

    - set_fact:
        tarr: "{{ tarr|d(arr.0)|zip(item)|map('flatten') }}"
      loop: "{{ arr[1:] }}"

gives

tarr:
  - [srv01, srv04, srv07]
  - [srv02, srv05, srv08]
  - [srv03, srv06, srv09]

Create the list of servers

list_of_servers: "{{ tarr|flatten }}"

gives

list_of_servers: [srv01, srv04, srv07, srv02, srv05, srv08, srv03, srv06, srv09]

Slice the list

    - debug:
        var: list_of_servers[:5]

gives the first 5 servers

list_of_servers[:5]: [srv01, srv04, srv07, srv02, srv05]

Example of a complete playbook

- hosts: localhost
  vars:
    servers:
      srv01: a
      srv02: a
      srv03: a
      srv04: b
      srv05: b
      srv06: b
      srv07: c
      srv08: c
      srv09: c
    arr: "{{ servers|dict2items|
                     groupby('value')|
                     map(attribute=1)|
                     map('map', attribute='key')|
                     list }}"
    list_of_servers: "{{ tarr|flatten }}"
  tasks:
    - set_fact:
        tarr: "{{ tarr|d(arr.0)|zip(item)|map('flatten') }}"
      loop: "{{ arr[1:] }}"
    - debug:
        var: list_of_servers[:5]

CodePudding user response:

@Vladimir Botka : I copy past your "Example of a complete playbook"

here the result.

fatal: [localhost]: FAILED! => {"msg": "Invalid data passed to 'loop',
it requires a list, got this instead:
<generator object do_map at 0x7fe97cca3900>, <generator object do_map at 
0x7fe97cca39e0>, <generator object do_map at 0x7fe97cca3a50>]. Hint: If you 
passed a list/dict of just one element, try adding wantlist=True to your 
lookup invocation or use q/query instead of lookup."}
  • Related