Initial commit for keystone group tempest tests

Change-Id: I7144897568de2b877bcb9742457920f9570a61d6
This commit is contained in:
stewie925 2019-04-01 09:26:07 -07:00 committed by STEW TY
parent 2b78e52250
commit d0f4c901ce
5 changed files with 471 additions and 0 deletions

View File

@ -16,6 +16,7 @@
from ranger_tempest_plugin.services import base_client
from ranger_tempest_plugin.services.cms_client import CmsClient
from ranger_tempest_plugin.services.fms_client import FmsClient
from ranger_tempest_plugin.services.grp_client import GrpClient
from ranger_tempest_plugin.services.ims_client import ImsClient
from ranger_tempest_plugin.services.rms_client import RmsClient
@ -45,3 +46,7 @@ class OrmClientManager(clients.Manager):
CONF.identity.catalog_type,
CONF.identity.region,
CONF.ranger.RANGER_IMS_BASE_URL)
self.grp_client = GrpClient(base_client.RangerAuthProvider(credentials),
CONF.identity.catalog_type,
CONF.identity.region,
CONF.ranger.RANGER_CMS_BASE_URL)

View File

@ -0,0 +1,113 @@
# Copyright 2017
# 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
_status = {
'type': 'string',
'enum': ['Success', 'no regions', 'Error', 'Pending', 'Submitted']
}
_links = {
'type': 'object',
'properties': {
'self': {'type': 'string'}
},
'required': ['self']
}
_region = {
'type': 'object',
'properties': {
'added': {'type': 'string'},
'id': {'type': 'string'},
'links': _links
},
'required': ['added', 'id', 'links']
}
_group = {
'type': 'object',
'properties': {
'id': {'type': 'string'},
'links': _links,
'created': {'type': 'string', 'format': 'date-time'}
},
'required': ['id', 'links', 'created']
}
create_group = {
'status_code': [201],
'response_body': {
'type': 'object',
'properties': {
'group': _group,
'transaction_id': {'type': 'string'}
},
'required': ['group', 'transaction_id']
}
}
get_group = {
'status_code': [200],
'response_body': {
'type': 'object',
'properties': {
'status': _status,
'uuid': {'type': 'string'},
'enabled': {'type': 'boolean'},
'domain_name': {'type': 'string'},
'name': {'type': 'string'},
'regions': {'type': 'array'},
'description': {'type': 'string'}
},
'required': ['status', 'uuid', 'enabled', 'domain_name', 'name',
'regions', 'description']
}
}
list_groups = {
'status_code': [200],
'response_body': {
'type': 'object',
'properties': {
'groups': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'status': _status,
'description': {'type': 'string'},
'enabled': {'type': 'boolean'},
'domain_name': {'type': 'string'},
'regions': {
'type': 'array',
'items': {'type': 'string'}
},
'id': {'type': 'string'},
'name': {'type': 'string'}
},
'required': ['status', 'description', 'enabled',
'domain_name', 'regions', 'id', 'name']
}
}
},
'required': ['groups']
}
}
delete_group = {
'status_code': [204]
}
delete_region_from_group = delete_group

View File

@ -0,0 +1,56 @@
# Copyright 2016 AT&T Corp
# 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.
import json
import urllib
from ranger_tempest_plugin.schemas import group_schema as schema
from ranger_tempest_plugin.services import base_client
from tempest import config
CONF = config.CONF
class GrpClient(base_client.RangerClientBase):
cms_url = CONF.ranger.RANGER_CMS_BASE_URL
version = 'v1'
def create_group(self, **kwargs):
uri = '%s/%s/orm/groups' % (self.cms_url, self.version)
post_body = json.dumps(kwargs)
return self.post_request(uri, post_body, schema.create_group)
def get_group(self, identifier):
uri = '%s/%s/orm/groups/%s' \
% (self.cms_url, self.version, identifier)
return self.get_request(uri, schema.get_group)
def list_groups(self, filter=None):
uri = '%s/%s/orm/groups' % (self.cms_url, self.version)
if filter is not None:
uri += '?' + urllib.urlencode(filter)
return self.get_request(uri, schema.list_groups)
def delete_region_from_group(self, group_id, region_id):
uri = '%s/%s/orm/groups/%s/regions/%s' % (
self.cms_url, self.version, group_id, region_id)
return self.delete_request(uri, schema.delete_region_from_group)
def delete_group(self, group_id):
uri = '%s/%s/orm/groups/%s' \
% (self.cms_url, self.version, group_id)
return self.delete_request(uri, schema.delete_group)

