mirror of
https://github.com/famedly/ansible-collection-dns
synced 2024-11-14 16:27:14 +00:00
feat(powerdns-zone): add ansible role for creating an empty zone in powerdns
This commit is contained in:
parent
6ad5ddce32
commit
e36b29c3af
3 changed files with 129 additions and 0 deletions
32
roles/powerdns-zone/README.md
Normal file
32
roles/powerdns-zone/README.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# `famedly.dns.powerdns-zone` ansible role
|
||||
|
||||
This role aims to bootstrap an empty zone into powerdns so that it can be
|
||||
used immediately without needing to be created using powerdns-admin or
|
||||
API calls.
|
||||
|
||||
For this, the contents of the SOA record, the zone name and it's type
|
||||
need to be known, optionally the associated powerdns account.
|
||||
|
||||
## Configuration
|
||||
|
||||
A sample configuration is given below for setting up `demo.famedly.de`:
|
||||
|
||||
```yaml
|
||||
- hosts: [dns_authorative]
|
||||
roles:
|
||||
- name: powerdns-zone
|
||||
vars:
|
||||
powerdns_zone_name: demo.famedly.de
|
||||
powerdns_zone_type: "{{ 'MASTER' if 'dns_primary' in group_names else 'SLAVE' }}"
|
||||
# Assuming the primary has a variable called `ipv4`, store that ip in the
|
||||
# `master` column of the domain table of the secondaries
|
||||
powerdns_zone_master_ip: "{{ groups.dns_primary[0].ipv4 }}"
|
||||
powerdns_zone_account: famedlydemo
|
||||
powerdns_zone_soa_content: "ns0.famedly.de admin.famedly.de 2022010101 10800 3600 604800 3600"
|
||||
# Database configuration
|
||||
postgres_zone_database_type: postgres
|
||||
postgres_zone_database_user: pdns
|
||||
postgres_zone_database_password: asdoifjqwiejüojsdvinoöioeawjsf
|
||||
postgres_zone_database_name: pdns
|
||||
postgres_zone_database_host: 127.0.0.1
|
||||
```
|
16
roles/powerdns-zone/defaults/main.yml
Normal file
16
roles/powerdns-zone/defaults/main.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
|
||||
powerdns_zone_name: ~
|
||||
powerdns_zone_type: ~
|
||||
powerdns_zone_account: ~
|
||||
powerdns_zone_metadata:
|
||||
SOA-EDIT-API: DEFAULT
|
||||
ALLOW-AXFR-FROM: AUTO-NS
|
||||
powerdns_zone_master_ip: ~
|
||||
powerdns_zone_soa_content: ~
|
||||
|
||||
powerdns_zone_database_type: postgres
|
||||
powerdns_zone_database_user: pdns
|
||||
powerdns_zone_database_password: ~
|
||||
powerdns_zone_database_name: pdns
|
||||
powerdns_zone_database_host: ~
|
81
roles/powerdns-zone/tasks/main.yml
Normal file
81
roles/powerdns-zone/tasks/main.yml
Normal file
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
|
||||
- name: Configure zone '{{ powerdns_zone_name }}'
|
||||
postgresql_query:
|
||||
login_host: "{{ powerdns_zone_database_host }}"
|
||||
login_user: "{{ powerdns_zone_database_user }}"
|
||||
login_password: "{{ powerdns_zone_database_password }}"
|
||||
db: "{{ powerdns_zone_database_name }}"
|
||||
query: >-
|
||||
INSERT INTO domains (name, {{ 'master,' if powerdns_zone_master_ip else '' }} type, account)
|
||||
VALUES ( '{{ powerdns_zone_name }}', {{ "'" + powerdns_zone_master_ip + "'," if powerdns_zone_master_ip else '' }} '{{ powerdns_zone_type }}', '{{ powerdns_zone_account }}' )
|
||||
ON CONFLICT ( name )
|
||||
DO UPDATE SET "type" = '{{ powerdns_zone_type }}', "account" = '{{ powerdns_zone_account }}'
|
||||
WHERE domains.name = '{{ powerdns_zone_name }}' and
|
||||
(domains.type != '{{ powerdns_zone_type }}'
|
||||
or domains.account != '{{ powerdns_zone_account }}');
|
||||
SELECT * FROM domains WHERE name = '{{ powerdns_zone_name }}';
|
||||
when: powerdns_zone_database_type == 'postgres'
|
||||
register: zone_upsert_result
|
||||
|
||||
- name: Extract internal domain_id for zone
|
||||
set_fact:
|
||||
zone_domain_id: "{{ zone_upsert_result.query_result[0].id }}"
|
||||
|
||||
# TODO: this breaks encoding arrays, which are encoded by
|
||||
# using multiple (domain_id, kind) entries with different values
|
||||
- name: Create unique index (domain_id, kind) on domainmetadata table
|
||||
postgresql_idx:
|
||||
login_host: "{{ powerdns_zone_database_host }}"
|
||||
login_user: "{{ powerdns_zone_database_user }}"
|
||||
login_password: "{{ powerdns_zone_database_password }}"
|
||||
db: "{{ powerdns_zone_database_name }}"
|
||||
table: domainmetadata
|
||||
columns:
|
||||
- domain_id
|
||||
- kind
|
||||
name: domainmetadata_domain_kind_uniq
|
||||
type: btree
|
||||
unique: yes
|
||||
when: powerdns_zone_database_type == 'postgres'
|
||||
|
||||
- name: Configure zone metadata for '{{ powerdns_zone_name }}'
|
||||
postgresql_query:
|
||||
login_host: "{{ powerdns_zone_database_host }}"
|
||||
login_user: "{{ powerdns_zone_database_user }}"
|
||||
login_password: "{{ powerdns_zone_database_password }}"
|
||||
db: "{{ powerdns_zone_database_name }}"
|
||||
query: >-
|
||||
INSERT INTO domainmetadata (domain_id, kind, content)
|
||||
VALUES ( '{{ zone_domain_id }}', '{{ item.key }}', '{{ item.value }}' )
|
||||
ON CONFLICT ( domain_id, kind )
|
||||
DO UPDATE SET "content" = '{{ item.value }}'
|
||||
WHERE domainmetadata.domain_id = '{{ zone_domain_id }}' and domainmetadata.kind = '{{ item.key }}' and domainmetadata.content != '{{ item.value }}';
|
||||
loop: "{{ powerdns_zone_metadata | dict2items }}"
|
||||
loop_control: { label: "{{ item.key }} = {{ item.value }}" }
|
||||
when: powerdns_zone_database_type == 'postgres'
|
||||
|
||||
- name: Check if SOA record for zone '{{ powerdns_zone_name }}' exists
|
||||
postgresql_query:
|
||||
login_host: "{{ powerdns_zone_database_host }}"
|
||||
login_user: "{{ powerdns_zone_database_user }}"
|
||||
login_password: "{{ powerdns_zone_database_password }}"
|
||||
db: "{{ powerdns_zone_database_name }}"
|
||||
query: >-
|
||||
SELECT * FROM records
|
||||
WHERE records.domain_id = '{{ zone_domain_id }}'
|
||||
and records.name = '{{ powerdns_zone_name }}'
|
||||
and records.type = 'SOA';
|
||||
changed_when: false
|
||||
register: zone_records_type_soa
|
||||
|
||||
- name: Configure SOA record for zone '{{ powerdns_zone_name }}'
|
||||
postgresql_query:
|
||||
login_host: "{{ powerdns_zone_database_host }}"
|
||||
login_user: "{{ powerdns_zone_database_user }}"
|
||||
login_password: "{{ powerdns_zone_database_password }}"
|
||||
db: "{{ powerdns_zone_database_name }}"
|
||||
query: >-
|
||||
INSERT INTO records (domain_id, name, type, content, ttl, prio, disabled, auth)
|
||||
VALUES ( '{{ zone_domain_id }}', '{{ powerdns_zone_name }}', 'SOA', '{{ powerdns_zone_soa_content }}', 3600, 0, false, true)
|
||||
when: powerdns_zone_database_type == 'postgres' and zone_records_type_soa.rowcount|int == 0
|
Loading…
Reference in a new issue