Add tempest plugin

Added tempest plugin with ability to run new tempest tests for glare

Change-Id: I7577ed3aa8f2bd79f57afeb6916851da9ea47f62
This commit is contained in:
IlyaMenkov 2016-10-11 13:34:07 +03:00 committed by Mike Fedosin
parent a2950da92f
commit 299c09a4cd
12 changed files with 397 additions and 1 deletions

View File

View File

@ -0,0 +1,57 @@
# Copyright (c) 2015 Mirantis, Inc.
# 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 tempest.common import credentials_factory as common_creds
from tempest import config
from tempest.lib import auth
from glare_tempest_plugin.services.artifacts import artifacts_client
CONF = config.CONF
class Manager(object):
def __init__(self,
credentials=common_creds.get_configured_admin_credentials(
'identity_admin')):
self.auth_provider = get_auth_provider(credentials)
self.artifacts_client = artifacts_client.ArtifactsClient(
self.auth_provider)
def get_auth_provider(credentials, scope='project'):
default_params = {
'disable_ssl_certificate_validation':
CONF.identity.disable_ssl_certificate_validation,
'ca_certs': CONF.identity.ca_certificates_file,
'trace_requests': CONF.debug.trace_requests
}
if isinstance(credentials, auth.KeystoneV3Credentials):
auth_provider_class, auth_url = \
auth.KeystoneV3AuthProvider, CONF.identity.uri_v3
else:
auth_provider_class, auth_url = \
auth.KeystoneV2AuthProvider, CONF.identity.uri
_auth_provider = auth_provider_class(credentials, auth_url,
scope=scope,
**default_params)
_auth_provider.set_auth()
return _auth_provider

View File

@ -0,0 +1,38 @@
# Copyright 2016 Red Hat, Inc.
# 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 oslo_config import cfg
service_available_group = cfg.OptGroup(name='service_available',
title='Available OpenStack Services')
ServiceAvailableGroup = [
cfg.BoolOpt("glare",
default=True,
help="Whether or not glare is expected to be available")
]
artifacts_group = cfg.OptGroup(name="artifacts",
title='Glare Options')
ArtifactGroup = [
cfg.StrOpt("catalog_type",
default="artifact"),
cfg.StrOpt("endpoint_type",
default="publicURL",
choices=["publicURL", "adminURL", "internalURL"],
help="The endpoint type for artifacts service")
]

View File

@ -0,0 +1,56 @@
# Copyright 2016 Red Hat, Inc.
# 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 os
from oslo_config import cfg
from tempest import config
from tempest.test_discover import plugins
from glare_tempest_plugin import config as glare_config
class GlareTempestPlugin(plugins.TempestPlugin):
def load_tests(self):
base_path = os.path.split(os.path.dirname(
os.path.abspath(__file__)))[0]
test_dir = "glare_tempest_plugin/tests"
full_test_dir = os.path.join(base_path, test_dir)
return full_test_dir, base_path
def register_opts(self, conf):
try:
config.register_opt_group(
conf, glare_config.service_available_group,
glare_config.ServiceAvailableGroup
)
except cfg.DuplicateOptError:
pass
try:
config.register_opt_group(conf, glare_config.artifacts_group,
glare_config.ArtifactGroup)
except cfg.DuplicateOptError:
pass
def get_opt_lists(self):
return [
(glare_config.service_available_group.name,
glare_config.ServiceAvailableGroup),
(glare_config.artifacts_group.name,
glare_config.ArtifactGroup)
]

View File

@ -0,0 +1,121 @@
# Copyright (c) 2016 Mirantis, Inc.
# 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
from tempest import config
from tempest.lib.common import rest_client
CONF = config.CONF
class ArtifactsClient(rest_client.RestClient):
def __init__(self, auth_provider):
super(ArtifactsClient, self).__init__(
auth_provider,
CONF.artifacts.catalog_type,
CONF.identity.region,
endpoint_type=CONF.artifacts.endpoint_type)
def create_artifact(self, type_name, name, version='0.0.0', **kwargs):
kwargs.update({'name': name, 'version': version})
uri = '/artifacts/{type_name}'.format(type_name=type_name)
resp, body = self.post(uri, body=json.dumps(kwargs))
self.expected_success(201, resp.status)
parsed = self._parse_resp(body)
return parsed
def get_artifact(self, type_name, art_id):
uri = '/artifacts/{type_name}/{id}'.format(
type_name=type_name,
id=art_id)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
parsed = self._parse_resp(body)
return parsed
def update_artifact(self, type_name, art_id, remove_props=None, **kwargs):
headers = {'Content-Type': 'application/json-patch+json'}
uri = '/artifacts/{type_name}/{id}'.format(type_name=type_name,
id=art_id)
changes = []
if remove_props:
for prop_name in remove_props:
if prop_name not in kwargs:
if '/' in prop_name:
changes.append({'op': 'remove',
'path': '/%s' % prop_name})
else:
changes.append({'op': 'replace',
'path': '/%s' % prop_name,
'value': None})
for prop_name in kwargs:
changes.append({'op': 'add',
'path': '/%s' % prop_name,
'value': kwargs[prop_name]})
resp, body = self.patch(uri, json.dumps(changes), headers=headers)
self.expected_success(200, resp.status)
parsed = self._parse_resp(body)
return parsed
def activate_artifact(self, type_name, art_id):
return self.update_artifact(type_name, art_id, status='active')
def deactivate_artifact(self, type_name, art_id):
return self.update_artifact(type_name, art_id, status='deactivated')
def reactivate_artifact(self, type_name, art_id):
return self.update_artifact(type_name, art_id, status='active')
def publish_artifact(self, type_name, art_id):
return self.update_artifact(type_name, art_id, visibility='public')
def upload_blob(self, type_name, art_id, blob_property, data):
headers = {'Content-Type': 'application/octet-stream'}
uri = '/artifacts/{type_name}/{id}/{blob_prop}'.format(
type_name=type_name,
id=art_id,
blob_prop=blob_property)
resp, body = self.put(uri, data, headers=headers)
self.expected_success(200, resp.status)
parsed = self._parse_resp(body)
return parsed
def download_blob(self, type_name, art_id, blob_property):
uri = '/artifacts/{type_name}/{id}/{blob_prop}'.format(
type_name=type_name,
id=art_id,
blob_prop=blob_property)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
parsed = self._parse_resp(body)
return parsed
def delete_artifact(self, type_name, art_id):
uri = '/artifacts/{type_name}/{id}'.format(
type_name=type_name,
id=art_id)
self.delete(uri)
def list_artifacts(self, type_name):
uri = '/artifacts/{}'.format(type_name)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
parsed = self._parse_resp(body)
return parsed

