summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/errors.py17
-rw-r--r--ipaserver/plugins/ldap2.py7
-rw-r--r--tests/test_xmlrpc/test_host_plugin.py35
3 files changed, 58 insertions, 1 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py
index cad6e37b4..04211e6ed 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -1210,6 +1210,23 @@ class AttrValueNotFound(ExecutionError):
format = _('%(attr)s does not contain \'%(value)s\'')
+class SingleMatchExpected(ExecutionError):
+ """
+ **4027** Raised when a search should return a single match
+
+ For example:
+
+ >>> raise SingleMatchExpected(found=9)
+ Traceback (most recent call last):
+ ...
+ SingleMatchExpected: The search criteria was not specific enough. Expected 1 and found 9.
+ """
+
+ errno = 4027
+ rval = 1
+ format = _('The search criteria was not specific enough. Expected 1 and found %(found)d.')
+
+
class BuiltinError(ExecutionError):
"""
**4100** Base class for builtin execution errors (*4100 - 4199*).
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index 5d6d21d43..6f34984ca 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -620,7 +620,12 @@ class ldap2(CrudBackend, Encoder):
"""
search_kw = {attr: value, 'objectClass': object_class}
filter = self.make_filter(search_kw, rules=self.MATCH_ALL)
- return self.find_entries(filter, attrs_list, base_dn)[0][0]
+ (entries, truncated) = self.find_entries(filter, attrs_list, base_dn)
+
+ if len(entries) > 1:
+ raise errors.SingleMatchExpected(found=len(entries))
+ else:
+ return entries[0]
def get_entry(self, dn, attrs_list=None, time_limit=None,
size_limit=None, normalize=True):
diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py
index f4e020ed7..793729629 100644
--- a/tests/test_xmlrpc/test_host_plugin.py
+++ b/tests/test_xmlrpc/test_host_plugin.py
@@ -39,6 +39,8 @@ dn2 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn2, api.env.basedn)
fqdn3 = u'testhost2.%s' % api.env.domain
short3 = u'testhost2'
dn3 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn3, api.env.basedn)
+fqdn4 = u'testhost2.lab.%s' % api.env.domain
+dn4 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn4, api.env.basedn)
# We can use the same cert we generated for the service tests
fd = open('tests/test_xmlrpc/service.crt', 'r')
@@ -53,6 +55,7 @@ class test_host(Declarative):
('host_del', [fqdn1], {}),
('host_del', [fqdn2], {}),
('host_del', [fqdn3], {}),
+ ('host_del', [fqdn4], {}),
('service_del', [service1], {}),
]
@@ -295,6 +298,32 @@ class test_host(Declarative):
dict(
+ desc='Create %r' % fqdn4,
+ command=('host_add', [fqdn4],
+ dict(
+ description=u'Test host 4',
+ l=u'Undisclosed location 4',
+ force=True,
+ ),
+ ),
+ expected=dict(
+ value=fqdn4,
+ summary=u'Added host "%s"' % fqdn4,
+ result=dict(
+ dn=dn4,
+ fqdn=[fqdn4],
+ description=[u'Test host 4'],
+ l=[u'Undisclosed location 4'],
+ krbprincipalname=[u'host/%s@%s' % (fqdn4, api.env.realm)],
+ objectclass=objectclasses.host,
+ ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn4],
+ ),
+ ),
+ ),
+
+
+ dict(
desc='Add managedby_host %r to %r' % (fqdn1, fqdn3),
command=('host_add_managedby', [fqdn3],
dict(
@@ -363,6 +392,12 @@ class test_host(Declarative):
),
+ dict(
+ desc='Show a host with multiple matches %s' % short3,
+ command=('host_show', [short3], {}),
+ expected=errors.SingleMatchExpected(found=2),
+ ),
+
dict(
desc='Try to rename %r' % fqdn1,