Add tempest plugin
Added tempest plugin with ability to run new tempest tests for glare Change-Id: I7577ed3aa8f2bd79f57afeb6916851da9ea47f62
This commit is contained in:
parent
a2950da92f
commit
299c09a4cd
0
glare_tempest_plugin/__init__.py
Normal file
0
glare_tempest_plugin/__init__.py
Normal file
57
glare_tempest_plugin/clients.py
Normal file
57
glare_tempest_plugin/clients.py
Normal 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
|
38
glare_tempest_plugin/config.py
Normal file
38
glare_tempest_plugin/config.py
Normal 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")
|
||||
]
|
56
glare_tempest_plugin/plugin.py
Normal file
56
glare_tempest_plugin/plugin.py
Normal 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)
|
||||
]
|
0
glare_tempest_plugin/services/__init__.py
Normal file
0
glare_tempest_plugin/services/__init__.py
Normal file
0
glare_tempest_plugin/services/artifacts/__init__.py
Normal file
0
glare_tempest_plugin/services/artifacts/__init__.py
Normal file
121
glare_tempest_plugin/services/artifacts/artifacts_client.py
Normal file
121
glare_tempest_plugin/services/artifacts/artifacts_client.py
Normal 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
|
0
glare_tempest_plugin/tests/__init__.py
Normal file
0
glare_tempest_plugin/tests/__init__.py
Normal file
0
glare_tempest_plugin/tests/api/__init__.py
Normal file
0
glare_tempest_plugin/tests/api/__init__.py
Normal file
81
glare_tempest_plugin/tests/api/base.py
Normal file
81
glare_tempest_plugin/tests/api/base.py
Normal 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
|
40
glare_tempest_plugin/tests/api/test_list_artifact.py
Normal file
40
glare_tempest_plugin/tests/api/test_list_artifact.py
Normal 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'])
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user