diff --git a/ospurge/resources/heat.py b/ospurge/resources/heat.py new file mode 100644 index 0000000..48da0a6 --- /dev/null +++ b/ospurge/resources/heat.py @@ -0,0 +1,29 @@ +# 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 ospurge.resources import base + + +class Stacks(base.ServiceResource): + ORDER = 10 + + def list(self): + if not self.cloud.has_service('orchestration'): + return [] + return self.cloud.list_stacks() + + def delete(self, resource): + self.cloud.delete_stack(resource['id'], wait=True) + + @staticmethod + def to_str(resource): + return "Heat Stack (id='{}', name='{}'".format( + resource['id'], resource['name']) diff --git a/ospurge/resources/heat.pyi b/ospurge/resources/heat.pyi new file mode 100644 index 0000000..3e25aee --- /dev/null +++ b/ospurge/resources/heat.pyi @@ -0,0 +1,28 @@ +# 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 typing import Any +from typing import Dict +from typing import Iterable + +from ospurge.resources import base + + +class Stacks(base.ServiceResource): + def list(self) -> Iterable: + ... + + def delete(self, resource: Dict[str, Any]) -> None: + ... + + @staticmethod + def to_str(resource: Dict[str, Any]) -> str: + ... diff --git a/ospurge/tests/resources/test_heat.py b/ospurge/tests/resources/test_heat.py new file mode 100644 index 0000000..d21af8f --- /dev/null +++ b/ospurge/tests/resources/test_heat.py @@ -0,0 +1,44 @@ +# 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 unittest + +import shade + +from ospurge.resources import heat +from ospurge.tests import mock + + +class TestStacks(unittest.TestCase): + def setUp(self): + self.cloud = mock.Mock(spec_set=shade.openstackcloud.OpenStackCloud) + self.creds_manager = mock.Mock(cloud=self.cloud) + + def test_list_without_service(self): + self.cloud.has_service.return_value = False + self.assertEqual(heat.Stacks(self.creds_manager).list(), []) + self.cloud.list_stacks.assert_not_called() + + def test_list_with_service(self): + self.cloud.has_service.return_value = True + self.assertIs(self.cloud.list_stacks.return_value, + heat.Stacks(self.creds_manager).list()) + self.cloud.list_stacks.assert_called_once_with() + + def test_delete(self): + stack = mock.MagicMock() + self.assertIsNone(heat.Stacks(self.creds_manager).delete(stack)) + self.cloud.delete_stack.assert_called_once_with(stack['id'], wait=True) + + def test_to_string(self): + stack = mock.MagicMock() + self.assertIn("Heat Stack", + heat.Stacks(self.creds_manager).to_str(stack))