diff --git a/README.md b/README.md index 4ca56af..fdcba61 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ named.conf bind configuration is set through the various bind9_*_config parameters. These are, in order of precedence: 1. bind9_default_config 2. bind9_group_config -3. bind9_leaf_config +3. bind9_site_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: @@ -59,7 +59,7 @@ bind9_group_config: - name: "." type: mirror -bind9_leaf_config: +bind9_site_config: - name: named.conf.local zone: - name: "." @@ -81,7 +81,7 @@ bind9_config: 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 --------------------- diff --git a/defaults/main.yml b/defaults/main.yml index 42c96d6..34ba28d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -14,7 +14,7 @@ bind9_debug_config: false bind9_config_indent: 4 bind9_group_config: [] -bind9_leaf_config: [] +bind9_site_config: [] bind9_host_config: [] bind9_default_config: @@ -30,7 +30,7 @@ bind9_default_config: bind9_config: "{{ [bind9_default_config, bind9_group_config, - bind9_leaf_config, + bind9_site_config, bind9_host_config] | community.general.lists_mergeby('name', recursive=true, diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml new file mode 100644 index 0000000..fac379f --- /dev/null +++ b/meta/argument_specs.yml @@ -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. diff --git a/tasks/main.yml b/tasks/main.yml index d9585f0..12df4a5 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -16,20 +16,69 @@ owner: root group: root 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 - ansible.builtin.template: - src: named.conf.generator.j2 - dest: "{{ bind9_cfgdir }}/{{ item.name }}" - owner: root - group: bind - mode: 0640 - backup: "{{ item.backup | default('false') | bool }}" - # validate: 'named-checkconf -z -j %s' - loop: "{{ bind9_config }}" - loop_control: - label: "{{ item.name }}" +- name: Deploy and Validate Configuration + block: + - name: Create backup of current config + ansible.builtin.copy: + src: "{{ bind9_cfgdir }}/{{ item.name }}" + dest: "{{ bind9_cfgdir }}/{{ item.name }}.bak" + remote_src: true + owner: root + group: bind + mode: 0640 + failed_when: false # It's okay if the file doesn't exist yet + # 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: - bind9 - template