Repository: ansible/ansible

Issue:
nsupdate doesn't check for ttl changes
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
nsupdate

##### ANSIBLE VERSION
```
ansible 2.5.0
  config file = /home/user/project/ansible.cfg
  configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Jan  5 2018, 10:41:29) [GCC 7.2.1 20171224]
```

##### CONFIGURATION
```
DEFAULT_HOST_LIST(/home/user/project/ansible.cfg) = [u'/home/user/project/inventory.yml']
HOST_KEY_CHECKING(/home/user/project/ansible.cfg) = False
RETRY_FILES_ENABLED(/home/user/project/ansible.cfg) = False
```

##### OS / ENVIRONMENT
Ansible running on Arch Linux, managed host is Debian Stretch.

##### SUMMARY
The module does not check for the ttl when it checks whether a change is required.

##### STEPS TO REPRODUCE
```yaml
- nsupdate:
    server: "{{ dns_server}}"
    ttl: "{{ item }}"
    zone: "example.com"
    record: "test"
    type: "a"
    value: "127.0.0.1"
  with_items:
    - 100
    - 200
```

##### EXPECTED RESULTS
The task should first create the record with 100s ttl, then change it to 200s ttl. This should at least cause 1 change on the first run, later runs should always cause 2 changes.

##### ACTUAL RESULTS
```
TASK [dnsrecords : Configure dns records] **********************************************************************************************
ok: [dnshost] => (item=100)
ok: [dnshost] => (item=200)

PLAY RECAP *****************************************************************************************************************************
dnshost                    : ok=2    changed=0    unreachable=0    failed=0   
```



Discussion:
Files identified in the description:
* [lib/ansible/modules/net_tools/nsupdate.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/net_tools/nsupdate.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @nerzhul
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/net_tools/nsupdate.py b/lib/ansible/modules/net_tools/nsupdate.py
--- a/lib/ansible/modules/net_tools/nsupdate.py
+++ b/lib/ansible/modules/net_tools/nsupdate.py
@@ -190,6 +190,11 @@ def __init__(self, module):
             if self.zone[-1] != '.':
                 self.zone += '.'
 
+        if module.params['record'][-1] != '.':
+            self.fqdn = module.params['record'] + '.' + self.zone
+        else:
+            self.fqdn = module.params['record']
+
         if module.params['key_name']:
             try:
                 self.keyring = dns.tsigkeyring.from_text({
@@ -326,12 +331,26 @@ def record_exists(self):
             response = self.__do_update(update)
             self.dns_rc = dns.message.Message.rcode(response)
             if self.dns_rc == 0:
-                return 1
+                if self.ttl_changed():
+                    return 2
+                else:
+                    return 1
             else:
                 return 2
         else:
             return 0
 
+    def ttl_changed(self):
+        query = dns.message.make_query(self.fqdn, self.module.params['type'])
+
+        try:
+            lookup = dns.query.tcp(query, self.module.params['server'], timeout=10, port=self.module.params['port'])
+        except (socket_error, dns.exception.Timeout) as e:
+            self.module.fail_json(msg='DNS server error: (%s): %s' % (e.__class__.__name__, to_native(e)))
+
+        current_ttl = lookup.answer[0].ttl
+        return current_ttl != self.module.params['ttl']
+
 
 def main():
     tsig_algs = ['HMAC-MD5.SIG-ALG.REG.INT', 'hmac-md5', 'hmac-sha1', 'hmac-sha224',


Test patch: