ticktockhouse
ticktockhouse

Reputation: 599

jinja2 ansible - accessing complex var

I've spent hours trying to template a .pgpass file given a fairly complex variable structure. I think I need a nested "for" loop to access what I need, but I'm not sure how to drill down properly.

Here's the var:

clients:
  - client1:
      postgres_users:
        - name: user1
          pass: mypassword1
        - name: user3
          pass: mypassword2
      postgres_user_priv_ssh_key: |   
        a
        multiline
        var
      postgres_user_pub_ssh_key: "ssh-rsa blahblahblah"
  - client2:
      postgres_users:
        - name: user3
          pass: mypassword3
        - name: user4
          pass: mypassword4
      postgres_user_priv_ssh_key: |   
        a.n.other
        multiline
        var
      postgres_user_pub_ssh_key: "ssh-rsa blahblahblahdeblah"

The .pgpass file is of the format:

hostname:port:database:username:password 

So, for each "client" under "clients", I need to iterate through and render the name and pass of each one. I've tried so many iterations of the jinja2 template, that it's probably not worth putting any down here, as none of them worked :) I'm open to restructuring the data in some way, but I feel that that's a fairly good way to structure it, as it may need to be read by multiple machines for other purposes (one to many?)

Any advice appreciated!

Upvotes: 1

Views: 947

Answers (2)

ilias-sp
ilias-sp

Reputation: 6685

here is a playbook/template. please note some changes done in the variable structure. More specifically, the clients is not a list variable anymore. added 2 more variables for db_name and db_port as well:

---
- name: test play
  hosts: localhost
  connection: local
  gather_facts: false
  become: yes
  vars:
    db_port: 5432
    db_name: "*"
    clients:
      client1:
        postgres_users:
          - name: user1
            pass: mypassword1
          - name: user3
            pass: mypassword2
        postgres_user_priv_ssh_key: |   
          a
          multiline
          var
        postgres_user_pub_ssh_key: "ssh-rsa blahblahblah"
      client2:
        postgres_users:
          - name: user3
            pass: mypassword3
          - name: user4
            pass: mypassword4
        postgres_user_priv_ssh_key: |   
          a.n.other
          multiline
          var
        postgres_user_pub_ssh_key: "ssh-rsa blahblahblahdeblah"

  tasks:
  - name: run the template
    template:
      src: templates/testt.j2
      dest: /tmp/testt.txt

jinja template:

{% for db_client in lookup('dict', clients) %}
{% for user in clients[db_client.key].postgres_users %}
{{ db_client.key }}:{{ db_port }}:{{ db_name }}:{{ user.name }}:{{ user.pass }}
{% endfor %}
{% endfor %}

result:

[root@optima-ansible ILIAS]# cat /tmp/testt.txt        
client1:5432:*:user1:mypassword1
client1:5432:*:user3:mypassword2
client2:5432:*:user3:mypassword3
client2:5432:*:user4:mypassword4
[root@optima-ansible ILIAS]# 

hope it helps

Upvotes: 1

Vladimir Botka
Vladimir Botka

Reputation: 67984

Is this what you are looking for?

.

> cat create-pgpass.yml
- hosts: localhost                                                                           
  become: yes                                                                                
  become_method: sudo                                                                        
  become_user: root                                                                          
  vars:                                                                                      
    pg_hostname: srv.example.com                                                             
    pg_port: 5432                                                                            
    pg_database: db001                                                                       
    pg_clients:                                                                              
      - client1:                                                                             
        postgres_users:                                                                      
          - name: user1                                                                      
            pass: mypassword1                                                                
          - name: user3                                                                      
            pass: mypassword2                                                                
        postgres_user_priv_ssh_key: |                                                        
            a                                                                                
            multiline                                                                        
            var                                                                              
        postgres_user_pub_ssh_key: "ssh-rsa blahblahblah"                                    
      - client2:                                                                             
        postgres_users:                                                                      
          - name: user3                                                                      
            pass: mypassword3                                                                
          - name: user4                                                                      
            pass: mypassword4                                                                
        postgres_user_priv_ssh_key: |                                                        
            a.n.other                                                                        
            multiline                                                                        
            var                                                                              
        postgres_user_pub_ssh_key: "ssh-rsa blahblahblahdeblah"                              
  tasks:                                                                                     
    - template:                                                                              
        src: /scratch/pgpass.j2                                                              
        dest: /scratch/.pgpass                                                               

.

> cat /scratch/pgpass.j2
{% for item in pg_clients %}
{% for user in item.postgres_users %}
{{ pg_hostname }}:{{ pg_port }}:{{ pg_database }}:{{ user.name }}:{{ user.pass }}
{% endfor %}
{% endfor %}

.

> ansible-playbook create-pgpass.yml
PLAY [localhost] 
****************************************************************************
TASK [Gathering Facts] 
**********************************************************************
ok: [localhost]
TASK [template] 
*****************************************************************************
ok: [localhost]
PLAY RECAP
*****************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   

.

> cat /scratch/.pgpass 
srv.example.com:5432:db001:user1:mypassword1
srv.example.com:5432:db001:user3:mypassword2
srv.example.com:5432:db001:user3:mypassword3
srv.example.com:5432:db001:user4:mypassword4

Upvotes: 1

Related Questions