frontend: re-raise remote RequirementError using CLI name in CLI

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

Reviewed-By: David Kupka <dkupka@redhat.com>
This commit is contained in:
Jan Cholasta 2016-05-18 10:03:39 +02:00
parent e0275abe6f
commit 2f6b333187
9 changed files with 34 additions and 46 deletions

View File

@ -37,7 +37,7 @@ from ipalib.text import _
from ipalib.errors import (ZeroArgumentError, MaxArgumentError, OverlapError,
VersionError, OptionError, InvocationError,
ValidationError, ConversionError)
from ipalib import messages
from ipalib import errors, messages
from ipalib.request import context, context_frame
from ipalib.util import json_serialize
@ -351,13 +351,6 @@ class HasParam(Plugin):
for spec in get():
param = create_param(spec)
if env is None or param.use_in_context(env):
if env is not None and not hasattr(param, 'env'):
# Force specified environment. The way it is done is violation of ReadOnly promise.
# Unfortunately, all alternatives are worse from both performance and code complexity
# points of view. See following threads on freeipa-devel@ for references:
# https://www.redhat.com/archives/freeipa-devel/2011-August/msg00000.html
# https://www.redhat.com/archives/freeipa-devel/2011-August/msg00011.html
object.__setattr__(param, 'env', env)
yield param
def _create_param_namespace(self, name, env=None):
@ -735,7 +728,7 @@ class Command(HasParam):
"""
for param in self.params():
value = kw.get(param.name, None)
param.validate(value, self.env.context, supplied=param.name in kw)
param.validate(value, supplied=param.name in kw)
def verify_client_version(self, client_version):
"""
@ -796,7 +789,15 @@ class Command(HasParam):
"""
Forward call over RPC to this same command on server.
"""
return self.Backend.rpcclient.forward(self.name, *args, **kw)
try:
return self.Backend.rpcclient.forward(self.name, *args, **kw)
except errors.RequirementError as e:
if self.api.env.context != 'cli':
raise
name = getattr(e, 'name', None)
if name is None or name not in self.params:
raise
raise errors.RequirementError(name=self.params[name].cli_name)
def _on_finalize(self):
"""

View File

@ -572,10 +572,7 @@ class Param(ReadOnly):
value = self.get_default(**kw)
else:
value = self.convert(self.normalize(value))
if hasattr(self, 'env'):
self.validate(value, self.env.context, supplied=self.name in kw) #pylint: disable=E1101
else:
self.validate(value, supplied=self.name in kw)
self.validate(value, supplied=self.name in kw)
return value
def get_param_name(self):
@ -811,20 +808,16 @@ class Param(ReadOnly):
return value
raise ConversionError(name=self.name, error=ugettext(self.type_error))
def validate(self, value, context=None, supplied=None):
def validate(self, value, supplied=None):
"""
Check validity of ``value``.
:param value: A proposed value for this parameter.
:param context: The context we are running in.
:param supplied: True if this parameter was supplied explicitly.
"""
if value is None:
if self.required or (supplied and 'nonempty' in self.flags):
if context == 'cli':
raise RequirementError(name=self.cli_name)
else:
raise RequirementError(name=self.name)
raise RequirementError(name=self.name)
return
if self.multivalue:
if type(value) is not tuple:

View File

@ -413,7 +413,7 @@ class group_mod(LDAPUpdate):
# Can't check for this in a validator because we lack context
if 'gidnumber' in options and options['gidnumber'] is None:
raise errors.RequirementError(name='gid')
raise errors.RequirementError(name='gidnumber')
return dn
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -422,7 +422,7 @@ class group_mod(LDAPUpdate):
if call_func.__name__ == 'update_entry':
if isinstance(exc, errors.ObjectclassViolation):
if 'gidNumber' in exc.message and 'posixGroup' in exc.message:
raise errors.RequirementError(name='gid')
raise errors.RequirementError(name='gidnumber')
raise exc

View File

@ -787,7 +787,7 @@ sides.
)
if 'trust_type' not in options:
raise errors.RequirementError(name=_('trust type'))
raise errors.RequirementError(name='trust_type')
if options['trust_type'] != u'ad':
raise errors.ValidationError(

View File

@ -459,38 +459,32 @@ class test_Param(ClassChecker):
# Test in default state (with no rules, no kwarg):
o = self.cls('my_param')
e = raises(errors.RequirementError, o.validate, None, 'cli')
e = raises(errors.RequirementError, o.validate, None)
assert e.name == 'my_param'
# Test in default state that cli_name gets returned in the exception
# when context == 'cli'
o = self.cls('my_param', cli_name='short')
e = raises(errors.RequirementError, o.validate, None, 'cli')
assert e.name == 'short'
# Test with required=False
o = self.cls('my_param', required=False)
assert o.required is False
assert o.validate(None, 'cli') is None
assert o.validate(None) is None
# Test with query=True:
o = self.cls('my_param', query=True)
assert o.query is True
e = raises(errors.RequirementError, o.validate, None, 'cli')
e = raises(errors.RequirementError, o.validate, None)
assert_equal(e.name, 'my_param')
# Test with multivalue=True:
o = self.cls('my_param', multivalue=True)
e = raises(TypeError, o.validate, [], 'cli')
e = raises(TypeError, o.validate, [])
assert str(e) == TYPE_ERROR % ('value', tuple, [], list)
e = raises(ValueError, o.validate, tuple(), 'cli')
e = raises(ValueError, o.validate, tuple())
assert str(e) == 'value: empty tuple must be converted to None'
# Test with wrong (scalar) type:
e = raises(TypeError, o.validate, (None, None, 42, None), 'cli')
e = raises(TypeError, o.validate, (None, None, 42, None))
assert str(e) == TYPE_ERROR % ('my_param', type(None), 42, int)
o = self.cls('my_param')
e = raises(TypeError, o.validate, 'Hello', 'cli')
e = raises(TypeError, o.validate, 'Hello')
assert str(e) == TYPE_ERROR % ('my_param', type(None), 'Hello', str)
class Example(self.cls):
@ -502,13 +496,13 @@ class test_Param(ClassChecker):
fail = DummyRule(u'no good')
o = Example('example', pass1, pass2)
assert o.multivalue is False
assert o.validate(11, 'cli') is None
assert o.validate(11) is None
assert pass1.calls == [(text.ugettext, 11)]
assert pass2.calls == [(text.ugettext, 11)]
pass1.reset()
pass2.reset()
o = Example('example', pass1, pass2, fail)
e = raises(errors.ValidationError, o.validate, 42, 'cli')
e = raises(errors.ValidationError, o.validate, 42)
assert e.name == 'example'
assert e.error == u'no good'
assert e.index is None
@ -522,7 +516,7 @@ class test_Param(ClassChecker):
fail = DummyRule(u'this one is not good')
o = Example('example', pass1, pass2, multivalue=True)
assert o.multivalue is True
assert o.validate((3, 9), 'cli') is None
assert o.validate((3, 9)) is None
assert pass1.calls == [
(text.ugettext, 3),
(text.ugettext, 9),
@ -535,7 +529,7 @@ class test_Param(ClassChecker):
pass2.reset()
o = Example('multi_example', pass1, pass2, fail, multivalue=True)
assert o.multivalue is True
e = raises(errors.ValidationError, o.validate, (3, 9), 'cli')
e = raises(errors.ValidationError, o.validate, (3, 9))
assert e.name == 'multi_example'
assert e.error == u'this one is not good'
assert e.index == 0

View File

@ -147,7 +147,7 @@ class TestAttrOnUser(XMLRPC_test):
""" Try setting givenname to None with setattr in user """
user.ensure_exists()
command = user.make_update_command(dict(setattr=(u'givenname=')))
with raises_exact(errors.RequirementError(name='givenname')):
with raises_exact(errors.RequirementError(name='first')):
command()
def test_set_givenname_to_none_with_option(self, user):
@ -219,7 +219,7 @@ class TestAttrOnConfigs(XMLRPC_test):
**dict(delattr=u'ipasearchrecordslimit=100')
)
with raises_exact(errors.RequirementError(
name='ipasearchrecordslimit')):
name='searchrecordslimit')):
command()
def test_set_nonexistent_attribute(self, user):

View File

@ -61,7 +61,7 @@ class test_config(Declarative):
desc='Try to remove ipausersearchfields',
command=('config_mod', [],
dict(delattr=u'ipausersearchfields=uid,givenname,sn,telephonenumber,ou,title')),
expected=errors.RequirementError(name='ipausersearchfields'),
expected=errors.RequirementError(name='usersearch'),
),
dict(

View File

@ -1179,7 +1179,7 @@ class test_dns(Declarative):
dict(
desc='Try to modify SRV record in zone %r without specifying modified value' % (zone1),
command=('dnsrecord_mod', [zone1, u'_foo._tcp'], {'srv_part_priority': 1,}),
expected=errors.RequirementError(name='srvrecord'),
expected=errors.RequirementError(name='srv_rec'),
),
dict(

View File

@ -195,7 +195,7 @@ class test_permission_negative(Declarative):
attrs=[u'sn'],
)
),
expected=errors.RequirementError(name='ipapermright'),
expected=errors.RequirementError(name='right'),
),
dict(
@ -310,7 +310,7 @@ class test_permission_negative(Declarative):
ipapermright=None,
)
),
expected=errors.RequirementError(name='ipapermright'),
expected=errors.RequirementError(name='right'),
),
dict(