Add new Murano scenarios
- added four new Murano scenarios which check performance of commands which work with packages, like 'import-package', 'list-packages', 'delete-package'. - added appropriate methods into the murano/utils.py - added unit tests Change-Id: I655bb0c8a0980c59cd4ab576f97ee94c2c3cd0f7
This commit is contained in:
parent
79f8809245
commit
a04841e71f
@ -5,6 +5,6 @@ Name: HelloReporter
|
|||||||
Description: |
|
Description: |
|
||||||
HelloReporter test app.
|
HelloReporter test app.
|
||||||
Author: 'Mirantis, Inc'
|
Author: 'Mirantis, Inc'
|
||||||
Tags: [App, Test, HelloWorld]
|
Tags: []
|
||||||
Classes:
|
Classes:
|
||||||
io.murano.apps.HelloReporter: HelloReporter.yaml
|
io.murano.apps.HelloReporter: HelloReporter.yaml
|
||||||
|
@ -61,6 +61,84 @@
|
|||||||
app_package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
|
app_package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
|
||||||
roles:
|
roles:
|
||||||
- "admin"
|
- "admin"
|
||||||
|
|
||||||
|
MuranoPackages.import_and_list_packages:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 10
|
||||||
|
concurrency: 2
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 2
|
||||||
|
users_per_tenant: 2
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 1
|
||||||
|
concurrency: 1
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
||||||
|
|
||||||
|
MuranoPackages.import_and_delete_package:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 10
|
||||||
|
concurrency: 2
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 2
|
||||||
|
users_per_tenant: 2
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
||||||
|
|
||||||
|
MuranoPackages.import_and_filter_applications:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
|
||||||
|
filter_query: {"category" : "Web"}
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 10
|
||||||
|
concurrency: 2
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 2
|
||||||
|
users_per_tenant: 2
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
||||||
|
|
||||||
|
MuranoPackages.package_lifecycle:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
|
||||||
|
body: {"categories": ["Web"]}
|
||||||
|
operation: "add"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 10
|
||||||
|
concurrency: 2
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 2
|
||||||
|
users_per_tenant: 2
|
||||||
sla:
|
sla:
|
||||||
failure_rate:
|
failure_rate:
|
||||||
max: 0
|
max: 0
|
||||||
|
142
rally/plugins/openstack/scenarios/murano/packages.py
Normal file
142
rally/plugins/openstack/scenarios/murano/packages.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
# Copyright 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.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from rally import consts
|
||||||
|
from rally.plugins.openstack.scenarios.murano import utils
|
||||||
|
from rally.task import scenario
|
||||||
|
from rally.task import validation
|
||||||
|
|
||||||
|
|
||||||
|
class MuranoPackages(utils.MuranoScenario):
|
||||||
|
"""Benchmark scenarios for Murano packages."""
|
||||||
|
|
||||||
|
@validation.required_parameters("package")
|
||||||
|
@validation.file_exists(param_name="package", mode=os.F_OK)
|
||||||
|
@validation.required_clients("murano")
|
||||||
|
@validation.required_services(consts.Service.MURANO)
|
||||||
|
@validation.required_openstack(users=True)
|
||||||
|
@scenario.configure(context={"cleanup": ["murano.packages"]})
|
||||||
|
def import_and_list_packages(self, package, include_disabled=False):
|
||||||
|
"""Import Murano package and get list of packages.
|
||||||
|
|
||||||
|
Measure the "murano import-package" and "murano package-list" commands
|
||||||
|
performance.
|
||||||
|
It imports Murano package from "package" (if it is not a zip archive
|
||||||
|
then zip archive will be prepared) and gets list of imported packages.
|
||||||
|
|
||||||
|
:param package: path to zip archive that represents Murano
|
||||||
|
application package or absolute path to folder with
|
||||||
|
package components
|
||||||
|
:param include_disabled: specifies whether the disabled packages will
|
||||||
|
be included in a the result or not.
|
||||||
|
Default value is False.
|
||||||
|
"""
|
||||||
|
package_path = self._zip_package(package)
|
||||||
|
try:
|
||||||
|
self._import_package(package_path)
|
||||||
|
self._list_packages(include_disabled=include_disabled)
|
||||||
|
finally:
|
||||||
|
os.remove(package_path)
|
||||||
|
|
||||||
|
@validation.required_parameters("package")
|
||||||
|
@validation.file_exists(param_name="package", mode=os.F_OK)
|
||||||
|
@validation.required_clients("murano")
|
||||||
|
@validation.required_services(consts.Service.MURANO)
|
||||||
|
@validation.required_openstack(users=True)
|
||||||
|
@scenario.configure(context={"cleanup": ["murano.packages"]})
|
||||||
|
def import_and_delete_package(self, package):
|
||||||
|
"""Import Murano package and then delete it.
|
||||||
|
|
||||||
|
Measure the "murano import-package" and "murano package-delete"
|
||||||
|
commands performance.
|
||||||
|
It imports Murano package from "package" (if it is not a zip archive
|
||||||
|
then zip archive will be prepared) and deletes it.
|
||||||
|
|
||||||
|
:param package: path to zip archive that represents Murano
|
||||||
|
application package or absolute path to folder with
|
||||||
|
package components
|
||||||
|
"""
|
||||||
|
package_path = self._zip_package(package)
|
||||||
|
try:
|
||||||
|
package = self._import_package(package_path)
|
||||||
|
self._delete_package(package)
|
||||||
|
finally:
|
||||||
|
os.remove(package_path)
|
||||||
|
|
||||||
|
@validation.required_parameters("package", "body")
|
||||||
|
@validation.file_exists(param_name="package", mode=os.F_OK)
|
||||||
|
@validation.required_clients("murano")
|
||||||
|
@validation.required_services(consts.Service.MURANO)
|
||||||
|
@validation.required_openstack(users=True)
|
||||||
|
@scenario.configure(context={"cleanup": ["murano.packages"]})
|
||||||
|
def package_lifecycle(self, package, body, operation="replace"):
|
||||||
|
"""Import Murano package, modify it and then delete it.
|
||||||
|
|
||||||
|
Measure the Murano import, update and delete package
|
||||||
|
commands performance.
|
||||||
|
It imports Murano package from "package" (if it is not a zip archive
|
||||||
|
then zip archive will be prepared), modifies it (using data from
|
||||||
|
"body") and deletes.
|
||||||
|
|
||||||
|
:param package: path to zip archive that represents Murano
|
||||||
|
application package or absolute path to folder with
|
||||||
|
package components
|
||||||
|
:param body: dict object that defines what package property will be
|
||||||
|
updated, e.g {"tags": ["tag"]} or {"enabled": "true"}
|
||||||
|
:param operation: string object that defines the way of how package
|
||||||
|
property will be updated, allowed operations are
|
||||||
|
"add", "replace" or "delete".
|
||||||
|
Default value is "replace".
|
||||||
|
|
||||||
|
"""
|
||||||
|
package_path = self._zip_package(package)
|
||||||
|
try:
|
||||||
|
package = self._import_package(package_path)
|
||||||
|
self._update_package(package, body, operation)
|
||||||
|
self._delete_package(package)
|
||||||
|
finally:
|
||||||
|
os.remove(package_path)
|
||||||
|
|
||||||
|
@validation.required_parameters("package", "filter_query")
|
||||||
|
@validation.file_exists(param_name="package", mode=os.F_OK)
|
||||||
|
@validation.required_clients("murano")
|
||||||
|
@validation.required_services(consts.Service.MURANO)
|
||||||
|
@validation.required_openstack(users=True)
|
||||||
|
@scenario.configure(context={"cleanup": ["murano.packages"]})
|
||||||
|
def import_and_filter_applications(self, package, filter_query):
|
||||||
|
"""Import Murano package and then filter packages by some criteria.
|
||||||
|
|
||||||
|
Measure the performance of package import and package
|
||||||
|
filtering commands.
|
||||||
|
It imports Murano package from "package" (if it is not a zip archive
|
||||||
|
then zip archive will be prepared) and filters packages by some
|
||||||
|
criteria.
|
||||||
|
|
||||||
|
:param package: path to zip archive that represents Murano
|
||||||
|
application package or absolute path to folder with
|
||||||
|
package components
|
||||||
|
:param filter_query: dict that contains filter criteria, lately it
|
||||||
|
will be passed as **kwargs to filter method
|
||||||
|
e.g. {"category": "Web"}
|
||||||
|
"""
|
||||||
|
package_path = self._zip_package(package)
|
||||||
|
try:
|
||||||
|
self._import_package(package_path)
|
||||||
|
self._filter_applications(filter_query)
|
||||||
|
finally:
|
||||||
|
os.remove(package_path)
|
@ -13,10 +13,17 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
|
import zipfile
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from rally.common import fileutils
|
||||||
|
from rally.common import utils as common_utils
|
||||||
from rally.plugins.openstack import scenario
|
from rally.plugins.openstack import scenario
|
||||||
from rally.task import atomic
|
from rally.task import atomic
|
||||||
from rally.task import utils
|
from rally.task import utils
|
||||||
@ -31,7 +38,7 @@ MURANO_TIMEOUT_OPTS = [
|
|||||||
cfg.IntOpt("delete_environment_check_interval", default=2,
|
cfg.IntOpt("delete_environment_check_interval", default=2,
|
||||||
help="Delete environment check interval in seconds"),
|
help="Delete environment check interval in seconds"),
|
||||||
cfg.IntOpt("deploy_environment_check_interval", default=5,
|
cfg.IntOpt("deploy_environment_check_interval", default=5,
|
||||||
help="Deploy environment check interval in seconds")
|
help="Deploy environment check interval in seconds"),
|
||||||
]
|
]
|
||||||
|
|
||||||
benchmark_group = cfg.OptGroup(name="benchmark", title="benchmark options")
|
benchmark_group = cfg.OptGroup(name="benchmark", title="benchmark options")
|
||||||
@ -125,3 +132,149 @@ class MuranoScenario(scenario.OpenStackScenario):
|
|||||||
timeout=CONF.benchmark.deploy_environment_timeout,
|
timeout=CONF.benchmark.deploy_environment_timeout,
|
||||||
check_interval=CONF.benchmark.deploy_environment_check_interval
|
check_interval=CONF.benchmark.deploy_environment_check_interval
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@atomic.action_timer("murano.list_packages")
|
||||||
|
def _list_packages(self, include_disabled=False):
|
||||||
|
"""Returns packages list.
|
||||||
|
|
||||||
|
:param include_disabled: if "True" then disabled packages will be
|
||||||
|
included in a the result.
|
||||||
|
Default value is False.
|
||||||
|
:returns: list of imported packages
|
||||||
|
"""
|
||||||
|
return self.clients("murano").packages.list(
|
||||||
|
include_disabled=include_disabled)
|
||||||
|
|
||||||
|
@atomic.action_timer("murano.import_package")
|
||||||
|
def _import_package(self, package):
|
||||||
|
"""Import package to the Murano.
|
||||||
|
|
||||||
|
:param package: path to zip archive with Murano application
|
||||||
|
:returns: imported package
|
||||||
|
"""
|
||||||
|
|
||||||
|
package = self.clients("murano").packages.create(
|
||||||
|
{}, {"file": open(package)}
|
||||||
|
)
|
||||||
|
|
||||||
|
return package
|
||||||
|
|
||||||
|
@atomic.action_timer("murano.delete_package")
|
||||||
|
def _delete_package(self, package):
|
||||||
|
"""Delete specified package.
|
||||||
|
|
||||||
|
:param package: package that will be deleted
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.clients("murano").packages.delete(package.id)
|
||||||
|
|
||||||
|
@atomic.action_timer("murano.update_package")
|
||||||
|
def _update_package(self, package, body, operation="replace"):
|
||||||
|
"""Update specified package.
|
||||||
|
|
||||||
|
:param package: package that will be updated
|
||||||
|
:param body: dict object that defines what package property will be
|
||||||
|
updated, e.g {"tags": ["tag"]} or {"enabled": "true"}
|
||||||
|
:param operation: string object that defines the way of how package
|
||||||
|
property will be updated, allowed operations are
|
||||||
|
"add", "replace" or "delete".
|
||||||
|
Default value is "replace".
|
||||||
|
:returns: updated package
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.clients("murano").packages.update(
|
||||||
|
package.id, body, operation)
|
||||||
|
|
||||||
|
@atomic.action_timer("murano.filter_applications")
|
||||||
|
def _filter_applications(self, filter_query):
|
||||||
|
"""Filter list of uploaded application by specified criteria.
|
||||||
|
|
||||||
|
:param filter_query: dict that contains filter criteria, it
|
||||||
|
will be passed as **kwargs to filter method
|
||||||
|
e.g. {"category": "Web"}
|
||||||
|
:returns: filtered list of packages
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.clients("murano").packages.filter(**filter_query)
|
||||||
|
|
||||||
|
def _zip_package(self, package_path):
|
||||||
|
"""Call _prepare_package method that returns path to zip archive."""
|
||||||
|
return MuranoPackageManager()._prepare_package(package_path)
|
||||||
|
|
||||||
|
|
||||||
|
class MuranoPackageManager(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _read_from_file(filename):
|
||||||
|
with open(filename, "r") as f:
|
||||||
|
read_data = f.read()
|
||||||
|
return yaml.safe_load(read_data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _write_to_file(data, filename):
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
yaml.safe_dump(data, f)
|
||||||
|
|
||||||
|
def _change_app_fullname(self, app_dir):
|
||||||
|
"""Change application full name.
|
||||||
|
|
||||||
|
To avoid name conflict error during package import (when user
|
||||||
|
tries to import a few packages into the same tenant) need to change the
|
||||||
|
application name. For doing this need to replace following parts
|
||||||
|
in manifest.yaml
|
||||||
|
from
|
||||||
|
...
|
||||||
|
FullName: app.name
|
||||||
|
...
|
||||||
|
Classes:
|
||||||
|
app.name: app_class.yaml
|
||||||
|
to:
|
||||||
|
...
|
||||||
|
FullName: <new_name>
|
||||||
|
...
|
||||||
|
Classes:
|
||||||
|
<new_name>: app_class.yaml
|
||||||
|
|
||||||
|
:param app_dir: path to directory with Murano application context
|
||||||
|
"""
|
||||||
|
|
||||||
|
new_fullname = common_utils.generate_random_name("app.")
|
||||||
|
|
||||||
|
manifest_file = os.path.join(app_dir, "manifest.yaml")
|
||||||
|
manifest = self._read_from_file(manifest_file)
|
||||||
|
|
||||||
|
class_file_name = manifest["Classes"][manifest["FullName"]]
|
||||||
|
|
||||||
|
# update manifest.yaml file
|
||||||
|
del manifest["Classes"][manifest["FullName"]]
|
||||||
|
manifest["FullName"] = new_fullname
|
||||||
|
manifest["Classes"][new_fullname] = class_file_name
|
||||||
|
self._write_to_file(manifest, manifest_file)
|
||||||
|
|
||||||
|
def _prepare_package(self, package_path):
|
||||||
|
"""Check whether the package path is path to zip archive or not.
|
||||||
|
|
||||||
|
If package_path is not a path to zip archive but path to Murano
|
||||||
|
application folder, than method prepares zip archive with Murano
|
||||||
|
application. It copies directory with Murano app files to temporary
|
||||||
|
folder, changes manifest.yaml and class file (to avoid '409 Conflict'
|
||||||
|
errors in Murano) and prepares zip package.
|
||||||
|
|
||||||
|
:param package_path: path to zip archive or directory with package
|
||||||
|
components
|
||||||
|
:returns: path to zip archive with Murano application
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not zipfile.is_zipfile(package_path):
|
||||||
|
tmp_dir = tempfile.mkdtemp()
|
||||||
|
pkg_dir = os.path.join(tmp_dir, "package/")
|
||||||
|
try:
|
||||||
|
shutil.copytree(package_path, pkg_dir)
|
||||||
|
|
||||||
|
self._change_app_fullname(pkg_dir)
|
||||||
|
package_path = fileutils.pack_dir(pkg_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp_dir)
|
||||||
|
|
||||||
|
return package_path
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
# Copyright 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.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from rally.plugins.openstack.scenarios.murano import packages
|
||||||
|
from tests.unit import test
|
||||||
|
|
||||||
|
MURANO_SCENARIO = ("rally.plugins.openstack.scenarios.murano."
|
||||||
|
"packages.MuranoPackages")
|
||||||
|
|
||||||
|
|
||||||
|
class MuranoPackagesTestCase(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(MuranoPackagesTestCase, self).setUp()
|
||||||
|
self.scenario = packages.MuranoPackages()
|
||||||
|
self.scenario._import_package = mock.Mock()
|
||||||
|
self.scenario._zip_package = mock.Mock()
|
||||||
|
self.scenario._list_packages = mock.Mock()
|
||||||
|
self.scenario._delete_package = mock.Mock()
|
||||||
|
self.scenario._update_package = mock.Mock()
|
||||||
|
self.scenario._filter_applications = mock.Mock()
|
||||||
|
self.mock_remove = mock.patch("os.remove")
|
||||||
|
self.mock_remove.start()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(MuranoPackagesTestCase, self).tearDown()
|
||||||
|
self.mock_remove.stop()
|
||||||
|
|
||||||
|
def test_make_zip_import_and_list_packages(self):
|
||||||
|
self.scenario.import_and_list_packages("foo_package.zip")
|
||||||
|
self.scenario._import_package.assert_called_once_with(
|
||||||
|
self.scenario._zip_package.return_value)
|
||||||
|
self.scenario._zip_package.assert_called_once_with("foo_package.zip")
|
||||||
|
self.scenario._list_packages.assert_called_once_with(
|
||||||
|
include_disabled=False)
|
||||||
|
|
||||||
|
def test_import_and_delete_package(self):
|
||||||
|
fake_package = mock.Mock()
|
||||||
|
self.scenario._import_package.return_value = fake_package
|
||||||
|
self.scenario.import_and_delete_package("foo_package.zip")
|
||||||
|
self.scenario._import_package.assert_called_once_with(
|
||||||
|
self.scenario._zip_package.return_value)
|
||||||
|
self.scenario._delete_package.assert_called_once_with(fake_package)
|
||||||
|
|
||||||
|
def test_package_lifecycle(self):
|
||||||
|
fake_package = mock.Mock()
|
||||||
|
self.scenario._import_package.return_value = fake_package
|
||||||
|
self.scenario.package_lifecycle(
|
||||||
|
"foo_package.zip", {"category": "Web"}, "add")
|
||||||
|
self.scenario._import_package.assert_called_once_with(
|
||||||
|
self.scenario._zip_package.return_value)
|
||||||
|
self.scenario._update_package.assert_called_once_with(
|
||||||
|
fake_package, {"category": "Web"}, "add")
|
||||||
|
self.scenario._delete_package.assert_called_once_with(fake_package)
|
||||||
|
|
||||||
|
def test_import_and_filter_applications(self):
|
||||||
|
fake_package = mock.Mock()
|
||||||
|
self.scenario._import_package.return_value = fake_package
|
||||||
|
self.scenario.import_and_filter_applications(
|
||||||
|
"foo_package.zip", {"category": "Web"})
|
||||||
|
self.scenario._import_package.assert_called_once_with(
|
||||||
|
self.scenario._zip_package.return_value)
|
||||||
|
self.scenario._filter_applications.assert_called_once_with(
|
||||||
|
{"category": "Web"}
|
||||||
|
)
|
@ -105,3 +105,129 @@ class MuranoScenarioTestCase(test.ScenarioTestCase):
|
|||||||
self.mock_resource_is.mock.assert_called_once_with("READY")
|
self.mock_resource_is.mock.assert_called_once_with("READY")
|
||||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
"murano.deploy_environment")
|
"murano.deploy_environment")
|
||||||
|
|
||||||
|
@mock.patch(MRN_UTILS + ".open",
|
||||||
|
side_effect=mock.mock_open(read_data="Key: value"),
|
||||||
|
create=True)
|
||||||
|
def test_read_from_file(self, mock_open):
|
||||||
|
utility = utils.MuranoPackageManager()
|
||||||
|
data = utility._read_from_file("filename")
|
||||||
|
expected_data = {"Key": "value"}
|
||||||
|
self.assertEqual(expected_data, data)
|
||||||
|
|
||||||
|
@mock.patch(MRN_UTILS + ".MuranoPackageManager._read_from_file")
|
||||||
|
@mock.patch(MRN_UTILS + ".MuranoPackageManager._write_to_file")
|
||||||
|
def test_change_app_fullname(
|
||||||
|
self, mock_murano_package_manager__write_to_file,
|
||||||
|
mock_murano_package_manager__read_from_file):
|
||||||
|
manifest = {"FullName": "app.name_abc",
|
||||||
|
"Classes": {"app.name_abc": "app_class.yaml"}}
|
||||||
|
mock_murano_package_manager__read_from_file.side_effect = (
|
||||||
|
[manifest])
|
||||||
|
utility = utils.MuranoPackageManager()
|
||||||
|
utility._change_app_fullname("tmp/tmpfile/")
|
||||||
|
mock_murano_package_manager__read_from_file.assert_has_calls(
|
||||||
|
[mock.call("tmp/tmpfile/manifest.yaml")]
|
||||||
|
)
|
||||||
|
mock_murano_package_manager__write_to_file.assert_has_calls(
|
||||||
|
[mock.call(manifest, "tmp/tmpfile/manifest.yaml")]
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch("zipfile.is_zipfile")
|
||||||
|
@mock.patch("tempfile.mkdtemp")
|
||||||
|
@mock.patch("shutil.copytree")
|
||||||
|
@mock.patch(MRN_UTILS + ".MuranoPackageManager._change_app_fullname")
|
||||||
|
@mock.patch("rally.common.fileutils.pack_dir")
|
||||||
|
@mock.patch("shutil.rmtree")
|
||||||
|
def test_prepare_zip_if_not_zip(
|
||||||
|
self, mock_shutil_rmtree, mock_pack_dir,
|
||||||
|
mock_murano_package_manager__change_app_fullname,
|
||||||
|
mock_shutil_copytree, mock_tempfile_mkdtemp,
|
||||||
|
mock_zipfile_is_zipfile):
|
||||||
|
utility = utils.MuranoPackageManager()
|
||||||
|
package_path = "tmp/tmpfile"
|
||||||
|
|
||||||
|
mock_zipfile_is_zipfile.return_value = False
|
||||||
|
mock_tempfile_mkdtemp.return_value = "tmp/tmpfile"
|
||||||
|
mock_pack_dir.return_value = "tmp/tmpzipfile"
|
||||||
|
|
||||||
|
zip_file = utility._prepare_package(package_path)
|
||||||
|
|
||||||
|
self.assertEqual("tmp/tmpzipfile", zip_file)
|
||||||
|
mock_tempfile_mkdtemp.assert_called_once_with()
|
||||||
|
mock_shutil_copytree.assert_called_once_with(
|
||||||
|
"tmp/tmpfile",
|
||||||
|
"tmp/tmpfile/package/"
|
||||||
|
)
|
||||||
|
(mock_murano_package_manager__change_app_fullname.
|
||||||
|
assert_called_once_with("tmp/tmpfile/package/"))
|
||||||
|
mock_shutil_rmtree.assert_called_once_with("tmp/tmpfile")
|
||||||
|
|
||||||
|
@mock.patch("zipfile.is_zipfile")
|
||||||
|
def test_prepare_zip_if_zip(self, mock_zipfile_is_zipfile):
|
||||||
|
utility = utils.MuranoPackageManager()
|
||||||
|
package_path = "tmp/tmpfile.zip"
|
||||||
|
mock_zipfile_is_zipfile.return_value = True
|
||||||
|
zip_file = utility._prepare_package(package_path)
|
||||||
|
self.assertEqual("tmp/tmpfile.zip", zip_file)
|
||||||
|
|
||||||
|
def test_list_packages(self):
|
||||||
|
scenario = utils.MuranoScenario()
|
||||||
|
self.assertEqual(self.clients("murano").packages.list.return_value,
|
||||||
|
scenario._list_packages())
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"murano.list_packages")
|
||||||
|
|
||||||
|
@mock.patch(MRN_UTILS + ".open", create=True)
|
||||||
|
def test_import_package(self, mock_open):
|
||||||
|
self.clients("murano").packages.create.return_value = (
|
||||||
|
"created_foo_package"
|
||||||
|
)
|
||||||
|
scenario = utils.MuranoScenario()
|
||||||
|
mock_open.return_value = "opened_foo_package.zip"
|
||||||
|
imp_package = scenario._import_package("foo_package.zip")
|
||||||
|
self.assertEqual("created_foo_package", imp_package)
|
||||||
|
self.clients("murano").packages.create.assert_called_once_with(
|
||||||
|
{}, {"file": "opened_foo_package.zip"})
|
||||||
|
mock_open.assert_called_once_with("foo_package.zip")
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"murano.import_package")
|
||||||
|
|
||||||
|
def test_delete_package(self):
|
||||||
|
package = mock.Mock(id="package_id")
|
||||||
|
scenario = utils.MuranoScenario()
|
||||||
|
scenario._delete_package(package)
|
||||||
|
self.clients("murano").packages.delete.assert_called_once_with(
|
||||||
|
"package_id"
|
||||||
|
)
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"murano.delete_package")
|
||||||
|
|
||||||
|
def test_update_package(self):
|
||||||
|
package = mock.Mock(id="package_id")
|
||||||
|
self.clients("murano").packages.update.return_value = "updated_package"
|
||||||
|
scenario = utils.MuranoScenario()
|
||||||
|
upd_package = scenario._update_package(
|
||||||
|
package, {"tags": ["tag"]}, "add"
|
||||||
|
)
|
||||||
|
self.assertEqual("updated_package", upd_package)
|
||||||
|
self.clients("murano").packages.update.assert_called_once_with(
|
||||||
|
"package_id",
|
||||||
|
{"tags": ["tag"]},
|
||||||
|
"add"
|
||||||
|
)
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"murano.update_package")
|
||||||
|
|
||||||
|
def test_filter_packages(self):
|
||||||
|
self.clients("murano").packages.filter.return_value = []
|
||||||
|
scenario = utils.MuranoScenario()
|
||||||
|
return_apps_list = scenario._filter_applications(
|
||||||
|
{"category": "Web"}
|
||||||
|
)
|
||||||
|
self.assertEqual([], return_apps_list)
|
||||||
|
self.clients("murano").packages.filter.assert_called_once_with(
|
||||||
|
category="Web"
|
||||||
|
)
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"murano.filter_applications")
|
||||||
|
Loading…
Reference in New Issue
Block a user