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