1

So I'm using a role to configure my postgresql server. That tole has a way of specifying server users & databases, like so:

postgresql_users:
  - name: baz

My hosts.yaml:

all:
  hosts:
  children:
    django:
      hosts:
        django_1:
          username: django1
          userpass: django1_pass
        django_2:
          username: django2
          userpass: django2_pass
    db:
      hosts:
        db1:

Any my playbook.yaml:

- hosts: db
  become: true
  roles:
    - role: anxs.postgresql

What I want to do with this information is to get all django hosts and get their username & userpass variables.

Then, from this information compose the postgresql_users variable as if it were written by hand (relevant (desired result) section of hosts.yaml below):

db:
  hosts:
    db1:
      postgresql_users:
        - name: django1
          password: django1_pass
          encrypted: true
        - name: django2
          password: django2_pass
          encrypted: true

I have found this question dealing with my problem, but unfortunately I'm too new to Ansible to really understand what's being suggested there.

So how can I make an appropriate iteration that would compose my postgresql_users variable as I want it?

velis
  • 233
  • 2
  • 10

1 Answers1

1

Q: "Get all django hosts and get their username & userpass variables."

A: It's possible to create the variable in the first play and use it later. For example

- hosts: all
  tasks:
    - set_fact:
        psql_users: "{{ groups['django']|
                        map('extract', hostvars)|
                        list|
                        json_query('[].{name: username,
                                        password: userpass,
                                        encrypted: `true`}') }}"
      delegate_to: localhost
      run_once: true

- hosts: db
  tasks:
    - debug:
        var: psql_users

gives

ok: [db1] => {
    "psql_users": [
        {
            "encrypted": true, 
            "name": "django1", 
            "password": "django1_pass"
        }, 
        {
            "encrypted": true, 
            "name": "django2", 
            "password": "django2_pass"
        }
    ]
}

It's also possible to use template and create an inventory file. For example with the template

$ cat hosts.j2
db:
  hosts:
    db1:
      postgresql_users:
{{ psql_users|to_nice_yaml|indent(8,true) }}

the task

- template:
    src: hosts.j2
    dest: hosts2

creates inventory

$ cat hosts2
db:
  hosts:
    db1:
      postgresql_users:
        -   encrypted: true
            name: django1
            password: django1_pass
        -   encrypted: true
            name: django2
            password: django2_pass
Vladimir Botka
  • 5,138
  • 8
  • 20
  • Not sure how I can actually do this such that it will always work: AFAIK, you always start with the playbook to run. What use is it then to define this in another playbook? I tried to move this to hosts.yml, but without any success. It wouldn't allow me to either import or specify this code directly... – velis Jan 14 '20 at 13:26
  • 1
    It's possible to create the inventory. I've updated the answer. – Vladimir Botka Jan 14 '20 at 13:51
  • Finally I got it working. Thanks. I'm such a n00b. When trying to implement the second solution it quickly became apparent that the first one was actually the way to go :D – velis Jan 14 '20 at 14:39