jcholast's pull request #34: " dns: prompt for missing record parts in CLI" was synchronize
See the full pull-request at https://github.com/freeipa/freeipa/pull/34 ... or pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/34/head:pr34 git checkout pr34
From 05b35053687b86b9347c0e95bacb220d58f58d58 Mon Sep 17 00:00:00 2001 From: Jan Cholasta <jchol...@redhat.com> Date: Mon, 5 Sep 2016 09:35:42 +0200 Subject: [PATCH 1/3] dns: normalize record type read interactively in dnsrecord_add When dnsrecord_add is called without options in interactive mode, it prompts the user to enter a record type. The record type is expected to be upper case further in the code, which causes non-upper case values not to work correctly. Fix this issue by upper casing the value after it is read. https://fedorahosted.org/freeipa/ticket/6203 --- ipaclient/plugins/dns.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py index e17c282..db9c17f 100644 --- a/ipaclient/plugins/dns.py +++ b/ipaclient/plugins/dns.py @@ -175,6 +175,8 @@ def interactive_prompt_callback(self, kw): if rrtype is None: return + rrtype = rrtype.upper() + try: name = record_name_format % rrtype.lower() param = self.params[name] From ef637073f0bef5ba7137f3b179d7e2fa79e0ef71 Mon Sep 17 00:00:00 2001 From: Jan Cholasta <jchol...@redhat.com> Date: Fri, 2 Sep 2016 16:42:57 +0200 Subject: [PATCH 2/3] dns: prompt for missing record parts in CLI Fix the code which determines if a record part is required and thus should be prompted not to wrongfully consider all record parts to be optional. https://fedorahosted.org/freeipa/ticket/6203 --- API.txt | 29 +++++++++++++++++++++++++++++ ipaclient/plugins/dns.py | 30 ++++++++++++++++-------------- ipaserver/plugins/dns.py | 15 +++++++++++++++ 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/API.txt b/API.txt index 5b83bfb..fb5bf83 100644 --- a/API.txt +++ b/API.txt @@ -6312,9 +6312,20 @@ default: dns_is_enabled/1 default: dns_resolve/1 default: dns_system_records/1 default: dns_update_system_records/1 +default: dnsa6record/1 +default: dnsaaaarecord/1 +default: dnsafsdbrecord/1 +default: dnsaplrecord/1 +default: dnsarecord/1 +default: dnscertrecord/1 +default: dnscnamerecord/1 default: dnsconfig/1 default: dnsconfig_mod/1 default: dnsconfig_show/1 +default: dnsdhcidrecord/1 +default: dnsdlvrecord/1 +default: dnsdnamerecord/1 +default: dnsdsrecord/1 default: dnsforwardzone/1 default: dnsforwardzone_add/1 default: dnsforwardzone_add_permission/1 @@ -6325,6 +6336,16 @@ default: dnsforwardzone_find/1 default: dnsforwardzone_mod/1 default: dnsforwardzone_remove_permission/1 default: dnsforwardzone_show/1 +default: dnshiprecord/1 +default: dnsipseckeyrecord/1 +default: dnskeyrecord/1 +default: dnskxrecord/1 +default: dnslocrecord/1 +default: dnsmxrecord/1 +default: dnsnaptrrecord/1 +default: dnsnsecrecord/1 +default: dnsnsrecord/1 +default: dnsptrrecord/1 default: dnsrecord/1 default: dnsrecord_add/1 default: dnsrecord_del/1 @@ -6333,12 +6354,20 @@ default: dnsrecord_find/1 default: dnsrecord_mod/1 default: dnsrecord_show/1 default: dnsrecord_split_parts/1 +default: dnsrprecord/1 +default: dnsrrsigrecord/1 default: dnsserver/1 default: dnsserver_add/1 default: dnsserver_del/1 default: dnsserver_find/1 default: dnsserver_mod/1 default: dnsserver_show/1 +default: dnssigrecord/1 +default: dnsspfrecord/1 +default: dnssrvrecord/1 +default: dnssshfprecord/1 +default: dnstlsarecord/1 +default: dnstxtrecord/1 default: dnszone/1 default: dnszone_add/1 default: dnszone_add_permission/1 diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py index db9c17f..5e29b8c 100644 --- a/ipaclient/plugins/dns.py +++ b/ipaclient/plugins/dns.py @@ -25,10 +25,10 @@ from ipaclient.frontend import MethodOverride from ipalib import errors -from ipalib.dns import (get_part_rrtype, - get_record_rrtype, +from ipalib.dns import (get_record_rrtype, has_cli_options, iterate_rrparams_by_parts, + part_name_format, record_name_format) from ipalib.parameters import Bool from ipalib.plugable import Registry @@ -46,9 +46,9 @@ _zone_top_record_types = ('NS', 'MX', 'LOC', ) -def __get_part_param(cmd, part, output_kw, default=None): - name = part.name - label = unicode(part.label) +def __get_part_param(rrtype, cmd, part, output_kw, default=None): + name = part_name_format % (rrtype.lower(), part.name) + label = unicode(cmd.params[name].label) optional = not part.required output_kw[name] = cmd.prompt_param(part, @@ -64,29 +64,31 @@ def prompt_parts(rrtype, cmd, mod_dnsvalue=None): name, mod_dnsvalue)['result'] user_options = {} - parts = [p for p in cmd.params() if get_part_rrtype(p.name) == rrtype] - if not parts: + try: + rrobj = cmd.api.Object['dns{}record'.format(rrtype.lower())] + except KeyError: return user_options - for part_id, part in enumerate(parts): + for part_id, part in enumerate(rrobj.params()): if mod_parts: default = mod_parts[part_id] else: default = None - __get_part_param(cmd, part, user_options, default) + __get_part_param(rrtype, cmd, part, user_options, default) return user_options def prompt_missing_parts(rrtype, cmd, kw, prompt_optional=False): user_options = {} - parts = [p for p in cmd.params() if get_part_rrtype(p.name) == rrtype] - if not parts: + try: + rrobj = cmd.api.Object['dns{}record'.format(rrtype.lower())] + except KeyError: return user_options - for part in parts: - name = part.name + for part in rrobj.params(): + name = part_name_format % (rrtype.lower(), part.name) if name in kw: continue @@ -96,7 +98,7 @@ def prompt_missing_parts(rrtype, cmd, kw, prompt_optional=False): continue default = part.get_default(**kw) - __get_part_param(cmd, part, user_options, default) + __get_part_param(rrtype, cmd, part, user_options, default) return user_options diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py index 6f1bd71..f048351 100644 --- a/ipaserver/plugins/dns.py +++ b/ipaserver/plugins/dns.py @@ -3471,6 +3471,21 @@ def warning_suspicious_relative_name(self, result, *keys, **options): ) +# Make DNS record types available as objects in the API. +# This is used by the CLI to get otherwise unavailable attributes of record +# parts. +for param in _dns_records: + register()( + type( + 'dns{}record'.format(param.rrtype.lower()), + (Object,), + dict( + takes_params=(param.parts or ()) + (param.extra or ()), + ) + ) + ) + + @register() class dnsrecord_split_parts(Command): NO_CLI = True From d51fe56d033481e64c47480c62d95e24444c2580 Mon Sep 17 00:00:00 2001 From: Jan Cholasta <jchol...@redhat.com> Date: Tue, 23 Aug 2016 12:53:39 +0200 Subject: [PATCH 3/3] dns: fix crash in interactive mode against old servers Add a client-side fallback of the dnsrecord_split_parts command for old servers to avoid CommandError in dnsrecord_add and dnsrecord_mod CLI interactive mode. https://fedorahosted.org/freeipa/ticket/6203 --- ipaclient/plugins/dns.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py index 5e29b8c..b9ab709 100644 --- a/ipaclient/plugins/dns.py +++ b/ipaclient/plugins/dns.py @@ -22,6 +22,7 @@ import six import copy +import re from ipaclient.frontend import MethodOverride from ipalib import errors @@ -30,7 +31,8 @@ iterate_rrparams_by_parts, part_name_format, record_name_format) -from ipalib.parameters import Bool +from ipalib.frontend import Command +from ipalib.parameters import Bool, Str from ipalib.plugable import Registry from ipalib import _, ngettext from ipapython.dnsutil import DNSName @@ -121,6 +123,64 @@ class dnszone_mod(DNSZoneMethodOverride): pass +# Support old servers without dnsrecord_split_parts +# Do not add anything new here! +@register(no_fail=True) +class dnsrecord_split_parts(Command): + NO_CLI = True + + takes_args = ( + Str('name'), + Str('value'), + ) + + def execute(self, name, value, *args, **options): + def split_exactly(count): + values = value.split() + if len(values) != count: + return None + return tuple(values) + + result = () + + rrtype = get_record_rrtype(name) + if rrtype in ('A', 'AAAA', 'CNAME', 'DNAME', 'NS', 'PTR'): + result = split_exactly(1) + elif rrtype in ('AFSDB', 'KX', 'MX'): + result = split_exactly(2) + elif rrtype in ('CERT', 'DLV', 'DS', 'SRV', 'TLSA'): + result = split_exactly(4) + elif rrtype in ('NAPTR'): + result = split_exactly(6) + elif rrtype in ('A6', 'TXT'): + result = (value,) + elif rrtype == 'LOC': + regex = re.compile( + r'(?P<d1>\d{1,2}\s+)' + r'(?:(?P<m1>\d{1,2}\s+)' + r'(?P<s1>\d{1,2}(?:\.\d{1,3})?\s+)?)?' + r'(?P<dir1>[NS])\s+' + r'(?P<d2>\d{1,3}\s+)' + r'(?:(?P<m2>\d{1,2}\s+)' + r'(?P<s2>\d{1,2}(?:\.\d{1,3})?\s+)?)?' + r'(?P<dir2>[WE])\s+' + r'(?P<alt>-?\d{1,8}(?:\.\d{1,2})?)m?' + r'(?:\s+(?P<siz>\d{1,8}(?:\.\d{1,2})?)m?' + r'(?:\s+(?P<hp>\d{1,8}(?:\.\d{1,2})?)m?' + r'(?:\s+(?P<vp>\d{1,8}(?:\.\d{1,2})?)m?\s*)?)?)?$') + + m = regex.match(value) + if m is not None: + result = tuple( + x.strip() if x is not None else x for x in m.groups()) + elif rrtype == 'SSHFP': + values = value.split(None, 2) + if len(values) == 3: + result = tuple(values) + + return dict(result=result) + + @register(override=True, no_fail=True) class dnsrecord_add(MethodOverride): no_option_msg = 'No options to add a specific record provided.\n' \
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code