Add update_service()

Services can be updated, we can even update them!

Keystone v2.0 did not allow updates, Keystone v3 does

Improve unit tests to test v3 items for service functions

Change-Id: I36b9f92f7b551451973e3681dd8814ed90614b9c
This commit is contained in:
SamYaple 2016-03-02 22:44:26 +00:00
parent 3850774d8f
commit f10f704bfa
5 changed files with 133 additions and 12 deletions

View File

@ -0,0 +1,6 @@
---
features:
- Add the ability to update a keystone service information. This feature is
not available on keystone v2.0. The new function, update_service(), allows
the user to update description, name of service, service type, and enabled
status.

View File

@ -607,6 +607,11 @@ class ServiceList(task_manager.Task):
return client.keystone_client.services.list()
class ServiceUpdate(task_manager.Task):
def main(self, client):
return client.keystone_client.services.update(**self.args)
class ServiceDelete(task_manager.Task):
def main(self, client):
return client.keystone_client.services.delete(**self.args)

View File

@ -747,13 +747,14 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
_tasks.MachineNodeUpdate(node_id=uuid, patch=patch))
@_utils.valid_kwargs('type', 'service_type', 'description')
def create_service(self, name, **kwargs):
def create_service(self, name, enabled=True, **kwargs):
"""Create a service.
:param name: Service name.
:param type: Service type. (type or service_type required.)
:param service_type: Service type. (type or service_type required.)
:param description: Service description (optional).
:param enabled: Whether the service is enabled (v3 only)
:returns: a dict containing the services description, i.e. the
following attributes::
@ -767,17 +768,47 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
openstack API call.
"""
service_type = kwargs.get('type', kwargs.get('service_type'))
description = kwargs.get('description', None)
with _utils.shade_exceptions("Failed to create service {name}".format(
name=name)):
if self.cloud_config.get_api_version('identity').startswith('2'):
service_kwargs = {'service_type': service_type}
else:
service_kwargs = {'type': service_type}
type_ = kwargs.pop('type', None)
service_type = kwargs.pop('service_type', None)
service = self.manager.submitTask(_tasks.ServiceCreate(
name=name, description=description, **service_kwargs))
if self.cloud_config.get_api_version('identity').startswith('2'):
kwargs['service_type'] = type_ or service_type
else:
kwargs['type'] = type_ or service_type
kwargs['enabled'] = enabled
with _utils.shade_exceptions(
"Failed to create service {name}".format(name=name)
):
service = self.manager.submitTask(
_tasks.ServiceCreate(name=name, **kwargs)
)
return _utils.normalize_keystone_services([service])[0]
@_utils.valid_kwargs('name', 'enabled', 'type', 'service_type',
'description')
def update_service(self, name_or_id, **kwargs):
# NOTE(SamYaple): Service updates are only available on v3 api
if self.cloud_config.get_api_version('identity').startswith('2'):
raise OpenStackCloudUnavailableFeature(
'Unavailable Feature: Service update requires Identity v3'
)
# NOTE(SamYaple): Keystone v3 only accepts 'type' but shade accepts
# both 'type' and 'service_type' with a preference
# towards 'type'
type_ = kwargs.pop('type', None)
service_type = kwargs.pop('service_type', None)
if type_ or service_type:
kwargs['type'] = type_ or service_type
with _utils.shade_exceptions(
"Error in updating service {service}".format(service=name_or_id)
):
service = self.manager.submitTask(
_tasks.ServiceUpdate(service=name_or_id, **kwargs)
)
return _utils.normalize_keystone_services([service])[0]

View File

