52 Commits

Author SHA1 Message Date
Daniel Akulenok fa35922646 AGENTS 2026-01-28 22:03:18 +01:00
Daniel Akulenok 3d7a403409 fix: Update issue tracker URL in metadata 2026-01-27 23:42:07 +01:00
Daniel Akulenok 30098d48d8 fix: Update issue tracker URL in metadata 2026-01-27 23:40:56 +01:00
Daniel Akulenok 8cbf5279ae docs: Update author and company contact information 2026-01-27 23:30:01 +01:00
Daniel Akulenok 8c0961dd13 test: Configure Molecule testing framework
- Add Ansible collections configuration
- Update converge and prepare playbooks
- Restructure molecule.yml for improved testing
2026-01-27 23:30:01 +01:00
Daniel Akulenok 7fc4c26217 fix: Add explicit boolean comparison for Ansible 2.12+ compatibility 2026-01-27 23:30:01 +01:00
Daniel Akulenok ebdddc37e2 refactor: Rename leaf config to site config
feat: Add argument specs and atomic validation
2026-01-27 23:30:01 +01:00
Daniel Akulenok 400d13457c style: Fix formatting and spacing 2026-01-27 23:18:56 +01:00
Daniel Akulenok 651df7c29a style: Fix formatting and spacing 2026-01-27 23:18:56 +01:00
Daniel Akulenok 32755369b4 refactor: Remove unnecessary comments 2026-01-27 23:18:56 +01:00
Daniel Akulenok f3d4db5f72 refactor: Replace Jinja2 macros with direct logic in zone and view templates 2026-01-27 23:18:56 +01:00
Daniel Akulenok 95033ef863 refactor: Simplify trust-anchors template implementation 2026-01-27 23:18:56 +01:00
Daniel Akulenok 4da4a6ef7d refactor: Remove macro usage from TLS configuration template 2026-01-27 23:18:56 +01:00
Daniel Akulenok 08fb247110 refactor: Simplify statistics-channels template 2026-01-27 23:18:56 +01:00
Daniel Akulenok 98f33fb989 refactor: Remove Jinja2 macro dependencies from templates 2026-01-27 23:18:56 +01:00
Daniel Akulenok 3ab22fc5f2 refactor: Remove Jinja2 macro dependencies from templates 2026-01-27 23:18:56 +01:00
Daniel Akulenok 5c5f3d1687 test: Add Podman support for testing 2026-01-27 23:18:56 +01:00
Daniel Akulenok f495ab55b8 refactor: Simplify key configuration template by removing macros 2026-01-27 23:18:56 +01:00
Daniel Akulenok 212861a3ac refactor: Remove macro usage from HTTP configuration template 2026-01-27 23:18:56 +01:00
Daniel Akulenok fbe5eaaddd refactor: Remove macro usage from HTTP configuration template 2026-01-27 23:18:56 +01:00
Daniel Akulenok 91c2c611db refactor: Simplify DNSSEC policy template by removing macros 2026-01-27 23:18:56 +01:00
Daniel Akulenok 530c0a2bd5 refactor: Remove macro dependencies from DLZ template 2026-01-27 23:18:56 +01:00
Daniel Akulenok b67ae1184f refactor: Simplify include template by removing macro usage 2026-01-27 23:18:56 +01:00
Daniel Akulenok 3c6e8befb4 refactor: Remove Jinja2 macros from controls template 2026-01-27 23:18:56 +01:00
Daniel Akulenok a327b0a19a fix: Correct typo in template 2026-01-27 23:18:56 +01:00
Daniel Akulenok ac99d7b5c8 fix: Correct typo in template 2026-01-27 23:18:56 +01:00
Daniel Akulenok 18b5c5a20f refactor: Continue removing macro dependencies from templates 2026-01-27 23:18:56 +01:00
Daniel Akulenok fdf150c640 fix: Replace incorrectly used macro with proper Jinja2 filter 2026-01-27 23:18:56 +01:00
Daniel Akulenok 9bed66418f refactor: Remove macro usage from options template 2026-01-27 23:18:56 +01:00
Daniel Akulenok d488bbafaa chore: Synchronize with local development changes
- Update handler implementation
- Adjust Molecule configuration
- Remove obsolete verification tasks
2026-01-27 23:18:56 +01:00
Daniel Akulenok e3249912d7 fix: Correct backup file path string in handlers 2026-01-27 23:18:56 +01:00
Daniel Akulenok 7e8d3eb6f5 fix: Make zone name parameter optional in template 2026-01-27 23:18:56 +01:00
Daniel Akulenok 986a6843e9 feat: Support address lists with shared keys in configuration
- Extend function template to iterate over address lists
- Enable multiple addresses to use the same key
2026-01-27 23:18:56 +01:00
Daniel Akulenok 96bf462521 fix: Support both boolean and 'auto' values for dnssec_validation
- Update options template to handle multiple value types
- Improve DNSSEC configuration flexibility
2026-01-27 23:18:56 +01:00
Daniel Akulenok ad09e0081d style: Remove excessive blank lines from GitLab CI configuration 2026-01-27 23:18:56 +01:00
Daniel Akulenok 556da9b256 style: Fix template indentation issues
- Correct indentation in generator template
- Update options template formatting
- Normalize parental-agents template spacing
2026-01-27 23:18:56 +01:00
Daniel Akulenok 2f181751e2 style: Apply Molecule linting fixes
- Fix YAML formatting in defaults and handlers
- Update meta information formatting
- Improve task syntax consistency
2026-01-27 23:18:56 +01:00
Daniel Akulenok ab300c5cd6 ci: Add GitLab CI/CD configuration
- Set up pipeline for automated testing
- Configure Molecule integration
2026-01-27 23:18:56 +01:00
Daniel Akulenok 06b18a8224 chore: Remove Travis CI configuration
- Remove .travis.yml as CI is now handled by GitLab
2026-01-27 23:18:56 +01:00
Daniel Akulenok 714a36546f refactor: Remove inline variable definitions from test files
- Clean up converge and test playbooks
- Move test configuration to external files
2026-01-27 23:18:56 +01:00
Daniel Akulenok 7fb722e6f1 test: Configure Molecule testing framework
- Add comprehensive converge playbook with test scenarios
- Create Molecule configuration for role testing
- Set up verification tasks
2026-01-27 23:18:56 +01:00
Daniel Akulenok 0e19ca7112 docs: Add missing line break to README 2026-01-27 23:18:48 +01:00
Daniel Akulenok 0bd2953288 docs: Simplify and reorganize README content
- Remove redundant documentation sections
- Streamline variable descriptions
- Improve readability and structure
2026-01-27 23:18:48 +01:00
Daniel Akulenok defbc2d53c docs: Add comprehensive variable documentation to README 2026-01-27 23:18:40 +01:00
Daniel Akulenok d2c03feb17 docs: Clarify key-tls configuration in README 2026-01-27 23:18:40 +01:00
Daniel Akulenok 5d5588fbe8 docs: Enhance README documentation structure 2026-01-27 23:18:40 +01:00
Daniel Akulenok 1342baadcc docs: Expand README with comprehensive usage examples 2026-01-27 23:18:40 +01:00
Daniel Akulenok 71abdaa2e4 style: Standardize indentation across all templates
- Update indentation in controls, DLZ, and DNSSEC policy templates
- Normalize spacing in options and logging templates
- Ensure consistent formatting throughout role
2026-01-27 23:18:40 +01:00
Daniel Akulenok 8de3b75eec refactor: Reorganize configuration options in generator template 2026-01-27 23:18:40 +01:00
Daniel Akulenok fdc91f6ade docs: Remove extraneous line from README 2026-01-27 23:18:40 +01:00
Daniel Akulenok 5d79a3775d fix: Remove debug statement from default variables 2022-08-05 14:45:34 +02:00
Daniel Akulenok 8db883cba9 feat: Initialize BIND9 Ansible role
- Add complete role structure with templates
- Create comprehensive README documentation
- Set up Travis CI configuration
- Add meta information and default variables
2022-08-04 12:41:40 +02:00
13 changed files with 1496 additions and 114 deletions
+6
View File
@@ -0,0 +1,6 @@
<!--# cspell: ignore SSOT CMDB -->
# AGENTS.md
Ensure that all practices and instructions described by
https://raw.githubusercontent.com/ansible/ansible-creator/refs/heads/main/docs/agents.md
are followed.
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -38,7 +38,7 @@ named.conf
bind configuration is set through the various bind9_*_config parameters. These are, in order of precedence: bind configuration is set through the various bind9_*_config parameters. These are, in order of precedence:
1. bind9_default_config 1. bind9_default_config
2. bind9_group_config 2. bind9_group_config
3. bind9_leaf_config 3. bind9_site_config
4. bind9_host_config 4. bind9_host_config
All these configuration parameters are merged in a way where each successing config supercedes the previous one at a config-file level. To illustrate: All these configuration parameters are merged in a way where each successing config supercedes the previous one at a config-file level. To illustrate:
@@ -59,7 +59,7 @@ bind9_group_config:
- name: "." - name: "."
type: mirror type: mirror
bind9_leaf_config: bind9_site_config:
- name: named.conf.local - name: named.conf.local
zone: zone:
- name: "." - name: "."
@@ -81,7 +81,7 @@ bind9_config:
file: /etc/share/dns/root.hints file: /etc/share/dns/root.hints
``` ```
The `named.conf.options` block in `bind9_default_config` got completely overwritten by the `bind9_group_config`, and the `bind9_leaf_config` completely overwrote `named.conf.local`, however, `named.conf.options` was left intact after merging with `bind9_leaf_config`. The `named.conf.options` block in `bind9_default_config` got completely overwritten by the `bind9_group_config`, and the `bind9_site_config` completely overwrote `named.conf.local`, however, `named.conf.options` was left intact after merging with `bind9_site_config`.
Configuration Grammar Configuration Grammar
--------------------- ---------------------
@@ -198,5 +198,5 @@ BSD
Author Information Author Information
------------------ ------------------
Daniel Akulenok <dak@keepit.com> Daniel Akulenok <daniel@valid.dk>
Keepit A/S - keepit.com Valid.dk
+2 -2
View File
@@ -14,7 +14,7 @@ bind9_debug_config: false
bind9_config_indent: 4 bind9_config_indent: 4
bind9_group_config: [] bind9_group_config: []
bind9_leaf_config: [] bind9_site_config: []
bind9_host_config: [] bind9_host_config: []
bind9_default_config: bind9_default_config:
@@ -30,7 +30,7 @@ bind9_default_config:
bind9_config: "{{ [bind9_default_config, bind9_config: "{{ [bind9_default_config,
bind9_group_config, bind9_group_config,
bind9_leaf_config, bind9_site_config,
bind9_host_config] | bind9_host_config] |
community.general.lists_mergeby('name', community.general.lists_mergeby('name',
recursive=true, recursive=true,
+55
View File
@@ -0,0 +1,55 @@
---
argument_specs:
main:
short_description: The main entry point for the bind9 role.
options:
bind9_config:
type: list
elements: dict
description:
- A list of configuration dictionaries that are merged to produce the final configuration.
- Each element must have a 'name' key (filename).
bind9_default_config:
type: list
elements: dict
description: Default configuration.
bind9_group_config:
type: list
elements: dict
description: Group-level configuration.
bind9_site_config:
type: list
elements: dict
description: Site/Leaf-level configuration.
bind9_host_config:
type: list
elements: dict
description: Host-level configuration.
bind9_backup_config:
type: bool
default: true
description: Whether to backup configuration files before overwriting.
bind9_debug_config:
type: bool
default: false
description: Whether to print the merged configuration during execution.
bind9_config_indent:
type: int
default: 4
description: Indentation level for generated configuration files.
bind9_packages:
type: list
elements: str
description: List of packages to install.
bind9_cfgdir:
type: str
description: Directory for configuration files.
bind9_working_directory:
type: str
description: Working directory for BIND.
bind9_libdir:
type: str
description: Library directory for BIND.
bind9_backup_dir:
type: str
description: Directory for backups.
+3 -3
View File
@@ -1,13 +1,13 @@
--- ---
galaxy_info: galaxy_info:
role_name: bind9 role_name: bind9
namespace: keepit namespace: valid
author: Daniel Akulenok author: Daniel Akulenok
description: Configure Bind9 description: Configure Bind9
company: Keepit company: Valid.dk
issue_tracker_url: https://gitlab.off.keepit.com/operations/ansible-bind9-role issue_tracker_url: https://git.valid.dk/daniel/ansible-bind9-role
license: GPL-3.0-or-later license: GPL-3.0-or-later
-24
View File
@@ -1,30 +1,6 @@
--- ---
- name: Converge - name: Converge
hosts: all hosts: all
vars:
bind9_group_config:
- name: named.conf.options
options:
directory: "{{ bind9_working_directory }}"
forwarders:
port: 853
tls: common-upstream
addresses:
- address: 192.0.2.10
port: 5353
tls: leaf-a
- address:
- 2001:db8::10
- 198.51.100.10
tls: dual-stack
- 203.0.113.10
tls:
- name: common-upstream
remote_hostname: upstream.example
- name: leaf-a
remote_hostname: leaf-a.example
- name: dual-stack
remote_hostname: dual-stack.example
tasks: tasks:
- name: Include bind9 role - name: Include bind9 role
ansible.builtin.include_role: ansible.builtin.include_role:
+7
View File
@@ -2,6 +2,13 @@
driver: driver:
name: podman name: podman
platforms: platforms:
- name: debian-bookworm
image: docker.io/jrei/systemd-debian:12
command: /lib/systemd/systemd
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
- name: debian-trixie - name: debian-trixie
image: docker.io/jrei/systemd-debian:13 image: docker.io/jrei/systemd-debian:13
command: /lib/systemd/systemd command: /lib/systemd/systemd
-21
View File
@@ -1,21 +0,0 @@
---
- name: Verify forwarders configuration
hosts: all
gather_facts: false
tasks:
- name: Read named.conf.options
ansible.builtin.slurp:
src: /etc/bind/named.conf.options
register: forwarders_file
- name: Assert forwarders render with port and tls
ansible.builtin.assert:
that:
- forwarders_content is search('forwarders port 853 tls common-upstream \{')
- forwarders_content is search('192.0.2.10 port 5353 tls leaf-a;')
- forwarders_content is search('2001:db8::10 tls dual-stack;')
- forwarders_content is search('198.51.100.10 tls dual-stack;')
- forwarders_content is search('203.0.113.10;')
fail_msg: "Forwarders block missing expected port/tls entries"
vars:
forwarders_content: "{{ forwarders_file.content | b64decode }}"
+62 -13
View File
@@ -16,20 +16,69 @@
owner: root owner: root
group: root group: root
mode: 0750 mode: 0750
when: bind9_backup_config is defined and bind9_backup_config when: bind9_backup_config is defined and bind9_backup_config | bool
- name: Template named.conf.generator - name: Deploy and Validate Configuration
ansible.builtin.template: block:
src: named.conf.generator.j2 - name: Create backup of current config
dest: "{{ bind9_cfgdir }}/{{ item.name }}" ansible.builtin.copy:
owner: root src: "{{ bind9_cfgdir }}/{{ item.name }}"
group: bind dest: "{{ bind9_cfgdir }}/{{ item.name }}.bak"
mode: 0640 remote_src: true
backup: "{{ item.backup | default('false') | bool }}" owner: root
# validate: 'named-checkconf -z -j %s' group: bind
loop: "{{ bind9_config }}" mode: 0640
loop_control: failed_when: false # It's okay if the file doesn't exist yet
label: "{{ item.name }}" # We do this for every file in the loop
loop: "{{ bind9_config }}"
loop_control:
label: "{{ item.name }}"
- name: Template named.conf.generator
ansible.builtin.template:
src: named.conf.generator.j2
dest: "{{ bind9_cfgdir }}/{{ item.name }}"
owner: root
group: bind
mode: 0640
loop: "{{ bind9_config }}"
loop_control:
label: "{{ item.name }}"
register: _template_result
- name: Validate configuration using named-checkconf
ansible.builtin.command:
cmd: "named-checkconf -z {{ bind9_cfgdir }}/named.conf"
changed_when: false
rescue:
- name: Restore configuration from backup
ansible.builtin.copy:
src: "{{ bind9_cfgdir }}/{{ item.name }}.bak"
dest: "{{ bind9_cfgdir }}/{{ item.name }}"
remote_src: true
owner: root
group: bind
mode: 0640
loop: "{{ bind9_config }}"
loop_control:
label: "{{ item.name }}"
failed_when: false # Best effort restore
- name: Fail due to invalid configuration
ansible.builtin.fail:
msg: "Configuration validation failed. Changes have been reverted. Check the logs for named-checkconf errors."
always:
- name: Remove backup files
ansible.builtin.file:
path: "{{ bind9_cfgdir }}/{{ item.name }}.bak"
state: absent
loop: "{{ bind9_config }}"
loop_control:
label: "{{ item.name }}"
when: bind9_backup_config | bool is false # Keep if backup is forced, otherwise cleanup temporary atomic backup
tags: tags:
- bind9 - bind9
- template - template
+2 -44
View File
@@ -42,46 +42,6 @@
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro list_address_port_tls(dict, indent=bind9_config_indent) %}
{# This macro is for use for statements with grammar like #}
{# address port 00 tls string; address port 00 tls string; #}
{# it is usually called by a parent macro #}
{% filter indent(indent, true) %}
{% for item in dict %}
{% if item is not mapping %}
{{ item }};
{% elif item.address is string %}
{{ item.address -}}
{{- (' port ' + item.port | string) if item.port is defined and item.port -}}
{{- (' tls ' + item.tls | string) if item.tls is defined and item.tls -}};
{% elif item.address is sequence %}
{% for address in item.address %}
{{ address -}}
{{- (' port ' + item.port | string) if item.port is defined and item.port -}}
{{- (' tls ' + item.tls | string) if item.tls is defined and item.tls -}};
{% endfor %}
{% endif %}
{% endfor %}
{% endfilter %}
{% endmacro %}
{% macro parent_address_port_tls(name, dict) %}
{# This macro is for statements with grammar like #}
{# statement port 00 tls string { address port 00 tls string; address port 00 tls string; } #}
{# the list inside the statement is handled by list_address_port_tls #}
{% if dict is not mapping and dict is iterable %}
{{ name }} {
{{ list_address_port_tls(dict) -}}
};
{% else %}
{{ name }}
{{- (' port ' + dict.port | string) if dict.port is defined and dict.port -}}
{{- (' tls ' + dict.tls | string) if dict.tls is defined and dict.tls }} {
{{ list_address_port_tls(dict.addresses) -}}
};
{% endif %}
{% endmacro %}
{% macro list_address_port_dscp(dict, indent=bind9_config_indent) %} {% macro list_address_port_dscp(dict, indent=bind9_config_indent) %}
{# This macro is for use for statements with grammar like #} {# This macro is for use for statements with grammar like #}
{# address port 00 dscp 00; address port 00 dscp 00; #} {# address port 00 dscp 00; address port 00 dscp 00; #}
@@ -105,14 +65,12 @@
{# the list inside the statement is handled by list_address_port #} {# the list inside the statement is handled by list_address_port #}
{% if dict is not mapping and dict is iterable %} {% if dict is not mapping and dict is iterable %}
{{ name }} { {{ name }} {
{{ list_address_port_dscp(dict) }} {{ list_address_port_dscp(dict) }}};
};
{% else %} {% else %}
{{ name }} {{ name }}
{{- (' port ' + dict.port | string) if dict.port is defined and dict.port -}} {{- (' port ' + dict.port | string) if dict.port is defined and dict.port -}}
{{- (' dscp ' + dict.dscp | string) if dict.dscp is defined and dict.dscp }} { {{- (' dscp ' + dict.dscp | string) if dict.dscp is defined and dict.dscp }} {
{{ list_address_port_dscp(dict.addresses) }} {{ list_address_port_dscp(dict.addresses) }}};
};
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
+1 -1
View File
@@ -101,7 +101,7 @@ listen-on
{{ functions.simple_item_list(item.options.listen_on.addresses) }}}; {{ functions.simple_item_list(item.options.listen_on.addresses) }}};
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{{ functions.parent_address_port_tls('forwarders', item.options.forwarders) if item.options.forwarders is defined and item.options.forwarders -}} {{ functions.parent_address_port_dscp("forwarders", item.options.forwarders) if item.options.forwarders is defined and item.options.forwarders -}}
{% if item.options.dual_stack_servers is defined and item.options.dual_stack_servers %} {% if item.options.dual_stack_servers is defined and item.options.dual_stack_servers %}
dual-stack-servers dual-stack-servers
{{ (' port ' + item.options.dual_stack_servers.port | string) if item.options.dual_stack_servers.port is defined and item.options.dual_stack_servers }} { {{ (' port ' + item.options.dual_stack_servers.port | string) if item.options.dual_stack_servers.port is defined and item.options.dual_stack_servers }} {
+1 -1
View File
@@ -47,7 +47,7 @@ server-names {
server-addresses { server-addresses {
{{ functions.simple_item_list(zone.server_addresses) }}}; {{ functions.simple_item_list(zone.server_addresses) }}};
{% endif %} {% endif %}
{{ functions.parent_address_port_tls('forwarders', zone.forwarders) if zone.forwarders is defined and zone.forwarders -}} {{ functions.parent_address_port_dscp('forwarders', zone.forwarders) if zone.forwarders is defined and zone.forwarders -}}
{% if zone.allow_transfer is defined and zone.allow_transfer is not string %} {% if zone.allow_transfer is defined and zone.allow_transfer is not string %}
allow-transfer allow-transfer
{{- (' port ' + zone.allow_transfer.port | string) if zone.allow_transfer.port is defined and zone.allow_transfer.port -}} {{- (' port ' + zone.allow_transfer.port | string) if zone.allow_transfer.port is defined and zone.allow_transfer.port -}}