Add instance type CLI
Add the CLI of instance type and entry point, update openstack request id key to offical format, modify the related unit tests. Change-Id: Ie736d99e5a9756dbae372793f39ad3c5cca72fe8
This commit is contained in:
@@ -35,13 +35,13 @@ except NameError:
|
||||
|
||||
|
||||
def getid(obj):
|
||||
"""Get obj's id or object itself if no id
|
||||
"""Get obj's uuid or object itself if no uuid
|
||||
|
||||
Abstracts the common pattern of allowing both an object or
|
||||
an object's ID (UUID) as a parameter when dealing with relationships.
|
||||
"""
|
||||
try:
|
||||
return obj.id
|
||||
return obj.uuid
|
||||
except AttributeError:
|
||||
return obj
|
||||
|
||||
@@ -168,7 +168,7 @@ class ManagerWithFind(Manager):
|
||||
elif num > 1:
|
||||
raise exceptions.NoUniqueMatch
|
||||
else:
|
||||
return self.get(matches[0].id)
|
||||
return self.get(matches[0].uuid)
|
||||
|
||||
def findall(self, **kwargs):
|
||||
"""Find all items with attributes matching ``**kwargs``.
|
||||
@@ -214,7 +214,7 @@ class RequestIdMixin(object):
|
||||
|
||||
def _append_request_id(self, resp):
|
||||
if isinstance(resp, Response):
|
||||
# Extract 'x-openstack-request-id' from headers if
|
||||
# Extract 'X-Openstack-Request-Id' from headers if
|
||||
# response is a Response object.
|
||||
request_id = (resp.headers.get('x-openstack-request-id') or
|
||||
resp.headers.get('x-compute-request-id'))
|
||||
@@ -280,7 +280,7 @@ class Resource(RequestIdMixin):
|
||||
if not hasattr(self.manager, 'get'):
|
||||
return
|
||||
|
||||
new = self.manager.get(self.id)
|
||||
new = self.manager.get(self.uuid)
|
||||
if new:
|
||||
self._add_details(new._info)
|
||||
# The 'request_ids' attribute has been added,
|
||||
|
||||
@@ -299,7 +299,7 @@ class SessionClient(adapter.LegacyJsonAdapter):
|
||||
kwargs.setdefault('user_agent', USER_AGENT)
|
||||
|
||||
if 'data' in kwargs:
|
||||
kwargs['data'] = jsonutils.dumps(kwargs['data'])
|
||||
kwargs['json'] = kwargs.pop('data')
|
||||
|
||||
resp, body = super(SessionClient, self).request(
|
||||
url, method,
|
||||
|
||||
182
nimbleclient/osc/v1/instance_type.py
Normal file
182
nimbleclient/osc/v1/instance_type.py
Normal file
@@ -0,0 +1,182 @@
|
||||
# Copyright 2016 Huawei, Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
|
||||
"""Nimble v1 Type action implementations"""
|
||||
|
||||
import logging
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import exceptions
|
||||
from osc_lib import utils
|
||||
import six
|
||||
|
||||
from nimbleclient.common.i18n import _
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CreateType(command.ShowOne):
|
||||
"""Create a new instance type"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateType, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"name",
|
||||
metavar="<name>",
|
||||
help=_("New type name")
|
||||
)
|
||||
public_group = parser.add_mutually_exclusive_group()
|
||||
public_group.add_argument(
|
||||
"--public",
|
||||
action="store_true",
|
||||
help=_("Type is available to other projects (default)")
|
||||
)
|
||||
public_group.add_argument(
|
||||
"--private",
|
||||
action="store_true",
|
||||
help=_("Type is not available to other projects")
|
||||
)
|
||||
parser.add_argument(
|
||||
"--description",
|
||||
metavar="<description>",
|
||||
help=_("Type description"),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
bc_client = self.app.client_manager.baremetal_compute
|
||||
|
||||
info = {}
|
||||
is_public = True
|
||||
if parsed_args.public:
|
||||
is_public = True
|
||||
if parsed_args.private:
|
||||
is_public = False
|
||||
|
||||
data = bc_client.instance_type.create(
|
||||
name=parsed_args.name,
|
||||
is_public=is_public,
|
||||
description=parsed_args.description,
|
||||
)
|
||||
info.update(data._info)
|
||||
|
||||
return zip(*sorted(six.iteritems(info)))
|
||||
|
||||
|
||||
class DeleteType(command.Command):
|
||||
"""Delete existing instance type(s)"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteType, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'type',
|
||||
metavar='<type>',
|
||||
nargs='+',
|
||||
help=_("Type(s) to delete (name or UUID)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
bc_client = self.app.client_manager.baremetal_compute
|
||||
result = 0
|
||||
for one_type in parsed_args.type:
|
||||
try:
|
||||
data = utils.find_resource(
|
||||
bc_client.instance_type, one_type)
|
||||
bc_client.instance_type.delete(data.uuid)
|
||||
except Exception as e:
|
||||
result += 1
|
||||
LOG.error(_("Failed to delete type with name or UUID "
|
||||
"'%(type)s': %(e)s") % {'type': one_type, 'e': e})
|
||||
|
||||
if result > 0:
|
||||
total = len(parsed_args.type)
|
||||
msg = (_("%(result)s of %(total)s types failed "
|
||||
"to delete.") % {'result': result, 'total': total})
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
|
||||
class ListType(command.Lister):
|
||||
"""List all types"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListType, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_("List additional fields in output")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
bc_client = self.app.client_manager.baremetal_compute
|
||||
|
||||
data = bc_client.instance_type.list()
|
||||
|
||||
if parsed_args.long:
|
||||
# This is the easiest way to change column headers
|
||||
column_headers = (
|
||||
"UUID",
|
||||
"Name",
|
||||
"Is Public",
|
||||
"Description",
|
||||
"Properties",
|
||||
)
|
||||
columns = (
|
||||
"UUID",
|
||||
"Name",
|
||||
"Is Public",
|
||||
"Description",
|
||||
"Extra Specs",
|
||||
)
|
||||
else:
|
||||
column_headers = columns = (
|
||||
"UUID",
|
||||
"Name",
|
||||
"Is Public",
|
||||
)
|
||||
|
||||
return (column_headers,
|
||||
(utils.get_item_properties(
|
||||
s, columns,
|
||||
) for s in data))
|
||||
|
||||
|
||||
class ShowType(command.ShowOne):
|
||||
"""Display instance type details"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowType, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'type',
|
||||
metavar='<type>',
|
||||
help=_("Type to display (name or UUID)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
|
||||
bc_client = self.app.client_manager.baremetal_compute
|
||||
data = utils.find_resource(
|
||||
bc_client.instance_type,
|
||||
parsed_args.type,
|
||||
)
|
||||
|
||||
info = {}
|
||||
info.update(data._info)
|
||||
return zip(*sorted(six.iteritems(info)))
|
||||
@@ -16,7 +16,19 @@
|
||||
|
||||
from osc_lib.tests import utils
|
||||
|
||||
from nimbleclient.tests.unit import fakes
|
||||
|
||||
|
||||
class TestBase(utils.TestCommand):
|
||||
"""Test case base class for all unit tests."""
|
||||
pass
|
||||
|
||||
|
||||
class TestBaremetalComputeV1(TestBase):
|
||||
"""Test case base class for the unit tests of Baremetal Compute V1 API."""
|
||||
|
||||
def setUp(self):
|
||||
super(TestBaremetalComputeV1, self).setUp()
|
||||
|
||||
fake_client = fakes.FakeBaremetalComputeV1Client()
|
||||
self.app.client_manager.baremetal_compute = fake_client
|
||||
|
||||
@@ -34,7 +34,7 @@ class TestResource(test_base.TestBase):
|
||||
self.assertEqual(4, base.getid(4))
|
||||
|
||||
class TmpObject(object):
|
||||
id = 4
|
||||
uuid = 4
|
||||
self.assertEqual(4, base.getid(TmpObject))
|
||||
|
||||
def test_init_with_attribute_info(self):
|
||||
@@ -46,13 +46,13 @@ class TestResource(test_base.TestBase):
|
||||
|
||||
def test_resource_lazy_getattr(self):
|
||||
fake_manager = mock.Mock()
|
||||
return_resource = base.Resource(None, dict(id=mock.sentinel.fake_id,
|
||||
return_resource = base.Resource(None, dict(uuid=mock.sentinel.fake_id,
|
||||
foo='bar',
|
||||
name='fake_name'))
|
||||
fake_manager.get.return_value = return_resource
|
||||
|
||||
r = base.Resource(fake_manager,
|
||||
dict(id=mock.sentinel.fake_id, foo='bar'))
|
||||
dict(uuid=mock.sentinel.fake_id, foo='bar'))
|
||||
self.assertTrue(hasattr(r, 'foo'))
|
||||
self.assertEqual('bar', r.foo)
|
||||
self.assertFalse(r.is_loaded())
|
||||
@@ -73,7 +73,7 @@ class TestResource(test_base.TestBase):
|
||||
|
||||
# Two resources of different types: never equal
|
||||
r1 = base.Resource(None, {'id': 1})
|
||||
r2 = fakes.FaksResource(None, {'id': 1})
|
||||
r2 = fakes.FakeResource(None, {'id': 1})
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
||||
# Two resources with no ID: equal if their info is equal
|
||||
@@ -99,8 +99,8 @@ class TestManager(test_base.TestBase):
|
||||
def test_manager_get(self, mock_get):
|
||||
mock_get.return_value = (fakes.create_response_obj_with_header(),
|
||||
mock.MagicMock())
|
||||
fake_resource = fakes.FaksResource(
|
||||
None, dict(id=fakes.FAKE_RESOURCE_ID,
|
||||
fake_resource = fakes.FakeResource(
|
||||
None, dict(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME))
|
||||
result = self.fake_manager.get(fake_resource)
|
||||
self.assertIsInstance(result, base.Resource)
|
||||
@@ -123,8 +123,8 @@ class TestManager(test_base.TestBase):
|
||||
def test_manager_update(self, mock_patch):
|
||||
mock_patch.return_value = (fakes.create_response_obj_with_header(),
|
||||
mock.MagicMock())
|
||||
fake_resource = fakes.FaksResource(
|
||||
None, dict(id=fakes.FAKE_RESOURCE_ID,
|
||||
fake_resource = fakes.FakeResource(
|
||||
None, dict(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME))
|
||||
result = self.fake_manager.update(fake_resource)
|
||||
self.assertIsInstance(result, base.Resource)
|
||||
@@ -138,8 +138,8 @@ class TestManager(test_base.TestBase):
|
||||
def test_manager_delete(self, mock_delete):
|
||||
mock_delete.return_value = (fakes.create_response_obj_with_header(),
|
||||
None)
|
||||
fake_resource = fakes.FaksResource(
|
||||
None, dict(id=fakes.FAKE_RESOURCE_ID,
|
||||
fake_resource = fakes.FakeResource(
|
||||
None, dict(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME))
|
||||
result = self.fake_manager.delete(fake_resource)
|
||||
self.assertIsInstance(result, base.TupleWithMeta)
|
||||
@@ -151,8 +151,8 @@ class TestManager(test_base.TestBase):
|
||||
def test_manager_create(self, mock_post):
|
||||
mock_post.return_value = (fakes.create_response_obj_with_header(),
|
||||
mock.MagicMock())
|
||||
fake_resource = fakes.FaksResource(
|
||||
None, dict(id=fakes.FAKE_RESOURCE_ID,
|
||||
fake_resource = fakes.FakeResource(
|
||||
None, dict(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME))
|
||||
result = self.fake_manager.create(fake_resource)
|
||||
self.assertIsInstance(result, base.Resource)
|
||||
@@ -164,9 +164,9 @@ class TestManager(test_base.TestBase):
|
||||
|
||||
@mock.patch.object(fakes.FakeHTTPClient, 'get')
|
||||
def test_manager_find(self, mock_get):
|
||||
fake_json_body_1 = dict(id=fakes.FAKE_RESOURCE_ID,
|
||||
fake_json_body_1 = dict(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME)
|
||||
fake_json_body_2 = dict(id='no_existed_id',
|
||||
fake_json_body_2 = dict(uuid='no_existed_id',
|
||||
name='no_existed_name')
|
||||
mock_get.side_effect = [
|
||||
(fakes.create_response_obj_with_header(),
|
||||
@@ -175,10 +175,10 @@ class TestManager(test_base.TestBase):
|
||||
(fakes.create_response_obj_with_header(),
|
||||
fake_json_body_1)
|
||||
]
|
||||
result = self.fake_manager.find(id=fakes.FAKE_RESOURCE_ID,
|
||||
result = self.fake_manager.find(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME)
|
||||
self.assertIsInstance(result, base.Resource)
|
||||
self.assertEqual(fakes.FAKE_RESOURCE_ID, result.id)
|
||||
self.assertEqual(fakes.FAKE_RESOURCE_ID, result.uuid)
|
||||
self.assertEqual(fakes.FAKE_RESOURCE_NAME, result.name)
|
||||
self.assertTrue(result.is_loaded())
|
||||
expect_collection_url = fakes.FAKE_RESOURCE_COLLECTION_URL
|
||||
@@ -194,14 +194,14 @@ class TestManager(test_base.TestBase):
|
||||
{'resources': []})
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.fake_manager.find,
|
||||
id=fakes.FAKE_RESOURCE_ID,
|
||||
uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME)
|
||||
expect_collection_url = fakes.FAKE_RESOURCE_COLLECTION_URL
|
||||
mock_get.assert_called_once_with(expect_collection_url, headers={})
|
||||
|
||||
@mock.patch.object(fakes.FakeHTTPClient, 'get')
|
||||
def test_manager_find_more_than_one_result(self, mock_get):
|
||||
fake_json_body_1 = dict(id=fakes.FAKE_RESOURCE_ID,
|
||||
fake_json_body_1 = dict(uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME)
|
||||
fake_json_body_2 = copy.deepcopy(fake_json_body_1)
|
||||
mock_get.return_value = (fakes.create_response_obj_with_header(),
|
||||
@@ -209,7 +209,7 @@ class TestManager(test_base.TestBase):
|
||||
fake_json_body_2]})
|
||||
self.assertRaises(exceptions.NoUniqueMatch,
|
||||
self.fake_manager.find,
|
||||
id=fakes.FAKE_RESOURCE_ID,
|
||||
uuid=fakes.FAKE_RESOURCE_ID,
|
||||
name=fakes.FAKE_RESOURCE_NAME)
|
||||
expect_collection_url = fakes.FAKE_RESOURCE_COLLECTION_URL
|
||||
mock_get.assert_called_once_with(expect_collection_url, headers={})
|
||||
|
||||
@@ -633,7 +633,7 @@ class TestSessionClient(base.TestBase):
|
||||
resp, body = client.request('', 'GET', **kwargs)
|
||||
|
||||
self.assertEqual({'endpoint_override': 'http://no.where/',
|
||||
'data': '"some_data"',
|
||||
'json': 'some_data',
|
||||
'user_agent': 'python-nimbleclient',
|
||||
'raise_exc': False}, self.request.call_args[1])
|
||||
self.assertEqual(200, resp.status_code)
|
||||
@@ -655,7 +655,7 @@ class TestSessionClient(base.TestBase):
|
||||
resp, body = client.request('', 'GET', **kwargs)
|
||||
|
||||
self.assertEqual({'endpoint_override': 'http://no.where/',
|
||||
'data': "{'files': test}}",
|
||||
'json': {'files': data},
|
||||
'user_agent': 'python-nimbleclient',
|
||||
'raise_exc': False}, self.request.call_args[1])
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
@@ -13,10 +13,15 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
from oslo_serialization import jsonutils
|
||||
from requests import Response
|
||||
|
||||
from nimbleclient.common import base
|
||||
from nimbleclient.v1 import instance_type
|
||||
|
||||
# fake request id
|
||||
FAKE_REQUEST_ID = 'req-0594c66b-6973-405c-ae2c-43fcfc00f2e3'
|
||||
@@ -47,6 +52,16 @@ def create_resource_manager():
|
||||
return FakeManager()
|
||||
|
||||
|
||||
class FakeBaremetalComputeV1Client(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fake_http_client = mock.Mock()
|
||||
|
||||
self.instance_type = instance_type.InstanceTypeManager(
|
||||
self.fake_http_client)
|
||||
self.instance = None
|
||||
|
||||
|
||||
class FakeHTTPClient(object):
|
||||
|
||||
def get(self):
|
||||
@@ -68,12 +83,12 @@ class FakeHTTPClient(object):
|
||||
pass
|
||||
|
||||
|
||||
class FaksResource(base.Resource):
|
||||
id = 'N/A'
|
||||
class FakeResource(base.Resource):
|
||||
pass
|
||||
|
||||
|
||||
class FakeManager(base.ManagerWithFind):
|
||||
resource_class = FaksResource
|
||||
resource_class = FakeResource
|
||||
|
||||
def __init__(self, api=None):
|
||||
if not api:
|
||||
@@ -129,3 +144,75 @@ class FakeHTTPResponse(object):
|
||||
|
||||
def json(self):
|
||||
return jsonutils.loads(self.content)
|
||||
|
||||
|
||||
class FakeInstanceType(object):
|
||||
"""Fake one instance type."""
|
||||
|
||||
@staticmethod
|
||||
def create_one_instance_type(attrs=None):
|
||||
"""Create a fake instance type.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:return:
|
||||
A FakeResource object, with uuid and other attributes
|
||||
"""
|
||||
attrs = attrs or {}
|
||||
|
||||
# Set default attribute
|
||||
instance_type_info = {
|
||||
"created_at": "2016-09-27T02:37:21.966342+00:00",
|
||||
"description": "fake_description",
|
||||
"extra_specs": {},
|
||||
"is_public": True,
|
||||
"name": "instance-type-name-" + uuid.uuid4().hex,
|
||||
"updated_at": None,
|
||||
"uuid": "instance-type-id-" + uuid.uuid4().hex,
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
instance_type_info.update(attrs)
|
||||
|
||||
instance_type = FakeResource(
|
||||
manager=None,
|
||||
info=copy.deepcopy(instance_type_info),
|
||||
loaded=True)
|
||||
return instance_type
|
||||
|
||||
@staticmethod
|
||||
def create_instance_types(attrs=None, count=2):
|
||||
"""Create multiple fake instance types.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:param int count:
|
||||
The number of instance types to fake
|
||||
:return:
|
||||
A list of FakeResource objects faking the instance types
|
||||
"""
|
||||
instance_types = []
|
||||
for i in range(0, count):
|
||||
instance_types.append(
|
||||
FakeInstanceType.create_one_instance_type(attrs))
|
||||
|
||||
return instance_types
|
||||
|
||||
@staticmethod
|
||||
def get_instance_types(instance_types=None, count=2):
|
||||
"""Get an iterable Mock object with a list of faked instance types.
|
||||
|
||||
If instance_types list is provided, then initialize the Mock object
|
||||
with the list. Otherwise create one.
|
||||
|
||||
:param List instance_types:
|
||||
A list of FakeResource objects faking instance types
|
||||
:param int count:
|
||||
The number of instance types to fake
|
||||
:return:
|
||||
An iterable Mock object with side_effect set to a list of faked
|
||||
instance types
|
||||
"""
|
||||
if instance_types is None:
|
||||
instance_types = FakeInstanceType.create_instance_types(count)
|
||||
return mock.Mock(side_effect=instance_types)
|
||||
|
||||
0
nimbleclient/tests/unit/osc/v1/__init__.py
Normal file
0
nimbleclient/tests/unit/osc/v1/__init__.py
Normal file
263
nimbleclient/tests/unit/osc/v1/test_instance_type.py
Normal file
263
nimbleclient/tests/unit/osc/v1/test_instance_type.py
Normal file
@@ -0,0 +1,263 @@
|
||||
# Copyright 2016 Huawei, Inc. All rights reserved.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from osc_lib import utils
|
||||
|
||||
from nimbleclient.common import base
|
||||
from nimbleclient.osc.v1 import instance_type
|
||||
from nimbleclient.tests.unit import base as test_base
|
||||
from nimbleclient.tests.unit import fakes
|
||||
from nimbleclient.v1 import instance_type as instance_type_mgr
|
||||
|
||||
|
||||
class TestInstanceType(test_base.TestBaremetalComputeV1):
|
||||
fake_type = fakes.FakeInstanceType.create_one_instance_type()
|
||||
|
||||
columns = (
|
||||
'created_at',
|
||||
'description',
|
||||
'extra_specs',
|
||||
'is_public',
|
||||
'name',
|
||||
'updated_at',
|
||||
'uuid',
|
||||
)
|
||||
|
||||
data = (
|
||||
fake_type.created_at,
|
||||
fake_type.description,
|
||||
fake_type.extra_specs,
|
||||
fake_type.is_public,
|
||||
fake_type.name,
|
||||
fake_type.updated_at,
|
||||
fake_type.uuid,
|
||||
)
|
||||
|
||||
|
||||
@mock.patch.object(instance_type_mgr.InstanceTypeManager, '_create')
|
||||
class TestInstanceTypeCreate(TestInstanceType):
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstanceTypeCreate, self).setUp()
|
||||
self.cmd = instance_type.CreateType(self.app, None)
|
||||
|
||||
def test_type_create(self, mock_create):
|
||||
arglist = [
|
||||
'type1',
|
||||
]
|
||||
verifylist = [
|
||||
('name', 'type1'),
|
||||
]
|
||||
mock_create.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
mock_create.assert_called_once_with('/types',
|
||||
data={
|
||||
'name': 'type1',
|
||||
'is_public': True,
|
||||
'description': None,
|
||||
})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
def test_type_create_with_public(self, mock_create):
|
||||
arglist = [
|
||||
'--public',
|
||||
'type1',
|
||||
]
|
||||
verifylist = [
|
||||
('public', True),
|
||||
('name', 'type1'),
|
||||
]
|
||||
mock_create.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
mock_create.assert_called_once_with('/types',
|
||||
data={
|
||||
'name': 'type1',
|
||||
'is_public': True,
|
||||
'description': None,
|
||||
})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
def test_type_create_with_private(self, mock_create):
|
||||
arglist = [
|
||||
'--private',
|
||||
'type1',
|
||||
]
|
||||
verifylist = [
|
||||
('private', True),
|
||||
('name', 'type1'),
|
||||
]
|
||||
mock_create.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
mock_create.assert_called_once_with('/types',
|
||||
data={
|
||||
'name': 'type1',
|
||||
'is_public': False,
|
||||
'description': None,
|
||||
})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
def test_type_create_with_description(self, mock_create):
|
||||
arglist = [
|
||||
'--description', 'test description.',
|
||||
'type1',
|
||||
]
|
||||
verifylist = [
|
||||
('description', 'test description.'),
|
||||
('name', 'type1'),
|
||||
]
|
||||
mock_create.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
mock_create.assert_called_once_with(
|
||||
'/types',
|
||||
data={
|
||||
'name': 'type1',
|
||||
'is_public': True,
|
||||
'description': 'test description.',
|
||||
})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
|
||||
@mock.patch.object(utils, 'find_resource')
|
||||
@mock.patch.object(instance_type_mgr.InstanceTypeManager, '_delete')
|
||||
class TestInstanceTypeDelete(TestInstanceType):
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstanceTypeDelete, self).setUp()
|
||||
self.cmd = instance_type.DeleteType(self.app, None)
|
||||
|
||||
def test_type_delete(self, mock_delete, mock_find):
|
||||
arglist = [
|
||||
'type1',
|
||||
]
|
||||
verifylist = [
|
||||
('type', ['type1']),
|
||||
]
|
||||
mock_find.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
expected_url = '/types/%s' % base.getid(self.fake_type)
|
||||
mock_delete.assert_called_once_with(expected_url)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_type_multiple_delete(self, mock_delete, mock_find):
|
||||
arglist = [
|
||||
'type1',
|
||||
'type2',
|
||||
'type3'
|
||||
]
|
||||
verifylist = [
|
||||
('type', ['type1', 'type2', 'type3']),
|
||||
]
|
||||
mock_find.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
expected_url = '/types/%s' % base.getid(self.fake_type)
|
||||
expected_call = [mock.call(expected_url), mock.call(expected_url),
|
||||
mock.call(expected_url)]
|
||||
mock_delete.assert_has_calls(expected_call)
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
@mock.patch.object(instance_type_mgr.InstanceTypeManager, '_list')
|
||||
class TestInstanceTypeList(TestInstanceType):
|
||||
|
||||
list_columns = (
|
||||
"UUID",
|
||||
"Name",
|
||||
"Is Public",
|
||||
)
|
||||
|
||||
list_columns_long = (
|
||||
"UUID",
|
||||
"Name",
|
||||
"Is Public",
|
||||
"Description",
|
||||
"Properties",
|
||||
)
|
||||
|
||||
list_data = ((
|
||||
TestInstanceType.fake_type.uuid,
|
||||
TestInstanceType.fake_type.name,
|
||||
TestInstanceType.fake_type.is_public,
|
||||
), )
|
||||
|
||||
list_data_long = ((
|
||||
TestInstanceType.fake_type.uuid,
|
||||
TestInstanceType.fake_type.name,
|
||||
TestInstanceType.fake_type.is_public,
|
||||
TestInstanceType.fake_type.description,
|
||||
TestInstanceType.fake_type.extra_specs,
|
||||
), )
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstanceTypeList, self).setUp()
|
||||
self.cmd = instance_type.ListType(self.app, None)
|
||||
|
||||
def test_type_list(self, mock_list):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
mock_list.return_value = [self.fake_type]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
mock_list.assert_called_once_with('/types', response_key='types')
|
||||
self.assertEqual(self.list_columns, columns)
|
||||
self.assertEqual(self.list_data, tuple(data))
|
||||
|
||||
def test_type_list_with_long(self, mock_list):
|
||||
arglist = [
|
||||
'--long',
|
||||
]
|
||||
verifylist = [
|
||||
('long', True),
|
||||
]
|
||||
mock_list.return_value = [self.fake_type]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
mock_list.assert_called_once_with('/types', response_key='types')
|
||||
self.assertEqual(self.list_columns_long, columns)
|
||||
self.assertEqual(self.list_data_long, tuple(data))
|
||||
|
||||
|
||||
@mock.patch.object(instance_type_mgr.InstanceTypeManager, '_get')
|
||||
class TestInstanceTypeShow(TestInstanceType):
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstanceTypeShow, self).setUp()
|
||||
self.cmd = instance_type.ShowType(self.app, None)
|
||||
|
||||
def test_type_show(self, mock_get):
|
||||
arglist = [
|
||||
'type1',
|
||||
]
|
||||
verifylist = [
|
||||
('type', 'type1'),
|
||||
]
|
||||
mock_get.return_value = self.fake_type
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
expected_url = '/types/%s' % parsed_args.type
|
||||
mock_get.assert_called_once_with(expected_url)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
@@ -14,6 +14,7 @@
|
||||
#
|
||||
|
||||
from nimbleclient.common import http
|
||||
from nimbleclient.v1 import instance_type
|
||||
|
||||
|
||||
class Client(object):
|
||||
@@ -22,3 +23,7 @@ class Client(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize a new client for the Nimble v1 API."""
|
||||
self.http_client = http._construct_http_client(*args, **kwargs)
|
||||
|
||||
self.instance_type = instance_type.InstanceTypeManager(
|
||||
self.http_client)
|
||||
self.instance = None
|
||||
|
||||
45
nimbleclient/v1/instance_type.py
Normal file
45
nimbleclient/v1/instance_type.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# Copyright 2016 Huawei, Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
from nimbleclient.common import base
|
||||
|
||||
|
||||
class InstanceType(base.Resource):
|
||||
pass
|
||||
|
||||
|
||||
class InstanceTypeManager(base.ManagerWithFind):
|
||||
resource_class = InstanceType
|
||||
|
||||
def create(self, name, is_public, description=None):
|
||||
url = '/types'
|
||||
data = {
|
||||
'name': name,
|
||||
'is_public': is_public,
|
||||
'description': description,
|
||||
}
|
||||
return self._create(url, data=data)
|
||||
|
||||
def delete(self, instance_type):
|
||||
url = '/types/%s' % base.getid(instance_type)
|
||||
return self._delete(url)
|
||||
|
||||
def get(self, instance_type):
|
||||
url = '/types/%s' % base.getid(instance_type)
|
||||
return self._get(url)
|
||||
|
||||
def list(self):
|
||||
url = '/types'
|
||||
return self._list(url, response_key='types')
|
||||
@@ -28,6 +28,10 @@ openstack.cli.extension =
|
||||
baremetal_compute = nimbleclient.osc.plugin
|
||||
|
||||
openstack.baremetal_compute.v1 =
|
||||
baremetal_compute_type_create = nimbleclient.osc.v1.instance_type:CreateType
|
||||
baremetal_compute_type_delete = nimbleclient.osc.v1.instance_type:DeleteType
|
||||
baremetal_compute_type_list = nimbleclient.osc.v1.instance_type:ListType
|
||||
baremetal_compute_type_show = nimbleclient.osc.v1.instance_type:ShowType
|
||||
|
||||
|
||||
[build_sphinx]
|
||||
@@ -55,4 +59,4 @@ output_file = nimbleclient/locale/nimbleclient.pot
|
||||
[build_releasenotes]
|
||||
all_files = 1
|
||||
build-dir = releasenotes/build
|
||||
source-dir = releasenotes/source
|
||||
source-dir = releasenotes/source
|
||||
|
||||
Reference in New Issue
Block a user