diff options
-rw-r--r-- | ipalib/plugins/dns.py | 60 | ||||
-rw-r--r-- | tests/test_xmlrpc/test_dns_plugin.py | 27 |
2 files changed, 59 insertions, 28 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index a1d495449..7b22f2f7b 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -1481,7 +1481,7 @@ def zone_is_reverse(zone_name): return False -def is_ns_rec_resolvable(name): +def check_ns_rec_resolvable(name): try: return api.Command['dns_resolve'](name) except errors.NotFound: @@ -1708,7 +1708,7 @@ class dnszone_add(LDAPCreate): error=unicode(_("Nameserver address is not a fully qualified domain name"))) if not 'ip_address' in options and not options['force']: - is_ns_rec_resolvable(nameserver) + check_ns_rec_resolvable(nameserver) if nameserver[-1] != '.': nameserver += '.' @@ -1877,17 +1877,20 @@ class dnsrecord(LDAPObject): ) def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options): - if options.get('force', False): - return dn - - for ns in options['nsrecord']: - is_ns_rec_resolvable(ns) - return dn + nsrecords = entry_attrs.get('nsrecord') + if options.get('force', False) or nsrecords is None: + return + map(check_ns_rec_resolvable, nsrecords) def _ptrrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options): - components = dn.split(',',2) - addr = components[0].split('=')[1] - zone = components[1].split('=')[1] + ptrrecords = entry_attrs.get('ptrrecord') + if ptrrecords is None: + return + zone = keys[-2] + if self.is_pkey_zone_record(*keys): + addr = u'' + else: + addr = keys[-1] zone_len = 0 for valid_zone in _valid_reverse_zones: if zone.find(valid_zone) != -1: @@ -1897,16 +1900,23 @@ class dnsrecord(LDAPObject): if not zone_len: allowed_zones = ', '.join(_valid_reverse_zones) - raise errors.ValidationError(name='cn', + raise errors.ValidationError(name='ptrrecord', error=unicode(_('Reverse zone for PTR record should be a sub-zone of one the following fully qualified domains: %s') % allowed_zones)) - ip_addr_comp_count = len(addr.split('.')) + len(zone.split('.')) + addr_len = len(addr.split('.')) if addr else 0 + ip_addr_comp_count = addr_len + len(zone.split('.')) if ip_addr_comp_count != zone_len: - raise errors.ValidationError(name='cn', + raise errors.ValidationError(name='ptrrecord', error=unicode(_('Reverse zone %(name)s requires exactly %(count)d IP address components, %(user_count)d given') % dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count))) - return dn + def run_precallback_validators(self, dn, entry_attrs, *keys, **options): + ldap = self.api.Backend.ldap2 + + for rtype in entry_attrs: + rtype_cb = getattr(self, '_%s_pre_callback' % rtype, None) + if rtype_cb: + rtype_cb(ldap, dn, entry_attrs, *keys, **options) def is_pkey_zone_record(self, *keys): idnsname = keys[-1] @@ -2120,11 +2130,6 @@ class dnsrecord_add(LDAPCreate): kw.update(user_options) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - for rtype in options: - rtype_cb = '_%s_pre_callback' % rtype - if hasattr(self.obj, rtype_cb): - dn = getattr(self.obj, rtype_cb)(ldap, dn, entry_attrs, *keys, **options) - precallback_attrs = [] for option in options: try: @@ -2153,6 +2158,9 @@ class dnsrecord_add(LDAPCreate): # extra option is passed, run per-type pre_callback for given RR type precallback_attrs.append(rrparam.name) + # Run pre_callback validators + self.obj.run_precallback_validators(dn, entry_attrs, *keys, **options) + # run precallback also for all new RR type attributes in entry_attrs for attr in entry_attrs: try: @@ -2232,14 +2240,7 @@ class dnsrecord_mod(LDAPUpdate): self.obj.has_cli_options(options, self.no_option_msg, True) return super(dnsrecord_mod, self).args_options_2_entry(*keys, **options) - def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): - for rtype in options: - rtype_cb = '_%s_pre_callback' % rtype - if options[rtype] is None and rtype in _record_attributes: - options[rtype] = [] - if hasattr(self.obj, rtype_cb): - dn = getattr(self.obj, rtype_cb)(ldap, dn, entry_attrs, *keys, **options) - + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): # check if any attr should be updated using structured instead of replaced # format is recordname : (old_value, new_parts) updated_attrs = {} @@ -2264,6 +2265,9 @@ class dnsrecord_mod(LDAPUpdate): updated_attrs[attr] = (old_value, parts) + # Run pre_callback validators + self.obj.run_precallback_validators(dn, entry_attrs, *keys, **options) + if len(updated_attrs): try: (dn_, old_entry) = ldap.get_entry( diff --git a/tests/test_xmlrpc/test_dns_plugin.py b/tests/test_xmlrpc/test_dns_plugin.py index ec6565197..93093ec8a 100644 --- a/tests/test_xmlrpc/test_dns_plugin.py +++ b/tests/test_xmlrpc/test_dns_plugin.py @@ -744,6 +744,33 @@ class test_dns(Declarative): ), dict( + desc='Try to add unresolvable NS record to %r using dnsrecord_add' % (dnsres1), + command=('dnsrecord_add', [dnszone1, dnsres1], {'nsrecord': u'does.not.exist'}), + expected=errors.NotFound(reason=u"Nameserver 'does.not.exist' does not have a corresponding A/AAAA record"), + ), + + dict( + desc='Add unresolvable NS record with --force to %r using dnsrecord_add' % (dnsres1), + command=('dnsrecord_add', [dnszone1, dnsres1], {'nsrecord': u'does.not.exist', + 'force' : True}), + expected={ + 'value': dnsres1, + 'summary': None, + 'result': { + 'objectclass': [u'top', u'idnsrecord'], + 'dn': unicode(dnsres1_dn), + 'idnsname': [dnsres1], + 'arecord': [u'10.10.0.1'], + 'cnamerecord': [u'foo-1.example.com.'], + 'kxrecord': [u'1 foo-1'], + 'txtrecord': [u'foo bar'], + 'nsecrecord': [dnszone1 + u' TXT A'], + 'nsrecord': [u'does.not.exist'], + }, + }, + ), + + dict( desc='Delete record %r in zone %r' % (dnsres1, dnszone1), command=('dnsrecord_del', [dnszone1, dnsres1], {'del_all': True }), expected={ |