summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/dns/plugins/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:22 +0000
commit38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch)
tree356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/community/dns/plugins/modules
parentAdding upstream version 7.7.0+dfsg. (diff)
downloadansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz
ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/dns/plugins/modules')
-rw-r--r--ansible_collections/community/dns/plugins/modules/hetzner_dns_record.py1
-rw-r--r--ansible_collections/community/dns/plugins/modules/hetzner_dns_record_info.py9
-rw-r--r--ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set.py6
-rw-r--r--ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set_info.py13
-rw-r--r--ansible_collections/community/dns/plugins/modules/hetzner_dns_record_sets.py1
-rw-r--r--ansible_collections/community/dns/plugins/modules/hetzner_dns_zone_info.py2
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_record.py1
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_record_info.py7
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set.py5
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set_info.py11
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_record_sets.py1
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_records.py1
-rw-r--r--ansible_collections/community/dns/plugins/modules/hosttech_dns_zone_info.py10
-rw-r--r--ansible_collections/community/dns/plugins/modules/nameserver_info.py168
-rw-r--r--ansible_collections/community/dns/plugins/modules/nameserver_record_info.py568
-rw-r--r--ansible_collections/community/dns/plugins/modules/wait_for_txt.py193
16 files changed, 890 insertions, 107 deletions
diff --git a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record.py b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record.py
index b17e0842c..23c873322 100644
--- a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record.py
+++ b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record.py
@@ -27,6 +27,7 @@ description:
extends_documentation_fragment:
- community.dns.hetzner
- community.dns.hetzner.record_default_ttl
+ - community.dns.hetzner.record_notes
- community.dns.hetzner.record_type_choices
- community.dns.hetzner.zone_id_type
- community.dns.module_record
diff --git a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_info.py b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_info.py
index 9d77a38d5..edf65aaca 100644
--- a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_info.py
+++ b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_info.py
@@ -37,6 +37,11 @@ attributes:
author:
- Markus Bergholz (@markuman) <markuman+spambelongstogoogle@gmail.com>
- Felix Fontein (@felixfontein)
+
+seealso:
+ - module: community.dns.hetzner_dns_record_set_info
+ - plugin: community.dns.hetzner_dns_records
+ plugin_type: inventory
'''
EXAMPLES = '''
@@ -58,7 +63,7 @@ records:
description: The list of fetched records.
type: list
elements: dict
- returned: success and I(what) is not C(single_record)
+ returned: success and O(what) is not V(single_record)
contains:
record:
description: The record name.
@@ -75,7 +80,7 @@ records:
ttl:
description:
- The TTL.
- - Will return C(none) if the zone's default TTL is used.
+ - Will return V(none) if the zone's default TTL is used.
type: int
sample: 3600
value:
diff --git a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set.py b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set.py
index 0766e6465..ce3ad313a 100644
--- a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set.py
+++ b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set.py
@@ -23,6 +23,7 @@ description:
extends_documentation_fragment:
- community.dns.hetzner
- community.dns.hetzner.record_default_ttl
+ - community.dns.hetzner.record_notes
- community.dns.hetzner.record_type_choices
- community.dns.hetzner.zone_id_type
- community.dns.module_record_set
@@ -128,10 +129,9 @@ EXAMPLES = '''
zone: foo.com
record: foo.com
type: CAA
- ttl: 3600
value:
- - "128 issue letsencrypt.org"
- - "128 iodef mailto:webmaster@foo.com"
+ - '128 issue "letsencrypt.org"'
+ - '128 iodef "mailto:webmaster@foo.com"'
hetzner_token: access_token
- name: Add an MX record
diff --git a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set_info.py b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set_info.py
index 5c70d1fb0..2df5d0f77 100644
--- a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set_info.py
+++ b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_set_info.py
@@ -37,6 +37,11 @@ attributes:
author:
- Markus Bergholz (@markuman) <markuman+spambelongstogoogle@gmail.com>
- Felix Fontein (@felixfontein)
+
+seealso:
+ - module: community.dns.hetzner_dns_record_info
+ - plugin: community.dns.hetzner_dns_records
+ plugin_type: inventory
'''
EXAMPLES = '''
@@ -57,7 +62,7 @@ RETURN = '''
set:
description: The fetched record set. Is empty if record set does not exist.
type: dict
- returned: success and I(what) is C(single_record)
+ returned: success and O(what) is V(single_record)
contains:
record:
description: The record name.
@@ -76,7 +81,7 @@ set:
description:
- The TTL.
- If there are records in this set with different TTLs, the minimum of the TTLs will be presented here.
- - Will return C(none) if the zone's default TTL is used.
+ - Will return V(none) if the zone's default TTL is used.
type: int
sample: 3600
ttls:
@@ -109,7 +114,7 @@ sets:
description: The list of fetched record sets.
type: list
elements: dict
- returned: success and I(what) is not C(single_record)
+ returned: success and O(what) is not V(single_record)
contains:
record:
description: The record name.
@@ -128,7 +133,7 @@ sets:
description:
- The TTL.
- If there are records in this set with different TTLs, the minimum of the TTLs will be presented here.
- - Will return C(none) if the zone's default TTL is used.
+ - Will return V(none) if the zone's default TTL is used.
type: int
sample: 3600
ttls:
diff --git a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_sets.py b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_sets.py
index 52857186c..e7d515efe 100644
--- a/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_sets.py
+++ b/ansible_collections/community/dns/plugins/modules/hetzner_dns_record_sets.py
@@ -22,6 +22,7 @@ description:
extends_documentation_fragment:
- community.dns.hetzner
+ - community.dns.hetzner.record_notes
- community.dns.hetzner.record_type_choices_record_sets_module
- community.dns.hetzner.zone_id_type
- community.dns.module_record_sets
diff --git a/ansible_collections/community/dns/plugins/modules/hetzner_dns_zone_info.py b/ansible_collections/community/dns/plugins/modules/hetzner_dns_zone_info.py
index 44cc88af5..9f4626e06 100644
--- a/ansible_collections/community/dns/plugins/modules/hetzner_dns_zone_info.py
+++ b/ansible_collections/community/dns/plugins/modules/hetzner_dns_zone_info.py
@@ -121,7 +121,7 @@ zone_info:
status:
description:
- Status of the zone.
- - Can be one of C(verified), C(failed) and C(pending).
+ - Can be one of V(verified), V(failed) and V(pending).
type: str
sample: verified
# choices:
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record.py
index 0756b6a4c..1473f6624 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record.py
@@ -28,6 +28,7 @@ description:
extends_documentation_fragment:
- community.dns.hosttech
- community.dns.hosttech.record_default_ttl
+ - community.dns.hosttech.record_notes
- community.dns.hosttech.record_type_choices
- community.dns.hosttech.zone_id_type
- community.dns.module_record
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_info.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_info.py
index 84ee8e3b2..71004464e 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_info.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_info.py
@@ -36,6 +36,11 @@ attributes:
author:
- Felix Fontein (@felixfontein)
+
+seealso:
+ - module: community.dns.hosttech_dns_record_set_info
+ - plugin: community.dns.hosttech_dns_records
+ plugin_type: inventory
'''
EXAMPLES = '''
@@ -57,7 +62,7 @@ records:
description: The list of fetched records.
type: list
elements: dict
- returned: success and I(what) is not C(single_record)
+ returned: success and O(what) is not V(single_record)
contains:
record:
description: The record name.
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set.py
index d16c82ad7..7da02aec4 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set.py
@@ -24,6 +24,7 @@ description:
extends_documentation_fragment:
- community.dns.hosttech
- community.dns.hosttech.record_default_ttl
+ - community.dns.hosttech.record_notes
- community.dns.hosttech.record_type_choices
- community.dns.hosttech.zone_id_type
- community.dns.module_record_set
@@ -128,8 +129,8 @@ EXAMPLES = '''
type: CAA
ttl: 3600
value:
- - "128 issue letsencrypt.org"
- - "128 iodef mailto:webmaster@foo.com"
+ - '128 issue "letsencrypt.org"'
+ - '128 iodef "mailto:webmaster@foo.com"'
hosttech_token: access_token
- name: Add an MX record
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set_info.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set_info.py
index 5b7c576b8..60a54809d 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set_info.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_set_info.py
@@ -19,7 +19,7 @@ version_added: 0.1.0
description:
- "Retrieves DNS record sets in Hosttech DNS service."
- - This module was renamed from C(community.dns.hosttech_dns_record_info) to C(community.dns.hosttech_dns_record_set_info)
+ - This module was renamed from C(community.dns.hosttech_dns_record_info) to M(community.dns.hosttech_dns_record_set_info)
in community.dns 2.0.0.
extends_documentation_fragment:
@@ -38,6 +38,11 @@ attributes:
author:
- Felix Fontein (@felixfontein)
+
+seealso:
+ - module: community.dns.hosttech_dns_record_info
+ - plugin: community.dns.hosttech_dns_records
+ plugin_type: inventory
'''
EXAMPLES = '''
@@ -58,7 +63,7 @@ RETURN = '''
set:
description: The fetched record set. Is empty if record set does not exist.
type: dict
- returned: success and I(what) is C(single_record)
+ returned: success and O(what=single_record)
contains:
record:
description: The record name.
@@ -109,7 +114,7 @@ sets:
description: The list of fetched record sets.
type: list
elements: dict
- returned: success and I(what) is not C(single_record)
+ returned: success and O(what=single_record)
contains:
record:
description: The record name.
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_sets.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_sets.py
index c985779ca..583cfa58e 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_sets.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_record_sets.py
@@ -23,6 +23,7 @@ description:
extends_documentation_fragment:
- community.dns.hosttech
+ - community.dns.hosttech.record_notes
- community.dns.hosttech.record_type_choices_record_sets_module
- community.dns.hosttech.zone_id_type
- community.dns.module_record_sets
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_records.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_records.py
index c985779ca..583cfa58e 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_records.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_records.py
@@ -23,6 +23,7 @@ description:
extends_documentation_fragment:
- community.dns.hosttech
+ - community.dns.hosttech.record_notes
- community.dns.hosttech.record_type_choices_record_sets_module
- community.dns.hosttech.zone_id_type
- community.dns.module_record_sets
diff --git a/ansible_collections/community/dns/plugins/modules/hosttech_dns_zone_info.py b/ansible_collections/community/dns/plugins/modules/hosttech_dns_zone_info.py
index 6621893a7..d364d0694 100644
--- a/ansible_collections/community/dns/plugins/modules/hosttech_dns_zone_info.py
+++ b/ansible_collections/community/dns/plugins/modules/hosttech_dns_zone_info.py
@@ -80,22 +80,22 @@ zone_info:
description:
- Whether DNSSEC is enabled for the zone or not.
type: bool
- returned: When I(hosttech_token) has been specified.
+ returned: When O(hosttech_token) has been specified.
dnssec_email:
description:
- The email address contacted when the DNSSEC key is changed.
- - Is C(none) if DNSSEC is not enabled.
+ - Is V(none) if DNSSEC is not enabled.
type: str
- returned: When I(hosttech_token) has been specified.
+ returned: When O(hosttech_token) has been specified.
ds_records:
description:
- The DS records.
- See L(Section 5 of RFC 4034,https://datatracker.ietf.org/doc/html/rfc4034#section-5) and
L(Section 2.1 of RFC 4034,https://datatracker.ietf.org/doc/html/rfc4034#section-2.1) for details.
- - Is C(none) if DNSSEC is not enabled.
+ - Is V(none) if DNSSEC is not enabled.
type: list
elements: dict
- returned: When I(hosttech_token) has been specified.
+ returned: When O(hosttech_token) has been specified.
contains:
algorithm:
description:
diff --git a/ansible_collections/community/dns/plugins/modules/nameserver_info.py b/ansible_collections/community/dns/plugins/modules/nameserver_info.py
new file mode 100644
index 000000000..62ba30961
--- /dev/null
+++ b/ansible_collections/community/dns/plugins/modules/nameserver_info.py
@@ -0,0 +1,168 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
+# 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
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+DOCUMENTATION = r'''
+---
+module: nameserver_info
+short_description: Look up nameservers for a DNS name
+version_added: 2.6.0
+description:
+ - Retrieve all nameservers that are responsible for a DNS name.
+extends_documentation_fragment:
+ - community.dns.attributes
+ - community.dns.attributes.info_module
+author:
+ - Felix Fontein (@felixfontein)
+options:
+ name:
+ description:
+ - A list of DNS names whose nameservers to retrieve.
+ required: true
+ type: list
+ elements: str
+ resolve_addresses:
+ description:
+ - Whether to resolve the nameserver names to IP addresses.
+ type: bool
+ default: false
+ query_retry:
+ description:
+ - Number of retries for DNS query timeouts.
+ type: int
+ default: 3
+ query_timeout:
+ description:
+ - Timeout per DNS query in seconds.
+ type: float
+ default: 10
+ always_ask_default_resolver:
+ description:
+ - When set to V(true) (default), will use the default resolver to find the authoritative nameservers
+ of a subzone. See O(server) for how to configure the default resolver.
+ - When set to V(false), will use the authoritative nameservers of the parent zone to find the
+ authoritative nameservers of a subzone. This only makes sense when the nameservers were recently
+ changed and have not yet propagated.
+ type: bool
+ default: true
+ servfail_retries:
+ description:
+ - How often to retry on SERVFAIL errors.
+ type: int
+ default: 0
+ server:
+ description:
+ - The DNS server(s) to use to look up the result. Must be a list of one or more IP addresses.
+ - By default, the system's standard resolver is used.
+ type: list
+ elements: str
+ version_added: 2.7.0
+requirements:
+ - dnspython >= 1.15.0 (maybe older versions also work)
+'''
+
+EXAMPLES = r'''
+- name: Retrieve name servers of two DNS names
+ community.dns.nameserver_info:
+ name:
+ - www.example.com
+ - example.org
+ register: result
+
+- name: Show nameservers for www.example.com
+ ansible.builtin.debug:
+ msg: '{{ result.results[0].nameserver }}'
+'''
+
+RETURN = r'''
+results:
+ description:
+ - Information on the nameservers for every DNS name provided in O(name).
+ returned: always
+ type: list
+ elements: dict
+ contains:
+ name:
+ description:
+ - The DNS name this entry is for.
+ returned: always
+ type: str
+ sample: www.example.com
+ nameservers:
+ description:
+ - A list of nameservers for this DNS name.
+ returned: success
+ type: list
+ elements: str
+ sample:
+ - ns1.example.com
+ - ns2.example.com
+ sample:
+ - name: www.example.com
+ nameservers:
+ - ns1.example.com
+ - ns2.example.com
+ - name: example.org
+ nameservers:
+ - ns1.example.org
+ - ns2.example.org
+ - ns3.example.org
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.community.dns.plugins.module_utils.resolver import (
+ ResolveDirectlyFromNameServers,
+ assert_requirements_present,
+ guarded_run,
+)
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ name=dict(required=True, type='list', elements='str'),
+ resolve_addresses=dict(type='bool', default=False),
+ query_retry=dict(type='int', default=3),
+ query_timeout=dict(type='float', default=10),
+ always_ask_default_resolver=dict(type='bool', default=True),
+ servfail_retries=dict(type='int', default=0),
+ server=dict(type='list', elements='str'),
+ ),
+ supports_check_mode=True,
+ )
+ assert_requirements_present(module)
+
+ names = module.params['name']
+ resolve_addresses = module.params['resolve_addresses']
+
+ resolver = ResolveDirectlyFromNameServers(
+ timeout=module.params['query_timeout'],
+ timeout_retries=module.params['query_retry'],
+ servfail_retries=module.params['servfail_retries'],
+ always_ask_default_resolver=module.params['always_ask_default_resolver'],
+ server_addresses=module.params['server'],
+ )
+ results = [None] * len(names)
+ for index, name in enumerate(names):
+ results[index] = {
+ 'name': name,
+ }
+
+ def f():
+ for index, name in enumerate(names):
+ results[index]['nameservers'] = sorted(resolver.resolve_nameservers(name, resolve_addresses=resolve_addresses))
+
+ guarded_run(f, module, generate_additional_results=lambda: dict(results=results))
+ module.exit_json(results=results)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/dns/plugins/modules/nameserver_record_info.py b/ansible_collections/community/dns/plugins/modules/nameserver_record_info.py
new file mode 100644
index 000000000..f9374acae
--- /dev/null
+++ b/ansible_collections/community/dns/plugins/modules/nameserver_record_info.py
@@ -0,0 +1,568 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
+# 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
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+DOCUMENTATION = r'''
+---
+module: nameserver_record_info
+short_description: Look up all records of a type from all nameservers for a DNS name
+version_added: 2.6.0
+description:
+ - Given a DNS name and a record type, will retrieve all nameservers that are responsible for
+ this DNS name, and from them all records for this name of the given type.
+extends_documentation_fragment:
+ - community.dns.attributes
+ - community.dns.attributes.info_module
+author:
+ - Felix Fontein (@felixfontein)
+options:
+ name:
+ description:
+ - A list of DNS names whose nameservers to retrieve.
+ required: true
+ type: list
+ elements: str
+ type:
+ description:
+ - The record type to retrieve.
+ required: true
+ type: str
+ choices:
+ - A
+ - ALL
+ - AAAA
+ - CAA
+ - CNAME
+ - DNAME
+ - DNSKEY
+ - DS
+ - HINFO
+ - LOC
+ - MX
+ - NAPTR
+ - NS
+ - NSEC
+ - NSEC3
+ - NSEC3PARAM
+ - PTR
+ - RP
+ - RRSIG
+ - SOA
+ - SPF
+ - SRV
+ - SSHFP
+ - TLSA
+ - TXT
+ query_retry:
+ description:
+ - Number of retries for DNS query timeouts.
+ type: int
+ default: 3
+ query_timeout:
+ description:
+ - Timeout per DNS query in seconds.
+ type: float
+ default: 10
+ always_ask_default_resolver:
+ description:
+ - When set to V(true) (default), will use the default resolver to find the authoritative nameservers
+ of a subzone. See O(server) for how to configure the default resolver.
+ - When set to V(false), will use the authoritative nameservers of the parent zone to find the
+ authoritative nameservers of a subzone. This only makes sense when the nameservers were recently
+ changed and have not yet propagated.
+ type: bool
+ default: true
+ servfail_retries:
+ description:
+ - How often to retry on SERVFAIL errors.
+ type: int
+ default: 0
+ server:
+ description:
+ - The DNS server(s) to use to look up the result. Must be a list of one or more IP addresses.
+ - By default, the system's standard resolver is used.
+ type: list
+ elements: str
+ version_added: 2.7.0
+requirements:
+ - dnspython >= 1.15.0 (maybe older versions also work)
+notes:
+ - dnspython before 2.0.0 does not correctly support (un-)escaping UTF-8 in TXT-like records. This can
+ result in wrongly decoded TXT records. Please use dnspython 2.0.0 or later to fix this issue; see also
+ U(https://github.com/rthalley/dnspython/issues/321).
+ Unfortunately dnspython 2.0.0 requires Python 3.6 or newer.
+'''
+
+EXAMPLES = r'''
+- name: Retrieve TXT values from all nameservers for two DNS names
+ community.dns.nameserver_record_info:
+ name:
+ - www.example.com
+ - example.org
+ type: TXT
+ register: result
+
+- name: Show TXT values for www.example.com for all nameservers
+ ansible.builtin.debug:
+ msg: '{{ result.results[0].result }}'
+'''
+
+RETURN = r'''
+results:
+ description:
+ - Information on the records for every DNS name provided in O(name).
+ returned: always
+ type: list
+ elements: dict
+ contains:
+ name:
+ description:
+ - The DNS name this entry is for.
+ returned: always
+ type: str
+ sample: www.example.com
+ result:
+ description:
+ - A list of values per nameserver.
+ returned: success
+ type: list
+ elements: dict
+ sample:
+ - nameserver: ns1.example.com
+ values:
+ - X
+ - nameserver: ns2.example.com
+ values:
+ - X
+ contains:
+ nameserver:
+ description:
+ - The nameserver.
+ returned: success
+ type: str
+ sample: ns1.example.com
+ values:
+ description:
+ - The records of type O(type).
+ - Depending on O(type), different fields are returned.
+ - For O(type=TXT) and O(type=SPF), also the concatenated value is returned as RV(results[].result[].values[].value).
+ returned: success
+ type: list
+ elements: dict
+ sample:
+ - address: 127.0.0.1
+ contains:
+ address:
+ description:
+ - A IPv4 respectively IPv6 address.
+ type: str
+ returned: if O(type=A) or O(type=AAAA)
+ algorithm:
+ description:
+ - The algorithm ID.
+ type: int
+ returned: if O(type=DNSKEY) or O(type=DS) or O(type=NSEC3) or O(type=NSEC3PARAM) or O(type=RRSIG) or O(type=SSHFP)
+ altitude:
+ description:
+ - The altitude.
+ type: float
+ returned: if O(type=LOC)
+ cert:
+ description:
+ - The certificate.
+ type: str
+ returned: if O(type=TLSA)
+ cpu:
+ description:
+ - The CPU.
+ type: str
+ returned: if O(type=HINFO)
+ digest:
+ description:
+ - The digest.
+ type: str
+ returned: if O(type=DS)
+ digest_type:
+ description:
+ - The digest's type.
+ type: int
+ returned: if O(type=DS)
+ exchange:
+ description:
+ - The exchange server.
+ type: str
+ returned: if O(type=MX)
+ expiration:
+ description:
+ - The expiration Unix timestamp.
+ type: int
+ returned: if O(type=RRSIG)
+ expire:
+ description:
+ - Number of seconds after which secondary name servers should stop answering request
+ for this zone if the main name server does not respond.
+ type: int
+ returned: if O(type=SOA)
+ fingerprint:
+ description:
+ - The fingerprint.
+ type: str
+ returned: if O(type=SSHFP)
+ flags:
+ description:
+ - Flags.
+ - This is actually of type C(string) for O(type=NAPTR).
+ type: int
+ returned: if O(type=CAA) or O(type=DNSKEY) or O(type=NAPTR) or O(type=NSEC3) or O(type=NSEC3PARAM)
+ fp_type:
+ description:
+ - The fingerprint's type.
+ type: int
+ returned: if O(type=SSHFP)
+ horizontal_precision:
+ description:
+ - The horizontal precision of the location.
+ type: float
+ returned: if O(type=LOC)
+ inception:
+ description:
+ - The inception Unix timestamp.
+ type: int
+ returned: if O(type=RRSIG)
+ iterations:
+ description:
+ - The number of iterations.
+ type: int
+ returned: if O(type=NSEC3) or O(type=NSEC3PARAM)
+ key:
+ description:
+ - The key.
+ type: str
+ returned: if O(type=DNSKEY)
+ key_tag:
+ description:
+ - The key's tag.
+ type: int
+ returned: if O(type=DS) or O(type=RRSIG)
+ labels:
+ description:
+ - The labels.
+ type: int
+ returned: if O(type=RRSIG)
+ latitude:
+ description:
+ - The location's latitude.
+ type: list
+ elements: int
+ returned: if O(type=LOC)
+ longitude:
+ description:
+ - The location's longitude.
+ type: list
+ elements: int
+ returned: if O(type=LOC)
+ mbox:
+ description:
+ - The mbox.
+ type: str
+ returned: if O(type=RP)
+ minimum:
+ description:
+ - Used to calculate the TTL for purposes of negative caching.
+ type: int
+ returned: if O(type=SOA)
+ mname:
+ description:
+ - Primary main name server for this zone.
+ type: str
+ returned: if O(type=SOA)
+ mtype:
+ description:
+ - The mtype.
+ type: int
+ returned: if O(type=TLSA)
+ next:
+ description:
+ - The next value.
+ type: str
+ returned: if O(type=NSEC) or O(type=NSEC3)
+ order:
+ description:
+ - The order value.
+ type: int
+ returned: if O(type=NAPTR)
+ original_ttl:
+ description:
+ - The original TTL.
+ type: int
+ returned: if O(type=RRSIG)
+ os:
+ description:
+ - The operating system.
+ type: str
+ returned: if O(type=HINFO)
+ port:
+ description:
+ - The port.
+ type: int
+ returned: if O(type=SRV)
+ preference:
+ description:
+ - The preference value for this record.
+ type: int
+ returned: if O(type=MX) or O(type=NAPTR)
+ priority:
+ description:
+ - The priority value for this record.
+ type: int
+ returned: if O(type=SRV)
+ protocol:
+ description:
+ - The protocol.
+ type: int
+ returned: if O(type=DNSKEY)
+ refresh:
+ description:
+ - Number of seconds after which secondary name servers should query the main
+ name server for the SOA record to detect zone changes.
+ type: int
+ returned: if O(type=SOA)
+ regexp:
+ description:
+ - A regular expression.
+ type: str
+ returned: if O(type=NAPTR)
+ replacement:
+ description:
+ - The replacement.
+ type: str
+ returned: if O(type=NAPTR)
+ retry:
+ description:
+ - Number of seconds after which secondary name servers should retry to request
+ the serial number from the main name server if the main name server does not respond.
+ type: int
+ returned: if O(type=SOA)
+ rname:
+ description:
+ - E-mail address of the administrator responsible for this zone.
+ type: str
+ returned: if O(type=SOA)
+ salt:
+ description:
+ - The salt.
+ type: str
+ returned: if O(type=NSEC3) or O(type=NSEC3PARAM)
+ selector:
+ description:
+ - The selector.
+ type: int
+ returned: if O(type=TLSA)
+ serial:
+ description:
+ - Serial number for this zone.
+ type: int
+ returned: if O(type=SOA)
+ service:
+ description:
+ - The service.
+ type: str
+ returned: if O(type=NAPTR)
+ signature:
+ description:
+ - The signature.
+ type: str
+ returned: if O(type=RRSIG)
+ signer:
+ description:
+ - The signer.
+ type: str
+ returned: if O(type=RRSIG)
+ size:
+ description:
+ - The size of the location.
+ type: float
+ returned: if O(type=LOC)
+ strings:
+ description:
+ - List of strings for this record.
+ - See RV(results[].result[].values[].value) for the concatenated result.
+ type: list
+ elements: str
+ returned: if O(type=SPF) or O(type=TXT)
+ tag:
+ description:
+ - The tag.
+ type: str
+ returned: if O(type=CAA)
+ target:
+ description:
+ - The target.
+ type: str
+ returned: if O(type=CNAME) or O(type=DNAME) or O(type=NS) or O(type=PTR) or O(type=SRV)
+ txt:
+ description:
+ - The TXT value.
+ type: str
+ returned: if O(type=RP)
+ type_covered:
+ description:
+ - The type covered.
+ type: str
+ returned: if O(type=RRSIG)
+ usage:
+ description:
+ - The usage flag.
+ type: int
+ returned: if O(type=TLSA)
+ value:
+ description:
+ - The value.
+ - For O(type=SPF) or O(type=TXT), this is the concatenation of RV(results[].result[].values[].strings).
+ type: str
+ returned: if O(type=CAA) or O(type=SPF) or O(type=TXT)
+ vertical_precision:
+ description:
+ - The vertical precision of the location.
+ type: float
+ returned: if O(type=LOC)
+ weight:
+ description:
+ - The service's weight.
+ type: int
+ returned: if O(type=SRV)
+ windows:
+ description:
+ - The windows.
+ type: str
+ returned: if O(type=NSEC) or O(type=NSEC3)
+ sample:
+ - name: www.example.com
+ result:
+ - nameserver: ns1.example.com
+ values:
+ - address: 127.0.0.1
+ - nameserver: ns2.example.com
+ values:
+ - address: 127.0.0.1
+ - name: example.org
+ result:
+ - nameserver: ns1.example.org
+ values:
+ - address: 127.0.0.1
+ - address: 127.0.0.2
+ - nameserver: ns2.example.org
+ values:
+ - address: 127.0.0.2
+ - nameserver: ns3.example.org
+ values:
+ - address: 127.0.0.1
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.community.dns.plugins.module_utils.resolver import (
+ ResolveDirectlyFromNameServers,
+ assert_requirements_present,
+ guarded_run,
+)
+
+from ansible_collections.community.dns.plugins.module_utils.dnspython_records import (
+ NAME_TO_RDTYPE,
+ convert_rdata_to_dict,
+)
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ name=dict(required=True, type='list', elements='str'),
+ type=dict(
+ required=True,
+ type='str',
+ choices=[
+ 'A',
+ 'ALL',
+ 'AAAA',
+ 'CAA',
+ 'CNAME',
+ 'DNAME',
+ 'DNSKEY',
+ 'DS',
+ 'HINFO',
+ 'LOC',
+ 'MX',
+ 'NAPTR',
+ 'NS',
+ 'NSEC',
+ 'NSEC3',
+ 'NSEC3PARAM',
+ 'PTR',
+ 'RP',
+ 'RRSIG',
+ 'SOA',
+ 'SPF',
+ 'SRV',
+ 'SSHFP',
+ 'TLSA',
+ 'TXT',
+ ],
+ ),
+ query_retry=dict(type='int', default=3),
+ query_timeout=dict(type='float', default=10),
+ always_ask_default_resolver=dict(type='bool', default=True),
+ servfail_retries=dict(type='int', default=0),
+ server=dict(type='list', elements='str'),
+ ),
+ supports_check_mode=True,
+ )
+ assert_requirements_present(module)
+
+ names = module.params['name']
+ record_type = module.params['type']
+
+ resolver = ResolveDirectlyFromNameServers(
+ timeout=module.params['query_timeout'],
+ timeout_retries=module.params['query_retry'],
+ servfail_retries=module.params['servfail_retries'],
+ always_ask_default_resolver=module.params['always_ask_default_resolver'],
+ server_addresses=module.params['server'],
+ )
+ results = [None] * len(names)
+ for index, name in enumerate(names):
+ results[index] = {
+ 'name': name,
+ }
+
+ rdtype = NAME_TO_RDTYPE[record_type]
+
+ def f():
+ for index, name in enumerate(names):
+ result = []
+ results[index]['result'] = result
+ records_for_nameservers = resolver.resolve(name, rdtype=rdtype)
+ for nameserver, records in records_for_nameservers.items():
+ ns_result = {
+ 'nameserver': nameserver,
+ }
+ result.append(ns_result)
+ values = []
+ if records is not None:
+ for data in records:
+ values.append(convert_rdata_to_dict(data))
+ ns_result['values'] = values
+ result.sort(key=lambda v: v['nameserver'])
+
+ guarded_run(f, module, generate_additional_results=lambda: dict(results=results))
+ module.exit_json(results=results)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/dns/plugins/modules/wait_for_txt.py b/ansible_collections/community/dns/plugins/modules/wait_for_txt.py
index 1a09c5ed6..7252ae883 100644
--- a/ansible_collections/community/dns/plugins/modules/wait_for_txt.py
+++ b/ansible_collections/community/dns/plugins/modules/wait_for_txt.py
@@ -40,7 +40,7 @@ options:
suboptions:
name:
description:
- - A DNS name, like C(www.example.com).
+ - A DNS name, like V(www.example.com).
type: str
required: true
values:
@@ -51,17 +51,17 @@ options:
required: true
mode:
description:
- - Comparison modes for the values in I(values).
- - If C(subset), I(values) should be a (not necessarily proper) subset of the TXT values set for
+ - Comparison modes for the values in O(records[].values).
+ - If V(subset), O(records[].values) should be a (not necessarily proper) subset of the TXT values set for
the DNS name.
- - If C(superset), I(values) should be a (not necessarily proper) superset of the TXT values set
+ - If V(superset), O(records[].values) should be a (not necessarily proper) superset of the TXT values set
for the DNS name.
This includes the case that no TXT entries are set.
- - If C(superset_not_empty), I(values) should be a (not necessarily proper) superset of the TXT
+ - If V(superset_not_empty), O(records[].values) should be a (not necessarily proper) superset of the TXT
values set for the DNS name, assuming at least one TXT record is present.
- - If C(equals), I(values) should be the same set of strings as the TXT values for the DNS name
+ - If V(equals), O(records[].values) should be the same set of strings as the TXT values for the DNS name
(up to order).
- - If C(equals_ordered), I(values) should be the same ordered list of strings as the TXT values
+ - If V(equals_ordered), O(records[].values) should be the same ordered list of strings as the TXT values
for the DNS name.
type: str
default: subset
@@ -93,13 +93,26 @@ options:
default: 10
always_ask_default_resolver:
description:
- - When set to C(true) (default), will use the default resolver to find the authoritative nameservers
- of a subzone.
- - When set to C(false), will use the authoritative nameservers of the parent zone to find the
+ - When set to V(true) (default), will use the default resolver to find the authoritative nameservers
+ of a subzone. See O(server) for how to configure the default resolver.
+ - When set to V(false), will use the authoritative nameservers of the parent zone to find the
authoritative nameservers of a subzone. This only makes sense when the nameservers were recently
- changed and haven't propagated.
+ changed and have not yet propagated.
type: bool
default: true
+ servfail_retries:
+ description:
+ - How often to retry on SERVFAIL errors.
+ type: int
+ default: 0
+ version_added: 2.6.0
+ server:
+ description:
+ - The DNS server(s) to use to look up the result. Must be a list of one or more IP addresses.
+ - By default, the system's standard resolver is used.
+ type: list
+ elements: str
+ version_added: 2.7.0
requirements:
- dnspython >= 1.15.0 (maybe older versions also work)
'''
@@ -124,7 +137,7 @@ RETURN = r'''
records:
description:
- Results on the TXT records queried.
- - The entries are in a 1:1 correspondence to the entries of the I(records) parameter,
+ - The entries are in a 1:1 correspondence to the entries of the O(records) parameter,
in exactly the same order.
returned: always
type: list
@@ -180,7 +193,6 @@ completed:
'''
import time
-import traceback
try:
from time import monotonic
@@ -188,16 +200,15 @@ except ImportError:
from time import clock as monotonic
from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.common.text.converters import to_native, to_text
+from ansible.module_utils.common.text.converters import to_text
from ansible_collections.community.dns.plugins.module_utils.resolver import (
ResolveDirectlyFromNameServers,
- ResolverError,
assert_requirements_present,
+ guarded_run,
)
try:
- import dns.exception
import dns.rdatatype
except ImportError:
pass # handled in assert_requirements_present()
@@ -238,97 +249,107 @@ def validate_check(record_values, expected_values, comparison_mode):
raise Exception('Internal error!')
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- records=dict(required=True, type='list', elements='dict', options=dict(
- name=dict(required=True, type='str'),
- values=dict(required=True, type='list', elements='str'),
- mode=dict(type='str', default='subset', choices=['subset', 'superset', 'superset_not_empty', 'equals', 'equals_ordered']),
- )),
- query_retry=dict(type='int', default=3),
- query_timeout=dict(type='float', default=10),
- timeout=dict(type='float'),
- max_sleep=dict(type='float', default=10),
- always_ask_default_resolver=dict(type='bool', default=True),
- ),
- supports_check_mode=True,
- )
- assert_requirements_present(module)
+class Waiter(object):
+ def __init__(self, module):
+ self.module = module
+
+ self.resolver = ResolveDirectlyFromNameServers(
+ timeout=self.module.params['query_timeout'],
+ timeout_retries=self.module.params['query_retry'],
+ servfail_retries=self.module.params['servfail_retries'],
+ always_ask_default_resolver=self.module.params['always_ask_default_resolver'],
+ server_addresses=self.module.params['server'],
+ )
+ self.records = self.module.params['records']
+ self.timeout = self.module.params['timeout']
+ self.max_sleep = self.module.params['max_sleep']
+
+ self.results = [None] * len(self.records)
+ for index in range(len(self.records)):
+ self.results[index] = {
+ 'name': self.records[index]['name'],
+ 'done': False,
+ 'check_count': 0,
+ }
+ self.finished_checks = 0
+
+ def _run(self):
+ self.start_time = monotonic()
- resolver = ResolveDirectlyFromNameServers(
- timeout=module.params['query_timeout'],
- timeout_retries=module.params['query_retry'],
- always_ask_default_resolver=module.params['always_ask_default_resolver'],
- )
- records = module.params['records']
- timeout = module.params['timeout']
- max_sleep = module.params['max_sleep']
-
- results = [None] * len(records)
- for index in range(len(records)):
- results[index] = {
- 'name': records[index]['name'],
- 'done': False,
- 'check_count': 0,
- }
- finished_checks = 0
-
- start_time = monotonic()
- try:
step = 0
while True:
has_timeout = False
- if timeout is not None:
- expired = monotonic() - start_time
- has_timeout = expired > timeout
+ if self.timeout is not None:
+ expired = monotonic() - self.start_time
+ has_timeout = expired > self.timeout
done = True
- for index, record in enumerate(records):
- if results[index]['done']:
+ for index, record in enumerate(self.records):
+ if self.results[index]['done']:
continue
- txts = lookup(resolver, record['name'])
- results[index]['values'] = txts
- results[index]['check_count'] += 1
+ txts = lookup(self.resolver, record['name'])
+ self.results[index]['values'] = txts
+ self.results[index]['check_count'] += 1
if txts and all(validate_check(txt, record['values'], record['mode']) for txt in txts.values()):
- results[index]['done'] = True
- finished_checks += 1
+ self.results[index]['done'] = True
+ self.finished_checks += 1
else:
done = False
if done:
- module.exit_json(
+ self.module.exit_json(
msg='All checks passed',
- records=results,
- completed=finished_checks)
+ **self._generate_additional_results()
+ )
if has_timeout:
- module.fail_json(
- msg='Timeout ({0} out of {1} check(s) passed).'.format(finished_checks, len(records)),
- records=results,
- completed=finished_checks)
+ self.module.fail_json(
+ msg='Timeout ({0} out of {1} check(s) passed).'.format(self.finished_checks, len(self.records)),
+ **self._generate_additional_results()
+ )
# Simple quadratic sleep with maximum wait of max_sleep seconds
- wait = min(2 + step * 0.5, max_sleep)
- if timeout is not None:
+ wait = min(2 + step * 0.5, self.max_sleep)
+ if self.timeout is not None:
# Make sure we do not exceed the timeout by much by waiting
- expired = monotonic() - start_time
- wait = max(min(wait, timeout - expired + 0.1), 0.1)
+ expired = monotonic() - self.start_time
+ wait = max(min(wait, self.timeout - expired + 0.1), 0.1)
time.sleep(wait)
step += 1
- except ResolverError as e:
- module.fail_json(
- msg='Unexpected resolving error: {0}'.format(to_native(e)),
- records=results,
- completed=finished_checks,
- exception=traceback.format_exc())
- except dns.exception.DNSException as e:
- module.fail_json(
- msg='Unexpected DNS error: {0}'.format(to_native(e)),
- records=results,
- completed=finished_checks,
- exception=traceback.format_exc())
+
+ def _generate_additional_results(self):
+ return dict(
+ records=self.results,
+ completed=self.finished_checks,
+ )
+
+ def run(self):
+ guarded_run(self._run, self.module, generate_additional_results=self._generate_additional_results)
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ records=dict(required=True, type='list', elements='dict', options=dict(
+ name=dict(required=True, type='str'),
+ values=dict(required=True, type='list', elements='str'),
+ mode=dict(type='str', default='subset', choices=['subset', 'superset', 'superset_not_empty', 'equals', 'equals_ordered']),
+ )),
+ query_retry=dict(type='int', default=3),
+ query_timeout=dict(type='float', default=10),
+ timeout=dict(type='float'),
+ max_sleep=dict(type='float', default=10),
+ always_ask_default_resolver=dict(type='bool', default=True),
+ servfail_retries=dict(type='int', default=0),
+ server=dict(type='list', elements='str'),
+ ),
+ supports_check_mode=True,
+ )
+ assert_requirements_present(module)
+
+ waiter = Waiter(module)
+ waiter.run()
if __name__ == "__main__":