Add tempest versioning test suite
This patch adds tempest tests for Murano Package versioning. The next tests are provided: 1. Upload two packages which differ with only versions and check their availability in artifact repository. 2. Deployment test of two packages in one environment, which differ with only versions. 3. Deploy package with missed class by manifest version require. 4. Deploy package with available class by manifest version require. Change-Id: I48fb1a1af475a99f3b7a6313338d2bbcfb95d579
This commit is contained in:
parent
5475ac13ad
commit
46657301c1
@ -19,6 +19,7 @@ from tempest import config
|
||||
from tempest.lib import base
|
||||
|
||||
from murano_tempest_tests import clients
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
@ -85,6 +86,7 @@ class BaseArtifactsTest(base.BaseTestCase):
|
||||
creds = cls.get_configured_isolated_creds(type_of_creds='primary')
|
||||
cls.os = clients.Manager(credentials=creds)
|
||||
cls.artifacts_client = cls.os.artifacts_client
|
||||
cls.application_catalog_client = cls.os.application_catalog_client
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
@ -94,3 +96,24 @@ class BaseArtifactsTest(base.BaseTestCase):
|
||||
def clear_isolated_creds(cls):
|
||||
if hasattr(cls, "dynamic_cred"):
|
||||
cls.dynamic_cred.clear_creds()
|
||||
|
||||
@classmethod
|
||||
def upload_package(cls, application_name, version=None, require=None):
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name, version=version,
|
||||
add_class_name=True, require=require)
|
||||
package = cls.artifacts_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
return package, abs_archive_path
|
||||
|
||||
@staticmethod
|
||||
def create_obj_model(package):
|
||||
return {
|
||||
"name": package['display_name'],
|
||||
"?": {
|
||||
"type": package['name'],
|
||||
"id": utils.generate_uuid(),
|
||||
"classVersion": package['version']
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,164 @@
|
||||
# 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 six
|
||||
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 TestVersioning(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(TestVersioning, cls).resource_setup()
|
||||
|
||||
application_name = utils.generate_name('package_test')
|
||||
# create first package
|
||||
version1 = '1.0.0'
|
||||
package1, _ = cls.upload_package(application_name,
|
||||
version=version1)
|
||||
|
||||
# create second package
|
||||
version2 = '2.0.0'
|
||||
package2, path1 = cls.upload_package(application_name,
|
||||
version=version2)
|
||||
|
||||
# create package with require >=2.0.0 for 2.0.0 package
|
||||
expected_version = '>=2.0.0'
|
||||
main_app_name = utils.generate_name('main_package_test')
|
||||
require = [(package2['name'], expected_version)]
|
||||
package3, path2 = cls.upload_package(main_app_name, require=require)
|
||||
|
||||
cls.packages = {
|
||||
'1.0.0': package1,
|
||||
'2.0.0': package2,
|
||||
'require_for_2.0.0': package3,
|
||||
}
|
||||
cls.abs_archive_paths = [path1, path2]
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
for pkg in six.itervalues(cls.packages):
|
||||
cls.artifacts_client.delete_package(pkg['id'])
|
||||
map(os.remove, cls.abs_archive_paths)
|
||||
super(TestVersioning, cls).resource_cleanup()
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
def test_availability_of_packages_with_different_versions(self):
|
||||
"""Test availability of packages with different versions.
|
||||
|
||||
1) Check two packages to have the same names.
|
||||
2) Check two packages to have different ids.
|
||||
3) Check two packages to be in repository.
|
||||
"""
|
||||
self.assertEqual(self.packages['1.0.0']['name'],
|
||||
self.packages['2.0.0']['name'])
|
||||
self.assertNotEqual(self.packages['1.0.0']['id'],
|
||||
self.packages['2.0.0']['id'])
|
||||
|
||||
# check packages availability
|
||||
artifact_packages = {pkg['id'] for pkg in
|
||||
self.artifacts_client.get_list_packages()}
|
||||
|
||||
self.assertIn(self.packages['1.0.0']['id'], artifact_packages)
|
||||
self.assertIn(self.packages['2.0.0']['id'], artifact_packages)
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
def test_deploy_packages_with_different_versions(self):
|
||||
"""Test deployment of packages with different versions.
|
||||
|
||||
1) Create environment.
|
||||
2) Add package with version 1.0.0 to the environment.
|
||||
3) Add package with version 2.0.0 to the environment.
|
||||
4) Deploy environment.
|
||||
5) Check if deployment status ok.
|
||||
"""
|
||||
|
||||
# create environment
|
||||
environment_name = utils.generate_name('create_environment')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
environment_name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
# create session
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
|
||||
# add first application
|
||||
object_model = self.create_obj_model(self.packages['1.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
# add second application
|
||||
object_model = self.create_obj_model(self.packages['2.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
self.application_catalog_client.deploy_session(
|
||||
environment['id'], session['id'])
|
||||
|
||||
deploy_result = utils.wait_for_environment_deploy(
|
||||
self.application_catalog_client, environment['id'])['status']
|
||||
|
||||
self.assertEqual(deploy_result, 'ready')
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
def test_deploy_package_with_required_package_version(self):
|
||||
"""Test deployment of package which requires package with present version.
|
||||
|
||||
1) Create environment.
|
||||
2) Add to the environment package which requires version 2.0.0 of the
|
||||
package, which is present with versions 1.0.0 and 2.0.0 in repository.
|
||||
3) Deploy environment.
|
||||
4) Check if deployment status ok.
|
||||
"""
|
||||
|
||||
# create environment
|
||||
environment_name = utils.generate_name('create_environment')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
environment_name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
# create session
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
|
||||
object_model = self.create_obj_model(
|
||||
self.packages['require_for_2.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
self.application_catalog_client.deploy_session(
|
||||
environment['id'], session['id'])
|
||||
|
||||
deploy_result = utils.wait_for_environment_deploy(
|
||||
self.application_catalog_client, environment['id'])['status']
|
||||
|
||||
self.assertEqual(deploy_result, 'ready')
|
@ -0,0 +1,97 @@
|
||||
# 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 six
|
||||
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 TestVersioningNegative(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(TestVersioningNegative, cls).resource_setup()
|
||||
|
||||
# create package with version 1.0.0
|
||||
application_name = utils.generate_name('package_test')
|
||||
provided_version = '1.0.0'
|
||||
package1, path1 = cls.upload_package(
|
||||
application_name, version=provided_version)
|
||||
|
||||
# main application
|
||||
expected_version = '2.0.0'
|
||||
main_app_name = utils.generate_name('main_package_test')
|
||||
require = [(package1['name'], expected_version)]
|
||||
package2, path2 = cls.upload_package(main_app_name, require=require)
|
||||
|
||||
cls.packages = {
|
||||
'1.0.0': package1,
|
||||
'require_for_1.0.0': package2
|
||||
}
|
||||
cls.abs_archive_paths = [path1, path2]
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
for pkg in six.itervalues(cls.packages):
|
||||
cls.artifacts_client.delete_package(pkg['id'])
|
||||
map(os.remove, cls.abs_archive_paths)
|
||||
super(TestVersioningNegative, cls).resource_cleanup()
|
||||
|
||||
@testtools.testcase.attr('negative')
|
||||
@testtools.testcase.attr('smoke')
|
||||
def test_deploy_package_with_no_required_package_version(self):
|
||||
"""Test deployment of package which requires package with absent version.
|
||||
|
||||
1) Create environment.
|
||||
2) Add to the environment package which requires version 2.0.0 of the
|
||||
package, which is present with version 1.0.0 only in repository.
|
||||
3) Deploy environment.
|
||||
4) Check if deployment status failure.
|
||||
"""
|
||||
|
||||
# create environment
|
||||
environment_name = utils.generate_name('create_environment')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
environment_name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
# create session
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
|
||||
object_model = self.create_obj_model(
|
||||
self.packages['require_for_1.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
self.application_catalog_client.deploy_session(
|
||||
environment['id'], session['id'])
|
||||
|
||||
deploy_result = utils.wait_for_environment_deploy(
|
||||
self.application_catalog_client, environment['id'])['status']
|
||||
|
||||
self.assertEqual(deploy_result, 'deploy failure')
|
@ -16,6 +16,7 @@ import collections
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import uuid
|
||||
import yaml
|
||||
import zipfile
|
||||
@ -35,7 +36,7 @@ MANIFEST = {'Format': 'MuranoPL/1.0',
|
||||
|
||||
def compose_package(app_name, manifest, package_dir,
|
||||
require=None, archive_dir=None, add_class_name=False,
|
||||
manifest_required=True):
|
||||
manifest_required=True, version=None):
|
||||
"""Composes a murano package
|
||||
|
||||
Composes package `app_name` with `manifest` file as a template for the
|
||||
@ -44,6 +45,13 @@ def compose_package(app_name, manifest, package_dir,
|
||||
Puts the resulting .zip file into `acrhive_dir` if present or in the
|
||||
`package_dir`.
|
||||
"""
|
||||
class_file_changes = add_class_name or require
|
||||
# store class file before changes
|
||||
if class_file_changes:
|
||||
class_path = os.path.join(package_dir, 'Classes', 'mock_muranopl.yaml')
|
||||
with open(class_path, 'r') as f:
|
||||
class_store = f.read()
|
||||
|
||||
if manifest_required:
|
||||
with open(manifest, 'w') as f:
|
||||
fqn = 'io.murano.apps.' + app_name
|
||||
@ -52,7 +60,10 @@ def compose_package(app_name, manifest, package_dir,
|
||||
mfest_copy['Name'] = app_name
|
||||
mfest_copy['Classes'] = {fqn: 'mock_muranopl.yaml'}
|
||||
if require:
|
||||
mfest_copy['Require'] = require
|
||||
mfest_copy['Require'] = {str(name): version
|
||||
for name, version in require}
|
||||
if version:
|
||||
mfest_copy['Version'] = version
|
||||
f.write(yaml.dump(mfest_copy, default_flow_style=False))
|
||||
|
||||
if add_class_name:
|
||||
@ -66,6 +77,20 @@ def compose_package(app_name, manifest, package_dir,
|
||||
with open(class_file, 'w') as f:
|
||||
f.write(contents)
|
||||
|
||||
if require:
|
||||
class_file = os.path.join(package_dir, 'Classes', 'mock_muranopl.yaml')
|
||||
with open(class_file, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
index_string = 'deploy:\n Body:\n '
|
||||
index = content.index(index_string) + len(index_string)
|
||||
class_names = [req[0][req[0].rfind('.') + 1:] for req in require]
|
||||
addition = "".join(["- new({})\n".format(name) + ' ' * 6
|
||||
for name in class_names])
|
||||
content = content[:index] + addition + content[index:]
|
||||
with open(class_file, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
name = app_name + '.zip'
|
||||
|
||||
if not archive_dir:
|
||||
@ -80,11 +105,17 @@ def compose_package(app_name, manifest, package_dir,
|
||||
arcname=os.path.join(os.path.relpath(root, package_dir), f)
|
||||
)
|
||||
|
||||
# restore class file after changes
|
||||
if class_file_changes:
|
||||
with open(class_path, 'w') as f:
|
||||
f.write(class_store)
|
||||
|
||||
return archive_path, name
|
||||
|
||||
|
||||
def prepare_package(name, require=None, add_class_name=False,
|
||||
app='MockApp', manifest_required=True):
|
||||
app='MockApp', manifest_required=True,
|
||||
version=None):
|
||||
"""Prepare package.
|
||||
|
||||
:param name: Package name to compose
|
||||
@ -98,7 +129,8 @@ def prepare_package(name, require=None, add_class_name=False,
|
||||
arc_path, filename = compose_package(
|
||||
name, os.path.join(app_dir, 'manifest.yaml'),
|
||||
app_dir, require=require, archive_dir=target_arc_path,
|
||||
add_class_name=add_class_name, manifest_required=manifest_required)
|
||||
add_class_name=add_class_name, manifest_required=manifest_required,
|
||||
version=version)
|
||||
return arc_path, target_arc_path, filename
|
||||
|
||||
|
||||
@ -477,3 +509,13 @@ def get_local_inheritance(classes):
|
||||
base_fqn = base_class
|
||||
result.setdefault(base_fqn, []).append(class_name)
|
||||
return result
|
||||
|
||||
|
||||
def wait_for_environment_deploy(client, environment_id,
|
||||
timeout=1800, interval=10):
|
||||
start_time = time.time()
|
||||
while client.get_environment(environment_id)['status'] == 'deploying':
|
||||
if time.time() - start_time > timeout:
|
||||
break
|
||||
time.sleep(interval)
|
||||
return client.get_environment(environment_id)
|
||||
|
Loading…
Reference in New Issue
Block a user