Commit 86aadabc authored by Zuul's avatar Zuul Committed by Gerrit Code Review

Merge "Support hostname in show, update and delete host operations"

parents b96c671a 60e658d6
......@@ -26,6 +26,11 @@ from cliff import show
from blazarclient import exception
from blazarclient import utils
HEX_ELEM = '[0-9A-Fa-f]'
UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}',
HEX_ELEM + '{4}', HEX_ELEM + '{4}',
HEX_ELEM + '{12}'])
class OpenStackCommand(command.Command):
"""Base class for OpenStack commands."""
......@@ -65,6 +70,8 @@ class BlazarCommand(OpenStackCommand):
json_indent = None
resource = None
allow_names = True
name_key = None
id_pattern = UUID_PATTERN
def __init__(self, app, app_args):
super(BlazarCommand, self).__init__(app, app_args)
......@@ -164,7 +171,9 @@ class UpdateCommand(BlazarCommand):
if self.allow_names:
res_id = utils.find_resource_id_by_name_or_id(blazar_client,
self.resource,
parsed_args.id)
parsed_args.id,
self.name_key,
self.id_pattern)
else:
res_id = parsed_args.id
resource_manager = getattr(blazar_client, self.resource)
......@@ -199,7 +208,9 @@ class DeleteCommand(BlazarCommand):
if self.allow_names:
res_id = utils.find_resource_id_by_name_or_id(blazar_client,
self.resource,
parsed_args.id)
parsed_args.id,
self.name_key,
self.id_pattern)
else:
res_id = parsed_args.id
resource_manager.delete(res_id)
......@@ -284,7 +295,9 @@ class ShowCommand(BlazarCommand, show.ShowOne):
if self.allow_names:
res_id = utils.find_resource_id_by_name_or_id(blazar_client,
self.resource,
parsed_args.id)
parsed_args.id,
self.name_key,
self.id_pattern)
else:
res_id = parsed_args.id
......
# Copyright (c) 2018 NTT
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import mock
from blazarclient import shell
from blazarclient import tests
from blazarclient.v1.shell_commands import hosts
class CreateHostTest(tests.TestCase):
def setUp(self):
super(CreateHostTest, self).setUp()
self.create_host = hosts.CreateHost(shell.BlazarShell(), mock.Mock())
def test_args2body(self):
args = argparse.Namespace(
name='test-host',
extra_capabilities=[
'extra_key1=extra_value1',
'extra_key2=extra_value2',
]
)
expected = {
'name': 'test-host',
'extra_key1': 'extra_value1',
'extra_key2': 'extra_value2',
}
ret = self.create_host.args2body(args)
self.assertDictEqual(ret, expected)
class UpdateHostTest(tests.TestCase):
def create_update_command(self, list_value):
mock_host_manager = mock.Mock()
mock_host_manager.list.return_value = list_value
mock_client = mock.Mock()
mock_client.host = mock_host_manager
blazar_shell = shell.BlazarShell()
blazar_shell.client = mock_client
return hosts.UpdateHost(blazar_shell, mock.Mock()), mock_host_manager
def test_update_host(self):
list_value = [
{'id': '101', 'hypervisor_hostname': 'host-1'},
{'id': '201', 'hypervisor_hostname': 'host-2'},
]
update_host, host_manager = self.create_update_command(list_value)
args = argparse.Namespace(
id='101',
extra_capabilities=[
'key1=value1',
'key2=value2'
])
expected = {
'values': {
'key1': 'value1',
'key2': 'value2'
}
}
update_host.run(args)
host_manager.update.assert_called_once_with('101', **expected)
def test_update_host_with_name(self):
list_value = [
{'id': '101', 'hypervisor_hostname': 'host-1'},
{'id': '201', 'hypervisor_hostname': 'host-2'},
]
update_host, host_manager = self.create_update_command(list_value)
args = argparse.Namespace(
id='host-1',
extra_capabilities=[
'key1=value1',
'key2=value2'
])
expected = {
'values': {
'key1': 'value1',
'key2': 'value2'
}
}
update_host.run(args)
host_manager.update.assert_called_once_with('101', **expected)
def test_update_host_with_name_startwith_number(self):
list_value = [
{'id': '101', 'hypervisor_hostname': '1-host'},
{'id': '201', 'hypervisor_hostname': '2-host'},
]
update_host, host_manager = self.create_update_command(list_value)
args = argparse.Namespace(
id='1-host',
extra_capabilities=[
'key1=value1',
'key2=value2'
])
expected = {
'values': {
'key1': 'value1',
'key2': 'value2'
}
}
update_host.run(args)
host_manager.update.assert_called_once_with('101', **expected)
class ShowHostTest(tests.TestCase):
def create_show_command(self, list_value, get_value):
mock_host_manager = mock.Mock()
mock_host_manager.list.return_value = list_value
mock_host_manager.get.return_value = get_value
mock_client = mock.Mock()
mock_client.host = mock_host_manager
blazar_shell = shell.BlazarShell()
blazar_shell.client = mock_client
return hosts.ShowHost(blazar_shell, mock.Mock()), mock_host_manager
def test_show_host(self):
list_value = [
{'id': '101', 'hypervisor_hostname': 'host-1'},
{'id': '201', 'hypervisor_hostname': 'host-2'},
]
get_value = {
'id': '101', 'hypervisor_hostname': 'host-1'}
show_host, host_manager = self.create_show_command(list_value,
get_value)
args = argparse.Namespace(id='101')
expected = [('hypervisor_hostname', 'id'), ('host-1', '101')]
ret = show_host.get_data(args)
self.assertEqual(ret, expected)
host_manager.get.assert_called_once_with('101')
def test_show_host_with_name(self):
list_value = [
{'id': '101', 'hypervisor_hostname': 'host-1'},
{'id': '201', 'hypervisor_hostname': 'host-2'},
]
get_value = {
'id': '101', 'hypervisor_hostname': 'host-1'}
show_host, host_manager = self.create_show_command(list_value,
get_value)
args = argparse.Namespace(id='host-1')
expected = [('hypervisor_hostname', 'id'), ('host-1', '101')]
ret = show_host.get_data(args)
self.assertEqual(ret, expected)
host_manager.get.assert_called_once_with('101')
def test_show_host_with_name_startwith_number(self):
list_value = [
{'id': '101', 'hypervisor_hostname': '1-host'},
{'id': '201', 'hypervisor_hostname': '2-host'},
]
get_value = {
'id': '101', 'hypervisor_hostname': '1-host'}
show_host, host_manager = self.create_show_command(list_value,
get_value)
args = argparse.Namespace(id='1-host')
expected = [('hypervisor_hostname', 'id'), ('1-host', '101')]
ret = show_host.get_data(args)
self.assertEqual(ret, expected)
host_manager.get.assert_called_once_with('101')
class DeleteHostTest(tests.TestCase):
def create_delete_command(self, list_value):
mock_host_manager = mock.Mock()
mock_host_manager.list.return_value = list_value
mock_client = mock.Mock()
mock_client.host = mock_host_manager
blazar_shell = shell.BlazarShell()
blazar_shell.client = mock_client
return hosts.DeleteHost(blazar_shell, mock.Mock()), mock_host_manager
def test_delete_host(self):
list_value = [
{'id': '101', 'hypervisor_hostname': 'host-1'},
{'id': '201', 'hypervisor_hostname': 'host-2'},
]
delete_host, host_manager = self.create_delete_command(list_value)
args = argparse.Namespace(id='101')
delete_host.run(args)
host_manager.delete.assert_called_once_with('101')
def test_delete_host_with_name(self):
list_value = [
{'id': '101', 'hypervisor_hostname': 'host-1'},
{'id': '201', 'hypervisor_hostname': 'host-2'},
]
delete_host, host_manager = self.create_delete_command(list_value)
args = argparse.Namespace(id='host-1')
delete_host.run(args)
host_manager.delete.assert_called_once_with('101')
def test_delete_host_with_name_startwith_number(self):
list_value = [
{'id': '101', 'hypervisor_hostname': '1-host'},
{'id': '201', 'hypervisor_hostname': '2-host'},
]
delete_host, host_manager = self.create_delete_command(list_value)
args = argparse.Namespace(id='1-host')
delete_host.run(args)
host_manager.delete.assert_called_once_with('101')
......@@ -22,10 +22,6 @@ from oslo_serialization import jsonutils as json
from blazarclient import exception
from blazarclient.i18n import _
HEX_ELEM = '[0-9A-Fa-f]'
UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}',
HEX_ELEM + '{4}', HEX_ELEM + '{4}',
HEX_ELEM + '{12}'])
ELAPSED_TIME_REGEX = '^(\d+)([s|m|h|d])$'
LEASE_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
......@@ -106,9 +102,10 @@ def get_item_properties(item, fields, mixed_case_fields=None, formatters=None):
return tuple(row)
def find_resource_id_by_name_or_id(client, resource, name_or_id):
def find_resource_id_by_name_or_id(client, resource, name_or_id,
name_key, id_pattern):
resource_manager = getattr(client, resource)
is_id = re.match(UUID_PATTERN, name_or_id)
is_id = re.match(id_pattern, name_or_id)
if is_id:
resources = resource_manager.list()
for resource in resources:
......@@ -116,17 +113,18 @@ def find_resource_id_by_name_or_id(client, resource, name_or_id):
return name_or_id
raise exception.BlazarClientException('No resource found with ID %s' %
name_or_id)
return _find_resource_id_by_name(client, resource, name_or_id)
return _find_resource_id_by_name(client, resource, name_or_id, name_key)
def _find_resource_id_by_name(client, resource, name):
def _find_resource_id_by_name(client, resource, name, name_key):
resource_manager = getattr(client, resource)
resources = resource_manager.list()
named_resources = []
key = name_key if name_key else 'name'
for resource in resources:
if resource['name'] == name:
if resource[key] == name:
named_resources.append(resource['id'])
if len(named_resources) > 1:
raise exception.NoUniqueMatch(message="There are more than one "
......
......@@ -17,6 +17,8 @@ import logging
from blazarclient import command
HOST_ID_PATTERN = '^[0-9]+$'
class ListHosts(command.ListCommand):
"""Print a list of hosts."""
......@@ -39,9 +41,8 @@ class ShowHost(command.ShowCommand):
"""Show host details."""
resource = 'host'
json_indent = 4
# NOTE(sbauza): We can't find by name as there is currently no column
# called 'name' but rather 'hypervisor_hostname'
allow_names = False
name_key = 'hypervisor_hostname'
id_pattern = HOST_ID_PATTERN
log = logging.getLogger(__name__ + '.ShowHost')
......@@ -85,8 +86,9 @@ class UpdateHost(command.UpdateCommand):
"""Update attributes of a host."""
resource = 'host'
json_indent = 4
allow_names = False
log = logging.getLogger(__name__ + '.UpdateHost')
name_key = 'hypervisor_hostname'
id_pattern = HOST_ID_PATTERN
def get_parser(self, prog_name):
parser = super(UpdateHost, self).get_parser(prog_name)
......@@ -115,7 +117,6 @@ class UpdateHost(command.UpdateCommand):
class DeleteHost(command.DeleteCommand):
"""Delete a host."""
resource = 'host'
# NOTE(sbauza): We can't find by name as there is currently no column
# called 'name' but rather 'hypervisor_hostname'
allow_names = False
log = logging.getLogger(__name__ + '.DeleteHost')
name_key = 'hypervisor_hostname'
id_pattern = HOST_ID_PATTERN
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment