summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/cli.py4
-rw-r--r--ipalib/constants.py4
-rw-r--r--ipalib/errors2.py32
-rw-r--r--ipalib/frontend.py22
-rw-r--r--ipalib/parameters.py5
-rw-r--r--ipalib/plugins/misc.py2
-rw-r--r--ipaserver/rpcserver.py4
-rw-r--r--tests/test_ipalib/test_frontend.py4
8 files changed, 55 insertions, 22 deletions
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 6b3ab7e5b..0afe09c46 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -36,7 +36,7 @@ import frontend
import backend
import plugable
import util
-from errors2 import PublicError, CommandError
+from errors2 import PublicError, CommandError, HelpError
from constants import CLI_TAB
from parameters import Password, Bytes
@@ -398,7 +398,7 @@ class help(frontend.Application):
return
key = str(command)
if key not in self.application:
- raise errors.UnknownHelpError(key)
+ raise HelpError(topic=key)
cmd = self.application[key]
print 'Purpose: %s' % cmd.doc
self.application.build_parser(cmd).print_help()
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 14f7f25d4..13a60f2ba 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -61,10 +61,10 @@ FORMAT_STDERR = ': '.join([
# Log format for log file:
FORMAT_FILE = '\t'.join([
'%(created)f',
- '%(levelname)s',
- '%(message)r', # Using %r for repr() so message is a single line
'%(process)d',
'%(threadName)s',
+ '%(levelname)s',
+ '%(message)r', # Using %r for repr() so message is a single line
])
diff --git a/ipalib/errors2.py b/ipalib/errors2.py
index 042580936..91b231159 100644
--- a/ipalib/errors2.py
+++ b/ipalib/errors2.py
@@ -85,7 +85,9 @@ current block assignments:
- **4001 - 4099** Open for general execution errors
- - **4100 - 4199** `LDAPError` and its subclasses
+ - **4100 - 4199** `BuiltinError` and its subclasses
+
+ - **4200 - 4299** `LDAPError` and its subclasses
- **4300 - 4999** *Reserved for future use*
@@ -581,14 +583,38 @@ class ExecutionError(PublicError):
errno = 4000
-class LDAPError(ExecutionError):
+class BuiltinError(ExecutionError):
"""
- **4100** Base class for LDAP execution errors (*4100 - 4199*).
+ **4100** Base class for builtin execution errors (*4100 - 4199*).
"""
errno = 4100
+class HelpError(BuiltinError):
+ """
+ **4101** Raised when requesting help for an unknown topic.
+
+ For example:
+
+ >>> raise HelpError(topic='newfeature')
+ Traceback (most recent call last):
+ ...
+ HelpError: no command nor help topic 'newfeature'
+ """
+
+ errno = 4101
+ format = _('no command nor help topic %(topic)r')
+
+
+class LDAPError(ExecutionError):
+ """
+ **4200** Base class for LDAP execution errors (*4200 - 4299*).
+ """
+
+ errno = 4200
+
+
##############################################################################
# 5000 - 5999: Generic errors
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index 6efccbb4d..565060b5d 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -97,17 +97,28 @@ class Command(plugable.Plugin):
XML-RPC and the executed an the nearest IPA server.
"""
params = self.args_options_2_params(*args, **options)
+ self.info(
+ '%s(%s)', self.name, ', '.join(self.__repr_iter(params))
+ )
params = self.normalize(**params)
params = self.convert(**params)
params.update(self.get_default(**params))
self.validate(**params)
(args, options) = self.params_2_args_options(**params)
- # FIXME: don't log passords!
- self.info(make_repr(self.name, *args, **options))
result = self.run(*args, **options)
- self.debug('%s result: %r', self.name, result)
+ self.debug('result from %s(): %r', self.name, result)
return result
+ def __repr_iter(self, params):
+ for arg in self.args():
+ value = params.get(arg.name, None)
+ yield '%r' % (arg.safe_value(value),)
+ for option in self.options():
+ if option.name not in params:
+ continue
+ value = params[option.name]
+ yield '%s=%r' % (option.name, option.safe_value(value))
+
def args_options_2_params(self, *args, **options):
"""
Merge (args, options) into params.
@@ -245,10 +256,7 @@ class Command(plugable.Plugin):
"""
for param in self.params():
value = kw.get(param.name, None)
- if value is not None:
- param.validate(value)
- elif param.required:
- raise errors.RequirementError(param.name)
+ param.validate(value)
def run(self, *args, **options):
"""
diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index fc6880747..0cf6a1f75 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -353,6 +353,11 @@ class Param(ReadOnly):
self.validate(value)
return value
+ def safe_value(self, value):
+ if isinstance(self, Password) and value is not None:
+ return u'********'
+ return value
+
def clone(self, **overrides):
"""
Return a new `Param` instance similar to this one.
diff --git a/ipalib/plugins/misc.py b/ipalib/plugins/misc.py
index 327e52b56..a2f0fa4e4 100644
--- a/ipalib/plugins/misc.py
+++ b/ipalib/plugins/misc.py
@@ -22,7 +22,7 @@ Misc frontend plugins.
"""
import re
-from ipalib import api, LocalOrRemote, Bytes
+from ipalib import api, LocalOrRemote
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 7bc57751d..5e886abca 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -48,11 +48,7 @@ class xmlserver(Backend):
self.debug('Received RPC call to %r', method)
if method not in self.Command:
raise CommandError(name=method)
- self.info('params = %r', params)
(args, options) = params_2_args_options(params)
- self.info('args = %r', args)
- self.info('options = %r', options)
- self.debug(make_repr(method, *args, **options))
result = self.Command[method](*args, **options)
return (result,) # Must wrap XML-RPC response in a tuple singleton
diff --git a/tests/test_ipalib/test_frontend.py b/tests/test_ipalib/test_frontend.py
index 72fc889e6..91fc83558 100644
--- a/tests/test_ipalib/test_frontend.py
+++ b/tests/test_ipalib/test_frontend.py
@@ -285,10 +285,8 @@ class test_Command(ClassChecker):
# Check with a missing required arg
fail = dict(okay)
fail.pop('option1')
- e = raises(errors.RequirementError, sub.validate, **fail)
+ e = raises(errors2.RequirementError, sub.validate, **fail)
assert e.name == 'option1'
- assert e.value is None
- assert e.index is None
def test_execute(self):
"""