**named_domains: []**
-The ``named_domains`` dictionary is the bread and butter of creating zone files. It is in standard YAML syntax. Each domain (key) must have ``forward`` and ``ipvar`` defined although ``ipvar`` can be set to ``NULL``. Optional values include ``miscrecords`` and ``reverse``.
+The ``named_domains`` dictionary is the bread and butter of creating zone files. It is in standard YAML syntax. Each domain (key) must have ``forward``, ``ipvar``, and ``dynamic`` defined. ``ipvar`` can be set to ``NULL``. Optional values include ``miscrecords``, ``reverse``, and ``ddns_hostname_prefixes``.
``forward``
The domain of the forward lookup zone for each domain (key)
``ipvar``
The variable assigned to a system in the Ansible inventory. This allows systems to have multiple IPs assigned for a front and ipmi network, for example. See **Inventory Example** below.
+``dynamic``
+ Specifies whether the parent zone/domain should allow Dynamic DNS records. See **Dynamic DNS** below for more information.
+
+``ddns_hostname_prefixes``
+ This should be a list of dynamic hostname prefixes you don't want overwritten if a zone/domain has static and dynamic records. See **Dynamic DNS** below.
+
``miscrecords``
Records to add to corresponding ``forward`` zone file. This is a good place for CNAMEs and MX records and records for hosts you don't have in your Ansible inventory. If your main nameserver is in a subdomain, you should create its glue record here. See example.
named_domains:
example.com:
ipvar: NULL
+ dynamic: false
forward: example.com
miscrecords:
- www IN A 8.8.8.8
- ns1.private IN A 192.168.0.1
private.example.com:
ipvar: ip
+ dynamic: true
+ ddns_hostname_prefixes:
+ - dyn
forward: private.example.com
miscrecords:
- mail IN MX 192.168.0.2
- 192.168.2.0
mgmt.example.com:
ipvar: mgmt
+ dynamic: false
forward: mgmt.example.com
reverse:
- 192.168.10.0
- 192.168.11.0
- 192.168.12.0
+ ddns.example.com:
+ ipvar: NULL
+ dynamic: true
Inventory
+++++++++
set_fact:
named_serial: "{{ ansible_date_time.epoch }}"
+- name: Create non-existent forward zone files for dynamic domains
+ template:
+ src: forward.j2
+ dest: "{{ named_conf_zones_path }}/{{ item.key }}"
+ validate: named-checkzone {{ item.key }} %s
+ # only write if zone file doesn't already exist
+ # this makes sure we don't clobber ddns records
+ force: no
+ with_dict: "{{ named_domains }}"
+ notify: reload named
+ when: item.value.dynamic == true
+
+# This makes sure dynamic DNS records in the journal files are in sync with the
+# actual zone files so we can store them in the next step.
+- name: Sync Dynamic DNS journals with zone files
+ command: "rndc sync -clean {{ item.key }}"
+ with_dict: "{{ named_domains }}"
+ when: item.value.dynamic == true and
+ item.value.ddns_hostname_prefixes is defined
+ # Don't fail if there is no journal file
+ failed_when: false
+
+- name: Create temporary directory for dynamic A records
+ command: "mktemp -d"
+ register: named_tempdir
+
+# We need to store existing DNS records in a temp file so we can spit
+# them back out into the zone file after static records are written.
+# Given hostname prefix(es) to expect, this task greps for those records
+# and stores them in a temporary file named after the domain.
+- name: Store existing dynamic A records
+ shell: "grep -E '^({% for prefix in item.value.ddns_hostname_prefixes %}{{ prefix }}{% if not loop.last %}|{% endif %}{% endfor %})[0-9]+\\s+A' {{ named_conf_zones_path }}/{{ item.key }} > {{ named_tempdir.stdout }}/{{ item.key }}"
+ with_dict: "{{ named_domains }}"
+ when: item.value.dynamic == true and
+ item.value.ddns_hostname_prefixes is defined
+ # Don't fail if there are no records to store
+ failed_when: false
+
- name: Write forward zone files
template:
src: forward.j2
validate: named-checkzone {{ item.key }} %s
with_dict: "{{ named_domains }}"
notify: reload named
+ # Don't write zone files for pure dynamic zones
+ when: (item.value.dynamic != true) or
+ (item.value.dynamic == true and item.value.ddns_hostname_prefixes is defined)
- name: Write reverse zone files
template:
- flags:
skip_missing: True
notify: reload named
+
+- name: Restore dynamic A records from temp file(s)
+ shell: "cat {{ named_tempdir.stdout }}/{{ item.key }} >> {{ named_conf_zones_path }}/{{ item.key }}"
+ with_dict: "{{ named_domains }}"
+ when: item.value.dynamic == true and
+ item.value.ddns_hostname_prefixes is defined
+ # Don't fail if there are no records to restore
+ failed_when: false
+
+# This gets rid of any cached dynamic records that we didn't just restore
+- name: Freeze, reload, thaw dynamic zone files
+ shell: "rndc freeze; rndc reload; rndc thaw"
+
+- name: Clean up dynamic A records temp dir
+ file:
+ path: "{{ named_tempdir.stdout }}"
+ state: absent