From e4563aec1eb8f98e5e42fe513918432eddadcd37 Mon Sep 17 00:00:00 2001 From: spisarski Date: Tue, 6 Mar 2018 14:52:31 -0700 Subject: [PATCH] Updated stack tests to only use an admin user when necessary. Changed super test class OSIntegrationTestCase to allow subclasses to set the user roles when required. For all heat stack test, the user role will always be 'heat_stack_owner'. 'admin' will be used for tests requiring this role (i.e. heat template creates flavors) JIRA: SNAPS-268 Change-Id: I0ec01cfea6297547a6a158eec8e5c69af6d6c7d7 Signed-off-by: spisarski --- snaps/domain/stack.py | 10 ++- snaps/domain/test/stack_tests.py | 13 ++- snaps/openstack/create_stack.py | 7 +- snaps/openstack/os_credentials.py | 4 +- snaps/openstack/tests/create_stack_tests.py | 121 ++++++++++++--------------- snaps/openstack/tests/os_source_file_test.py | 13 +-- snaps/openstack/utils/heat_utils.py | 12 ++- 7 files changed, 99 insertions(+), 81 deletions(-) diff --git a/snaps/domain/stack.py b/snaps/domain/stack.py index 080ab17..2c593d3 100644 --- a/snaps/domain/stack.py +++ b/snaps/domain/stack.py @@ -19,14 +19,22 @@ class Stack: SNAPS domain object for Heat Stacks. Should contain attributes that are shared amongst cloud providers """ - def __init__(self, name, stack_id): + def __init__(self, name, stack_id, stack_project_id, + status, status_reason): """ Constructor :param name: the stack's name :param stack_id: the stack's stack_id + :param stack_project_id: the project ID that was spawned from this + deployment + :param status: the stack's last known status code + :param status_reason: the stack's last known explanation of the status """ self.name = name self.id = stack_id + self.stack_project_id = stack_project_id + self.status = status + self.status_reason = status_reason def __eq__(self, other): return (self.name == other.name and diff --git a/snaps/domain/test/stack_tests.py b/snaps/domain/test/stack_tests.py index 21e31d2..2ad690a 100644 --- a/snaps/domain/test/stack_tests.py +++ b/snaps/domain/test/stack_tests.py @@ -23,14 +23,23 @@ class StackDomainObjectTests(unittest.TestCase): """ def test_construction_positional(self): - stack = Stack('name', 'id') + stack = Stack( + 'name', 'id', 'stack_proj_id', 'fine', 'good') self.assertEqual('name', stack.name) self.assertEqual('id', stack.id) + self.assertEqual('stack_proj_id', stack.stack_project_id) + self.assertEqual('fine', stack.status) + self.assertEqual('good', stack.status_reason) def test_construction_named(self): - stack = Stack(stack_id='id', name='name') + stack = Stack( + stack_id='id', name='name', stack_project_id='stack_proj_id', + status='fine', status_reason='good') self.assertEqual('name', stack.name) self.assertEqual('id', stack.id) + self.assertEqual('stack_proj_id', stack.stack_project_id) + self.assertEqual('fine', stack.status) + self.assertEqual('good', stack.status_reason) class ResourceDomainObjectTests(unittest.TestCase): diff --git a/snaps/openstack/create_stack.py b/snaps/openstack/create_stack.py index c5c509f..aff10b7 100644 --- a/snaps/openstack/create_stack.py +++ b/snaps/openstack/create_stack.py @@ -158,7 +158,8 @@ class OpenStackHeatStack(OpenStackCloudObject, object): called :return: the object """ - return self.__stack + if self.__stack: + return heat_utils.get_stack_by_id(self.__heat_cli, self.__stack.id) def get_outputs(self): """ @@ -174,7 +175,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object): object :return: """ - return heat_utils.get_stack_status(self.__heat_cli, self.__stack.id) + stack = self.get_stack() + if stack: + return stack.status def stack_complete(self, block=False, timeout=None, poll_interval=snaps.config.stack.POLL_INTERVAL): diff --git a/snaps/openstack/os_credentials.py b/snaps/openstack/os_credentials.py index 72223e3..7cb5650 100644 --- a/snaps/openstack/os_credentials.py +++ b/snaps/openstack/os_credentials.py @@ -85,7 +85,9 @@ class OSCreds: if kwargs.get('heat_api_version') is None: self.heat_api_version = 1 else: - self.heat_api_version = float(kwargs['heat_api_version']) + val = kwargs['heat_api_version'] + ver = float(val) + self.heat_api_version = int(ver) if kwargs.get('volume_api_version') is None: self.volume_api_version = cinder_utils.VERSION_2 diff --git a/snaps/openstack/tests/create_stack_tests.py b/snaps/openstack/tests/create_stack_tests.py index ecb9dee..ad8ac31 100644 --- a/snaps/openstack/tests/create_stack_tests.py +++ b/snaps/openstack/tests/create_stack_tests.py @@ -133,19 +133,17 @@ class CreateStackSuccessTests(OSIntegrationTestCase): """ def setUp(self): + self.user_roles = ['heat_stack_owner'] super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.stack_creator = None self.image_creator = OpenStackImage( - self.heat_creds, openstack_tests.cirros_image_settings( + self.os_creds, openstack_tests.cirros_image_settings( name=self.guid + '-image', image_metadata=self.image_metadata)) self.image_creator.create() @@ -207,7 +205,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -231,7 +229,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): env_values=self.env_values, stack_create_timeout=0) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) with self.assertRaises(StackCreationError): self.stack_creator.create() @@ -249,7 +247,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): template=template_dict, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -273,7 +271,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): template=template_dict, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -317,7 +315,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): template=template_dict, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) created_stack1 = self.stack_creator.create() retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli, @@ -328,7 +326,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): self.assertEqual(0, len(self.stack_creator.get_outputs())) # Should be retrieving the instance data - stack_creator2 = OpenStackHeatStack(self.heat_creds, stack_settings) + stack_creator2 = OpenStackHeatStack(self.os_creds, stack_settings) stack2 = stack_creator2.create() self.assertEqual(created_stack1.id, stack2.id) @@ -342,7 +340,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -353,8 +351,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # Need to use 'admin' creds as heat creates objects under it's own # project/tenant - neutron = neutron_utils.neutron_client(self.admin_os_creds) - keystone = keystone_utils.keystone_client(self.admin_os_creds) + neutron = neutron_utils.neutron_client(self.os_creds) + keystone = keystone_utils.keystone_client(self.os_creds) net_by_name = neutron_utils.get_network( neutron, keystone, network_name=net_creators[0].get_network().name) self.assertEqual(net_creators[0].get_network(), net_by_name) @@ -381,7 +379,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -391,9 +389,9 @@ class CreateStackSuccessTests(OSIntegrationTestCase): self.assertEqual(self.vm_inst_name, vm_inst_creators[0].get_vm_inst().name) - nova = nova_utils.nova_client(self.admin_os_creds) - neutron = neutron_utils.neutron_client(self.admin_os_creds) - keystone = keystone_utils.keystone_client(self.admin_os_creds) + nova = nova_utils.nova_client(self.os_creds) + neutron = neutron_utils.neutron_client(self.os_creds) + keystone = keystone_utils.keystone_client(self.os_creds) vm_inst_by_name = nova_utils.get_server( nova, neutron, keystone, server_name=vm_inst_creators[0].get_vm_inst().name) @@ -410,19 +408,17 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase): """ def setUp(self): + self.user_roles = ['heat_stack_owner', 'admin'] super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.stack_creator = None self.image_creator = OpenStackImage( - self.heat_creds, openstack_tests.cirros_image_settings( + self.os_creds, openstack_tests.cirros_image_settings( name=self.guid + '-image', image_metadata=self.image_metadata)) self.image_creator.create() @@ -494,7 +490,7 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings, + self.os_creds, stack_settings, [self.image_creator.image_settings]) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -519,19 +515,17 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase): """ def setUp(self): + self.user_roles = ['heat_stack_owner'] super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.stack_creator = None self.image_creator = OpenStackImage( - self.heat_creds, openstack_tests.cirros_image_settings( + self.os_creds, openstack_tests.cirros_image_settings( name=self.guid + '-image', image_metadata=self.image_metadata)) self.image_creator.create() @@ -562,7 +556,7 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase): env_values=env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings, + self.os_creds, stack_settings, [self.image_creator.image_settings]) self.vm_inst_creators = list() @@ -632,14 +626,13 @@ class CreateStackRouterTests(OSIntegrationTestCase): Instantiates the CreateStack object that is responsible for downloading and creating an OS stack file within OpenStack """ + self.user_roles = ['heat_stack_owner'] + super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.neutron = neutron_utils.neutron_client(self.os_creds) self.stack_creator = None @@ -661,7 +654,7 @@ class CreateStackRouterTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -703,14 +696,13 @@ class CreateStackVolumeTests(OSIntegrationTestCase): def setUp(self): + self.user_roles = ['heat_stack_owner', 'admin'] + super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.stack_creator = None self.volume_name = self.guid + '-volume' @@ -728,7 +720,7 @@ class CreateStackVolumeTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -798,14 +790,13 @@ class CreateStackFlavorTests(OSIntegrationTestCase): def setUp(self): + self.user_roles = ['heat_stack_owner', 'admin'] + super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.stack_creator = None self.heat_tmplt_path = pkg_resources.resource_filename( @@ -815,7 +806,7 @@ class CreateStackFlavorTests(OSIntegrationTestCase): name=self.guid + '-stack', template_path=self.heat_tmplt_path) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -858,15 +849,14 @@ class CreateStackKeypairTests(OSIntegrationTestCase): def setUp(self): + self.user_roles = ['heat_stack_owner'] + super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) - self.nova = nova_utils.nova_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) + self.nova = nova_utils.nova_client(self.os_creds) self.stack_creator = None self.keypair_name = self.guid + '-kp' @@ -882,7 +872,7 @@ class CreateStackKeypairTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -943,15 +933,14 @@ class CreateStackSecurityGroupTests(OSIntegrationTestCase): Instantiates the CreateStack object that is responsible for downloading and creating an OS stack file within OpenStack """ + self.user_roles = ['heat_stack_owner'] + super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) - self.nova = nova_utils.nova_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) + self.nova = nova_utils.nova_client(self.os_creds) self.stack_creator = None self.security_group_name = self.guid + '-sec-grp' @@ -967,7 +956,7 @@ class CreateStackSecurityGroupTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -1033,12 +1022,10 @@ class CreateStackNegativeTests(OSIntegrationTestCase): """ def setUp(self): + self.user_roles = ['heat_stack_owner'] super(self.__class__, self).__start__() - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4()) self.stack_creator = None self.heat_tmplt_path = pkg_resources.resource_filename( @@ -1056,7 +1043,7 @@ class CreateStackNegativeTests(OSIntegrationTestCase): stack_settings = StackConfig(name=self.stack_name, template_path=self.heat_tmplt_path) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) with self.assertRaises(HTTPBadRequest): self.stack_creator.create() @@ -1067,7 +1054,7 @@ class CreateStackNegativeTests(OSIntegrationTestCase): stack_settings = StackConfig( name=self.stack_name, template_path='foo') self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) with self.assertRaises(IOError): self.stack_creator.create() @@ -1080,21 +1067,19 @@ class CreateStackFailureTests(OSIntegrationTestCase): """ def setUp(self): + self.user_roles = ['heat_stack_owner'] super(self.__class__, self).__start__() self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.heat_creds = self.admin_os_creds - self.heat_creds.project_name = self.admin_os_creds.project_name - - self.heat_cli = heat_utils.heat_client(self.heat_creds) + self.heat_cli = heat_utils.heat_client(self.os_creds) self.stack_creator = None self.tmp_file = file_utils.save_string_to_file( ' ', str(uuid.uuid4()) + '-bad-image') self.image_creator = OpenStackImage( - self.heat_creds, ImageConfig( + self.os_creds, ImageConfig( name=self.guid + 'image', image_file=self.tmp_file.name, image_user='foo', img_format='qcow2')) self.image_creator.create() @@ -1164,7 +1149,7 @@ class CreateStackFailureTests(OSIntegrationTestCase): template_path=self.heat_tmplt_path, env_values=self.env_values) self.stack_creator = OpenStackHeatStack( - self.heat_creds, stack_settings) + self.os_creds, stack_settings) with self.assertRaises(StackError): try: diff --git a/snaps/openstack/tests/os_source_file_test.py b/snaps/openstack/tests/os_source_file_test.py index addf06a..b361ea8 100644 --- a/snaps/openstack/tests/os_source_file_test.py +++ b/snaps/openstack/tests/os_source_file_test.py @@ -110,6 +110,7 @@ class OSIntegrationTestCase(OSComponentTestCase): self.use_keystone = use_keystone self.keystone = None self.flavor_metadata = flavor_metadata + self.user_roles = None @staticmethod def parameterize(testcase_klass, os_creds, ext_net_name, @@ -143,7 +144,6 @@ class OSIntegrationTestCase(OSComponentTestCase): self.project_creator = None self.user_creator = None self.admin_os_creds = self.os_creds - self.role = None if self.use_keystone: self.keystone = keystone_utils.keystone_client(self.admin_os_creds) @@ -154,10 +154,16 @@ class OSIntegrationTestCase(OSComponentTestCase): name=project_name, domain=self.admin_os_creds.project_domain_name)) + # Set by implementing class for setting the user's roles + roles = dict() + if self.user_roles: + for user_role in self.user_roles: + roles[user_role] = project_name + self.user_creator = deploy_utils.create_user( self.admin_os_creds, UserConfig( name=guid + '-user', password=guid, - project_name=project_name, + project_name=project_name, roles=roles, domain_name=self.admin_os_creds.user_domain_name)) self.os_creds = self.user_creator.get_os_creds( @@ -173,9 +179,6 @@ class OSIntegrationTestCase(OSComponentTestCase): called during setUp() else these objects will persist after the test is run """ - if self.role: - keystone_utils.delete_role(self.keystone, self.role) - if self.project_creator: self.project_creator.clean() diff --git a/snaps/openstack/utils/heat_utils.py b/snaps/openstack/utils/heat_utils.py index 0511ac8..d42eefa 100644 --- a/snaps/openstack/utils/heat_utils.py +++ b/snaps/openstack/utils/heat_utils.py @@ -65,7 +65,11 @@ def get_stack(heat_cli, stack_settings=None, stack_name=None): stacks = heat_cli.stacks.list(**stack_filter) for stack in stacks: - return Stack(name=stack.identifier, stack_id=stack.id) + return Stack( + name=stack.identifier, stack_id=stack.id, + stack_project_id=stack.stack_user_project_id, + status=stack.stack_status, + status_reason=stack.stack_status_reason) def get_stack_by_id(heat_cli, stack_id): @@ -76,7 +80,11 @@ def get_stack_by_id(heat_cli, stack_id): :return: the Stack domain object else None """ stack = heat_cli.stacks.get(stack_id) - return Stack(name=stack.identifier, stack_id=stack.id) + return Stack( + name=stack.identifier, stack_id=stack.id, + stack_project_id=stack.stack_user_project_id, + status=stack.stack_status, + status_reason=stack.stack_status_reason) def get_stack_status(heat_cli, stack_id): -- 2.16.6