Home > Blockchain >  How to create a dynamic dictionary in Ansible
How to create a dynamic dictionary in Ansible

Time:01-14

I have a list of users (this is not actual Ansible code, just an example):

users:
 -tom
 -jerry
 -pluto

Now I am trying to create a dynamic structure ( list of dictionaries ?) like this, for setting random (at runtime) passwords to them:

users_and_passwords:
  -tom, "random_password_here1"
  -jerry, "random_password_here2"
  -pluto, "random_password_here3"

How can I write a set_fact task to generate random password for each user and save it for later use?
How can I then read that and use it in other tasks later?

So far I tried declaring a list of users (later to be looped from a file), then an empty list of passwords. Now I am trying to populate the Password list with random strings, then to combine them into a single {user:password} dict.I can't figure out how to do this easier, and I am stuck in the "populate password list" phase.

    users:
      -top
      -jerry
      -pluto

    passwords: []


  tasks:
  - name: generate passwords in an empty Dict
    set_fact: 
      passwords: "{{ passwords | default({})   {{ lookup('password', '/dev/null chars=ascii_lowercase,ascii_uppercase,digits,punctuation length=20') }} }}"

    with_items: "{{users}}"

CodePudding user response:

Rather than having a complex dictionary that would read:

- tom: password123456
- jerry: password123456789
- muttley: password12345

Aim for a structure that would be normalized, like:

- name: tom
  password: password123456
- name: jerry
  password: password123456789
- name: muttley
  password: password12345

This can be achieved with the task:

- set_fact:
    users_with_passwords: >-
      {{
        users_with_passwords | default([])   
        [{
          'name': item,
          'password': lookup(
            'password', 
            '/dev/null chars=ascii_lowercase,ascii_uppercase,digits,punctuation length=20'
          )
        }]
      }}
  loop: "{{ users }}"

And, can be easily accessed via something like:

- debug:
    msg: "{{ item.name }}'s password is `{{ item.password }}`"
  loop: "{{ users_with_passwords }}"
  loop_control:
    label: "{{ item.name }}"

Given the playbook

- hosts: localhost
  gather_facts: no
  vars:
    users:
      - tom
      - jerry
      - muttley

  tasks:
    - set_fact:
        users_with_passwords: >-
          {{
            users_with_passwords | default([])   
            [{
              'name': item,
              'password': lookup(
                'password', 
                '/dev/null chars=ascii_lowercase,ascii_uppercase,digits,punctuation length=20'
              )
            }]
          }}
      loop: "{{ users }}"

    - debug:
        msg: "{{ item.name }}'s password is `{{ item.password }}`"
      loop: "{{ users_with_passwords }}"
      loop_control:
        label: "{{ item.name }}"

This yields:

TASK [set_fact] *************************************************************
ok: [localhost] => (item=tom)
ok: [localhost] => (item=jerry)
ok: [localhost] => (item=muttley)

TASK [debug] ****************************************************************
ok: [localhost] => (item=tom) => 
  msg: tom's password is `tLY>@jg6k/_|sqke{-mm`
ok: [localhost] => (item=jerry) => 
  msg: jerry's password is `Liu1wF@gPM$q^z~g|<E1`
ok: [localhost] => (item=muttley) => 
  msg: muttley's password is `BGHL_QUTHmbn\(NGW`pJ`

CodePudding user response:

How can I write a set_fact task to generate random password for each user and save it for later use?

This sound like a task for the password_lookup which "Retrieves or generate a random password, stored in a file", in Example

- name: Create random but idempotent password
  set_fact:
    toms_password: "{{ lookup('password', '/dev/null', seed=username) }}"

How can I then read that and use it in other tasks later?

Just by Using variable name which was defined during set_fact.

Further readings

  •  Tags:  
  • Related