Improve unit test coverage for dcmanager's APIs (subcloud_group)

Improves unit test coverage for dcmanager's subcloud_group
API from 77% to 98%.

Test plan:
  All of the tests were created taking into account the
output of 'tox -c tox.ini -e cover' command

Story: 2007082
Task: 49641

Change-Id: I4f8a87379c770409590ed84b0d2cd50c06110199
Signed-off-by: rlima <Raphael.Lima@windriver.com>
This commit is contained in:
rlima 2024-02-29 11:02:39 -03:00 committed by Raphael Lima
parent a7f0e617e0
commit 2fe10ca74d
1 changed files with 472 additions and 227 deletions

View File

@ -1,5 +1,5 @@
# Copyright (c) 2017 Ericsson AB # Copyright (c) 2017 Ericsson AB
# Copyright (c) 2020-2022 Wind River Systems, Inc. # Copyright (c) 2020-2022, 2024 Wind River Systems, Inc.
# All Rights Reserved. # All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -15,22 +15,21 @@
# under the License. # under the License.
# #
import mock import http.client
from six.moves import http_client
import mock
from oslo_messaging import RemoteError
from dcmanager.api.controllers.v1 import subcloud_group
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.db.sqlalchemy import api as db_api from dcmanager.db.sqlalchemy import api as db_api
from dcmanager.rpc import client as rpc_client from dcmanager.tests.unit.api.test_root_controller import DCManagerApiTest
from dcmanager.tests.unit.api import test_root_controller as testroot
from dcmanager.tests.unit.api.v1.controllers.mixins import APIMixin from dcmanager.tests.unit.api.v1.controllers.mixins import APIMixin
from dcmanager.tests.unit.api.v1.controllers.mixins import DeleteMixin from dcmanager.tests.unit.api.v1.controllers.mixins import DeleteMixin
from dcmanager.tests.unit.api.v1.controllers.mixins import GetMixin from dcmanager.tests.unit.api.v1.controllers.mixins import GetMixin
from dcmanager.tests.unit.api.v1.controllers.mixins import PostJSONMixin from dcmanager.tests.unit.api.v1.controllers.mixins import PostJSONMixin
from dcmanager.tests.unit.api.v1.controllers.mixins import UpdateMixin from dcmanager.tests.unit.api.v1.controllers.mixins import UpdateMixin
from dcmanager.tests.unit.api.v1.controllers.test_subclouds \ from dcmanager.tests.unit.common import fake_subcloud
import FAKE_SUBCLOUD_DATA
from dcmanager.tests import utils
SAMPLE_SUBCLOUD_GROUP_NAME = 'GroupX' SAMPLE_SUBCLOUD_GROUP_NAME = 'GroupX'
SAMPLE_SUBCLOUD_GROUP_DESCRIPTION = 'A Group of mystery' SAMPLE_SUBCLOUD_GROUP_DESCRIPTION = 'A Group of mystery'
@ -39,42 +38,31 @@ SAMPLE_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS = 3
class SubcloudGroupAPIMixin(APIMixin): class SubcloudGroupAPIMixin(APIMixin):
API_PREFIX = '/v1.0/subcloud-groups' API_PREFIX = '/v1.0/subcloud-groups'
RESULT_KEY = 'subcloud_groups' RESULT_KEY = 'subcloud_groups'
EXPECTED_FIELDS = ['id', EXPECTED_FIELDS = [
'name', 'id', 'name', 'description', 'max_parallel_subclouds', 'update_apply_type',
'description', 'created-at', 'updated-at'
'max_parallel_subclouds', ]
'update_apply_type',
'created-at',
'updated-at']
def setUp(self): def setUp(self):
super(SubcloudGroupAPIMixin, self).setUp() super().setUp()
self.fake_rpc_client.some_method = mock.MagicMock()
def _get_test_subcloud_group_dict(self, **kw): def _get_test_subcloud_group_dict(self, **kw):
# id should not be part of the structure # id should not be part of the structure
group = { return {
'name': kw.get('name', SAMPLE_SUBCLOUD_GROUP_NAME), 'name': kw.get('name', SAMPLE_SUBCLOUD_GROUP_NAME),
'description': kw.get('description', 'description': kw.get('description', SAMPLE_SUBCLOUD_GROUP_DESCRIPTION),
SAMPLE_SUBCLOUD_GROUP_DESCRIPTION),
'update_apply_type': kw.get( 'update_apply_type': kw.get(
'update_apply_type', 'update_apply_type', SAMPLE_SUBCLOUD_GROUP_UPDATE_APPLY_TYPE
SAMPLE_SUBCLOUD_GROUP_UPDATE_APPLY_TYPE), ),
'max_parallel_subclouds': kw.get( 'max_parallel_subclouds': kw.get(
'max_parallel_subclouds', 'max_parallel_subclouds',
SAMPLE_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS) SAMPLE_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS
)
} }
return group
def _post_get_test_subcloud_group(self, **kw):
post_body = self._get_test_subcloud_group_dict(**kw)
return post_body
# The following methods are required for subclasses of APIMixin # The following methods are required for subclasses of APIMixin
def get_api_prefix(self): def get_api_prefix(self):
return self.API_PREFIX return self.API_PREFIX
@ -92,227 +80,484 @@ class SubcloudGroupAPIMixin(APIMixin):
return db_api.subcloud_group_create(context, **creation_fields) return db_api.subcloud_group_create(context, **creation_fields)
def get_post_object(self): def get_post_object(self):
return self._post_get_test_subcloud_group() return self._get_test_subcloud_group_dict()
def get_update_object(self): def get_update_object(self):
update_object = { return {"description": "Updated description"}
'description': 'Updated description'
}
return update_object
# Combine Subcloud Group API with mixins to test post, get, update and delete class BaseTestSubcloudGroupController(DCManagerApiTest, SubcloudGroupAPIMixin):
class TestSubcloudGroupPost(testroot.DCManagerApiTest, """Base class for testing the SubcloudGroupController"""
SubcloudGroupAPIMixin,
PostJSONMixin):
def setUp(self):
super(TestSubcloudGroupPost, self).setUp()
def verify_post_failure(self, response):
# Failures will return text rather than json
self.assertEqual(response.content_type, 'text/plain')
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_create_with_numerical_name_fails(self, mock_client):
# A numerical name is not permitted. otherwise the 'get' operations
# which support getting by either name or ID could become confused
# if a name for one group was the same as an ID for another.
ndict = self.get_post_object()
ndict['name'] = '123'
response = self.app.post_json(self.get_api_prefix(),
ndict,
headers=self.get_api_headers(),
expect_errors=True)
self.verify_post_failure(response)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_create_with_blank_name_fails(self, mock_client):
# An empty name is not permitted
ndict = self.get_post_object()
ndict['name'] = ''
response = self.app.post_json(self.get_api_prefix(),
ndict,
headers=self.get_api_headers(),
expect_errors=True)
self.verify_post_failure(response)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_create_with_default_name_fails(self, mock_client):
# A name that is the same as the 'Default' group is not permitted.
# This would be a duplicate, and names must be unique.
ndict = self.get_post_object()
ndict['name'] = 'Default'
response = self.app.post_json(self.get_api_prefix(),
ndict,
headers=self.get_api_headers(),
expect_errors=True)
self.verify_post_failure(response)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_create_with_empty_description_fails(self, mock_client):
# An empty description is considered invalid
ndict = self.get_post_object()
ndict['description'] = ''
response = self.app.post_json(self.get_api_prefix(),
ndict,
headers=self.get_api_headers(),
expect_errors=True)
self.verify_post_failure(response)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_create_with_bad_apply_type(self, mock_client):
# update_apply_type must be either 'serial' or 'parallel'
ndict = self.get_post_object()
ndict['update_apply_type'] = 'something_invalid'
response = self.app.post_json(self.get_api_prefix(),
ndict,
headers=self.get_api_headers(),
expect_errors=True)
self.verify_post_failure(response)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_create_with_bad_max_parallel_subclouds(self, mock_client):
# max_parallel_subclouds must be an integer between 1 and 500
ndict = self.get_post_object()
# All the entries in bad_values should be considered invalid
bad_values = [0, 501, -1, 'abc']
for bad_value in bad_values:
ndict['max_parallel_subclouds'] = bad_value
response = self.app.post_json(self.get_api_prefix(),
ndict,
headers=self.get_api_headers(),
expect_errors=True)
self.verify_post_failure(response)
class TestSubcloudGroupGet(testroot.DCManagerApiTest,
SubcloudGroupAPIMixin,
GetMixin):
def setUp(self): def setUp(self):
super(TestSubcloudGroupGet, self).setUp() super().setUp()
self.url = self.API_PREFIX
self._mock_rpc_client()
class TestSubcloudGroupController(BaseTestSubcloudGroupController):
"""Test class for SubcloudGroupController"""
def setUp(self):
super().setUp()
def test_unmapped_method(self):
"""Test requesting an unmapped method results in success with null content"""
self.method = self.app.put
response = self._send_request()
self._assert_response(response)
self.assertEqual(response.text, "null")
class TestSubcloudGroupPost(BaseTestSubcloudGroupController, PostJSONMixin):
"""Test class for post requests"""
def setUp(self):
super().setUp()
self.method = self.app.post_json
self.params = self.get_post_object()
def test_post_fails_without_params(self):
"""Test post fails without params"""
self.params = {}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Body required"
)
def test_post_fails_with_numerical_name(self):
"""Test post fails with numerical name
A numerical name is not permitted, otherwise the 'get' operations
which support getting by either name or ID could become confusing
if a group's name was the same as the id of another.
"""
self.params["name"] = "999"
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group name"
)
def test_post_fails_with_empty_name(self):
"""Test post fails with empty name"""
self.params["name"] = ""
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group name"
)
def test_post_fails_with_default_name(self):
"""Test post fails with default name
The name 'Default' is not permitted because it would be a duplicate, but it
should be unique
"""
self.params["name"] = consts.DEFAULT_SUBCLOUD_GROUP_NAME
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group name"
)
def test_post_fails_with_invalid_description(self):
"""Test post fails with invalid description"""
invalid_values = [
"", "a" * (subcloud_group.MAX_SUBCLOUD_GROUP_DESCRIPTION_LEN + 1)
]
for index, invalid_value in enumerate(invalid_values, start=1):
self.params["description"] = invalid_value
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group description",
call_count=index
)
def test_post_fails_with_invalid_update_apply_type(self):
"""Test post fails with invalid update apply type
The update apply type should be either serial or parallel
"""
self.params["update_apply_type"] = "fake"
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group update_apply_type"
)
def test_post_fails_without_update_apply_type(self):
"""Test post fails without update apply type"""
del self.params["update_apply_type"]
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group update_apply_type"
)
def test_post_fails_with_invalid_max_parallel_subclouds(self):
"""Test post fails with invalid max parallel subclouds
The acceptable range is between 1 and 500
"""
invalid_values = [0, 501, -1, "fake"]
for index, invalid_value in enumerate(invalid_values, start=1):
self.params["max_parallel_subclouds"] = invalid_value
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST,
"Invalid group max_parallel_subclouds", call_count=index
)
def test_post_fails_with_db_api_duplicate_entry(self):
"""Test post fails with db api duplicate entry"""
self._create_db_object(self.ctx)
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST,
"A subcloud group with this name already exists"
)
@mock.patch.object(db_api, "subcloud_group_create")
def test_post_fails_with_db_api_remote_error(self, mock_db_api):
"""Test post fails with db api remote error"""
mock_db_api.side_effect = RemoteError("msg", "value")
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.UNPROCESSABLE_ENTITY, "value"
)
@mock.patch.object(db_api, "subcloud_group_create")
def test_post_fails_with_db_api_generic_exception(self, mock_db_api):
"""Test post fails with db api generic exception"""
mock_db_api.side_effect = Exception()
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.INTERNAL_SERVER_ERROR,
"Unable to create subcloud group"
)
class BaseTestSubcloudGroupGet(BaseTestSubcloudGroupController):
"""Base test class for get requests"""
def setUp(self):
super().setUp()
self.subcloud_group = db_api.subcloud_group_get(self.ctx, 1)
self.url = f"{self.url}/{self.subcloud_group.id}"
self.method = self.app.get
class TestSubcloudGroupGet(BaseTestSubcloudGroupGet, GetMixin):
"""Test class for get requests"""
def setUp(self):
super().setUp()
# Override initial_list_size. Default group is setup during db sync # Override initial_list_size. Default group is setup during db sync
self.initial_list_size = 1 self.initial_list_size = 1
@mock.patch.object(rpc_client, 'ManagerClient') def test_get_succeeds_with_id(self):
def test_get_single_by_name(self, mock_client): """Test get succeeds with id"""
# create a group
context = utils.dummy_context()
# todo(abailey) make this a generic method
group_name = 'TestGroup'
self._create_db_object(context, name=group_name)
# Test that a GET operation for a valid ID works response = self._send_request()
response = self.app.get(self.get_single_url(group_name),
headers=self.get_api_headers())
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.status_code, http_client.OK)
self.validate_entry(response.json)
@mock.patch.object(rpc_client, 'ManagerClient') self._assert_response(response)
def test_list_subclouds_empty(self, mock_client):
# API GET on: subcloud-groups/<uuid>/subclouds def test_get_succeeds_with_name(self):
uuid = 1 # The Default Subcloud Group is always ID=1 """Test get succeeds with name"""
url = '%s/%s/subclouds' % (self.get_api_prefix(), uuid)
response = self.app.get(url, self.url = f"{self.API_PREFIX}/{self.subcloud_group.name}"
headers=self.get_api_headers())
response = self._send_request()
self._assert_response(response)
class TestSubcloudGroupGetSubclouds(BaseTestSubcloudGroupGet):
"""Test class for get requests with subclouds verb"""
def setUp(self):
super().setUp()
self.url = f"{self.url}/subclouds"
def test_get_subclouds_succeeds(self):
"""Test get subclouds succeeds
The list size is 0 because there isn't a subcloud associated to the group
"""
response = self._send_request()
self._assert_response(response)
# This API returns 'subclouds' rather than 'subcloud-groups' # This API returns 'subclouds' rather than 'subcloud-groups'
self.assertIn('subclouds', response.json) self.assertIn('subclouds', response.json)
# no subclouds exist yet, so this length should be zero self.assertEqual(0, len(response.json.get('subclouds')))
result_list = response.json.get('subclouds')
self.assertEqual(0, len(result_list))
def _create_subcloud_db_object(self, context): def test_get_subclouds_succeeds_with_subcloud_in_group(self):
creation_fields = { """Test get subclouds succeeds with subcloud in group
'name': FAKE_SUBCLOUD_DATA.get('name'),
'description': FAKE_SUBCLOUD_DATA.get('description'), When a subcloud is created, it is associated with the Default group
'location': FAKE_SUBCLOUD_DATA.get('location'), """
'software_version': FAKE_SUBCLOUD_DATA.get('software_version'),
'management_subnet': FAKE_SUBCLOUD_DATA.get('management_subnet'),
'management_gateway_ip':
FAKE_SUBCLOUD_DATA.get('management_gateway_ip'),
'management_start_ip':
FAKE_SUBCLOUD_DATA.get('management_start_ip'),
'management_end_ip': FAKE_SUBCLOUD_DATA.get('management_end_ip'),
'systemcontroller_gateway_ip':
FAKE_SUBCLOUD_DATA.get('systemcontroller_gateway_ip'),
'deploy_status': FAKE_SUBCLOUD_DATA.get('deploy_status'),
'error_description': FAKE_SUBCLOUD_DATA.get('error_description'),
'region_name': FAKE_SUBCLOUD_DATA.get('region_name'),
'openstack_installed':
FAKE_SUBCLOUD_DATA.get('openstack_installed'),
'group_id': FAKE_SUBCLOUD_DATA.get('group_id', 1)
}
return db_api.subcloud_create(context, **creation_fields)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_list_subclouds_populated(self, mock_client):
# subclouds are to Default group by default (unless specified) # subclouds are to Default group by default (unless specified)
context = utils.dummy_context() fake_subcloud.create_fake_subcloud(self.ctx)
self._create_subcloud_db_object(context)
response = self._send_request()
# API GET on: subcloud-groups/<uuid>/subclouds
uuid = 1 # The Default Subcloud Group is always ID=1
url = '%s/%s/subclouds' % (self.get_api_prefix(), uuid)
response = self.app.get(url,
headers=self.get_api_headers())
# This API returns 'subclouds' rather than 'subcloud-groups'
self.assertIn('subclouds', response.json) self.assertIn('subclouds', response.json)
# the subcloud created earlier will have been queried self.assertEqual(1, len(response.json.get('subclouds')))
result_list = response.json.get('subclouds')
self.assertEqual(1, len(result_list))
class TestSubcloudGroupUpdate(testroot.DCManagerApiTest, class TestSubcloudGroupPatch(BaseTestSubcloudGroupController, UpdateMixin):
SubcloudGroupAPIMixin, """Test class for patch requests"""
UpdateMixin):
def setUp(self): def setUp(self):
super(TestSubcloudGroupUpdate, self).setUp() super().setUp()
@mock.patch.object(rpc_client, 'ManagerClient') self.subcloud_group = db_api.subcloud_group_get(self.ctx, 1)
def test_update_invalid_apply_type(self, mock_client):
context = utils.dummy_context() self.method = self.app.patch_json
single_obj = self._create_db_object(context) self.url = f"{self.url}/{self.subcloud_group.id}"
update_data = {
'update_apply_type': 'something_bad' def test_patch_succeeds_with_name_and_max_parallel_subclouds(self):
"""Test patch succeeds with name and max parallel subclouds"""
self.subcloud_group = self._create_db_object(self.ctx)
self.url = f"{self.API_PREFIX}/{self.subcloud_group.id}"
self.params = {"name": "new name", "max_parallel_subclouds": 2}
response = self._send_request()
self._assert_response(response)
def test_patch_fails_with_group_not_found(self):
"""Test patch fails with group not found"""
self.url = f"{self.API_PREFIX}/999"
self.params = {"update_apply_type": "fake"}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.NOT_FOUND, "Subcloud Group not found"
)
def test_patch_fails_with_invalid_property_to_update(self):
"""Test patch fails with invalid property to update"""
self.params = {"fake": "value"}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "nothing to update"
)
def test_patch_fails_with_invalid_name(self):
"""Test patch fails with invalid name"""
self.params = {"name": consts.DEFAULT_SUBCLOUD_GROUP_NAME}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group name"
)
def test_patch_fails_with_new_name_for_default_group(self):
"""Test patch fails with new name for default group"""
self.params = {"name": "new name"}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Default group name cannot be changed"
)
def test_patch_fails_with_invalid_update_apply_type(self):
"""Test patch fails with invalid update apply type"""
self.params = {"update_apply_type": "fake"}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST, "Invalid group update_apply_type"
)
def test_patch_fails_with_invalid_max_parallel_subclouds(self):
"""Test patch fails with invalid max parallel subclouds"""
invalid_values = [0, 501, -1, "fake"]
for index, invalid_value in enumerate(invalid_values, start=1):
self.params = {"max_parallel_subclouds": str(invalid_value)}
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST,
"Invalid group max_parallel_subclouds", call_count=index
)
def test_patch_fails_with_invalid_description(self):
"""Test patch fails with invalid description"""
self.params = {
"description":
"a" * (subcloud_group.MAX_SUBCLOUD_GROUP_DESCRIPTION_LEN + 1)
} }
response = self.app.patch_json(self.get_single_url(single_obj.id),
headers=self.get_api_headers(),
params=update_data,
expect_errors=True)
# Failures will return text rather than json
self.assertEqual(response.content_type, 'text/plain')
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
@mock.patch.object(rpc_client, 'ManagerClient') response = self._send_request()
def test_update_invalid_max_parallel(self, mock_client):
context = utils.dummy_context() self._assert_pecan_and_response(
single_obj = self._create_db_object(context) response, http.client.BAD_REQUEST, "Invalid group description",
update_data = { )
'max_parallel_subclouds': -1
} @mock.patch.object(db_api, "subcloud_group_update")
response = self.app.patch_json(self.get_single_url(single_obj.id), def test_patch_fails_with_db_api_remote_error(self, mock_db_api):
headers=self.get_api_headers(), """Test patch fails with db api remote error"""
params=update_data,
expect_errors=True) self.params = {"update_apply_type": "serial"}
# Failures will return text rather than json
self.assertEqual(response.content_type, 'text/plain') mock_db_api.side_effect = RemoteError("msg", "value")
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.UNPROCESSABLE_ENTITY, "value"
)
@mock.patch.object(db_api, "subcloud_group_update")
def test_patch_fails_with_db_api_generic_exception(self, mock_db_api):
"""Test patch fails with db api generic exception"""
self.params = {"update_apply_type": "serial"}
mock_db_api.side_effect = Exception()
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.INTERNAL_SERVER_ERROR,
"Unable to update subcloud group"
)
class TestSubcloudGroupDelete(testroot.DCManagerApiTest, class TestSubcloudGroupDelete(BaseTestSubcloudGroupController, DeleteMixin):
SubcloudGroupAPIMixin, """Test class for delete requests"""
DeleteMixin):
def setUp(self): def setUp(self):
super(TestSubcloudGroupDelete, self).setUp() super().setUp()
@mock.patch.object(rpc_client, 'ManagerClient') self.subcloud_group = db_api.subcloud_group_get(self.ctx, 1)
def test_delete_default_fails(self, mock_client):
default_zone_id = 1 self.method = self.app.delete
response = self.app.delete(self.get_single_url(default_zone_id), self.url = f"{self.url}/{self.subcloud_group.id}"
headers=self.get_api_headers(),
expect_errors=True) def test_delete_fails_for_default(self):
# Failures will return text rather than json """Test delete fails for default
self.assertEqual(response.content_type, 'text/plain')
self.assertEqual(response.status_code, http_client.BAD_REQUEST) The default subcloud group can't be deleted
"""
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.BAD_REQUEST,
"Default Subcloud Group may not be deleted"
)
def test_delete_fails_with_subcloud_in_group(self):
"""Test delete fails with subcloud in group"""
subcloud_group = self._create_db_object(self.ctx)
fake_subcloud.create_fake_subcloud(
self.ctx, group_id=subcloud_group.id
)
self.url = f"{self.API_PREFIX}/{subcloud_group.id}"
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.INTERNAL_SERVER_ERROR,
"Unable to delete subcloud group", call_count=2
)
@mock.patch.object(db_api, "subcloud_group_destroy")
def test_delete_fails_with_db_api_remote_error(self, mock_db_api):
"""Test delete fails with db api remote error"""
self.subcloud_group = self._create_db_object(self.ctx)
self.url = f"{self.API_PREFIX}/{self.subcloud_group.id}"
mock_db_api.side_effect = RemoteError("msg", "value")
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.UNPROCESSABLE_ENTITY, "value"
)
@mock.patch.object(db_api, "subcloud_group_destroy")
def test_delete_fails_with_db_api_generic_exception(self, mock_db_api):
"""Test delete fails with db api generic exception"""
self.subcloud_group = self._create_db_object(self.ctx)
self.url = f"{self.API_PREFIX}/{self.subcloud_group.id}"
mock_db_api.side_effect = Exception()
response = self._send_request()
self._assert_pecan_and_response(
response, http.client.INTERNAL_SERVER_ERROR,
"Unable to delete subcloud group"
)