403b09
From 89544d521e6aa52e8b9e5e7dc4676046b5792abd Mon Sep 17 00:00:00 2001
403b09
From: Jan Cholasta <jcholast@redhat.com>
403b09
Date: Tue, 23 Aug 2016 12:53:39 +0200
403b09
Subject: [PATCH] dns: fix crash in interactive mode against old servers
403b09
403b09
Add a client-side fallback of the dnsrecord_split_parts command for old
403b09
servers to avoid CommandError in dnsrecord_add and dnsrecord_mod CLI
403b09
interactive mode.
403b09
403b09
https://fedorahosted.org/freeipa/ticket/6203
403b09
403b09
Reviewed-By: Martin Basti <mbasti@redhat.com>
403b09
---
403b09
 ipaclient/plugins/dns.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++-
403b09
 1 file changed, 61 insertions(+), 1 deletion(-)
403b09
403b09
diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py
403b09
index 5e29b8c6666f94f52add7f2e1de8679127886fc2..b9ab709bf0b1d72cfb9d32aeefd77a0e8bc74d7a 100644
403b09
--- a/ipaclient/plugins/dns.py
403b09
+++ b/ipaclient/plugins/dns.py
403b09
@@ -22,6 +22,7 @@ from __future__ import print_function
403b09
 
403b09
 import six
403b09
 import copy
403b09
+import re
403b09
 
403b09
 from ipaclient.frontend import MethodOverride
403b09
 from ipalib import errors
403b09
@@ -30,7 +31,8 @@ from ipalib.dns import (get_record_rrtype,
403b09
                         iterate_rrparams_by_parts,
403b09
                         part_name_format,
403b09
                         record_name_format)
403b09
-from ipalib.parameters import Bool
403b09
+from ipalib.frontend import Command
403b09
+from ipalib.parameters import Bool, Str
403b09
 from ipalib.plugable import Registry
403b09
 from ipalib import _, ngettext
403b09
 from ipapython.dnsutil import DNSName
403b09
@@ -121,6 +123,64 @@ class dnszone_mod(DNSZoneMethodOverride):
403b09
     pass
403b09
 
403b09
 
403b09
+# Support old servers without dnsrecord_split_parts
403b09
+# Do not add anything new here!
403b09
+@register(no_fail=True)
403b09
+class dnsrecord_split_parts(Command):
403b09
+    NO_CLI = True
403b09
+
403b09
+    takes_args = (
403b09
+        Str('name'),
403b09
+        Str('value'),
403b09
+    )
403b09
+
403b09
+    def execute(self, name, value, *args, **options):
403b09
+        def split_exactly(count):
403b09
+            values = value.split()
403b09
+            if len(values) != count:
403b09
+                return None
403b09
+            return tuple(values)
403b09
+
403b09
+        result = ()
403b09
+
403b09
+        rrtype = get_record_rrtype(name)
403b09
+        if rrtype in ('A', 'AAAA', 'CNAME', 'DNAME', 'NS', 'PTR'):
403b09
+            result = split_exactly(1)
403b09
+        elif rrtype in ('AFSDB', 'KX', 'MX'):
403b09
+            result = split_exactly(2)
403b09
+        elif rrtype in ('CERT', 'DLV', 'DS', 'SRV', 'TLSA'):
403b09
+            result = split_exactly(4)
403b09
+        elif rrtype in ('NAPTR'):
403b09
+            result = split_exactly(6)
403b09
+        elif rrtype in ('A6', 'TXT'):
403b09
+            result = (value,)
403b09
+        elif rrtype == 'LOC':
403b09
+            regex = re.compile(
403b09
+                r'(?P<d1>\d{1,2}\s+)'
403b09
+                r'(?:(?P<m1>\d{1,2}\s+)'
403b09
+                r'(?P<s1>\d{1,2}(?:\.\d{1,3})?\s+)?)?'
403b09
+                r'(?P<dir1>[NS])\s+'
403b09
+                r'(?P<d2>\d{1,3}\s+)'
403b09
+                r'(?:(?P<m2>\d{1,2}\s+)'
403b09
+                r'(?P<s2>\d{1,2}(?:\.\d{1,3})?\s+)?)?'
403b09
+                r'(?P<dir2>[WE])\s+'
403b09
+                r'(?P<alt>-?\d{1,8}(?:\.\d{1,2})?)m?'
403b09
+                r'(?:\s+(?P<siz>\d{1,8}(?:\.\d{1,2})?)m?'
403b09
+                r'(?:\s+(?P<hp>\d{1,8}(?:\.\d{1,2})?)m?'
403b09
+                r'(?:\s+(?P<vp>\d{1,8}(?:\.\d{1,2})?)m?\s*)?)?)?$')
403b09
+
403b09
+            m = regex.match(value)
403b09
+            if m is not None:
403b09
+                result = tuple(
403b09
+                    x.strip() if x is not None else x for x in m.groups())
403b09
+        elif rrtype == 'SSHFP':
403b09
+            values = value.split(None, 2)
403b09
+            if len(values) == 3:
403b09
+                result = tuple(values)
403b09
+
403b09
+        return dict(result=result)
403b09
+
403b09
+
403b09
 @register(override=True, no_fail=True)
403b09
 class dnsrecord_add(MethodOverride):
403b09
     no_option_msg = 'No options to add a specific record provided.\n' \
403b09
-- 
403b09
2.7.4
403b09