View File

@ -0,0 +1,176 @@
# Copyright 2016 AT&T Corp
# 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.
import time
from oslo_log import log as logging
from ranger_tempest_plugin.tests.api import base
from tempest.common.utils import data_utils
from tempest import config
from tempest.lib import exceptions
CONF = config.CONF
LOG = logging.getLogger(__name__)
class GrpBaseOrmTest(base.BaseOrmTest):
credentials = ['admin', 'primary', 'alt']
@classmethod
def setup_clients(cls):
super(GrpBaseOrmTest, cls).setup_clients()
cls.client = cls.os_primary.grp_client
@classmethod
def _get_group_params(cls, enabled=True):
region, payload = {}, {}
grp_name = data_utils.rand_name('ormTempestGrp')
domain_name = CONF.auth.admin_domain_name
region['name'] = CONF.identity.region
region['type'] = 'single'
regions = [region]
payload["description"] = grp_name
payload["domain_name"] = domain_name
payload["enabled"] = True if enabled else False
payload["name"] = grp_name
payload["regions"] = regions
return payload
@classmethod
def _get_user_params(cls, alt=False):
users = []
if not alt:
users.append({'id': cls.os_primary.credentials.username,
'role': ['admin']})
else:
users.append({'id': cls.os_alt.credentials.username,
'role': ['admin_viewer', 'admin_support']})
return users
@classmethod
def _get_region_params(cls):
region = {}
region['name'] = CONF.identity.region
region['type'] = 'single'
return [region]
@classmethod
def _create_grp_validate_creation_on_dcp_and_lcp(self, **kwargs):
""" Creates a keystone group record: kwargs contains field data
needed for group customer POST body:
- name
- description
- enabled
- domain_name
- regions
"""
_, body = self.client.create_group(**kwargs)
group_id = body["group"]["id"]
_, group = self.client.get_group(group_id)
if group["name"] == kwargs["name"]:
if group["regions"] == []:
group_status = "no regions"
else:
group_status = "Success"
self._wait_for_group_status(group_id, group_status)
return group_id
else:
message = "group %s not created successfully" % kwargs["name"]
exceptions.TempestException(message)
@classmethod
def _wait_for_group_status(cls, group_id, status):
group_status = cls.client.get_group(group_id)[1]["status"]
start = int(time.time())
while group_status != status:
time.sleep(cls.build_interval)
group_status = cls.client.get_group(group_id)[1]["status"]
if group_status == 'Error':
message = ('group %s failed to reach %s status'
' and is in ERROR status on orm' %
(group_id, status))
raise exceptions.TempestException(message)
if int(time.time()) - start >= cls.build_timeout:
message = ('group %s failed to reach %s'
'status within the required time (%s s)'
'on orm and is in %s status.'
% (group_id, status,
cls.build_timeout,
group_status))
raise exceptions.TimeoutException(message)
@classmethod
def _del_group_validate_deletion_on_dcp_and_lcp(cls, group_id):
_, group = cls.client.get_group(group_id)
regions_on_group = [region for region in group["regions"]]
if regions_on_group:
region_name_on_group = regions_on_group[0]["name"]
cls._delete_region_from_group_and_validate_deletion(
group_id, region_name_on_group)
cls.client.delete_group(group_id)
cls._wait_for_group_deletion_on_dcp(group_id)
cls._validate_group_deletion_on_lcp(group_id)
@classmethod
def _delete_region_from_group_and_validate_deletion(
cls, group_id, rname):
_, region = cls.os_admin.rms_client.get_region(rname)
region_id = region["id"]
cls.client.delete_region_from_group(group_id, region_id)
cls._wait_for_group_status(group_id, "no regions")
_, body = cls.client.get_group(group_id)
regions_on_group = [rgn for rgn in body["regions"]]
if regions_on_group:
message = "Region %s failed to get deleted from group %s " % (
rname, group_id)
raise exceptions.TempestException(message)
@classmethod
def _wait_for_group_deletion_on_dcp(cls, group_id):
_, body = cls.client.list_groups()
group_list = body["groups"]
group_ids = [group["id"] for group in group_list
if group["id"] == group_id]
start = int(time.time())
while group_ids:
time.sleep(cls.build_interval)
_, body = cls.client.list_groups()["groups"]
group_list = body["groups"]
group_ids = [group["id"] for group in group_list
if group["id"] == group_id]
if group_ids:
group_status = group_ids[0]["status"]
if group_status == 'Error':
message = "group %s failed to get deleted and is in\
error status" % group_id
raise exceptions.TempestException(message)
if int(time.time()) - start >= cls.build_timeout:
message = (
'group %s failed to get deleted within '
'the required time (%s s) and is in %s status.'
% (group_id, cls.build_timeout,
group_status))
raise exceptions.TimeoutException(message)
@classmethod
def _validate_group_deletion_on_lcp(cls, group_id):
_, body = cls.client.list_groups()
group_ids = [group["id"] for group in body["groups"]
if group["id"] == group_id]
if group_ids:
message = "group %s failed to get deleted on lcp" \
% group_id
raise exceptions.TempestException(message)

