๐Ÿ“— Ansible playbooks and roles for building an idempotent, interconnected and scalable infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible-playbooks/roles/coredns/tasks/add_record.yml

120 lines
3.7 KiB

2 years ago
- name: check if record is an object
fail:
msg: record must be an object
when: record is not mapping
- name: check if record zone is a string
fail:
msg: record zone must be a string
when: record.zone is defined and record.zone is not string
- name: check if record zone exists
fail:
msg: '"{{ record.zone }}" does not seem to be a valid zone'
when: (record.zone is defined) and
(record.zone != 'root') and
((int_zones is not defined) or (record.zone not in int_zones))
- name: construct record parameters
set_fact:
ns_zone: "{%- if (record.zone is defined) and (record.zone != 'root') -%}{{ record.zone }}\
{%- else -%}{{ ns_tld | d(int_tld) }}\
{%- endif -%}"
ns_name: "{%- if record.name is defined -%}{{ record.name }}\
{%- else -%}{{ inventory_hostname }}\
{%- endif -%}"
ns_type: "{%- if record.type is defined -%}{{ record.type | upper }}\
{%- else -%}A\
{%- endif -%}"
ns_value: "{%- if record.value is defined -%}{{ record.value }}\
{%- else -%}{{ ansible_host }}\
{%- endif -%}"
- name: set ns_quote
set_fact:
ns_quote: "{{ '\"' if ns_type == 'TXT' else '' }}"
- name: construct full name
set_fact:
ns_full_name: '{%- if ns_name != "@" -%}{{ ns_name }}.{%- endif -%}{{ ns_zone }}'
- name: construct regex part
set_fact:
ns_regex_part: '{%- if record.allow_multiple is defined -%}{{ (ns_quote ~ ns_value ~ ns_quote) | regex_escape() }}\.?{%- else -%}{{ "" | string }}{%- endif -%}'
- name: construct regex
set_fact:
ns_regex: '^{{ ns_full_name | regex_escape() }}\s+\d+\s+IN\s+{{ ns_type | regex_escape() }}\s+{{ ns_regex_part }}'
- name: show debug info
debug:
msg: "{{ ns_zone }} {{ ns_name }} {{ ns_type }} {{ ns_quote ~ ns_value ~ ns_quote }} --> {{ ns_regex }}"
- name: slurp zone file
slurp:
src: "{{ coredns_conf_dir ~ '/' ~ (ns_tld | d(int_tld)) ~ '.zone' }}"
register: zf
changed_when: false
- name: enumerate stdout lines to check if an entry already exists
set_fact:
ns_exists: "{{ (zf.content | b64decode).split('\n') | select('search', ns_regex) | list | length > 0 }}"
- block:
- name: fail if there are multiple records
fail:
msg: single record mode is selected, but multiple records found
when: (zf.content | b64decode).split('\n') | select('search', ns_regex) | list | length > 1
- name: grab the value
set_fact:
ns_old_value: "{{ (zf.content | b64decode).split('\n') | select('search', ns_regex) | map('regex_search', '\\s+?(\\S+?)\\.?$', '\\1') | first | join('') }}"
- name: replace the record
lineinfile:
path: "{{ coredns_conf_dir ~ '/' ~ (ns_tld | d(int_tld)) ~ '.zone' }}"
regexp: '^\s*{{ ns_name | regex_escape() }}\s+IN\s+{{ ns_type | regex_escape() }}\s+'
line: "{{ ns_name }}\tIN\t{{ ns_type }}\t{{ ns_quote ~ ns_value ~ ns_quote }}"
backrefs: yes
when: ns_old_value != (ns_quote ~ ns_value ~ ns_quote)
register: rr1
when: ns_exists and rrset.allow_multiple is not defined
- name: add the record if it is missing
lineinfile:
path: "{{ coredns_conf_dir ~ '/' ~ (ns_tld | d(int_tld)) ~ '.zone' }}"
line: "{{ ns_name }}\tIN\t{{ ns_type }}\t{{ ns_quote ~ ns_value ~ ns_quote }}"
when: not ns_exists
register: rr2
- name: determine if records were changed
set_fact:
ns_records_changed: "{{ ((rr1 is defined) and rr1.changed) or ((rr2 is defined) and rr2.changed) }}"
- name: change serial
include_tasks: increase_serial.yml
when: ns_records_changed | d(false) == true
- name: restart coredns
service:
name: coredns
state: restarted
when: (ns_instant | d(false) == true) and (ns_records_changed or ns_serial_changed)