From c0b0cb7b4654e34bf17e8b19a58b9b81618c75ea Mon Sep 17 00:00:00 2001 From: pkomarov Date: Thu, 20 Jun 2019 16:03:03 +0300 Subject: [PATCH] List stack resources in HeatStackFixture Change-Id: Iad615e6a36c9bd6d5e23fdba1be9f5b1003ccedf --- tobiko/openstack/heat/_stack.py | 38 +++++++++++++++- tobiko/openstack/heat/_template.py | 5 +++ tobiko/tests/scenario/nova/__init__.py | 0 .../tests/scenario/nova/test_server_create.py | 43 +++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tobiko/tests/scenario/nova/__init__.py create mode 100644 tobiko/tests/scenario/nova/test_server_create.py diff --git a/tobiko/openstack/heat/_stack.py b/tobiko/openstack/heat/_stack.py index 701e2a50a..608cce9e6 100644 --- a/tobiko/openstack/heat/_stack.py +++ b/tobiko/openstack/heat/_stack.py @@ -134,7 +134,9 @@ class HeatStackFixture(tobiko.SharedFixture): stack = self.wait_for_stack_status( expected_status={DELETE_COMPLETE}) - self.stack = self._outputs = None + # Cleanup cached objects + self.stack = self._outputs = self._resources = None + # Compile template parameters parameters = self.get_stack_parameters() try: @@ -151,6 +153,15 @@ class HeatStackFixture(tobiko.SharedFixture): LOG.debug('Creating stack %r (id=%r)...', self.stack_name, stack_id) + _resources = None + + @tobiko.fixture_property + def resources(self): + resources = self._resources + if not self._resources: + self._resources = resources = HeatStackResourceFixture(self) + return resources + def cleanup_fixture(self): self.setup_client() self.cleanup_stack() @@ -162,7 +173,7 @@ class HeatStackFixture(tobiko.SharedFixture): """Deletes stack.""" if not stack_id: stack_id = self.stack_id - self.stack = self._outputs = None + self.stack = self._outputs = self._resources = None try: self.client.stacks.delete(stack_id) except exc.NotFound: @@ -241,6 +252,10 @@ class HeatStackKeyError(tobiko.TobikoException): message = "key {key!r} not found in stack {name!r}" +class HeatStackResourceKeyError(HeatStackKeyError): + message = "resource key {key!r} not found in stack {name!r}" + + class HeatStackParameterKeyError(HeatStackKeyError): message = "parameter key {key!r} not found in stack {name!r}" @@ -395,3 +410,22 @@ class HeatStackCreationFailed(InvalidHeatStackStatus): class HeatStackDeletionFailed(InvalidHeatStackStatus): pass + + +class HeatStackResourceFixture(HeatStackNamespaceFixture): + + key_error = HeatStackResourceKeyError + + def get_keys(self): + template = tobiko.setup_fixture(self.stack.template) + return frozenset(template.resources or []) + + def get_values(self): + self.stack.wait_for_create_complete() + client = self.stack.client + resources = client.resources.list(self.stack.stack_id) + return {r.resource_name: r for r in resources} + + @property + def fixture_name(self): + return self.stack_name + '.resources' diff --git a/tobiko/openstack/heat/_template.py b/tobiko/openstack/heat/_template.py index 1b2e2a018..b24610791 100644 --- a/tobiko/openstack/heat/_template.py +++ b/tobiko/openstack/heat/_template.py @@ -57,6 +57,11 @@ class HeatTemplateFixture(tobiko.SharedFixture): template = self.template return template and template.get('parameters') or None + @property + def resources(self): + template = self.template + return template and template.get('resources') or None + class HeatTemplateFileFixture(HeatTemplateFixture): diff --git a/tobiko/tests/scenario/nova/__init__.py b/tobiko/tests/scenario/nova/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tobiko/tests/scenario/nova/test_server_create.py b/tobiko/tests/scenario/nova/test_server_create.py new file mode 100644 index 000000000..df0ff68f9 --- /dev/null +++ b/tobiko/tests/scenario/nova/test_server_create.py @@ -0,0 +1,43 @@ +# Copyright (c) 2019 Red Hat +# 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 __future__ import absolute_import + +import tobiko +import testtools +from tobiko.openstack import stacks +from tobiko.openstack import neutron +from tobiko.openstack import nova + + +class ServerStackResourcesTest(testtools.TestCase): + + stack = tobiko.required_setup_fixture(stacks.FloatingIpServerStackFixture) + + def test_server(self): + "Test actual server details" + server = self.stack.resources.server + self.assertEqual('OS::Nova::Server', server.resource_type) + # Verify actual server status (is alive, etc.) + nova_client = nova.get_nova_client() + server_data = nova_client.servers.get(server.physical_resource_id) + self.assertEqual(self.stack.server_name, server_data.name) + + def test_port(self): + "Test actual server port details" + port = self.stack.resources.port + self.assertEqual('OS::Neutron::Port', port.resource_type) + # Verify actual port status (is alive, etc.) + port_data = neutron.show_port(port.physical_resource_id) + self.assertEqual(port.physical_resource_id, port_data['id'])