community.general
community.general copied to clipboard
lookup('dig', arg1) should be able to process lists
SUMMARY
lookup('dig', arg) should be able to process arguments that are lists to names to lookup.
ISSUE TYPE
- Feature Idea
COMPONENT NAME
lookup dig
ADDITIONAL INFORMATION
See also https://github.com/ansible/ansible/issues/20470
There was a suggestion there (https://github.com/ansible/ansible/issues/20470#issuecomment-443220060) that you could do:
lookup('dig', *list)
but that does not work for me - it only returns the IP of the last item in the list.
Files identified in the description:
If these files are inaccurate, please update the component name
section of the description or use the !component
bot command.
cc @jpmens click here for bot help
@opoplawski Following works for me -
---
- hosts: localhost
vars:
servers:
- google.com
- yahoo.com
tasks:
- debug:
msg: "{{ lookup('dig', *servers) }}"
ok: [localhost] => {
"msg": "74.6.231.21,74.6.143.26,98.137.11.163,74.6.143.25,98.137.11.164,74.6.231.20"
}
needs_info
The code only resolves one DNS name, so the last one wins: https://github.com/ansible-collections/community.general/blob/main/plugins/lookup/dig.py#L311 This is consistent with the result @Akasurde shows, all six IP addresses resolve to Yahoo servers (host -t NS yahoo.com
only gives me five nameservers though), and the four nameservers google.com
is using have different IPs.
Correct.
@opoplawski This issue is waiting for your response. Please respond or the issue will be closed.
I think this is still a valid request.
why not loop: "{{ servers }}"
?
Just lost an hour wondering why I was not getting the correct results. The documentation explicitly states that this module will resolve the domain_(s)_ provided: https://github.com/ansible-collections/community.general/blob/5470ea30dce806dc6c9d766baa57a9ea57aabcd2/plugins/lookup/dig.py#L29-L31
https://github.com/ansible/ansible/issues/20470#issuecomment-443220060 suggests that this is a regression and that it worked before.
It was never intended by me that dig be able to query multiple domains, and the description clearly states
The dig lookup runs queries against DNS servers to retrieve DNS records for a specific name
I think the (s
) in domains for the _terms
parameter is a typo.
I'd be happy to take a stab at this. I'm guessing we want to keep the pre-processing phase so that all options (qtype=
, etc) apply to previous terms as well as following ones (as is currently the case). Special care has to be taken if multiple qtype are specified (i.e. 'google.com', 'yahoo.com/TXT'
).
Maybe it should be an error to specify the same option twice to avoid the surprise where 'qtype=TXT', 'google.com', 'qtype=A', 'yahoo.com'
doesn't error, but doesn't do what one would expect just reading it.
Here is a basic (absolutely untested) patch:
diff --git a/plugins/lookup/dig.py b/plugins/lookup/dig.py
--- plugins/lookup/dig.py
+++ plugins/lookup/dig.py
@@ -280,9 +280,9 @@
myres = dns.resolver.Resolver(configure=True)
edns_size = 4096
myres.use_edns(0, ednsflags=dns.flags.DO, payload=edns_size)
- domain = None
+ domains = []
qtype = 'A'
flat = True
fail_on_error = False
rdclass = dns.rdataclass.from_text('IN')
@@ -330,61 +330,67 @@
if '/' in t:
try:
domain, qtype = t.split('/')
+ domains.append((domain, qtype))
except Exception:
- domain = t
+ domains.append(t)
else:
- domain = t
+ domains.append(t)
# print "--- domain = {0} qtype={1} rdclass={2}".format(domain, qtype, rdclass)
ret = []
- if qtype.upper() == 'PTR':
+ for domain in domains:
+ current_qtype = qtype
+ if isinstance(domain, tuple):
+ domain, current_qtype = domain
+
+ if current_qtype.upper() == 'PTR':
+ try:
+ n = dns.reversename.from_address(domain)
+ domain = n.to_text()
+ except dns.exception.SyntaxError:
+ pass
+ except Exception as e:
+ raise AnsibleError("dns.reversename unhandled exception %s" % to_native(e))
+
try:
- n = dns.reversename.from_address(domain)
- domain = n.to_text()
- except dns.exception.SyntaxError:
- pass
- except Exception as e:
- raise AnsibleError("dns.reversename unhandled exception %s" % to_native(e))
+ answers = myres.query(domain, current_qtype, rdclass=rdclass)
+ for rdata in answers:
+ s = rdata.to_text()
+ if current_qtype.upper() == 'TXT':
+ s = s[1:-1] # Strip outside quotes on TXT rdata
- try:
- answers = myres.query(domain, qtype, rdclass=rdclass)
- for rdata in answers:
- s = rdata.to_text()
- if qtype.upper() == 'TXT':
- s = s[1:-1] # Strip outside quotes on TXT rdata
+ if flat:
+ ret.append(s)
+ else:
+ try:
+ rd = make_rdata_dict(rdata)
+ rd['owner'] = answers.canonical_name.to_text()
+ rd['type'] = dns.rdatatype.to_text(rdata.rdtype)
+ rd['ttl'] = answers.rrset.ttl
+ rd['class'] = dns.rdataclass.to_text(rdata.rdclass)
- if flat:
- ret.append(s)
- else:
- try:
- rd = make_rdata_dict(rdata)
- rd['owner'] = answers.canonical_name.to_text()
- rd['type'] = dns.rdatatype.to_text(rdata.rdtype)
- rd['ttl'] = answers.rrset.ttl
- rd['class'] = dns.rdataclass.to_text(rdata.rdclass)
+ ret.append(rd)
+ except Exception as err:
+ if fail_on_error:
+ raise AnsibleError("Lookup failed: %s" % str(err))
+ ret.append(str(err))
- ret.append(rd)
- except Exception as err:
- if fail_on_error:
- raise AnsibleError("Lookup failed: %s" % str(err))
- ret.append(str(err))
+ except dns.resolver.NXDOMAIN as err:
+ if fail_on_error:
+ raise AnsibleError("Lookup failed: %s" % str(err))
+ ret.append('NXDOMAIN')
+ except dns.resolver.NoAnswer as err:
+ if fail_on_error:
+ raise AnsibleError("Lookup failed: %s" % str(err))
+ ret.append("")
+ except dns.resolver.Timeout as err:
+ if fail_on_error:
+ raise AnsibleError("Lookup failed: %s" % str(err))
+ ret.append('')
+ except dns.exception.DNSException as err:
+ raise AnsibleError("dns.resolver unhandled exception %s" % to_native(err))
- except dns.resolver.NXDOMAIN as err:
- if fail_on_error:
- raise AnsibleError("Lookup failed: %s" % str(err))
- ret.append('NXDOMAIN')
- except dns.resolver.NoAnswer as err:
- if fail_on_error:
- raise AnsibleError("Lookup failed: %s" % str(err))
- ret.append("")
- except dns.resolver.Timeout as err:
- if fail_on_error:
- raise AnsibleError("Lookup failed: %s" % str(err))
- ret.append('')
- except dns.exception.DNSException as err:
- raise AnsibleError("dns.resolver unhandled exception %s" % to_native(err))
-
return ret
I'd also like to re-iterate that this wouldn't be required if there was another way to apply a lookup to a list (being able to write somelist | map('lookup', 'dig')
would avoid having to solve this over and over again).