Add tempest GLARE sanity check tests

This commit adds very basic api tests for glare artifact type for murano
Also adds initial implementation of upload/delete package methods to
tempest artifact client.

Change-Id: Idc6c06570f4674d5d998fc4fb1ec72208662ff2e
Targets: bp murano-glare-devstack-testing
This commit is contained in:
Kirill Zaitsev 2016-07-21 01:26:02 +03:00
parent a1387135e8
commit 0e1647bc09
6 changed files with 219 additions and 7 deletions

View File

@ -19,6 +19,7 @@ from tempest.lib import auth
from murano_tempest_tests.services.application_catalog \
import application_catalog_client
from murano_tempest_tests.services.artifacts import artifacts_client
from murano_tempest_tests.services.service_broker import service_broker_client
CONF = config.CONF
@ -31,6 +32,11 @@ class Manager(object):
self.auth_provider = get_auth_provider(credentials)
self.service_broker_client = service_broker_client.ServiceBrokerClient(
self.auth_provider)
if CONF.application_catalog.glare_backend:
self.artifacts_client = artifacts_client.ArtifactsClient(
self.auth_provider)
else:
self.artifacts_client = None
self.application_catalog_client = \
application_catalog_client.ApplicationCatalogClient(
self.auth_provider)

View File

@ -14,10 +14,14 @@
# under the License.
import json
import os
from tempest import config
from tempest.lib.common import rest_client
from murano_tempest_tests import utils
import six
CONF = config.CONF
@ -39,7 +43,8 @@ class ArtifactsClient(rest_client.RestClient):
uri = 'v0.1/artifacts/murano/v1'
resp, body = self.get(uri)
self.expected_success(200, resp.status)
return self._parse_resp(body)
parsed = self._parse_resp(body)
return parsed['artifacts']
def list_drafts(self):
uri = 'v0.1/artifacts/murano/v1/creating'
@ -54,7 +59,7 @@ class ArtifactsClient(rest_client.RestClient):
return self._parse_resp(body)
def create_artifact_draft(self, name, version, **kwargs):
uri = 'v0.1/artifacts/murano/v1/creating'
uri = 'v0.1/artifacts/murano/v1/drafts'
kwargs.update({'name': name, 'version': version})
resp, body = self.post(uri, body=json.dumps(kwargs))
self.expected_success(201, resp.status)
@ -62,7 +67,7 @@ class ArtifactsClient(rest_client.RestClient):
def publish_artifact(self, artifact_id):
uri = 'v0.1/artifacts/murano/v1/{0}/publish'.format(artifact_id)
resp, body = self.post(uri)
resp, body = self.post(uri, body='')
self.expected_success(200, resp.status)
return self._parse_resp(body)
@ -83,7 +88,7 @@ class ArtifactsClient(rest_client.RestClient):
def delete_artifact(self, artifact_id):
uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id)
resp, body = self.delete(uri)
self.expected_success(200, resp.status)
self.expected_success(204, resp.status)
return self._parse_resp(body)
def upload_blob(self, artifact_id, blob_type, data):
@ -91,7 +96,7 @@ class ArtifactsClient(rest_client.RestClient):
uri = 'v0.1/artifacts/murano/v1/{0}/{1}'.format(
artifact_id, blob_type)
resp, body = self.put(uri, data, headers=headers)
self.expected_success(201, resp.status)
self.expected_success(200, resp.status)
return self._parse_resp(body)
def download_blob(self, artifact_id, blob_type):
@ -100,3 +105,54 @@ class ArtifactsClient(rest_client.RestClient):
resp, body = self.get(uri)
self.expected_success(200, resp.status)
return self._parse_resp(body)
# -----------------------------Packages methods-------------------------------
def get_list_packages(self):
return self.list_artifacts()
def delete_package(self, package_id):
return self.delete_artifact(package_id)
def upload_package(self, package_name, package_path, top_dir, body):
files = {package_name: open(os.path.join(top_dir, package_path), 'rb')}
is_public = body.pop('is_public', None)
if is_public is not None:
body['visibility'] = 'public' if is_public else 'private'
fqn = list(files.keys())[0]
package = utils.Package.from_file(files[fqn])
manifest = package.manifest
package_draft = {
'name': manifest.get('FullName', fqn),
'version': manifest.get('Version', '0.0.0'),
'description': manifest.get('Description'),
'display_name': manifest.get('Name', fqn),
'type': manifest.get('Type', 'Application'),
'author': manifest.get('Author'),
'tags': manifest.get('Tags', []),
'class_definitions': package.classes.keys()
}
for k, v in six.iteritems(body):
package_draft[k] = v
inherits = utils.get_local_inheritance(package.classes)
# TODO(kzaitsev): add local and global inheritance information tests
package_draft['inherits'] = inherits
keywords = package_draft['tags']
package_draft['keywords'] = keywords
draft = self.create_artifact_draft(**package_draft)
self.upload_blob(draft['id'], 'archive', package.file())
# TODO(kzaitsev): add logo upload code, currently it's failing for me
# with io.UnsupportedOperation: fileno
# if package.logo is not None:
# self.upload_blob(draft['id'], 'logo', package.logo)
# if package.ui is not None:
# self.client.artifacts.upload_blob(draft['id'], 'ui_definition',
# package.ui)
self.publish_artifact(draft['id'])
return draft

