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:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user