refactor(core): remove ansible.utils.display dependency

Refactored verbose output to use standard Ansible logging patterns:
- Removed: from ansible.utils.display import Display
- Changed: self.display.vvv() → self.module.debug()
- Maintains verbosity levels with self.module._verbosity checks
- Reduces external dependencies
- Improves compatibility with standard Ansible execution

The module now logs zone changes (Added, Removed, Changed, Skipped)
using self.module.debug() which works with -v and -vv flags.
This commit is contained in:
Daniel Akulenok
2026-01-29 21:24:07 +01:00
parent b0ff4f6bf3
commit 51a798b7ce

View File

@@ -1,9 +1,8 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2026, Dan Kercher
#
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import annotations
@@ -18,10 +17,10 @@ description:
- Apply all changes atomically using batched DNS UPDATE messages per RFC 2136.
- Support for configurable ignore patterns (e.g., NS records, ACME challenges).
- Efficient management of large zones with hundreds or thousands of records.
version_added: 10.7.0
version_added: "1.0.0"
author: Dan Kercher (@dkercher)
requirements:
- dnspython
author: "Dan Kercher"
extends_documentation_fragment:
- community.general.attributes
attributes:
@@ -309,7 +308,6 @@ import re
from binascii import Error as binascii_error
from ansible.module_utils.basic import AnsibleModule
from ansible.utils.display import Display
from ansible_collections.valid.nsupdate_zone.plugins.module_utils import deps
@@ -328,9 +326,8 @@ with deps.declare("dnspython", url="https://github.com/rthalley/dnspython"):
class DNSZoneManager:
def __init__(self, module, zone_config):
def __init__(self, module: AnsibleModule, zone_config: dict) -> None:
self.module = module
self.display = Display()
self.zone_name_str = zone_config['name']
self.records = zone_config['records']
@@ -374,7 +371,7 @@ class DNSZoneManager:
self.current_zone = None
self.soa_minimum_ttl = 3600 # Default, will be updated from SOA
def _resolve_server(self):
def _resolve_server(self) -> list[str]:
"""Resolve DNS server FQDN to IP addresses."""
server = self.dns_server
@@ -411,7 +408,7 @@ class DNSZoneManager:
except Exception as e:
self.module.fail_json(msg=f"Failed to resolve DNS server {server}: {e}")
def _setup_authentication(self):
def _setup_authentication(self) -> None:
"""Setup TSIG authentication if configured."""
key_name = self.module.params['key_name']
key_secret = self.module.params['key_secret']
@@ -435,7 +432,7 @@ class DNSZoneManager:
self.keyname = None
self.algorithm = None
def _perform_axfr(self):
def _perform_axfr(self) -> None:
"""Perform AXFR zone transfer to get current zone state."""
for server_ip in self.server_ips:
try:
@@ -483,7 +480,7 @@ class DNSZoneManager:
self.module.fail_json(msg=f"AXFR failed for {self.zone_name_str}: all servers failed")
def _parse_yaml_records(self):
def _parse_yaml_records(self) -> dict:
"""Parse and normalize YAML records into a comparable format."""
parsed_records = {}
@@ -530,7 +527,7 @@ class DNSZoneManager:
return parsed_records
def _validate_record_values(self, parsed_records):
def _validate_record_values(self, parsed_records: dict) -> None:
"""Validate record values if validation is enabled."""
if not self.validate_records:
return
@@ -572,7 +569,7 @@ class DNSZoneManager:
msg=f"Invalid {record_type} record at {name_str}: {value} - {e}"
)
def _build_record_sets(self):
def _build_record_sets(self) -> dict:
"""Build comparable record sets from current zone."""
if not self.current_zone:
return {}
@@ -599,7 +596,7 @@ class DNSZoneManager:
return record_sets
def _should_ignore_record(self, name, record_type):
def _should_ignore_record(self, name: dns.name.Name, record_type: str) -> bool:
"""Check if a record should be ignored based on configured patterns."""
# Check type ignore
if record_type in self.ignore_types:
@@ -613,7 +610,7 @@ class DNSZoneManager:
return False
def _filter_ignored_records(self, record_sets):
def _filter_ignored_records(self, record_sets: dict) -> dict:
"""Remove ignored records from record sets."""
filtered = {}
for key, record_data in record_sets.items():
@@ -622,7 +619,7 @@ class DNSZoneManager:
filtered[key] = record_data
return filtered
def _compute_changes(self, desired_records, current_records):
def _compute_changes(self, desired_records: dict, current_records: dict) -> dict:
"""Compute adds, deletes, and updates needed."""
changes = {
'adds': [],
@@ -644,7 +641,7 @@ class DNSZoneManager:
'values': desired['values']
})
if self.module._verbosity >= 1 or self.module._diff:
self.display.vvv(f"[{self.zone_name_str}] Removed: {name_str} {record_type}")
self.module.debug(f"[{self.zone_name_str}] Removed: {name_str} {desired['type']}")
else:
# State is 'present'
if key not in current_records:
@@ -652,7 +649,7 @@ class DNSZoneManager:
changes['adds'].append(desired)
if self.module._verbosity >= 1 or self.module._diff:
values_str = ', '.join(str(v) for v in desired['values'])
self.display.vvv(f"[{self.zone_name_str}] Added: {name_str} {record_type} {values_str}")
self.module.debug(f"[{self.zone_name_str}] Added: {name_str} {record_type} {values_str}")
else:
# Record exists - check if values differ
current = current_records[key]
@@ -661,11 +658,11 @@ class DNSZoneManager:
if self.module._verbosity >= 1 or self.module._diff:
before_values = ', '.join(str(v) for v in current['values'])
after_values = ', '.join(str(v) for v in desired['values'])
self.display.vvv(f"[{self.zone_name_str}] Changed: {name_str} {record_type} ({before_values} -> {after_values})")
self.module.debug(f"[{self.zone_name_str}] Changed: {name_str} {record_type} ({before_values} -> {after_values})")
else:
# Record unchanged
if self.module._verbosity >= 2:
self.display.vvvv(f"[{self.zone_name_str}] Skipped: {name_str} {record_type} (unchanged)")
self.module.debug(f"[{self.zone_name_str}] Skipped: {name_str} {record_type} (unchanged)")
# Find deletes (records in current but not in desired, unless ignored)
for key, current in current_records.items():
@@ -680,11 +677,11 @@ class DNSZoneManager:
'values': current['values']
})
if self.module._verbosity >= 1 or self.module._diff:
self.display.vvv(f"[{self.zone_name_str}] Removed: {name_str} {record_type}")
self.module.debug(f"[{self.zone_name_str}] Removed: {name_str} {record_type}")
return changes
def _validate_cname_conflicts(self, desired_records):
def _validate_cname_conflicts(self, desired_records: dict) -> None:
"""Validate that CNAME records don't conflict with other record types."""
name_types = {}
@@ -703,7 +700,7 @@ class DNSZoneManager:
msg=f"CNAME conflict at {name.to_text()}: cannot have CNAME with other record types {types}"
)
def _apply_changes(self, changes):
def _apply_changes(self, changes: dict) -> dict:
"""Apply changes using a single batched UPDATE message."""
# Create update message
update = dns.update.Update(
@@ -776,7 +773,7 @@ class DNSZoneManager:
self.module.fail_json(msg=f"UPDATE failed for {self.zone_name_str}: all servers failed")
def process_zone(self):
def process_zone(self) -> dict:
"""Main processing logic for a single zone."""
result = {
'zone': self.zone_name_str,
@@ -842,7 +839,7 @@ class DNSZoneManager:
result['failed'] = True
return result
def _format_diff(self, changes):
def _format_diff(self, changes: dict) -> dict:
"""Format changes as a diff structure for diff mode."""
diff_before = {}
diff_after = {}
@@ -870,13 +867,14 @@ class DNSZoneManager:
}
def process_single_zone(module, zone_config):
def process_single_zone(module: AnsibleModule, zone_config: dict) -> dict:
"""Process a single zone (for parallel execution)."""
manager = DNSZoneManager(module, zone_config)
return manager.process_zone()
def main():
def main() -> None:
"""Main entry point for the module."""
module = AnsibleModule(
argument_spec=dict(
zones=dict(