[Freeipa-devel] [PATCH 0029-0046] Internationalized domain names in DNS plugin
Martin Basti
mbasti at redhat.com
Fri Apr 4 13:51:28 UTC 2014
On Fri, 2014-04-04 at 15:46 +0200, Martin Basti wrote:
> On Fri, 2014-04-04 at 12:59 +0200, Petr Spacek wrote:
> > On 3.4.2014 15:35, Jan Cholasta wrote:
> > > On 2.4.2014 14:07, Martin Basti wrote:
> > > Patch 30:
> > > 2)
> > >
> > > + if isinstance(labels, str):
> > > + if not labels:
> > > + raise ValueError('empty string')
> > > ...
> > > + elif isinstance(labels, unicode):
> > > + if not labels:
> > > + raise ValueError('empty string')
> > >
> > > It might be nicer to:
> > >
> > > + if isinstance(labels, basestring) and not labels:
> > > + raise ValueError('empty string')
> > > +
> > > + if isinstance(labels, str):
> > > ...
> > > + elif isinstance(labels, unicode):
> > Is it expected that you can't create root name?
> >
> > I would like to imitate dns-python semantics as much as possible.
> >
> > In [2]: dns.name.from_text("")
> > Out[2]: <DNS name .>
> >
> > In [4]: dns.name.Name([])
> > Out[4]: <DNS name @>
> >
> > In [5]: dns.name.Name([""])
> > Out[5]: <DNS name .>
>
> Cos we need to keep if user added domain with/without zone, we use
I mean end dot not zone.
> origin=None, and there is allowed to add only '.' as domain name => root
> In [3]: a = dns.name.from_unicode(u'.', origin=None)
>
> In [4]: a.labels
> Out[4]: ('',)
>
> That is more clearly to user add . as root domain, instead of empty
> string
>
> > I would like to see more descriptive error texts if you insist on current
> > semantics.
> >
> > > 4)
> > >
> > > + @staticmethod
> > > + def get_root():
> > > + return DNSName(dns.name.root)
> > > +
> > > + @staticmethod
> > > + def get_origin_sign():
> > > + return DNSName(u'@')
> > > +
> > > + @staticmethod
> > > + def get_rev_zone():
> > > + return DNSName(u'in-addr.arpa.')
> > > +
> > > + @staticmethod
> > > + def get_ip6_rev_zone():
> > > + return DNSName(u'ip6.arpa.')
> > >
> > > I think you should either drop the "get_" prefix from the name, or (even
> > > better) make these global constants.
> > >
> > > I would shorten "origin_sign" to just "sign".
> > Sign of what? Decay? :-) I don't think that sign is descriptive enough, I
> > would personally stick with origin_sign.
> I agree with origin_sing, or zone_record, or origin, not sign.
> >
> > > Can you please use tuples of str objects (i.e. what dns.name.Name uses
> > > internally) instead of unicode objects for the initialization? I think it
> > > should be the preferred style of initializing DNSName objects (DN objects do
> > > the same).
> > Please don't forget to consult dns-python3 and try to make migration from
> > dns-python to dns-python3 easy.
> I will take look at dns-python3.
>
> > > 6)
> > >
> > > + def ToASCII(self, omit_final_dot=False):
> > > + return super(DNSName,
> > > self).to_text(omit_final_dot=omit_final_dot).decode('ascii')
> > > +
> > > + def ToUnicode(self, omit_final_dot=False):
> > > + return super(DNSName,
> > > self).to_unicode(omit_final_dot=omit_final_dot).decode('utf-8')
> > >
> > > What was the reason for the unusual naming again? I would prefer PEP-8
> > > compatible names (e.g. "to_ascii" and "to_unicode"), but if the current names
> > > absolutely have to stay, please add a comment with explanation.
> > >
> > > I don't like the "omit_final_dot" flag. IMHO it should be dropped and whether
> > > the result includes a final dot or not should depend solely on whether the
> > > name is absolute or relative. You can still use e.g.
> > > "name.derelativize(root).ToUnicode()" to drop the final dot, which is more
> > > explanatory.
> > Generally, I agree. We can get rid of the relative/absolute name madness by
> > using final dot everywhere.
> Ok I will remove it.
>
> > > 8)
> > >
> > > + def is_ip_reverse(self):
> > Please use is_ip4_reverse() instead. That name will always remind developer
> > not to forgot to IPv6 :-)
> As you wish.
> > > + if self.is_subdomain(self.get_rev_zone()):
> > > + return True
> > > + return False
> >
> >
> >
> > > Patch 31:
> > 2b)
> > + except dns.name.NameTooLong:
> > + raise ValueError(_('domain name cannot be longer than 255
> > characters'))
> >
> > Personally, I would say '255 bytes' instead of '255 characters'. Characters
> > are tricky when IDN is involved etc.
> Okay, bytes then. I will reword it.
> >
> >
> > Patch freeipa-mbasti-0036-DNSName-conversion-in-ipaldap.patch:
> >
> > @@ -255,6 +256,10 @@ class IPASimpleLDAPObject(object):
> > 'managedtemplate': DN,
> > 'managedbase': DN,
> > 'originscope': DN,
> > + 'idnsname': DNSName,
> > + 'idnssoamname': DNSName,
> > + 'idnssoarname': DNSName,
> > + 'dnszoneidnsname': DNSName,
> > })
> >
> > Maybe you can add following attributes too:
> > CNAMERecord
> > DNAMERecord
> > MDRecord
> > NSRecord
> > PTRRecord
> >
> I'm not sure with that. Now all record data are returned as string, only
> domain names and domain related attributes in zone are returned as
> DNSName. It could be mess if half of records be returned as DNSName and
> second as string.
> >
> >
> > > Patch 38:
> > >
> > > 1)
> > >
> > > +_dns_zone_record = DNSName(u'@')
> > >
> > > You know you already defined a constant for this in patch 30, right?
> > It seems that both constants are unnecessary because IMHO
> > DNSName(u'@')
> > is more readable and you don't need to dig into code to find out what the
> > cryptic name means.
> I like constants :-). I'm not sure if making new object, when in the most cases want only to compare, is good idea.
>
> > > 4)
> > >
> > > +def _hostname_validator_idn(ugettext, value):
> > > + assert isinstance(value, DNSName)
> > > +
> > > + req_len = 2
> > > + if value.is_absolute():
> > > + req_len = 3
> > > + if len(value.labels) < req_len:
> > > + return _('invalid domain-name: not fully qualified')
> > This test is not correct because FQDN = an absolute name.
> >
> > This code tries to guess if the name is FQDN or not but we can directly use
> > is_absolute() test.
> I know, but in this IPA case is FQDN something like 'example.domain', not 'domain.' .
> I kept behavior of original function.
>
> >
> > 4b)
> > def is_forward_record(zone, str_address):
> > addr = netaddr.IPAddress(str_address)
> > @@ -461,6 +444,7 @@ def is_forward_record(zone, str_address):
> >
> > def add_forward_record(zone, name, str_address):
> > addr = netaddr.IPAddress(str_address)
> > +
> > try:
> > if addr.version == 4:
> > api.Command['dnsrecord_add'](zone, name, arecord=str_address)
> >
> > Personally, I think that 'forward' is confusing (in this context). Could you
> > rename *_forward_record() functions to *_ipaddr_record(), please? (Maybe in a
> > separate patch...)
> I was confused too, maybe later, now I'm almost lost in all these
> changes.
> >
> > 4c)
> > def add_records_for_host(host, domain, ip_addresses, add_forward=True,
> > add_reverse=True):
> > + assert isinstance(host, DNSName)
> > + assert isinstance(domain, DNSName)
> >
> > The same applies to all places with:
> > + assert isinstance(value, DNSName)
> > scattered all over the patch.
> >
> > Is this really necessary? I thought that Python usually uses
> > http://en.wikipedia.org/wiki/Duck_typing
> >
> > It seems like leftovers from development phase. (Maybe it is not the case for
> > IPA framework, correct me if I'm wrong :-)
> I used in development phase, but it should be clear that these functions/methods dont work with unicode, some of them are used in other plugins (include 'private' functions)
>
> > > Patch 39:
> > >
> > > 1)
> > >
> > > - Str('hostname',
> > > - _hostname_validator,
> > > - normalizer=_normalize_hostname,
> > > + DNSNameParam('hostname',
> > > + #RFC 2317 section 5.2 -- don't have to be FQDN
> > >
> > > It seems you are changing behavior here. Such things belong in separate patches.
> > Note: This is (mostly) related to classless reverse zones.
>
> > freeipa-mbasti-0040-Modified-record-and-zone-class-to-support-IDN.patch
> > > * Records data are always returned as string
> > > * Attributes idnsname, idnssoamname, idnssoarname are returned as DNSName, with
> > > option --raw as string
> > > * option --raw returns all IDN domains punycoded
> >
> > I have mentioned
> > CNAMERecord
> > DNAMERecord
> > MDRecord
> > NSRecord
> > PTRRecord
> >
> > above. Their are also pure DNS names ...
> As I wrote above, it could be mayhem.
>
> > > def get_name_in_zone(self, zone, hostname):
> > [snip]
> > > - be added to a zone
> > > + be added to a zone. Returns '@' when the hostname is directly in the zone
> >
> > I would replace "in the zone" with "at zone apex". Technically, all records
> > with suffix = zone are "in" the zone.
> I would use zone record instead. Is it okay?
> >
> >
> > freeipa-mbasti-0046-DNS-new-tests.patch
> > +idnzone1_ip = u'192.168.11.1'
> > [snip]
> > +revidnzone1 = u'15.168.192.in-addr.arpa.'
> >
> > Please use addresses from 172.16/12 prefix so IPA tests don't consume more
> > than one prefix.
> >
> > More prefixes we use => higher probability that it will clash with somebody's
> > environment.
> Thank you for make it clear for me. I though the private address is enough.
>
> >
> > I'm looking forward to see this is IPA! Good work!
> >
>
> Thank you for your review.
--
Martin^2 Basti
More information about the Freeipa-devel
mailing list