Search code examples
ansibleyaml

How to iterate over variables in an ansible dictionary


I have a role that should scatter NGINX configs across different servers using Jinja2 templates, referring to the variables specified in defaults/main, please tell me how to write a loop to iterate over these variables correctly, tried it through with_items and with_nested, but nothing happens.
The defaults/main file looks like this:

allservers:
  server1:
    - { src: 'templates/sites-enabled/api.j2',                       dest: '/etc/nginx/sites-enabled/api.conf' }                               
    - { src: 'templates/sites-enabled/citizens.j2',                  dest: '/etc/nginx/sites-enabled/citizens.conf' }
    - { src: 'templates/sites-enabled/control.j2',                   dest: '/etc/nginx/sites-enabled/control.conf' }
    - { src: 'templates/sites-enabled/documents.j2',                 dest: '/etc/nginx/sites-enabled/documents.conf' }
    - { src: 'templates/sites-enabled/orders.j2',                    dest: '/etc/nginx/sites-enabled/orders.conf' }
    - { src: 'templates/sites-enabled/logs.j2',                      dest: '/etc/nginx/sites-enabled/logs.conf' }

  server2:
    - { src: 'templates/sites-enabled/permissions.j2',               dest: '/etc/nginx/sites-enabled/permissions.conf' }
    - { src: 'templates/sites-enabled/documents.j2',                 dest: '/etc/nginx/sites-enabled/documents.conf' }
    - { src: 'templates/sites-enabled/default.j2',                   dest: '/etc/nginx/sites-enabled/default' }
    - { src: 'templates/sites-enabled/orders.j2',                    dest: '/etc/nginx/sites-enabled/orders.conf' }
    - { src: 'templates/sites-enabled/settings.j2',                  dest: '/etc/nginx/sites-enabled/settings.conf' }

Solution

  • I assume you do not want to change your data structure, and that server1 and server2 refer to hosts in your inventory.

    ---                                                                             
    - hosts: server1:server2                                                        
      remote_user: ansible                                                          
      vars:                                                                         
        allservers:                                                                 
          server1:                                                                  
              - { src: "/tmp/file1", dest: "/tmp"}                                  
              - { src: "/tmp/file2", dest: "/tmp"}                                  
              - { src: "/tmp/file3", dest: "/tmp"}                                  
          server2:                                                                  
              - { src: "/tmp/file4", dest: "/tmp"}                                  
              - { src: "/tmp/file5", dest: "/tmp"}                                  
              - { src: "/tmp/file6", dest: "/tmp"}    
    
    
      tasks:
        - name: Copy template
          template:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
          when: inventory_hostname in allservers.keys()
          with_items:
            - "{{ allservers[inventory_hostname] }}"
    

    Another solutions is to include a task (copy_template.yml) which you will iterate over using with_dict: allservers.

    playbook.yml

    ---                                                                             
    - hosts: server1:server2                                                        
      remote_user: ansible                                                          
      vars:                                                                         
        allservers:                                                                 
          server1:                                                                  
              - { src: "/tmp/file1", dest: "/tmp"}                                  
              - { src: "/tmp/file2", dest: "/tmp"}                                  
              - { src: "/tmp/file3", dest: "/tmp"}                                  
          server2:                                                                  
              - { src: "/tmp/file4", dest: "/tmp"}                                  
              - { src: "/tmp/file5", dest: "/tmp"}                                  
              - { src: "/tmp/file6", dest: "/tmp"}                                  
      tasks:                                                                        
        - include: copy_template.yml                                                
          vars:                                                                     
            server: "{{ item.key }}"                                                
          with_dict:                                                                
            - "{{ allservers }}" 
    
    

    copy_template.yml

    ---                                                                             
    - debug:                                                                        
        msg: "{{ template.src }}  and  {{ template.dest }}"                         
      loop: "{{ allservers[server] }}"                                  
      when: server == inventory_hostname                                            
      loop_control:                                                                 
        loop_var: template