@ -26,6 +26,7 @@ import random
from shade import operator_cloud
from shade.exc import OpenStackCloudException
from shade.exc import OpenStackCloudUnavailableFeature
from shade.tests import base
@ -65,6 +66,30 @@ class TestServices(base.TestCase):
description='this is a test description')
self.assertIsNotNone(service.get('id'))
def test_update_service(self):
if self.operator_cloud.cloud_config.get_api_version(
'identity').startswith('2'):
# NOTE(SamYaple): Update service only works with v3 api
self.assertRaises(OpenStackCloudUnavailableFeature,
self.operator_cloud.update_service,
'service_id', name='new name')
else:
service = self.operator_cloud.create_service(
name=self.new_service_name + '_create', type='test_type',
description='this is a test description', enabled=True)
new_service = self.operator_cloud.update_service(
service.id,
name=self.new_service_name + '_update',
description='this is an updated description',
enabled=False
)
self.assertEqual(new_service.name,
self.new_service_name + '_update')
self.assertEqual(new_service.description,
'this is an updated description')
self.assertFalse(new_service.enabled)
self.assertEqual(service.id, new_service.id)
def test_list_services(self):
service = self.operator_cloud.create_service(
name=self.new_service_name + '_list', type='test_type')

View File

@ -22,7 +22,9 @@ Tests Keystone services commands.
from mock import patch
import os_client_config
from shade import _utils
from shade import meta
from shade import OpenStackCloudException
from shade.exc import OpenStackCloudUnavailableFeature
from shade import OperatorCloud
from shade.tests.fakes import FakeService
from shade.tests.unit import base
@ -50,7 +52,10 @@ class CloudServices(base.TestCase):
@patch.object(_utils, 'normalize_keystone_services')
@patch.object(OperatorCloud, 'keystone_client')
def test_create_service(self, mock_keystone_client, mock_norm):
@patch.object(os_client_config.cloud_config.CloudConfig, 'get_api_version')
def test_create_service_v2(self, mock_api_version, mock_keystone_client,
mock_norm):
mock_api_version.return_value = '2.0'
kwargs = {
'name': 'a service',
'type': 'network',
@ -62,6 +67,55 @@ class CloudServices(base.TestCase):
mock_keystone_client.services.create.assert_called_with(**kwargs)
self.assertTrue(mock_norm.called)
@patch.object(_utils, 'normalize_keystone_services')
@patch.object(OperatorCloud, 'keystone_client')
@patch.object(os_client_config.cloud_config.CloudConfig, 'get_api_version')
def test_create_service_v3(self, mock_api_version, mock_keystone_client,
mock_norm):
mock_api_version.return_value = '3'
kwargs = {
'name': 'a v3 service',
'type': 'cinderv2',
'description': 'This is a test service',
'enabled': False
}
self.client.create_service(**kwargs)
mock_keystone_client.services.create.assert_called_with(**kwargs)
self.assertTrue(mock_norm.called)
@patch.object(os_client_config.cloud_config.CloudConfig, 'get_api_version')
def test_update_service_v2(self, mock_api_version):
mock_api_version.return_value = '2.0'
# NOTE(SamYaple): Update service only works with v3 api
self.assertRaises(OpenStackCloudUnavailableFeature,
self.client.update_service,
'service_id', name='new name')
@patch.object(_utils, 'normalize_keystone_services')
@patch.object(OperatorCloud, 'keystone_client')
@patch.object(os_client_config.cloud_config.CloudConfig, 'get_api_version')
def test_update_service_v3(self, mock_api_version, mock_keystone_client,
mock_norm):
mock_api_version.return_value = '3'
kwargs = {
'name': 'updated_name',
'type': 'updated_type',
'service_type': 'updated_type',
'description': 'updated_name',
'enabled': False
}
service_obj = FakeService(id='id1', **kwargs)
mock_keystone_client.services.update.return_value = service_obj
self.client.update_service('id1', **kwargs)
del kwargs['service_type']
mock_keystone_client.services.update.assert_called_once_with(
service='id1', **kwargs
)
mock_norm.assert_called_once_with([meta.obj_to_dict(service_obj)])
@patch.object(OperatorCloud, 'keystone_client')
def test_list_services(self, mock_keystone_client):
mock_keystone_client.services.list.return_value = \