What this patch does:

* Make sure arguments are validated and default values are filled in before calling a command. * Add new parameter flag "validate_search" to force validation on search arguments.
  * Fix validation of IP network parameters in the DNS plugin.

https://fedorahosted.org/freeipa/ticket/1627

Honza

--
Jan Cholasta
>From 3b7cd2181857defa378e5536c3de20d7e8b0232a Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 25 Aug 2011 17:57:50 +0200
Subject: [PATCH] Make sure arguments are validated and default values are
 filled in before calling a command.

Add new parameter flag "validate_search" to force validation on search
arguments.

Fix validation of IP network parameters in the DNS plugin.

ticket 1627
---
 API.txt               |    6 +++---
 VERSION               |    2 +-
 ipalib/cli.py         |    1 +
 ipalib/crud.py        |    7 ++++---
 ipalib/frontend.py    |   35 ++++++++++++++++++++++++++---------
 ipalib/plugins/dns.py |    5 ++---
 6 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/API.txt b/API.txt
index 24f7634..8a5a05d 100644
--- a/API.txt
+++ b/API.txt
@@ -739,7 +739,7 @@ output: Output('value', <type 'unicode'>, "The primary_key value of the entry, e
 command: dnszone_add
 args: 1,19,3
 arg: Str('idnsname', attribute=True, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, required=True)
-option: Str('name_from_ip', _validate_ipnet, attribute=True, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
+option: Str('name_from_ip', _validate_ipnet, attribute=True, cli_name='name_from_ip', flags=['validate_search'], label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
 option: Str('idnssoamname', attribute=True, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, required=True)
 option: Str('idnssoarname', attribute=True, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, required=True)
 option: Int('idnssoaserial', attribute=True, autofill=True, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
@@ -784,7 +784,7 @@ command: dnszone_find
 args: 1,20,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Str('idnsname', attribute=True, autofill=False, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, query=True, required=False)
-option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
+option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', flags=['validate_search'], label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, query=False, required=False)
 option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
 option: Str('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, query=True, required=False)
 option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, query=True, required=False)
@@ -810,7 +810,7 @@ output: Output('truncated', <type 'bool'>, 'True if not all results were returne
 command: dnszone_mod
 args: 1,18,3
 arg: Str('idnsname', attribute=True, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, query=True, required=True)
-option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
+option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', flags=['validate_search'], label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
 option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, required=False)
 option: Str('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, required=False)
 option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
diff --git a/VERSION b/VERSION
index d7eaa86..51711ef 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=11
+IPA_API_VERSION_MINOR=12
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 5e1365d..627ed7a 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -951,6 +951,7 @@ class cli(backend.Executioner):
         if not isinstance(cmd, frontend.Local):
             self.create_context()
         kw = self.parse(cmd, argv)
+        kw = cmd.prepare_params(**kw)
         kw['version'] = API_VERSION
         if self.env.interactive:
             self.prompt_interactively(cmd, kw)
diff --git a/ipalib/crud.py b/ipalib/crud.py
index 97d6430..19f4cbf 100644
--- a/ipalib/crud.py
+++ b/ipalib/crud.py
@@ -226,19 +226,20 @@ class Search(Method):
         for option in self.obj.params_minus(self.args):
             if 'no_search' in option.flags:
                 continue
+            query = 'validate_search' not in option.flags
             if 'ask_search' in option.flags:
                 yield option.clone(
-                    attribute=True, query=True, required=False,
+                    attribute=True, query=query, required=False,
                     autofill=False, alwaysask=True
                 )
             elif isinstance(option, parameters.Flag):
                 yield option.clone_retype(
                     option.name, parameters.Bool,
-                    attribute=True, query=True, required=False, autofill=False
+                    attribute=True, query=query, required=False, autofill=False
                 )
             else:
                 yield option.clone(
-                    attribute=True, query=True, required=False, autofill=False
+                    attribute=True, query=query, required=False, autofill=False
                 )
         if not self.extra_options_first:
             for option in super(Search, self).get_options():
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index c2ae4e7..c754f94 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -32,7 +32,7 @@ from text import _, ngettext
 
 from errors import ZeroArgumentError, MaxArgumentError, OverlapError, RequiresRoot, VersionError, RequirementError
 from errors import InvocationError
-from constants import TYPE_ERROR
+from constants import TYPE_ERROR, NULLS
 from ipapython.version import API_VERSION
 from distutils import version
 
@@ -415,19 +415,12 @@ class Command(HasParam):
         self.debug(
             'raw: %s(%s)', self.name, ', '.join(self._repr_iter(**params))
         )
-        while True:
-            default = self.get_default(**params)
-            if len(default) == 0:
-                break
-            params.update(default)
-        params = self.normalize(**params)
-        params = self.convert(**params)
+        params = self.prepare_params(**params)
         self.debug(
             '%s(%s)', self.name, ', '.join(self._repr_iter(**params))
         )
         if not self.api.env.in_server and 'version' not in params:
             params['version'] = API_VERSION
-        self.validate(**params)
         (args, options) = self.params_2_args_options(**params)
         ret = self.run(*args, **options)
         if (
@@ -443,6 +436,30 @@ class Command(HasParam):
             self.validate_output(ret)
         return ret
 
+    def prepare_params(self, **kw):
+        for name in self.params:
+            if name not in kw:
+                continue
+            value = kw[name]
+            if value in NULLS:
+                del kw[name]
+                continue
+            kw[name] = self.params[name](value)
+
+        while True:
+            defaults = {}
+            for name in self.params:
+                if name in kw:
+                    continue
+                value = self.params[name].get_default(**kw)
+                if value is not None:
+                    defaults[name] = value
+            if len(defaults) == 0:
+                break
+            kw.update(defaults)
+
+        return kw
+
     def soft_validate(self, values):
         errors = dict()
         for p in self.params():
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index b4eee11..0a542c1 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -166,7 +166,7 @@ def _validate_ipaddr(ugettext, ipaddr):
 def _validate_ipnet(ugettext, ipnet):
     try:
         net = netaddr.IPNetwork(ipnet)
-    except (UnboundLocalError, ValueError):
+    except (netaddr.AddrFormatError, UnboundLocalError, ValueError):
         return u'invalid format'
     return None
 
@@ -315,6 +315,7 @@ class dnszone(LDAPObject):
         Str('name_from_ip?', _validate_ipnet,
             label=_('Reverse zone IP network'),
             doc=_('IP network to create reverse zone name from'),
+            flags=['validate_search'],
         ),
         Str('idnssoamname',
             cli_name='name_server',
@@ -489,8 +490,6 @@ class dnszone_find(LDAPSearch):
     """
     def args_options_2_entry(self, *args, **options):
         if 'name_from_ip' in options:
-            if 'idnsname' not in options:
-                options['idnsname'] = self.obj.params['idnsname'].get_default(**options)
             del options['name_from_ip']
         return super(dnszone_find, self).args_options_2_entry(self, *args, **options)
 
-- 
1.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to