View File

@ -0,0 +1,121 @@
# Copyright 2016 AT&T Corp
# 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.
import random
from ranger_tempest_plugin.tests.api import grp_base
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions
CONF = config.CONF
class TestTempestGrp(grp_base.GrpBaseOrmTest):
@classmethod
def resource_setup(cls):
cls.setup_group = cls._get_group_params()
cls.setup_group_id = \
cls._create_grp_validate_creation_on_dcp_and_lcp(
**cls.setup_group)
super(TestTempestGrp, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
cls._del_group_validate_deletion_on_dcp_and_lcp(cls.setup_group_id)
super(TestTempestGrp, cls).resource_cleanup()
@decorators.idempotent_id('deeb3b8a-fb38-46e1-97ba-c878b0ba890f')
def test_get_group(self):
""" Execute 'get_group' using the following options:
- get group by id
- get group by name
"""
# execute get_group using group id and group name
for identifier in [self.setup_group_id,
self.setup_group['name']]:
_, body = self.client.get_group(identifier)
self.assertIn(self.setup_group_id, body['uuid'])
@decorators.idempotent_id('8068e33f-a6aa-416a-9505-048c6ad037b2')
def test_list_groups_with_filters(self):
""" This function executes 'list groups' with all available filters:
- no filter (i.e. list all groups)
- filter by region
- group name contains a substring
- group name starts_with a string
"""
# format filter parameter values
region_name = [
region['name'] for region in self.setup_group['regions']]
group_name = self.setup_group['name']
substr_name = random.randint(0, len(group_name))
# define the list groups filters to be used for this test
no_filter = None
region_filter = {'region': region_name[0]}
contains_filter = {'contains': group_name[substr_name:]}
startswith_filter = {'starts_with': group_name[:substr_name]}
# execute list_groups with the available filters
for list_filter in [no_filter, region_filter, contains_filter,
startswith_filter]:
_, body = self.client.list_groups(list_filter)
groups = [grp['id'] for grp in body['groups']]
self.assertIn(self.setup_group_id, groups)
@decorators.idempotent_id('880f614f-6317-4973-a244-f2e44443f551')
def test_delete_regions(self):
# setup data for delete_region
post_body = self._get_group_params()
region_name = post_body["regions"][0]["name"]
test_group_id = self._create_grp_validate_creation_on_dcp_and_lcp(
**post_body)
self.addCleanup(self._del_group_validate_deletion_on_dcp_and_lcp,
test_group_id)
_, group = self.client.get_group(test_group_id)
self.assertTrue(group["regions"])
_, body = self.client.delete_region_from_group(test_group_id,
region_name)
self._wait_for_group_status(test_group_id, 'no regions')
_, group = self.client.get_group(test_group_id)
self.assertFalse(group["regions"])
@decorators.idempotent_id('bba25028-d962-47df-9566-557eec48f22d')
def test_create_group(self):
post_body = self._get_group_params()
test_group_name = post_body['name']
_, body = self.client.create_group(**post_body)
test_group_id = body['group']['id']
self.addCleanup(self._del_group_validate_deletion_on_dcp_and_lcp,
test_group_id)
self._wait_for_group_status(test_group_id, 'Success')
_, body = self.client.get_group(test_group_name)
self.assertIn(test_group_id, body['uuid'])
@decorators.idempotent_id('356633f0-c615-4bdc-8f0f-d97b6ca409e0')
def test_delete_group(self):
# setup data for test case
post_body = self._get_group_params()
test_group_id = self._create_grp_validate_creation_on_dcp_and_lcp(
**post_body)
# delete the data and do get_group to ensure 404-NotFound response
self._del_group_validate_deletion_on_dcp_and_lcp(test_group_id)
self.assertRaises(exceptions.NotFound, self.client.get_group,
test_group_id)