Skip to content

Commit

Permalink
Request ID when name is ambiguous.
Browse files Browse the repository at this point in the history
Fixes bug 931605

Change-Id: If0778915d964995dbb6647d56ed21075aec08baa
  • Loading branch information
rconradharris committed Apr 9, 2012
1 parent ea448e2 commit 0028eb4
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 19 deletions.
11 changes: 7 additions & 4 deletions novaclient/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,15 @@ def find(self, **kwargs):
This isn't very efficient: it loads the entire list then filters on
the Python side.
"""
rl = self.findall(**kwargs)
try:
return rl[0]
except IndexError:
matches = self.findall(**kwargs)
num_matches = len(matches)
if num_matches == 0:
msg = "No %s matching %s." % (self.resource_class.__name__, kwargs)
raise exceptions.NotFound(404, msg)
elif num_matches > 1:
raise exceptions.NoUniqueMatch
else:
return matches[0]

def findall(self, **kwargs):
"""
Expand Down
4 changes: 4 additions & 0 deletions novaclient/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class AuthorizationFailure(Exception):
pass


class NoUniqueMatch(Exception):
pass


class NoTokenLookupException(Exception):
"""This form of authentication does not support looking up
endpoints from an existing token."""
Expand Down
30 changes: 18 additions & 12 deletions novaclient/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,27 @@ def find_resource(manager, name_or_id):
pass

try:
return manager.find(human_id=name_or_id)
except exceptions.NotFound:
pass
try:
return manager.find(human_id=name_or_id)
except exceptions.NotFound:
pass

# finally try to find entity by name
try:
return manager.find(name=name_or_id)
except exceptions.NotFound:
# finally try to find entity by name
try:
# Volumes does not have name, but displayName
return manager.find(displayName=name_or_id)
return manager.find(name=name_or_id)
except exceptions.NotFound:
msg = "No %s with a name or ID of '%s' exists." % \
(manager.resource_class.__name__.lower(), name_or_id)
raise exceptions.CommandError(msg)
try:
# Volumes does not have name, but displayName
return manager.find(displayName=name_or_id)
except exceptions.NotFound:
msg = "No %s with a name or ID of '%s' exists." % \
(manager.resource_class.__name__.lower(), name_or_id)
raise exceptions.CommandError(msg)
except exceptions.NoUniqueMatch:
msg = ("Multiple %s matches found for '%s', use an ID to be more"
" specific." % (manager.resource_class.__name__.lower(),
name_or_id))
raise exceptions.CommandError(msg)


def _format_servers_list_networks(server):
Expand Down
7 changes: 4 additions & 3 deletions tests/v1_1/test_servers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import StringIO

from novaclient import exceptions
from novaclient.v1_1 import servers
from tests import utils
from tests.v1_1 import fakes
Expand Down Expand Up @@ -97,10 +98,10 @@ def test_find(self):
cs.assert_called('GET', '/servers/detail')
self.assertEqual(s.name, 'sample-server')

# Find with multiple results arbitraility returns the first item
s = cs.servers.find(flavor={"id": 1, "name": "256 MB Server"})
self.assertRaises(exceptions.NoUniqueMatch, cs.servers.find,
flavor={"id": 1, "name": "256 MB Server"})

sl = cs.servers.findall(flavor={"id": 1, "name": "256 MB Server"})
self.assertEqual(sl[0], s)
self.assertEqual([s.id for s in sl], [1234, 5678])

def test_reboot_server(self):
Expand Down

0 comments on commit 0028eb4

Please sign in to comment.