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:
oshykhkerimov 2016-07-26 13:12:48 +00:00 committed by Kirill Zaitsev
parent 5475ac13ad
commit 46657301c1
6 changed files with 332 additions and 6 deletions

View File

@ -26,7 +26,7 @@ Methods:
credentials:
uri: localhost
deploy:
Body:
Body:
- $this.find(std:Environment).reporter.report($this, 'Follow the white rabbit')
staticAction:

View File

@ -19,4 +19,4 @@ Forms:
type: string
description: Apache License, Version 2.0
hidden: false
required: false
required: false

View File

@ -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']
}
}

View File

@ -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')

View File

@ -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')

View File

@ -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)