View File

View File

@ -0,0 +1,81 @@
# Copyright 2016 Red Hat, Inc.
# 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 glare_tempest_plugin import clients
from tempest.common import credentials_factory as common_creds
from tempest.common import dynamic_creds
from tempest import config
from tempest.lib import base
CONF = config.CONF
class BaseArtifactTest(base.BaseTestCase):
@classmethod
def setUpClass(cls):
super(BaseArtifactTest, cls).setUpClass()
cls.resource_setup()
pass
@classmethod
def tearDownClass(cls):
pass
@classmethod
def get_client_with_isolated_creds(cls, type_of_creds="admin"):
creds = cls.get_configured_isolated_creds(
type_of_creds=type_of_creds)
os = clients.Manager(credentials=creds)
client = os.artifact_client
return client
@classmethod
def resource_setup(cls):
if not CONF.service_available.glare:
skip_msg = "Glare is disabled"
raise cls.skipException(skip_msg)
if not hasattr(cls, "os"):
creds = cls.get_configured_isolated_creds(
type_of_creds='primary')
cls.os = clients.Manager(credentials=creds)
cls.artifacts_client = cls.os.artifacts_client
@classmethod
def get_configured_isolated_creds(cls, type_of_creds='admin'):
identity_version = CONF.identity.auth_version
if identity_version == 'v3':
cls.admin_role = CONF.identity.admin_role
else:
cls.admin_role = 'admin'
cls.dynamic_cred = dynamic_creds.DynamicCredentialProvider(
identity_version=CONF.identity.auth_version,
name=cls.__name__, admin_role=cls.admin_role,
admin_creds=common_creds.get_configured_admin_credentials(
'identity_admin'))
if type_of_creds == 'primary':
creds = cls.dynamic_cred.get_primary_creds()
elif type_of_creds == 'admin':
creds = cls.dynamic_cred.get_admin_creds()
elif type_of_creds == 'alt':
creds = cls.dynamic_cred.get_alt_creds()
else:
creds = cls.dynamic_cred.get_credentials(type_of_creds)
cls.dynamic_cred.type_of_creds = type_of_creds
return creds.credentials

View File

@ -0,0 +1,40 @@
# Copyright 2016 Red Hat, Inc.
# 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 testtools
from glare_tempest_plugin.tests.api import base
from tempest import config
CONF = config.CONF
class TestListSanity(base.BaseArtifactTest):
@testtools.testcase.attr('smoke')
def test_list_artifacts(self):
art = self.artifacts_client.create_artifact('images', 'tempest_test')
self.artifacts_client.list_artifacts('images')
self.artifacts_client.get_artifact('images', art['id'])
self.artifacts_client.update_artifact(type_name='images',
art_id=art['id'],
name='newnewname')
data = 'dataaaa'
self.artifacts_client.upload_blob('images', art['id'], 'image', data)
self.artifacts_client.download_blob('images', art['id'], 'image')
self.artifacts_client.delete_artifact('images', art['id'])

View File

@ -21,6 +21,8 @@ classifier =
[files]
packages =
glare
glare_tempest_plugin
data_files =
etc/glare =
etc/glare-paste.ini
@ -34,9 +36,10 @@ oslo.config.opts =
glare = glare.opts:list_artifacts_opts
oslo.policy.enforcer =
glare = glare.common.policy:_get_enforcer
oslo.policy.policies =
glare = glare.common.policy:list_rules
tempest.test_plugins =
glare_tempest_tests = glare_tempest_plugin.plugin:GlareTempestPlugin
[build_sphinx]
all_files = 1