View File

@ -0,0 +1,96 @@
# 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.
from tempest.common import credentials_factory as common_creds
from tempest.common import dynamic_creds
from tempest import config
from tempest.lib import base
from murano_tempest_tests import clients
CONF = config.CONF
class BaseArtifactsTest(base.BaseTestCase):
"""Base test class for Murano Glare tests."""
@classmethod
def setUpClass(cls):
super(BaseArtifactsTest, cls).setUpClass()
cls.resource_setup()
@classmethod
def tearDownClass(cls):
cls.resource_cleanup()
super(BaseArtifactsTest, cls).tearDownClass()
@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.artifacts_client
return 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
@classmethod
def verify_nonempty(cls, *args):
if not all(args):
msg = "Missing API credentials in configuration."
raise cls.skipException(msg)
@classmethod
def resource_setup(cls):
if not CONF.service_available.murano:
skip_msg = "Murano 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 resource_cleanup(cls):
cls.clear_isolated_creds()
@classmethod
def clear_isolated_creds(cls):
if hasattr(cls, "dynamic_cred"):
cls.dynamic_cred.clear_creds()

View File

@ -0,0 +1,54 @@
# Copyright (c) 2016 Mirantis, Inc.
#
# 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
import testtools
from tempest import config
from murano_tempest_tests.tests.api.application_catalog.artifacts import base
from murano_tempest_tests import utils
CONF = config.CONF
class TestRepositorySanity(base.BaseArtifactsTest):
@classmethod
def resource_setup(cls):
if not CONF.application_catalog.glare_backend:
msg = ("Murano is not using GLARE backend. "
"Skipping GLARE tests.")
raise cls.skipException(msg)
super(TestRepositorySanity, cls).resource_setup()
@testtools.testcase.attr('smoke')
def test_get_list_packages(self):
package_list = self.artifacts_client.get_list_packages()
self.assertIsInstance(package_list, list)
@testtools.testcase.attr('smoke')
def test_upload_and_delete_package(self):
application_name = utils.generate_name('package_test_upload')
abs_archive_path, dir_with_archive, archive_name = \
utils.prepare_package(application_name)
self.addCleanup(os.remove, abs_archive_path)
package = self.artifacts_client.upload_package(
application_name, archive_name, dir_with_archive,
{"categories": [], "tags": [], 'is_public': False})
package_list = self.artifacts_client.get_list_packages()
self.assertIn(package['id'], {pkg['id'] for pkg in package_list})
self.artifacts_client.delete_package(package['id'])
package_list = self.artifacts_client.get_list_packages()
self.assertNotIn(package['id'], {pkg['id'] for pkg in package_list})

View File

@ -48,10 +48,10 @@ class TestRepositorySanity(base.BaseApplicationCatalogTest):
application_name, archive_name, dir_with_archive,
{"categories": [], "tags": [], 'is_public': False})
package_list = self.application_catalog_client.get_list_packages()
self.assertIn(package, package_list)
self.assertIn(package['id'], {pkg['id'] for pkg in package_list})
self.application_catalog_client.delete_package(package['id'])
package_list = self.application_catalog_client.get_list_packages()
self.assertNotIn(package, package_list)
self.assertNotIn(package['id'], {pkg['id'] for pkg in package_list})
class TestRepository(base.BaseApplicationCatalogIsolatedAdminTest):