bertvv/ansible-role-bind

looping leaves only 1 entry in /etc/named.conf

Closed this issue · 2 comments

Hi, I'm looping over many domains and doing that, only the last domain gets an entry in /etc/named.conf

--- 
- name: configure bind
  hosts: all
  vars: 
    DOMAINS: 
      - domain1.org
      - domain2.com
  tasks:
    - include_role:
        name: bertvv.bind
      vars:
        - bind_listen_ipv4: ['any']
        - bind_allow_query: ['localhost']
        - bind_allow_recursion: ['localhost']
        - bind_zones:
            # Example of a primary zone (hosts: and name_servers: ares defined)
            - name: "{{ loop_var }}"           
              create_reverse_zones: false  
              primaries:
                - 1.2.3.4             
              name_servers:
                - ns1.my.other.nameserver.
                - ns2.my.other.nameserver.
              mail_servers:
                - name: mail.mydomain.blabla.
                  preference: 1
              hosts:
                - name: '@'                
                  ip:
                    - 5.6.7.8             
                                               
                  aliases:
                    - www
      loop: "{{DOMAINS}}"
      loop_control:
        loop_var: loop_var

The only entry in /etc/named.conf to be created is this one:

zone "domain2.com" IN {
  type master;
  file "/var/named/domain2.com";
  notify yes;
  allow-update { none; };
};

The entry for domain1.org is missing.
Any advice? I will have to create several hundred domains, so I need a way to efficiently loop over those.

For now, I've templated it together in bash, but I'm open to learn about better ways to achieve the goal.
Hope it helps anyone.

So if I understand the role right, the concept is to have all DNS entries of that installation inside the playbook, right?

04_bind_configuration_template.yaml:

--- 
- name: configure bind
  hosts: all
  vars: 
    - bind_listen_ipv4: ['any']
    - bind_allow_query: ['localhost']
    - bind_allow_recursion: ['localhost']
    - bind_zone_dir: /var/named/master
    - bind_zones:
${ZONES}
  roles:
    - bertvv.bind

zones.tpl:

        - name: "###DOMAIN###"           # Domain name
          create_reverse_zones: false  # Skip creation of reverse zones
          primaries:
            - 1.2.3.4              # Primary server(s) for this zone
          name_servers:
            - ns1.mydomain.com.
            - ns2.mydomain.com.
          mail_servers:
            - name: mail2.mydomain.com.
              preference: 1
          hosts:
            - name: '@'                # Enables "http://mydomain.com/"
              ip:
                - ###IP###             # Multiple IP addresses for a single host
                                            #   results in DNS round robin
              aliases:
                - www

construct-playbook-zones.sh:

#!/bin/bash
ZONEFILE=zones.tpl
ANSIBLE_PLAYBOOK=04_bind_configuration.yaml
TEMPLATEFILE=04_bind_configuration_template.yaml
DOMAINSFILE=./domains.txt

export ZONES=$(cat $DOMAINSFILE| while read DOMAIN IP
do
    cat $ZONEFILE | \
        sed -e "s/###DOMAIN###/$DOMAIN/g" | \
        sed -e "s/###IP###/$IP/g"
done)



envsubst < $TEMPLATEFILE > $ANSIBLE_PLAYBOOK

domains.txt:

domain1.com 5.6.7.8
domain2.com 5.6.7.8
...

a more elegant way without the above templating stuff, resolving my issue above:

---
- hosts: all
  gather_facts: no
  vars:
    - bind_listen_ipv4: ['any']
    - bind_allow_query: ['localhost']
    - bind_allow_recursion: ['localhost']
    - bind_zone_dir: /var/named/master
    - zone_template:
        name: "{{ item.domain }}"           
        create_reverse_zones: false  
        primaries:
          - "1.2.3.4"            
        name_servers:
          - "ns1.mydomain.com."
          - "ns2.mydomain.com."
        mail_servers:
          - name: "mail.mydomain.com."
            preference: 1
        hosts:
          - name: '@'                
            ip:
              - "{{ item.ip }} "
            aliases:
              - "www"
  tasks:
    # construct list
    - set_fact:
        bind_zones: "{{ (bind_zones | default([])) + [zone_template] }}"
      loop:
        - {domain: "xmydomain1.com", ip: "1.2.3.4"}
        - {domain: "xmydomain2.com", ip: "5.6.7.8"}
    - debug:
        msg: "{{ bind_zones }}"

- name: bind stuff
  hosts: all
  tasks:
    - name: bind stuff
      import_role:
        name: bertvv.bind