Stack API improvements
The exception that would be raised from list_stacks() if it failed would not have any type of error message (except the inner exception). This could be confusing, so add some text that indicates where the exception is being thrown. Unit tests for this method are added. Also improve some comments in delete_stack() and add unit tests for this method. Change-Id: I979a2948938fc73b708c26d81599061bac7681d4
This commit is contained in:
parent
8d5abfbf56
commit
fb8ea73f27
@ -739,14 +739,14 @@ class OpenStackCloud(object):
|
|||||||
def delete_stack(self, name_or_id):
|
def delete_stack(self, name_or_id):
|
||||||
"""Delete a Heat Stack
|
"""Delete a Heat Stack
|
||||||
|
|
||||||
:param name_or_id: Stack name or id.
|
:param string name_or_id: Stack name or id.
|
||||||
|
|
||||||
:returns: True if delete succeeded, False otherwise.
|
:returns: True if delete succeeded, False if the stack was not found.
|
||||||
|
|
||||||
:raises: ``OpenStackCloudException`` if something goes wrong during
|
:raises: ``OpenStackCloudException`` if something goes wrong during
|
||||||
the openstack API call
|
the openstack API call
|
||||||
"""
|
"""
|
||||||
stack = self.get_stack(name_or_id=name_or_id)
|
stack = self.get_stack(name_or_id)
|
||||||
if stack is None:
|
if stack is None:
|
||||||
self.log.debug("Stack %s not found for deleting" % name_or_id)
|
self.log.debug("Stack %s not found for deleting" % name_or_id)
|
||||||
return False
|
return False
|
||||||
@ -1054,7 +1054,7 @@ class OpenStackCloud(object):
|
|||||||
:raises: ``OpenStackCloudException`` if something goes wrong during the
|
:raises: ``OpenStackCloudException`` if something goes wrong during the
|
||||||
openstack API call.
|
openstack API call.
|
||||||
"""
|
"""
|
||||||
with _utils.shade_exceptions():
|
with _utils.shade_exceptions("Error fetching stack list"):
|
||||||
stacks = self.manager.submitTask(_tasks.StackList())
|
stacks = self.manager.submitTask(_tasks.StackList())
|
||||||
return stacks
|
return stacks
|
||||||
|
|
||||||
|
@ -199,3 +199,11 @@ class FakeHypervisor(object):
|
|||||||
def __init__(self, id, hostname):
|
def __init__(self, id, hostname):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.hypervisor_hostname = hostname
|
self.hypervisor_hostname = hostname
|
||||||
|
|
||||||
|
|
||||||
|
class FakeStack(object):
|
||||||
|
def __init__(self, id, name, description=None, status=None):
|
||||||
|
self.id = id
|
||||||
|
self.stack_name = name
|
||||||
|
self.stack_description = description
|
||||||
|
self.stack_status = status
|
||||||
|
78
shade/tests/unit/test_stack.py
Normal file
78
shade/tests/unit/test_stack.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# 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
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
import shade
|
||||||
|
from shade import meta
|
||||||
|
from shade.tests import fakes
|
||||||
|
from shade.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestStack(base.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestStack, self).setUp()
|
||||||
|
self.cloud = shade.openstack_cloud(validate=False)
|
||||||
|
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'heat_client')
|
||||||
|
def test_list_stacks(self, mock_heat):
|
||||||
|
fake_stacks = [
|
||||||
|
fakes.FakeStack('001', 'stack1'),
|
||||||
|
fakes.FakeStack('002', 'stack2'),
|
||||||
|
]
|
||||||
|
mock_heat.stacks.list.return_value = fake_stacks
|
||||||
|
stacks = self.cloud.list_stacks()
|
||||||
|
mock_heat.stacks.list.assert_called_once_with()
|
||||||
|
self.assertEqual(meta.obj_list_to_dict(fake_stacks), stacks)
|
||||||
|
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'heat_client')
|
||||||
|
def test_list_stacks_exception(self, mock_heat):
|
||||||
|
mock_heat.stacks.list.side_effect = Exception()
|
||||||
|
with testtools.ExpectedException(
|
||||||
|
shade.OpenStackCloudException,
|
||||||
|
"Error fetching stack list"
|
||||||
|
):
|
||||||
|
self.cloud.list_stacks()
|
||||||
|
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'get_stack')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'heat_client')
|
||||||
|
def test_delete_stack(self, mock_heat, mock_get):
|
||||||
|
stack = {'id': 'stack_id', 'name': 'stack_name'}
|
||||||
|
mock_get.return_value = stack
|
||||||
|
self.assertTrue(self.cloud.delete_stack('stack_name'))
|
||||||
|
mock_get.assert_called_once_with('stack_name')
|
||||||
|
mock_heat.stacks.delete.assert_called_once_with(id=stack['id'])
|
||||||
|
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'get_stack')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'heat_client')
|
||||||
|
def test_delete_stack_not_found(self, mock_heat, mock_get):
|
||||||
|
mock_get.return_value = None
|
||||||
|
self.assertFalse(self.cloud.delete_stack('stack_name'))
|
||||||
|
mock_get.assert_called_once_with('stack_name')
|
||||||
|
self.assertFalse(mock_heat.stacks.delete.called)
|
||||||
|
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'get_stack')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'heat_client')
|
||||||
|
def test_delete_stack_exception(self, mock_heat, mock_get):
|
||||||
|
stack = {'id': 'stack_id', 'name': 'stack_name'}
|
||||||
|
mock_get.return_value = stack
|
||||||
|
mock_heat.stacks.delete.side_effect = Exception()
|
||||||
|
with testtools.ExpectedException(
|
||||||
|
shade.OpenStackCloudException,
|
||||||
|
"Failed to delete stack %s" % stack['id']
|
||||||
|
):
|
||||||
|
self.cloud.delete_stack('stack_name')
|
Loading…
Reference in New Issue
Block a user