From 1ea1cda5d47718a537f5e476426400bd1937ec92 Mon Sep 17 00:00:00 2001 From: zhurong Date: Mon, 4 Dec 2017 15:18:38 +0800 Subject: [PATCH] Remove murano_tempest_tests from murano repo Change-Id: I5da1c660393df335f8d5e8ab17b23bb21a8e3257 --- .../tests/unit/engine/test_package_loader.py | 2 +- murano/tests/unit/utils.py | 82 +++ murano_tempest_tests/__init__.py | 0 murano_tempest_tests/clients.py | 72 --- murano_tempest_tests/config.py | 132 ----- .../extras/MockApp/Classes/mock_muranopl.yaml | 47 -- .../extras/MockApp/UI/ui.yaml | 22 - murano_tempest_tests/extras/MockApp/logo.png | Bin 22607 -> 0 bytes .../Classes/ApacheHttpServer.yaml | 81 --- .../Resources/index.html | 8 - .../manifest.yaml | 28 - .../Classes/Lighttpd.yaml | 55 -- .../Resources/DeployLighttpd.template | 27 - .../Resources/scripts/deployLighttpd.sh | 14 - .../manifest.yaml | 24 - .../Classes/UpdateExecutor.yaml | 47 -- .../Resources/scripts/update.sh | 14 - .../manifest.yaml | 22 - .../io.murano.apps.test.VM/Classes/VM.yaml | 66 --- .../Resources/index.html | 8 - .../io.murano.apps.test.VM/manifest.yaml | 22 - murano_tempest_tests/plugin.py | 54 -- murano_tempest_tests/services/__init__.py | 0 .../services/application_catalog/__init__.py | 0 .../application_catalog_client.py | 449 --------------- .../services/artifacts/__init__.py | 0 .../services/artifacts/artifacts_client.py | 157 ------ .../services/service_broker/__init__.py | 0 .../service_broker/service_broker_client.py | 108 ---- murano_tempest_tests/tests/__init__.py | 0 murano_tempest_tests/tests/api/__init__.py | 0 .../tests/api/application_catalog/__init__.py | 0 .../application_catalog/artifacts/__init__.py | 0 .../api/application_catalog/artifacts/base.py | 97 ---- .../artifacts/test_repository.py | 56 -- .../artifacts/test_versioning.py | 166 ------ .../artifacts/test_versioning_negative.py | 96 ---- .../tests/api/application_catalog/base.py | 110 ---- .../application_catalog/test_categories.py | 113 ---- .../test_categories_negative.py | 72 --- .../application_catalog/test_deployments.py | 86 --- .../application_catalog/test_env_templates.py | 258 --------- .../test_env_templates_negative.py | 133 ----- .../application_catalog/test_environments.py | 128 ----- .../test_environments_negative.py | 104 ---- .../application_catalog/test_repository.py | 221 -------- .../test_repository_negative.py | 193 ------- .../api/application_catalog/test_services.py | 134 ----- .../test_services_negative.py | 272 ---------- .../api/application_catalog/test_sessions.py | 93 ---- .../test_sessions_negative.py | 146 ----- .../test_static_actions.py | 76 --- .../test_static_actions_negative.py | 115 ---- .../tests/api/service_broker/__init__.py | 0 .../tests/api/service_broker/base.py | 136 ----- .../test_service_broker_actions.py | 167 ------ .../test_service_broker_negative.py | 32 -- .../tests/scenario/__init__.py | 0 .../scenario/application_catalog/__init__.py | 0 .../scenario/application_catalog/base.py | 406 -------------- .../test_cinder_volumes.py | 510 ----------------- .../application_catalog/test_deployment.py | 257 --------- .../test_security_groups.py | 85 --- murano_tempest_tests/utils.py | 512 ------------------ 64 files changed, 83 insertions(+), 6232 deletions(-) delete mode 100644 murano_tempest_tests/__init__.py delete mode 100644 murano_tempest_tests/clients.py delete mode 100644 murano_tempest_tests/config.py delete mode 100644 murano_tempest_tests/extras/MockApp/Classes/mock_muranopl.yaml delete mode 100644 murano_tempest_tests/extras/MockApp/UI/ui.yaml delete mode 100644 murano_tempest_tests/extras/MockApp/logo.png delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Classes/ApacheHttpServer.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Resources/index.html delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/manifest.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Classes/Lighttpd.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/DeployLighttpd.template delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/scripts/deployLighttpd.sh delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/manifest.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Classes/UpdateExecutor.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Resources/scripts/update.sh delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/manifest.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.VM/Classes/VM.yaml delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.VM/Resources/index.html delete mode 100644 murano_tempest_tests/extras/io.murano.apps.test.VM/manifest.yaml delete mode 100644 murano_tempest_tests/plugin.py delete mode 100644 murano_tempest_tests/services/__init__.py delete mode 100644 murano_tempest_tests/services/application_catalog/__init__.py delete mode 100644 murano_tempest_tests/services/application_catalog/application_catalog_client.py delete mode 100644 murano_tempest_tests/services/artifacts/__init__.py delete mode 100644 murano_tempest_tests/services/artifacts/artifacts_client.py delete mode 100644 murano_tempest_tests/services/service_broker/__init__.py delete mode 100644 murano_tempest_tests/services/service_broker/service_broker_client.py delete mode 100644 murano_tempest_tests/tests/__init__.py delete mode 100644 murano_tempest_tests/tests/api/__init__.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/__init__.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/artifacts/__init__.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/artifacts/base.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/artifacts/test_repository.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/base.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_categories.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_categories_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_deployments.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_env_templates.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_env_templates_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_environments.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_environments_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_repository.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_repository_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_services.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_services_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_sessions.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_sessions_negative.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_static_actions.py delete mode 100644 murano_tempest_tests/tests/api/application_catalog/test_static_actions_negative.py delete mode 100644 murano_tempest_tests/tests/api/service_broker/__init__.py delete mode 100644 murano_tempest_tests/tests/api/service_broker/base.py delete mode 100644 murano_tempest_tests/tests/api/service_broker/test_service_broker_actions.py delete mode 100644 murano_tempest_tests/tests/api/service_broker/test_service_broker_negative.py delete mode 100644 murano_tempest_tests/tests/scenario/__init__.py delete mode 100644 murano_tempest_tests/tests/scenario/application_catalog/__init__.py delete mode 100644 murano_tempest_tests/tests/scenario/application_catalog/base.py delete mode 100644 murano_tempest_tests/tests/scenario/application_catalog/test_cinder_volumes.py delete mode 100644 murano_tempest_tests/tests/scenario/application_catalog/test_deployment.py delete mode 100644 murano_tempest_tests/tests/scenario/application_catalog/test_security_groups.py delete mode 100644 murano_tempest_tests/utils.py diff --git a/murano/tests/unit/engine/test_package_loader.py b/murano/tests/unit/engine/test_package_loader.py index 86badbdae..ad3a0ce0a 100644 --- a/murano/tests/unit/engine/test_package_loader.py +++ b/murano/tests/unit/engine/test_package_loader.py @@ -28,7 +28,7 @@ from murano.dsl import murano_package as dsl_package from murano.engine import package_loader from murano.packages import exceptions as pkg_exc from murano.tests.unit import base -from murano_tempest_tests import utils +from murano.tests.unit import utils class TestPackageCache(base.MuranoTestCase): diff --git a/murano/tests/unit/utils.py b/murano/tests/unit/utils.py index 0a0459723..87855009a 100644 --- a/murano/tests/unit/utils.py +++ b/murano/tests/unit/utils.py @@ -13,10 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os +import shutil +import yaml +import zipfile + from murano import context from murano.db import session +MANIFEST = {'Format': 'MuranoPL/1.0', + 'Type': 'Application', + 'Description': 'MockApp for API tests', + 'Author': 'Mirantis, Inc'} + + def dummy_context(user='test_username', tenant_id='test_tenant_id', request_id='dummy-request', **kwargs): @@ -35,3 +46,74 @@ def save_models(*models): s = session.get_session() for m in models: m.save(s) + + +def compose_package(app_name, package_dir, + require=None, archive_dir=None, add_class_name=False, + manifest_required=True, version=None): + """Composes a murano package + + Composes package `app_name` manifest and files from `package_dir`. + Includes `require` section if any in the manifest file. + Puts the resulting .zip file into `archive_dir` if present or in the + `package_dir`. + """ + tmp_package_dir = os.path.join(archive_dir, os.path.basename(package_dir)) + shutil.copytree(package_dir, tmp_package_dir) + package_dir = tmp_package_dir + + if manifest_required: + manifest = os.path.join(package_dir, "manifest.yaml") + with open(manifest, 'w') as f: + fqn = 'io.murano.apps.' + app_name + mfest_copy = MANIFEST.copy() + mfest_copy['FullName'] = fqn + mfest_copy['Name'] = app_name + mfest_copy['Classes'] = {fqn: 'mock_muranopl.yaml'} + if 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: + class_file = os.path.join(package_dir, 'Classes', 'mock_muranopl.yaml') + with open(class_file, 'r') as f: + contents = f.read() + + index = contents.index('Extends') + contents = "{0}Name: {1}\n\n{2}".format(contents[:index], app_name, + contents[index:]) + 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: + archive_dir = os.path.dirname(os.path.abspath(__file__)) + archive_path = os.path.join(archive_dir, name) + + with zipfile.ZipFile(archive_path, 'w') as zip_file: + for root, dirs, files in os.walk(package_dir): + for f in files: + zip_file.write( + os.path.join(root, f), + arcname=os.path.join(os.path.relpath(root, package_dir), f) + ) + + return archive_path, name diff --git a/murano_tempest_tests/__init__.py b/murano_tempest_tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/clients.py b/murano_tempest_tests/clients.py deleted file mode 100644 index 08d42f111..000000000 --- a/murano_tempest_tests/clients.py +++ /dev/null @@ -1,72 +0,0 @@ -# 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 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 - - -class Manager(object): - def __init__(self, - credentials=None): - if credentials is None: - credentials = common_creds.\ - get_configured_admin_credentials('identity_admin') - 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) - - -class AltManager(Manager): - def __init__(self, service=None): - super(AltManager, self).__init__( - common_creds.get_configured_admin_credentials('alt_user'), service) - - -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 diff --git a/murano_tempest_tests/config.py b/murano_tempest_tests/config.py deleted file mode 100644 index e00cdbf1b..000000000 --- a/murano_tempest_tests/config.py +++ /dev/null @@ -1,132 +0,0 @@ -# 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 oslo_config import cfg - -service_option = [ - cfg.BoolOpt("murano", - default=True, - help="Whether or not murano is expected to be available"), - cfg.BoolOpt("murano_cfapi", - default=False, - help="Whether or not murano-cfapi is expected to be " - "unavailable by default"), - cfg.BoolOpt("glare", - default=False, - help="Whether or not glare is expected to be unavailable") -] - -application_catalog_group = cfg.OptGroup(name="application_catalog", - title="Application Catalog Options") - -service_broker_group = cfg.OptGroup(name="service_broker", - title="Service Broker Options") - -artifacts_group = cfg.OptGroup(name="artifacts", - title="Glance Artifacts Options") - -ApplicationCatalogGroup = [ - # Application catalog tempest configuration - cfg.StrOpt("region", - default="", - help="The application_catalog region name to use. If empty, " - "the value of identity.region is used instead. " - "If no such region is found in the service catalog, " - "the first found one is used."), - - cfg.StrOpt("linux_image", - default="debian-8-m-agent.qcow2", - help="Image for linux services"), - - cfg.StrOpt("catalog_type", - default="application-catalog", - help="Catalog type of Application Catalog."), - - cfg.StrOpt("endpoint_type", - default="publicURL", - choices=["publicURL", "adminURL", "internalURL"], - help="The endpoint type for application catalog service."), - - cfg.IntOpt("build_interval", - default=3, - help="Time in seconds between application catalog" - " availability checks."), - - cfg.IntOpt("build_timeout", - default=500, - help="Timeout in seconds to wait for a application catalog" - " to become available."), - cfg.BoolOpt("glare_backend", - default=False, - help="Tells tempest about murano glare backend " - "configuration."), - cfg.BoolOpt("cinder_volume_tests", - default=False, - help="Whether or not cinder volumes attachment tests " - "are expected to run"), - cfg.BoolOpt("deployment_tests", - default=False, - help="Whether or not deployment tests are expected to run") -] - -ServiceBrokerGroup = [ - # Test runs control - cfg.BoolOpt("run_service_broker_tests", - default=False, - help="Defines whether run service broker api tests or not"), - - cfg.StrOpt("catalog_type", - default="service-broker", - help="Catalog type of Service Broker API"), - - cfg.StrOpt("endpoint_type", - default="publicURL", - choices=["publicURL", "adminURL", "internalURL"], - help="The endpoint type for service broker service"), - - cfg.IntOpt("build_interval", - default=3, - help="Time in seconds between service broker" - " availability checks."), - - cfg.IntOpt("build_timeout", - default=500, - help="Timeout in seconds to wait for a service broker" - " to become available.") - - -] - -ArtifactsGroup = [ - # Glance artifacts options - cfg.StrOpt("catalog_type", - default="artifact", - help="Catalog type of Artifacts API"), - - cfg.StrOpt("endpoint_type", - default="publicURL", - choices=["publicURL", "adminURL", "internalURL"], - help="The endpoint type for artifacts service"), - - cfg.IntOpt("build_interval", - default=3, - help="Time in seconds between artifacts" - " availability checks."), - - cfg.IntOpt("build_timeout", - default=500, - help="Timeout in seconds to wait for a artifacts" - " to become available.") -] diff --git a/murano_tempest_tests/extras/MockApp/Classes/mock_muranopl.yaml b/murano_tempest_tests/extras/MockApp/Classes/mock_muranopl.yaml deleted file mode 100644 index c89de41aa..000000000 --- a/murano_tempest_tests/extras/MockApp/Classes/mock_muranopl.yaml +++ /dev/null @@ -1,47 +0,0 @@ -Namespaces: - =: io.murano.apps - std: io.murano - -Extends: std:Application - -Properties: - - userName: - Contract: $.string() - - greeting: - Usage: Static - Contract: $.string() - Default: 'Hello, ' - -Methods: - testAction: - Scope: Public - Body: - - $this.find(std:Environment).reporter.report($this, 'Completed') - getCredentials: - Scope: Public - Body: - - Return: - credentials: - uri: localhost - deploy: - Body: - - $this.find(std:Environment).reporter.report($this, 'Follow the white rabbit') - - staticAction: - Scope: Public - Usage: Static - Arguments: - - myName: - Contract: $.string().notNull() - Body: - - Return: concat($.greeting, $myName) - - staticNotAction: - Usage: Static - Arguments: - - myName: - Contract: $.string().notNull() - Body: - - Return: concat($.greeting, $myName) diff --git a/murano_tempest_tests/extras/MockApp/UI/ui.yaml b/murano_tempest_tests/extras/MockApp/UI/ui.yaml deleted file mode 100644 index 6f1cda4a7..000000000 --- a/murano_tempest_tests/extras/MockApp/UI/ui.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# 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. - -Version: 2.2 - -Forms: - - appConfiguration: - fields: - - name: license - type: string - description: Apache License, Version 2.0 - hidden: false - required: false diff --git a/murano_tempest_tests/extras/MockApp/logo.png b/murano_tempest_tests/extras/MockApp/logo.png deleted file mode 100644 index ab7ca2c462f034e5c45cf5f54b3fc2ad2e5196a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22607 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 ZKjp20<1OfnBbEN?s;Q<6EmyIA^M4%A93=n% diff --git a/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Classes/ApacheHttpServer.yaml b/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Classes/ApacheHttpServer.yaml deleted file mode 100644 index cd13ff970..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Classes/ApacheHttpServer.yaml +++ /dev/null @@ -1,81 +0,0 @@ -# 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. - -Namespaces: - =: io.murano.apps.test - std: io.murano - res: io.murano.resources - sys: io.murano.system - conf: io.murano.configuration - - -Name: ApacheHttpServerCustom - -Extends: std:Application - -Properties: - name: - Contract: $.string().notNull() - - instance: - Contract: $.class(res:Instance).notNull() - - userName: - Contract: $.string() - -Methods: - initialize: - Body: - - $._environment: $.find(std:Environment).require() - - deploy: - Body: - - If: not $.getAttr(deployed, false) - Then: - - $._environment.reporter.report($this, 'Creating VM for Apache Server.') - - $securityGroupIngress: - - ToPort: 80 - FromPort: 80 - IpProtocol: tcp - External: true - - ToPort: 443 - FromPort: 443 - IpProtocol: tcp - External: true - - $._environment.securityGroupManager.addGroupIngress($securityGroupIngress) - - $.instance.deploy() - - $._environment.reporter.report($this, 'Instance is created. Deploying Apache') - - - $resources: new(sys:Resources) - - $linux: new(conf:Linux) - - - $linux.runCommand($.instance.agent, 'apt-get -y install apache2') - - $linux.runCommand($.instance.agent, 'iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT') - - $linux.runCommand($.instance.agent, 'iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT') - - $._environment.reporter.report($this, 'Apache is installed.') - - - If: $.userName != '' - Then: - - $linux.runCommand($.instance.agent, 'service apache2 stop') - - $fileReplacements: - "%USER_NAME%": $.userName - - $fileContent: $resources.string('index.html').replace($fileReplacements) - - $linux.putFile($.instance.agent, $fileContent, '/var/www/html/index.html') - - $linux.runCommand($.instance.agent, 'service apache2 start') - - - If: $.instance.assignFloatingIp - Then: - - $host: $.instance.floatingIpAddress - Else: - - $host: $.instance.ipAddresses[0] - - $._environment.reporter.report($this, format('Apache is available at http://{0}', $host)) - - $.setAttr(deployed, true) diff --git a/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Resources/index.html b/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Resources/index.html deleted file mode 100644 index 68436975b..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/Resources/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - Hello World - -Hello world. This is my first web page. My name is %USER_NAME%. - - diff --git a/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/manifest.yaml b/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/manifest.yaml deleted file mode 100644 index b0ab7c3d7..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.ApacheHttpServerCustom/manifest.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# 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. - -Format: 1.0 -Type: Application -FullName: io.murano.test.apache.ApacheHttpServerCustom -Name: Apache HTTP Server Custom -Description: | - The Apache HTTP Server Project is an effort to develop and maintain an - open-source HTTP server for modern operating systems including UNIX and - Windows NT. The goal of this project is to provide a secure, efficient and - extensible server that provides HTTP services in sync with the current HTTP - standards. - Apache httpd has been the most popular web server on the Internet since - April 1996, and celebrated its 17th birthday as a project this February. -Author: 'Mirantis, Inc' -Tags: [HTTP, Server, WebServer, HTML, Apache] -Classes: - io.murano.apps.test.ApacheHttpServerCustom: ApacheHttpServer.yaml diff --git a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Classes/Lighttpd.yaml b/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Classes/Lighttpd.yaml deleted file mode 100644 index c719f1204..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Classes/Lighttpd.yaml +++ /dev/null @@ -1,55 +0,0 @@ -# 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. - -Namespaces: - =: io.murano.apps.test - std: io.murano - sys: io.murano.system - -Name: Lighttpd - -Extends: std:Application - -Properties: - updater: - Contract: $.class(UpdateExecutor).notNull() - -Methods: - initialize: - Body: - - $._environment: $.find(std:Environment).require() - - deploy: - Body: - - If: not $.getAttr(deployed, false) - Then: - - $securityGroupIngress: - - ToPort: 80 - FromPort: 80 - IpProtocol: tcp - External: true - - ToPort: 443 - FromPort: 443 - IpProtocol: tcp - External: true - - $._environment.securityGroupManager.addGroupIngress($securityGroupIngress) - - $._environment.reporter.report($this, 'Ensuring Updater is deployed.') - - $.updater.deploy() - - $resources: new(sys:Resources) - - $template: $resources.yaml('DeployLighttpd.template') - - $.updater.instance.agent.call($template, $resources) - - - If: $.updater.instance.assignFloatingIp - Then: - - $address: $.updater.instance.floatingIpAddress - - $._environment.reporter.report($this, format('Running at http://{0}', $address)) - - $.setAttr(deployed, true) diff --git a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/DeployLighttpd.template b/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/DeployLighttpd.template deleted file mode 100644 index 7eba0d5a6..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/DeployLighttpd.template +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -FormatVersion: 2.0.0 -Version: 1.0.0 -Name: Deploy Lighttpd - -Body: | - deploy() - -Scripts: - deploy: - Type: Application - Version: 1.0.0 - EntryPoint: deployLighttpd.sh - Options: - captureStdout: true - captureStderr: true diff --git a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/scripts/deployLighttpd.sh b/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/scripts/deployLighttpd.sh deleted file mode 100644 index 09dcd46b6..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/Resources/scripts/deployLighttpd.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# 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. - -sudo apt-get -y -q install lighttpd diff --git a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/manifest.yaml b/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/manifest.yaml deleted file mode 100644 index 5bdb9029f..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.Lighttpd/manifest.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - -Format: 1.0 -Type: Application -FullName: io.murano.apps.test.Lighttpd -Name: Lighttpd -Description: | - Lighttpd... :) -Author: 'Mirantis, Inc' -Tags: [Web] -Classes: - io.murano.apps.test.Lighttpd: Lighttpd.yaml -Require: - io.murano.apps.test.UpdateExecutor: diff --git a/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Classes/UpdateExecutor.yaml b/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Classes/UpdateExecutor.yaml deleted file mode 100644 index fd47e8854..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Classes/UpdateExecutor.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# 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. - -Namespaces: - =: io.murano.apps.test - std: io.murano - res: io.murano.resources - sys: io.murano.system - conf: io.murano.configuration - - -Name: UpdateExecutor - -Extends: std:Application - -Properties: - name: - Contract: $.string().notNull() - - instance: - Contract: $.class(res:Instance).notNull() - -Methods: - initialize: - Body: - - $._environment: $.find(std:Environment).require() - - deploy: - Body: - - If: not $.getAttr(deployed, false) - Then: - - $._environment.reporter.report($this, 'Creating VM.') - - $.instance.deploy() - - $._environment.reporter.report($this, 'Starting packages updating.') - - $file: sys:Resources.string('scripts/update.sh') - - conf:Linux.runCommand($.instance.agent, $file) - - $._environment.reporter.report($this, 'Update completed.') - - $.setAttr(deployed, true) diff --git a/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Resources/scripts/update.sh b/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Resources/scripts/update.sh deleted file mode 100644 index 28cddd559..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/Resources/scripts/update.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# 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. - -sudo apt-get update diff --git a/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/manifest.yaml b/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/manifest.yaml deleted file mode 100644 index 49137b479..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.UpdateExecutor/manifest.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# 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. - -Format: 1.0 -Type: Application -FullName: io.murano.apps.test.UpdateExecutor -Name: Update Executor -Description: | - Test application, which updates packages on VM -Author: 'Mirantis, Inc' -Tags: [application] -Classes: - io.murano.apps.test.UpdateExecutor: UpdateExecutor.yaml diff --git a/murano_tempest_tests/extras/io.murano.apps.test.VM/Classes/VM.yaml b/murano_tempest_tests/extras/io.murano.apps.test.VM/Classes/VM.yaml deleted file mode 100644 index 478229462..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.VM/Classes/VM.yaml +++ /dev/null @@ -1,66 +0,0 @@ -# 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. - -Namespaces: - =: io.murano.apps.test - std: io.murano - res: io.murano.resources - sys: io.murano.system - conf: io.murano.configuration - - -Name: VM - -Extends: std:Application - -Properties: - name: - Contract: $.string().notNull() - - instance: - Contract: $.class(res:Instance).notNull() - - userName: - Contract: $.string() - -Methods: - initialize: - Body: - - $._environment: $.find(std:Environment).require() - - deploy: - Body: - - If: not $.getAttr(deployed, false) - Then: - - $._environment.reporter.report($this, 'Creating VM') - - $securityGroupIngress: - - ToPort: 80 - FromPort: 80 - IpProtocol: tcp - External: true - - ToPort: 443 - FromPort: 443 - IpProtocol: tcp - External: true - - $._environment.securityGroupManager.addGroupIngress($securityGroupIngress) - - $.instance.deploy() - - $._environment.reporter.report($this, 'Instance is created.') - - - $resources: new(sys:Resources) - - $linux: new(conf:Linux) - - - If: $.instance.assignFloatingIp - Then: - - $host: $.instance.floatingIpAddress - Else: - - $host: $.instance.ipAddresses[0] - - $.setAttr(deployed, true) diff --git a/murano_tempest_tests/extras/io.murano.apps.test.VM/Resources/index.html b/murano_tempest_tests/extras/io.murano.apps.test.VM/Resources/index.html deleted file mode 100644 index 68436975b..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.VM/Resources/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - Hello World - -Hello world. This is my first web page. My name is %USER_NAME%. - - diff --git a/murano_tempest_tests/extras/io.murano.apps.test.VM/manifest.yaml b/murano_tempest_tests/extras/io.murano.apps.test.VM/manifest.yaml deleted file mode 100644 index 7b1a21c5f..000000000 --- a/murano_tempest_tests/extras/io.murano.apps.test.VM/manifest.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# 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. - -Format: 1.0 -Type: Application -FullName: io.murano.test.VM.VM -Name: VM -Description: | - application which simply boot a virtual machine -Author: 'Mirantis, Inc' -Tags: [Server] -Classes: - io.murano.apps.test.VM: VM.yaml diff --git a/murano_tempest_tests/plugin.py b/murano_tempest_tests/plugin.py deleted file mode 100644 index 9231b0931..000000000 --- a/murano_tempest_tests/plugin.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -import os - -from tempest import config -from tempest.test_discover import plugins - -from murano_tempest_tests import config as config_application_catalog - - -class MuranoTempestPlugin(plugins.TempestPlugin): - def load_tests(self): - base_path = os.path.split(os.path.dirname( - os.path.abspath(__file__)))[0] - test_dir = "murano_tempest_tests/tests" - full_test_dir = os.path.join(base_path, test_dir) - return full_test_dir, base_path - - def register_opts(self, conf): - config.register_opt_group( - conf, config.service_available_group, - config_application_catalog.service_option) - config.register_opt_group( - conf, config_application_catalog.application_catalog_group, - config_application_catalog.ApplicationCatalogGroup) - config.register_opt_group( - conf, config_application_catalog.service_broker_group, - config_application_catalog.ServiceBrokerGroup) - config.register_opt_group( - conf, config_application_catalog.artifacts_group, - config_application_catalog.ArtifactsGroup) - - def get_opt_lists(self): - return [(config_application_catalog.application_catalog_group.name, - config_application_catalog.ApplicationCatalogGroup), - (config_application_catalog.service_broker_group.name, - config_application_catalog.ServiceBrokerGroup), - (config.service_available_group.name, - config_application_catalog.service_option), - (config_application_catalog.artifacts_group.name, - config_application_catalog.ArtifactsGroup)] diff --git a/murano_tempest_tests/services/__init__.py b/murano_tempest_tests/services/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/services/application_catalog/__init__.py b/murano_tempest_tests/services/application_catalog/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/services/application_catalog/application_catalog_client.py b/murano_tempest_tests/services/application_catalog/application_catalog_client.py deleted file mode 100644 index 372185018..000000000 --- a/murano_tempest_tests/services/application_catalog/application_catalog_client.py +++ /dev/null @@ -1,449 +0,0 @@ -# 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. - -import json -import os - -import requests -from tempest import config -from tempest.lib.common import rest_client - -from murano_tempest_tests import utils - -CONF = config.CONF - - -class ApplicationCatalogClient(rest_client.RestClient): - """Tempest REST client for Murano Application Catalog""" - - def __init__(self, auth_provider): - super(ApplicationCatalogClient, self).__init__( - auth_provider, - CONF.application_catalog.catalog_type, - CONF.identity.region, - endpoint_type=CONF.application_catalog.endpoint_type) - self.build_interval = CONF.application_catalog.build_interval - self.build_timeout = CONF.application_catalog.build_timeout - -# -----------------------------Packages methods-------------------------------- - def upload_package(self, package_name, package_path, top_dir, body): - """Upload a Murano package into Murano repository - - :param package_name: Package name - :param package_path: Path with .zip relatively top_dir - :param top_dir: Top directory with tests - :param body: dict of tags, parameters, etc - :return: - """ - headers = {'X-Auth-Token': self.auth_provider.get_token()} - files = open(os.path.join(top_dir, package_path), 'rb') - uri = "/v1/catalog/packages" - post_body = {'JsonString': json.dumps(body)} - endpoint = self.base_url - url = endpoint + uri - resp = requests.post(url, files={package_name: files}, data=post_body, - headers=headers, timeout=self.build_timeout) - self.expected_success(200, resp.status_code) - return self._parse_resp(resp.text) - - def update_package(self, package_id, post_body): - headers = { - 'content-type': 'application/murano-packages-json-patch' - } - - uri = 'v1/catalog/packages/{0}'.format(package_id) - resp, body = self.patch(uri, json.dumps(post_body), headers=headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_package(self, package_id): - """Removes a package from a repository - - :param package_id: Package ID - """ - uri = 'v1/catalog/packages/{0}'.format(package_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - - def get_package(self, package_id): - uri = 'v1/catalog/packages/{0}'.format(package_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_list_packages(self): - uri = 'v1/catalog/packages' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def download_package(self, package_id): - headers = { - 'content-type': 'application/octet-stream' - } - uri = 'v1/catalog/packages/{0}/download'.format(package_id) - resp, body = self.get(uri, headers=headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_ui_definition(self, package_id): - headers = { - 'content-type': 'application/octet-stream' - } - uri = 'v1/catalog/packages/{0}/ui'.format(package_id) - resp, body = self.get(uri, headers=headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_logo(self, package_id): - headers = { - 'content-type': 'application/octet-stream' - } - uri = 'v1/catalog/packages/{0}/ui'.format(package_id) - resp, body = self.get(uri, headers=headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - -# -----------------------Methods for environment CRUD-------------------------- - def get_environments_list(self): - uri = 'v1/environments' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - - return self._parse_resp(body) - - def create_environment(self, name): - uri = 'v1/environments' - post_body = {'name': name} - resp, body = self.post(uri, json.dumps(post_body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_environment(self, environment_id): - uri = 'v1/environments/{0}'.format(environment_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - - def abandon_environment(self, environment_id): - uri = 'v1/environments/{0}?abandon=True'.format(environment_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - - def update_environment(self, environment_id): - uri = 'v1/environments/{0}'.format(environment_id) - name = utils.generate_name("updated_env") - post_body = {"name": name} - resp, body = self.put(uri, json.dumps(post_body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_environment(self, environment_id): - uri = 'v1/environments/{0}'.format(environment_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_environment_model(self, environment_id, path='/', session_id=None): - headers = self.get_headers() - if session_id: - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = '/v1/environments/{id}/model/{path}'.format( - id=environment_id, path=path) - resp, body = self.get(uri, headers=headers) - self.expected_success(200, resp.status) - return json.loads(body) - - def update_environment_model(self, environment_id, data, session_id): - headers = self.get_headers(send_type='env-model-json-patch') - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = '/v1/environments/{id}/model/'.format(id=environment_id) - resp, body = self.patch(uri, json.dumps(data), headers=headers) - self.expected_success(200, resp.status) - return json.loads(body) - -# -----------------------Methods for session manage --------------------------- - def create_session(self, environment_id): - body = None - uri = 'v1/environments/{0}/configure'.format(environment_id) - resp, body = self.post(uri, body) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_session(self, environment_id, session_id): - uri = 'v1/environments/{0}/sessions/{1}'.format(environment_id, - session_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_session(self, environment_id, session_id): - uri = 'v1/environments/{0}/sessions/{1}'.format(environment_id, - session_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def deploy_session(self, environment_id, session_id): - body = None - url = 'v1/environments/{0}/sessions/{1}/deploy'.format(environment_id, - session_id) - resp, body = self.post(url, body) - self.expected_success(200, resp.status) - return self._parse_resp(body) - -# ----------------------------Deployment methods------------------------------- - - def list_deployments(self, environment_id): - uri = 'v1/environments/{0}/deployments'.format( - environment_id) - body = None - - resp, body = self.get(uri, body) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def list_deployment_statuses(self, environment_id, deployment_id): - uri = 'v1/environments/{0}/deployments/{1}'.format( - environment_id, deployment_id) - body = None - - resp, body = self.get(uri, body) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def list_all_deployments(self): - uri = 'v1/deployments' - body = None - - resp, body = self.get(uri, body) - self.expected_success(200, resp.status) - return self._parse_resp(body) - -# -----------------------------Service methods--------------------------------- - def create_service(self, environment_id, session_id, post_body): - headers = self.get_headers() - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = 'v1/environments/{0}/services'.format(environment_id) - resp, body = self.post(uri, json.dumps(post_body), headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def update_services(self, environment_id, session_id, put_body=None): - headers = self.get_headers() - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = 'v1/environments/{0}/services'.format(environment_id) - resp, body = self.put(uri, json.dumps(put_body), headers) - self.expected_success(200, resp.status) - # TODO(freerunner): Need to replace json.loads() to _parse_resp - # method, when fix for https://bugs.launchpad.net/tempest/+bug/1539927 - # will resolved and new version of tempest-lib released. - return json.loads(body) - - def delete_service(self, environment_id, session_id, service_id): - headers = self.get_headers() - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = 'v1/environments/{0}/services/{1}'.format(environment_id, - service_id) - resp, body = self.delete(uri, headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_services_list(self, environment_id, session_id=None): - headers = self.get_headers() - if session_id: - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = 'v1/environments/{0}/services'.format(environment_id) - resp, body = self.get(uri, headers) - self.expected_success(200, resp.status) - # TODO(freerunner): Need to replace json.loads() to _parse_resp - # method, when fix for https://bugs.launchpad.net/tempest/+bug/1539927 - # will resolved and new version of tempest-lib released. - return json.loads(body) - - def get_service(self, environment_id, service_id, session_id=None): - headers = self.get_headers() - if session_id: - headers.update( - {'X-Configuration-Session': session_id} - ) - uri = 'v1/environments/{0}/services/{1}'.format(environment_id, - service_id) - resp, body = self.get(uri, headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - -# -----------------------------Category methods-------------------------------- - def list_categories(self): - uri = 'v1/catalog/categories' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_category(self, name): - body = {'name': name} - uri = 'v1/catalog/categories' - resp, body = self.post(uri, json.dumps(body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_category(self, category_id): - uri = 'v1/catalog/categories/{0}'.format(category_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_category(self, category_id): - uri = 'v1/catalog/categories/{0}'.format(category_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - -# ----------------------Environment templates methods-------------------------- - def get_env_templates_list(self): - uri = 'v1/templates' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_public_env_templates_list(self): - uri = 'v1/templates?is_public=true' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_private_env_templates_list(self): - uri = 'v1/templates?is_public=false' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_env_template(self, env_template_name): - body = {'name': env_template_name, "is_public": False, - "description_text": "description"} - uri = 'v1/templates' - resp, body = self.post(uri, json.dumps(body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def clone_env_template(self, env_template_id, cloned_env_template_name): - body = {'name': cloned_env_template_name} - uri = 'v1/templates/{0}/clone'.format(env_template_id) - resp, body = self.post(uri, json.dumps(body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_public_env_template(self, env_template_name): - body = {'name': env_template_name, "is_public": True} - uri = 'v1/templates' - resp, body = self.post(uri, json.dumps(body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_env_template_with_services(self, env_template_name, post_body): - body = { - 'name': env_template_name, - 'services': [post_body] - } - uri = 'v1/templates' - resp, body = self.post(uri, json.dumps(body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_service_in_env_template(self, env_template_id, post_body): - uri = 'v1/templates/{0}/services'.format(env_template_id) - resp, body = self.post(uri, json.dumps(post_body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_services_list_in_env_template(self, env_template_id): - uri = 'v1/templates/{0}/services'.format(env_template_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - # TODO(freerunner): Need to replace json.loads() to _parse_resp - # method, when fix for https://bugs.launchpad.net/tempest/+bug/1539927 - # will resolved and new version of tempest-lib released. - return json.loads(body) - - def get_service_in_env_template(self, env_template_name, service_id): - uri = 'v1/templates/{0}/services/{1}'.format(env_template_name, - service_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return json.loads(body) - - def update_service_from_env_template(self, env_template_id, service_id, - post_body): - uri = 'v1/templates/{0}/services/{1}'.format(env_template_id, - service_id) - resp, body = self.put(uri, json.dumps(post_body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_service_from_env_template(self, env_template_name, service_id): - uri = 'v1/templates/{0}/services/{1}'.format(env_template_name, - service_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_env_template(self, env_template_id): - uri = 'v1/templates/{0}'.format(env_template_id) - resp, body = self.delete(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_env_template(self, env_template_id): - uri = 'v1/templates/{0}'.format(env_template_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_env_from_template(self, env_template_id, env_name): - body = {'name': env_name} - uri = 'v1/templates/{0}/create-environment'.format(env_template_id) - resp, body = self.post(uri, json.dumps(body)) - self.expected_success(200, resp.status) - return self._parse_resp(body) - -# ----------------------------Static action methods---------------------------- - def call_static_action(self, class_name=None, method_name=None, args=None, - package_name=None, class_version="=0"): - uri = 'v1/actions' - post_body = { - 'parameters': args or {}, - 'packageName': package_name, - 'classVersion': class_version - } - if class_name: - post_body['className'] = class_name - if method_name: - post_body['methodName'] = method_name - - resp, body = self.post(uri, json.dumps(post_body)) - self.expected_success(200, resp.status) - # _parse_resp() cannot be used because body is expected to be string - return body diff --git a/murano_tempest_tests/services/artifacts/__init__.py b/murano_tempest_tests/services/artifacts/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/services/artifacts/artifacts_client.py b/murano_tempest_tests/services/artifacts/artifacts_client.py deleted file mode 100644 index 789497b54..000000000 --- a/murano_tempest_tests/services/artifacts/artifacts_client.py +++ /dev/null @@ -1,157 +0,0 @@ -# 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 -import os - -from tempest import config -from tempest.lib.common import rest_client - -from murano_tempest_tests import utils - -CONF = config.CONF - - -class ArtifactsClient(rest_client.RestClient): - """Tempest REST client for Glance Artifacts""" - - def __init__(self, auth_provider): - super(ArtifactsClient, self).__init__( - auth_provider, - CONF.artifacts.catalog_type, - CONF.identity.region, - endpoint_type=CONF.artifacts.endpoint_type) - self.build_interval = CONF.artifacts.build_interval - self.build_timeout = CONF.artifacts.build_timeout - -# -----------------------------Artifacts methods------------------------------- - - def list_artifacts(self): - uri = 'v0.1/artifacts/murano/v1' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - parsed = self._parse_resp(body) - return parsed['artifacts'] - - def list_drafts(self): - uri = 'v0.1/artifacts/murano/v1/creating' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def list_deactivated_drafts(self): - uri = 'v0.1/artifacts/murano/v1/deactivated' - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def create_artifact_draft(self, name, version, **kwargs): - 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) - return self._parse_resp(body) - - def publish_artifact(self, artifact_id): - uri = 'v0.1/artifacts/murano/v1/{0}/publish'.format(artifact_id) - resp, body = self.post(uri, body='') - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def get_artifact(self, artifact_id): - uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def update_artifact(self, artifact_id, body): - headers = { - 'Content-Type': 'application/openstack-images-v2.1-json-patch'} - uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id) - resp, body = self.patch(uri, json.dumps(body), headers=headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def delete_artifact(self, artifact_id): - uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return self._parse_resp(body) - - def upload_blob(self, artifact_id, blob_type, data): - headers = {'Content-Type': 'application/octet-stream'} - uri = 'v0.1/artifacts/murano/v1/{0}/{1}'.format( - artifact_id, blob_type) - resp, body = self.put(uri, data, headers=headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def download_blob(self, artifact_id, blob_type): - uri = 'v0.1/artifacts/murano/v1/{0}/{1}/download'.format( - artifact_id, blob_type) - 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 body.items(): - 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 diff --git a/murano_tempest_tests/services/service_broker/__init__.py b/murano_tempest_tests/services/service_broker/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/services/service_broker/service_broker_client.py b/murano_tempest_tests/services/service_broker/service_broker_client.py deleted file mode 100644 index 04132375b..000000000 --- a/murano_tempest_tests/services/service_broker/service_broker_client.py +++ /dev/null @@ -1,108 +0,0 @@ -# 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. - -import base64 -import json - -from tempest import config -from tempest.lib.common import rest_client - -from murano_tempest_tests import utils - -CONF = config.CONF - - -class ServiceBrokerClient(rest_client.RestClient): - """Tempest REST client for Murano Service Broker""" - - def __init__(self, auth_provider): - super(ServiceBrokerClient, self).__init__( - auth_provider, - CONF.service_broker.catalog_type, - CONF.identity.region, - endpoint_type=CONF.service_broker.endpoint_type) - self.build_interval = CONF.service_broker.build_interval - self.build_timeout = CONF.service_broker.build_timeout - self.headers = self._generate_headers(auth_provider) - - @classmethod - def _generate_headers(cls, auth_provider): - """Generate base64-encoded auth string for murano-cfapi - - :param auth_provider: - :return: headers - """ - uname = auth_provider.credentials.username - pwd = auth_provider.credentials.password - - encoded_auth = base64.b64encode('{0}:{1}'.format(uname, pwd)) - headers = {"Authorization": "Basic " + encoded_auth, - 'content-type': 'application/json'} - return headers - - def get_applications_list(self): - """Get list of all available applications""" - uri = "/v2/catalog" - resp, body = self.get(uri, headers=self.headers) - self.expected_success(200, resp.status) - return self._parse_resp(body) - - def provision(self, instance_id, service_id, plan_id, space_id, post_json): - """Create new service resources for developer""" - uri = '/v2/service_instances/{0}?accepts_incomplete=true'.\ - format(instance_id) - body = { - 'service_id': service_id, - 'plan_id': plan_id, - 'organization_guid': self.tenant_id, - 'space_guid': space_id, - 'parameters': post_json - } - body = json.dumps(body) - resp, body = self.put(uri, body, headers=self.headers) - self.expected_success([200, 202], resp.status) - return body - - def deprovision(self, instance_id): - uri = '/v2/service_instances/{0}?accepts_incomplete=true'.\ - format(instance_id) - resp, body = self.delete(uri, headers=self.headers) - self.expected_success(202, resp.status) - return body - - def get_last_status(self, instance_id): - uri = '/v2/service_instances/{0}/last_operation'.format(instance_id) - resp, body = self.get(uri, headers=self.headers) - self.expected_success([200, 202], resp.status) - return self._parse_resp(body) - - def get_application(self, name, app_list): - for app in app_list: - if app['name'] == name: - return app - - def create_binding(self, instance_id): - binding_id = utils.generate_uuid() - uri = "/v2/service_instances/{0}/service_bindings/{1}".format( - instance_id, binding_id) - post_body = { - "plan_id": utils.generate_uuid(), - "service_id": utils.generate_uuid(), - "app_guid": utils.generate_uuid() - } - body = json.dumps(post_body) - resp, body = self.put(uri, body, headers=self.headers) - self.expected_success([200, 201], resp.status) - return self._parse_resp(body) diff --git a/murano_tempest_tests/tests/__init__.py b/murano_tempest_tests/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/api/__init__.py b/murano_tempest_tests/tests/api/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/api/application_catalog/__init__.py b/murano_tempest_tests/tests/api/application_catalog/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/api/application_catalog/artifacts/__init__.py b/murano_tempest_tests/tests/api/application_catalog/artifacts/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/api/application_catalog/artifacts/base.py b/murano_tempest_tests/tests/api/application_catalog/artifacts/base.py deleted file mode 100644 index e7d993cf5..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/artifacts/base.py +++ /dev/null @@ -1,97 +0,0 @@ -# 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 import config -from tempest import test - -from murano_tempest_tests import clients -from murano_tempest_tests import utils - -CONF = config.CONF - - -class BaseArtifactsTest(test.BaseTestCase): - """Base test class for Murano Glare tests.""" - - @classmethod - def skip_checks(cls): - super(BaseArtifactsTest, cls).skip_checks() - if not CONF.service_available.murano: - skip_msg = "Murano is disabled" - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(BaseArtifactsTest, cls).setup_clients() - if not hasattr(cls, "os_primary"): - creds = cls.get_configured_isolated_creds(type_of_creds='primary') - cls.os_primary = clients.Manager(credentials=creds) - cls.artifacts_client = cls.os_primary.artifacts_client - cls.application_catalog_client = \ - cls.os_primary.application_catalog_client - - @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.credentials = common_creds.get_credentials_provider( - name=cls.__name__, - force_tenant_isolation=CONF.auth.use_dynamic_credentials, - identity_version=CONF.identity.auth_version) - if type_of_creds == 'primary': - creds = cls.credentials.get_primary_creds() - elif type_of_creds == 'admin': - creds = cls.credentials.get_admin_creds() - elif type_of_creds == 'alt': - creds = cls.credentials.get_alt_creds() - else: - creds = cls.credentials.get_credentials(type_of_creds) - cls.credentials.type_of_creds = type_of_creds - - return creds.credentials - - @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'] - } - } diff --git a/murano_tempest_tests/tests/api/application_catalog/artifacts/test_repository.py b/murano_tempest_tests/tests/api/application_catalog/artifacts/test_repository.py deleted file mode 100644 index 1b9a842e8..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/artifacts/test_repository.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators - -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() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('2818aaa0-6613-4bd9-8abe-02713121357a') - def test_get_list_packages(self): - package_list = self.artifacts_client.get_list_packages() - self.assertIsInstance(package_list, list) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('bc717c98-5f6b-42a6-9131-43a711cfe848') - 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}) diff --git a/murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning.py b/murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning.py deleted file mode 100644 index 61f791688..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning.py +++ /dev/null @@ -1,166 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators - -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 cls.packages.values(): - cls.artifacts_client.delete_package(pkg['id']) - map(os.remove, cls.abs_archive_paths) - super(TestVersioning, cls).resource_cleanup() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('03ee155c-d65f-4ea7-a00a-bdbc7105fc8b') - 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) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('15c3a52d-cffe-4d03-82c2-31c9be8423d6') - 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') - - @decorators.attr(type='smoke') - @decorators.idempotent_id('2c472476-f9cd-424b-91ee-cbc770602bf3') - 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') diff --git a/murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning_negative.py b/murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning_negative.py deleted file mode 100644 index 2279b1ecf..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/artifacts/test_versioning_negative.py +++ /dev/null @@ -1,96 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators - -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 cls.packages.values(): - cls.artifacts_client.delete_package(pkg['id']) - map(os.remove, cls.abs_archive_paths) - super(TestVersioningNegative, cls).resource_cleanup() - - @decorators.attr(type=['negative', 'smoke']) - @decorators.idempotent_id('c72fcd24-4694-4479-b550-bdd8cf0bd348') - 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') diff --git a/murano_tempest_tests/tests/api/application_catalog/base.py b/murano_tempest_tests/tests/api/application_catalog/base.py deleted file mode 100644 index 6dce950e3..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/base.py +++ /dev/null @@ -1,110 +0,0 @@ -# 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 import config -from tempest import test - -from murano_tempest_tests import clients -from murano_tempest_tests import utils - -CONF = config.CONF - - -class BaseApplicationCatalogTest(test.BaseTestCase): - """Base test class for Murano Service Broker API tests.""" - - @classmethod - def skip_checks(cls): - super(BaseApplicationCatalogTest, cls).skip_checks() - if not CONF.service_available.murano: - skip_msg = "Murano is disabled" - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(BaseApplicationCatalogTest, cls).setup_clients() - if not hasattr(cls, "os_primary"): - creds = cls.get_configured_isolated_creds(type_of_creds='primary') - cls.os_primary = clients.Manager(credentials=creds) - cls.application_catalog_client = \ - cls.os_primary.application_catalog_client - cls.artifacts_client = cls.os_primary.artifacts_client - - @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.application_catalog_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.credentials = common_creds.get_credentials_provider( - name=cls.__name__, - force_tenant_isolation=CONF.auth.use_dynamic_credentials, - identity_version=CONF.identity.auth_version) - if type_of_creds == 'primary': - creds = cls.credentials.get_primary_creds() - elif type_of_creds == 'admin': - creds = cls.credentials.get_admin_creds() - elif type_of_creds == 'alt': - creds = cls.credentials.get_alt_creds() - else: - creds = cls.credentials.get_credentials(type_of_creds) - cls.credentials.type_of_creds = type_of_creds - - return creds.credentials - - @staticmethod - def _get_demo_app(): - return { - "instance": { - "assignFloatingIp": "true", - "keyname": "mykeyname", - "image": "cloud-fedora-v3", - "flavor": "m1.medium", - "?": { - "type": "io.murano.resources.LinuxMuranoInstance", - "id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e" - } - }, - "name": "orion", - "port": "8080", - "?": { - "type": "io.murano.apps.apache.Tomcat", - "id": utils.generate_uuid() - } - } - - -class BaseApplicationCatalogIsolatedAdminTest(BaseApplicationCatalogTest): - - @classmethod - def setup_clients(cls): - super(BaseApplicationCatalogIsolatedAdminTest, cls).setup_clients() - if not hasattr(cls, "os_admin"): - creds = cls.get_configured_isolated_creds(type_of_creds='admin') - cls.os_admin = clients.Manager(credentials=creds) - cls.application_catalog_client = \ - cls.os_admin.application_catalog_client - cls.artifacts_client = cls.os_admin.artifacts_client diff --git a/murano_tempest_tests/tests/api/application_catalog/test_categories.py b/murano_tempest_tests/tests/api/application_catalog/test_categories.py deleted file mode 100644 index cbd486aca..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_categories.py +++ /dev/null @@ -1,113 +0,0 @@ -# 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 - -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestCategories(base.BaseApplicationCatalogIsolatedAdminTest): - - @classmethod - def resource_setup(cls): - super(TestCategories, cls).resource_setup() - application_name = utils.generate_name(cls.__name__) - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - cls.package = cls.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - name = utils.generate_name(cls.__name__) - cls.category = cls.application_catalog_client.create_category(name) - - @classmethod - def resource_cleanup(cls): - os.remove(cls.abs_archive_path) - cls.application_catalog_client.delete_package(cls.package['id']) - cls.application_catalog_client.delete_category(cls.category['id']) - super(TestCategories, cls).resource_cleanup() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('4785781d-4bea-4559-939e-1c2fdf0dbec3') - def test_list_categories(self): - categories_list = self.application_catalog_client.list_categories() - self.assertIsInstance(categories_list, list) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('c02841bc-3305-4e88-a733-696fb8690552') - def test_create_and_delete_category(self): - name = utils.generate_name('create_and_delete_category') - categories_list = self.application_catalog_client.list_categories() - category_names = [c['name'] for c in categories_list] - self.assertNotIn(name, category_names) - - category = self.application_catalog_client.create_category(name) - self.assertEqual(name, category['name']) - - categories_list = self.application_catalog_client.list_categories() - category_names = [c['name'] for c in categories_list] - self.assertIn(name, category_names) - - self.application_catalog_client.delete_category(category['id']) - categories_list = self.application_catalog_client.list_categories() - category_names = [c['name'] for c in categories_list] - self.assertNotIn(name, category_names) - - @decorators.idempotent_id('c7931b7f-e811-4555-8ecc-84bea7885d96') - def test_get_category(self): - category = self.application_catalog_client.get_category( - self.category['id']) - self.assertEqual(self.category['id'], category['id']) - self.assertEqual(self.category['name'], category['name']) - - @decorators.idempotent_id('9b92705a-4203-4f02-9d6b-abc797c0eaac') - def test_add_package_to_new_category_and_remove_it_from_category(self): - category = self.application_catalog_client.get_category( - self.category['id']) - self.assertEqual(0, category['package_count']) - - post_body = [ - { - "op": "add", - "path": "/categories", - "value": [category['name']] - } - ] - - package = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertIn(self.category['name'], package['categories']) - category = self.application_catalog_client.get_category( - self.category['id']) - self.assertEqual(1, category['package_count']) - self.assertEqual(1, len(category['packages'])) - - post_body = [ - { - "op": "remove", - "path": "/categories", - "value": [category['name']] - } - ] - - package = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertNotIn(self.category['name'], package['categories']) - category = self.application_catalog_client.get_category( - self.category['id']) - self.assertEqual(0, category['package_count']) - self.assertEqual(0, len(category['packages'])) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_categories_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_categories_negative.py deleted file mode 100644 index 4f5ecec3f..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_categories_negative.py +++ /dev/null @@ -1,72 +0,0 @@ -# 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 - -from tempest.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestCategoriesNegative(base.BaseApplicationCatalogIsolatedAdminTest): - - @classmethod - def resource_setup(cls): - super(TestCategoriesNegative, cls).resource_setup() - application_name = utils.generate_name(cls.__name__) - name = utils.generate_name(cls.__name__) - cls.category = cls.application_catalog_client.create_category(name) - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - cls.package = cls.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [cls.category['name']], - "tags": [], 'is_public': False}) - - @classmethod - def resource_cleanup(cls): - os.remove(cls.abs_archive_path) - cls.application_catalog_client.delete_package(cls.package['id']) - cls.application_catalog_client.delete_category(cls.category['id']) - super(TestCategoriesNegative, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('20fe075f-7d07-462e-bfbc-3032b5367207') - def test_delete_category_by_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_category, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('e655365b-ec8b-49da-8745-5c80b1f5e65b') - def test_get_category_by_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_category, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('c4948d0f-3530-419c-8017-1ee8bbc29dee') - def test_create_category_with_same_name(self): - self.assertRaises(exceptions.Conflict, - self.application_catalog_client.create_category, - self.category['name']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('2bdce780-96dc-46d6-a28e-cdcf768359ae') - def test_delete_category_with_package(self): - self.assertRaises(exceptions.Forbidden, - self.application_catalog_client.delete_category, - self.category['id']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_deployments.py b/murano_tempest_tests/tests/api/application_catalog/test_deployments.py deleted file mode 100644 index 4103e8ee0..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_deployments.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2017 AT&T Corporation. -# -# 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.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestDeployments(base.BaseApplicationCatalogTest): - - def _create_and_deploy_env_session(self): - name = utils.generate_name('_create_and_deploy_env_session') - environment = self.application_catalog_client.create_environment( - name) - self.addCleanup(self.application_catalog_client.delete_environment, - environment['id']) - session = self.application_catalog_client.create_session( - environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - environment['id'], session['id']) - self.application_catalog_client.deploy_session(environment['id'], - session['id']) - utils.wait_for_environment_deploy(self.application_catalog_client, - environment['id']) - return environment - - @decorators.idempotent_id('ea4f6f21-bd97-4b58-af93-6fe5417543f9') - def test_list_all_deployments(self): - # Given two environments with deployments - environment1 = self._create_and_deploy_env_session() - environment2 = self._create_and_deploy_env_session() - - # When list_all_deployments is called - deployments = self.application_catalog_client.list_all_deployments() - - # Then both environment's deployments are returned - self.assertEqual(2, len(deployments)) - environment_ids = [d['environment_id'] for d in deployments] - self.assertIn(environment1['id'], environment_ids) - self.assertIn(environment2['id'], environment_ids) - - @decorators.idempotent_id('d76706f6-9281-4fdc-9758-57da825311b1') - def test_list_deployments(self): - # Given two environments with deployments - environment1 = self._create_and_deploy_env_session() - self._create_and_deploy_env_session() - - # When list_deployments is called for first environment - deployments = self.application_catalog_client.list_deployments( - environment1['id']) - - # Then only the first environment's deployment is returned - self.assertEqual(1, len(deployments)) - first_deployment = deployments[0] - self.assertEqual(environment1['id'], - first_deployment['environment_id']) - - @decorators.idempotent_id('d6fbba34-92a9-49b3-9c49-e4b7a65eb6e8') - def test_list_deployment_statuses(self): - # Given an environment with a deployment - environment = self._create_and_deploy_env_session() - deployment = self.application_catalog_client.list_deployments( - environment['id'])[0] - - # When list_deployment_statuses is called - statuses = self.application_catalog_client.list_deployment_statuses( - environment['id'], deployment['id']) - - # Then the correct statuses for the deployment are returned - status_deployment_ids = set([s['task_id'] for s in statuses]) - self.assertEqual([deployment['id']], list(status_deployment_ids)) - status_texts = [s['text'] for s in statuses] - self.assertEqual(['Action deploy is scheduled', 'Deployment finished'], - sorted(status_texts)) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_env_templates.py b/murano_tempest_tests/tests/api/application_catalog/test_env_templates.py deleted file mode 100644 index 436747a29..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_env_templates.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright (c) 2015 Telefonica I+D. -# 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. - -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestEnvironmentTemplatesSanity(base.BaseApplicationCatalogTest): - - @decorators.idempotent_id('c13f9799-ed80-463f-8275-6bba62933226') - def test_list_empty_env_templates(self): - templates_list = self.application_catalog_client.\ - get_env_templates_list() - self.assertIsInstance(templates_list, list) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('15363b15-c350-40b9-a96b-de8d7a56a185') - def test_create_and_delete_env_template(self): - name = utils.generate_name('create_and_delete_env_template') - env_template = self.application_catalog_client.\ - create_env_template(name) - self.assertFalse(env_template['is_public']) - self.assertEqual(name, env_template['name']) - self.assertEqual("description", env_template['description_text']) - env_templates_list = self.application_catalog_client.\ - get_env_templates_list() - # Deleting dates from dictionaries to skip it in assert - env_template.pop('updated', None) - env_template.pop('created', None) - map(lambda x: x.pop('updated', None), env_templates_list) - map(lambda x: x.pop('created', None), env_templates_list) - self.assertIn(env_template, env_templates_list) - self.application_catalog_client.\ - delete_env_template(env_template['id']) - env_templates_list = self.application_catalog_client.\ - get_env_templates_list() - self.assertNotIn(env_template, env_templates_list) - - -class TestEnvironmentTemplates(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestEnvironmentTemplates, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.env_template = cls.application_catalog_client.\ - create_public_env_template(name) - cls.alt_client = cls.get_client_with_isolated_creds('alt') - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_env_template(cls.env_template['id']) - super(TestEnvironmentTemplates, cls).resource_cleanup() - - @decorators.idempotent_id('3821a826-2d14-4287-b56b-4a022bca9044') - def test_get_env_template(self): - env_template = self.application_catalog_client.\ - get_env_template(self.env_template['id']) - self.assertEqual(self.env_template['name'], env_template['name']) - - @decorators.idempotent_id('c7f77fa4-cdc3-45b7-a013-668668da0c8e') - def test_create_env_template_with_a_service(self): - name = utils.generate_name('create_env_template_with_service') - post_body = self._get_demo_app() - env_template = self.application_catalog_client.\ - create_env_template_with_services(name, post_body) - self.addCleanup(self.application_catalog_client.delete_env_template, - env_template['id']) - list_services = self.application_catalog_client.\ - get_services_list_in_env_template(env_template['id']) - self.assertIsInstance(list_services, list) - self.assertIn(post_body, list_services) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('be1be6c8-b882-4b17-9221-4b88c71d8d31') - def test_add_and_remove_service_in_env_templates(self): - env_template_services = self.application_catalog_client.\ - get_services_list_in_env_template(self.env_template['id']) - self.assertIsInstance(env_template_services, list) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service_in_env_template(self.env_template['id'], post_body) - self.assertEqual(post_body['name'], service['name']) - services = self.application_catalog_client.\ - get_services_list_in_env_template(self.env_template['id']) - self.assertIn(service, services) - self.application_catalog_client.\ - delete_service_from_env_template(self.env_template['id'], - service['?']['id']) - services = self.application_catalog_client.\ - get_services_list_in_env_template(self.env_template['id']) - self.assertNotIn(service, services) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('4c409154-f848-42b5-99e4-3d1352d0cf3f') - def test_update_service_in_env_templates(self): - env_template_services = self.application_catalog_client.\ - get_services_list_in_env_template(self.env_template['id']) - self.assertIsInstance(env_template_services, list) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service_in_env_template(self.env_template['id'], post_body) - self.assertEqual(post_body['name'], service['name']) - post_body["name"] = "updated_name" - service = self.application_catalog_client.\ - update_service_from_env_template(self.env_template['id'], - service["?"]["id"], - post_body) - self.assertEqual("updated_name", service['name']) - - @decorators.idempotent_id('1fe4b071-8c1f-434a-bb37-0712879df931') - def test_create_public_env_template(self): - name = utils.generate_name('create_public_env_template') - env_template = self.application_catalog_client.\ - create_public_env_template(name) - self.addCleanup(self.application_catalog_client.delete_env_template, - env_template['id']) - self.assertEqual(name, env_template['name']) - env_temp = self.application_catalog_client.\ - get_env_template(env_template['id']) - self.assertTrue(env_temp['is_public']) - - @decorators.idempotent_id('1c79c1dc-c4ff-42d7-9382-6d523f2d9f5b') - def test_clone_env_template(self): - name = utils.generate_name('clone_env_template') - cloned_template = self.alt_client.\ - clone_env_template(self.env_template['id'], name) - self.addCleanup(self.alt_client.delete_env_template, - cloned_template['id']) - self.assertEqual(name, cloned_template['name']) - template = self.alt_client.get_env_template(cloned_template['id']) - self.assertEqual(name, template['name']) - - @decorators.idempotent_id('98f889cf-de5e-4cda-a97e-f2eff3b471ce') - def test_get_public_private_both_env_templates(self): - name = utils.generate_name('get_public_private_both') - public_env_template = self.application_catalog_client.\ - create_public_env_template(name) - self.addCleanup(self.application_catalog_client.delete_env_template, - public_env_template['id']) - self.assertTrue(public_env_template['is_public']) - private_name = utils.generate_name('get_public_private_both') - private_env_template = self.application_catalog_client.\ - create_env_template(private_name) - self.addCleanup(self.application_catalog_client.delete_env_template, - private_env_template['id']) - self.assertFalse(private_env_template['is_public']) - private_name_alt = utils.generate_name('get_public_private_both') - private_alt_env_template = self.alt_client.\ - create_env_template(private_name_alt) - self.addCleanup(self.alt_client.delete_env_template, - private_alt_env_template['id']) - - public_env_templates = self.application_catalog_client.\ - get_public_env_templates_list() - - # Deleting dates from dictionaries to skip it in assert - map(lambda x: x.pop('updated', None), - public_env_templates + [public_env_template] + - [private_env_template] + [private_alt_env_template]) - map(lambda x: x.pop('created', None), - public_env_templates + [public_env_template] + - [private_env_template] + [private_alt_env_template]) - - self.assertIn(public_env_template, public_env_templates) - self.assertNotIn(private_env_template, public_env_templates) - self.assertNotIn(private_alt_env_template, public_env_templates) - - private_env_templates = self.application_catalog_client.\ - get_private_env_templates_list() - - # Deleting dates from dictionaries to skip it in assert - map(lambda x: x.pop('updated', None), private_env_templates) - map(lambda x: x.pop('created', None), private_env_templates) - - self.assertNotIn(public_env_template, private_env_templates) - self.assertIn(private_env_template, private_env_templates) - self.assertNotIn(private_alt_env_template, private_env_templates) - - env_templates = self.application_catalog_client.\ - get_env_templates_list() - - # Deleting dates from dictionaries to skip it in assert - map(lambda x: x.pop('updated', None), env_templates) - map(lambda x: x.pop('created', None), env_templates) - - self.assertIn(public_env_template, env_templates) - self.assertIn(private_env_template, env_templates) - self.assertNotIn(private_alt_env_template, env_templates) - - alt_pub_templates = self.alt_client.get_public_env_templates_list() - - # Deleting dates from dictionaries to skip it in assert - map(lambda x: x.pop('updated', None), alt_pub_templates) - map(lambda x: x.pop('created', None), alt_pub_templates) - - self.assertIn(public_env_template, alt_pub_templates) - self.assertNotIn(private_env_template, alt_pub_templates) - self.assertNotIn(private_alt_env_template, alt_pub_templates) - - alt_priv_templates = self.alt_client.get_private_env_templates_list() - - # Deleting dates from dictionaries to skip it in assert - map(lambda x: x.pop('updated', None), alt_priv_templates) - map(lambda x: x.pop('created', None), alt_priv_templates) - - self.assertNotIn(public_env_template, alt_priv_templates) - self.assertNotIn(private_env_template, alt_priv_templates) - self.assertIn(private_alt_env_template, alt_priv_templates) - - alt_env_templates = self.alt_client.get_env_templates_list() - - # Deleting dates from dictionaries to skip it in assert - map(lambda x: x.pop('updated', None), alt_env_templates) - map(lambda x: x.pop('created', None), alt_env_templates) - - self.assertIn(public_env_template, alt_env_templates) - self.assertNotIn(private_env_template, alt_env_templates) - self.assertIn(private_alt_env_template, alt_env_templates) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('f7524a15-a4ad-43a5-bcb2-784fd515eb59') - def test_create_env_from_template(self): - name = utils.generate_name('create_env_from_template') - env_template = self.application_catalog_client.\ - create_public_env_template(name) - self.addCleanup(self.application_catalog_client.delete_env_template, - env_template['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service_in_env_template(env_template['id'], post_body) - self.assertEqual(post_body['name'], service['name']) - env_name = utils.generate_name('create_env_from_template') - environment = self.application_catalog_client.\ - create_env_from_template(env_template['id'], env_name) - self.addCleanup(self.application_catalog_client.delete_environment, - environment['environment_id']) - self.assertIsNotNone(environment) - service_from_env = self.application_catalog_client.\ - get_service(environment['environment_id'], - service['?']['id'], - environment['session_id']) - self.assertEqual(service, service_from_env) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_env_templates_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_env_templates_negative.py deleted file mode 100644 index 85c6d0098..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_env_templates_negative.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright (c) 2015 Telefonica I+D. -# 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. - -from tempest.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestEnvironmentTemplatesNegative(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestEnvironmentTemplatesNegative, cls).resource_setup() - cls.name = utils.generate_name(cls.__name__) - cls.env_template = cls.application_catalog_client.\ - create_env_template(cls.name) - cls.environment = cls.application_catalog_client.\ - create_environment(cls.name) - cls.alt_client = cls.get_client_with_isolated_creds('alt') - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_env_template(cls.env_template['id']) - cls.application_catalog_client.delete_environment( - cls.environment['id']) - super(TestEnvironmentTemplatesNegative, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('022d0889-c5b3-4853-934f-533b43dfa89f') - def test_clone_env_template_private(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.clone_env_template, - self.env_template['id'], 'cloned_template') - - @decorators.attr(type='negative') - @decorators.idempotent_id('1132afa7-6965-4f48-a4ed-aeedba25ad8c') - def test_delete_environment_with_wrong_env_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_env_template, - None) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a344b0be-d07d-4dfe-916d-900d93e44425') - def test_create_environment_with_wrong_payload(self): - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.create_env_template, - ' ') - - @decorators.attr(type='negative') - @decorators.idempotent_id('fa2efa91-75c0-430f-942d-f52fe208cb16') - def test_double_delete_env_template(self): - name = utils.generate_name('double_delete_env_template') - env_template = self.application_catalog_client.\ - create_env_template(name) - self.application_catalog_client.delete_env_template( - env_template['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_env_template, - env_template['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('3641cfa9-e74e-4e74-af09-6d0c7d4634fc') - def test_get_deleted_env_template(self): - name = utils.generate_name('get_deleted_env_template') - env_template = self.application_catalog_client.\ - create_env_template(name) - self.application_catalog_client.delete_env_template( - env_template['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_env_template, - env_template['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('106fe373-8232-4fb4-870f-290ffa3b475b') - def test_create_environment_template_with_same_name(self): - self.assertRaises(exceptions.Conflict, - self.application_catalog_client.create_env_template, - self.name) - - @decorators.attr(type='negative') - @decorators.idempotent_id('07f56f09-3ca4-4d2a-8713-6306f2c3c4f8') - def test_create_env_from_template_witch_existing_name(self): - self.assertRaises(exceptions.Conflict, - self.application_catalog_client. - create_env_from_template, - self.env_template['id'], - self.name) - - -class TestEnvTemplatesTenantIsolation(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestEnvTemplatesTenantIsolation, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.env_template = cls.application_catalog_client.\ - create_env_template(name) - cls.alt_client = cls.get_client_with_isolated_creds('alt') - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_env_template(cls.env_template['id']) - super(TestEnvTemplatesTenantIsolation, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('bdf6febf-51aa-4b0a-b0e8-645e4df2531c') - def test_get_env_template_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_env_template, - self.env_template['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('b664b388-489f-4036-918a-18fa34a2a04e') - def test_delete_env_template_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.delete_env_template, - self.env_template['id']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_environments.py b/murano_tempest_tests/tests/api/application_catalog/test_environments.py deleted file mode 100644 index 6aabcb707..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_environments.py +++ /dev/null @@ -1,128 +0,0 @@ -# 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. - -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestEnvironments(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestEnvironments, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestEnvironments, cls).resource_cleanup() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('32f26f2e-6c55-4e83-9d8c-023d86299d3e') - def test_list_environments(self): - environments_list = self.application_catalog_client.\ - get_environments_list() - self.assertIsInstance(environments_list, list) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('a4c0b2fd-2c1b-473c-80cc-d433ceec4c80') - def test_create_and_delete_environment(self): - environments_list = self.application_catalog_client.\ - get_environments_list() - name = utils.generate_name('create_and_delete_env') - environment = self.application_catalog_client.create_environment(name) - self.assertEqual(name, environment['name']) - upd_environments_list = self.application_catalog_client.\ - get_environments_list() - self.assertEqual(len(environments_list) + 1, - len(upd_environments_list)) - self.application_catalog_client.delete_environment(environment['id']) - upd_environments_list = self.application_catalog_client.\ - get_environments_list() - self.assertEqual(len(environments_list), - len(upd_environments_list)) - - @decorators.idempotent_id('52a06d5f-69e4-4184-a127-1bb13ce6dc7c') - def test_create_and_delete_environment_with_unicode_name(self): - environments_list = self.application_catalog_client.\ - get_environments_list() - name = u'$yaql \u2665 unicode' - environment = self.application_catalog_client.create_environment(name) - self.assertEqual(name, environment['name']) - upd_environments_list = self.application_catalog_client.\ - get_environments_list() - self.assertEqual(len(environments_list) + 1, - len(upd_environments_list)) - self.application_catalog_client.delete_environment(environment['id']) - upd_environments_list = self.application_catalog_client.\ - get_environments_list() - self.assertEqual(len(environments_list), - len(upd_environments_list)) - - @decorators.idempotent_id('2b45d30b-3f1d-4482-805e-7cf15d19fe38') - def test_get_environment(self): - environment = self.application_catalog_client.\ - get_environment(self.environment['id']) - self.assertEqual(self.environment['name'], environment['name']) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('950f5bc1-3e5c-48d1-8b05-dc33303ce6f3') - def test_update_environment(self): - environment = self.application_catalog_client.\ - update_environment(self.environment['id']) - self.assertIsNot(self.environment['name'], environment['name']) - - @decorators.idempotent_id('61001866-e885-4dda-9ac9-5b24c67a0e25') - def test_get_environment_model(self): - model = self.application_catalog_client.\ - get_environment_model(self.environment['id']) - self.assertIsInstance(model, dict) - self.assertIn('defaultNetworks', model) - self.assertEqual(self.environment['name'], model['name']) - self.assertEqual(model['?']['type'], "io.murano.Environment") - - net_name = self.application_catalog_client.\ - get_environment_model(self.environment['id'], - path='/defaultNetworks/environment/name') - self.assertEqual("{0}-network".format(self.environment['name']), - net_name) - - @decorators.idempotent_id('23416978-9701-49ff-9bb1-d312292a7f49') - def test_update_environment_model(self): - session = self.application_catalog_client. \ - create_session(self.environment['id']) - patch = [{ - "op": "replace", - "path": "/defaultNetworks/flat", - "value": True - }] - new_model = self.application_catalog_client. \ - update_environment_model(self.environment['id'], patch, - session['id']) - self.assertTrue(new_model['defaultNetworks']['flat']) - - value_draft = self.application_catalog_client. \ - get_environment_model(self.environment['id'], - '/defaultNetworks/flat', - session['id']) - self.assertTrue(value_draft) - - model_current = self.application_catalog_client. \ - get_environment_model(self.environment['id']) - self.assertIsNone(model_current['defaultNetworks']['flat']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_environments_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_environments_negative.py deleted file mode 100644 index 34934b70a..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_environments_negative.py +++ /dev/null @@ -1,104 +0,0 @@ -# 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. - -from tempest.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestEnvironmentsNegative(base.BaseApplicationCatalogTest): - - @decorators.attr(type='negative') - @decorators.idempotent_id('9e245625-ce24-4068-916e-20a5608f6d5a') - def test_delete_environment_with_wrong_env_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_environment, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('1dae123c-27f4-4996-871e-31c66f76ee49') - def test_double_delete_environment(self): - name = utils.generate_name('double_del_negavive') - environment = self.application_catalog_client.\ - create_environment(name) - self.application_catalog_client.delete_environment(environment['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_environment, - environment['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a8032052-5a48-48f0-b333-d1cefcfcbf5f') - def test_get_deleted_environment(self): - name = utils.generate_name('double_del_negavive') - environment = self.application_catalog_client.\ - create_environment(name) - self.application_catalog_client.delete_environment(environment['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_environment, - environment['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('f0b6102c-dd22-4f4d-9775-ce0a7a53d881') - def test_update_environment_with_wrong_env_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.update_environment, - None) - - @decorators.attr(type='negative') - @decorators.idempotent_id('03266970-2f9d-4b82-971f-532fe23d1027') - def test_abandon_environment_with_wrong_env_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.abandon_environment, - None) - - -class TestEnvironmentNegativeTenantIsolation(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestEnvironmentNegativeTenantIsolation, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - cls.alt_client = cls.get_client_with_isolated_creds( - type_of_creds='alt') - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestEnvironmentNegativeTenantIsolation, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('0fc96a16-5df9-48b9-a681-ba5b3730e95b') - def test_get_environment_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_environment, - self.environment['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('d3c6dc81-ed60-4346-869c-0a091c2fe5b8') - def test_update_environment_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.update_environment, - self.environment['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('56aea1db-9314-4558-8b97-5fcd35fd6955') - def test_delete_environment_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.delete_environment, - self.environment['id']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_repository.py b/murano_tempest_tests/tests/api/application_catalog/test_repository.py deleted file mode 100644 index a8494f2b5..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_repository.py +++ /dev/null @@ -1,221 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - -CONF = config.CONF - - -class TestRepositorySanity(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - if CONF.application_catalog.glare_backend: - msg = ("Murano using GLARE backend. " - "Repository tests will be skipped.") - raise cls.skipException(msg) - super(TestRepositorySanity, cls).resource_setup() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('d0f3ad6c-70b4-4ce0-90c5-e7afb20ace80') - def test_get_list_packages(self): - package_list = self.application_catalog_client.get_list_packages() - self.assertIsInstance(package_list, list) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('53f679d9-955f-4dc1-8cdc-1fcdcfbb07a5') - 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.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - package_list = self.application_catalog_client.get_list_packages() - 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['id'], {pkg['id'] for pkg in package_list}) - - -class TestRepository(base.BaseApplicationCatalogIsolatedAdminTest): - - @classmethod - def resource_setup(cls): - if CONF.application_catalog.glare_backend: - msg = ("Murano using GLARE backend. " - "Repository tests will be skipped.") - raise cls.skipException(msg) - - super(TestRepository, cls).resource_setup() - - application_name = utils.generate_name('test_repository_class') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - cls.package = cls.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - - @classmethod - def resource_cleanup(cls): - os.remove(cls.abs_archive_path) - cls.application_catalog_client.delete_package(cls.package['id']) - super(TestRepository, cls).resource_cleanup() - - @decorators.idempotent_id('5ea58ef1-1a63-403d-a57a-ef4423202993') - def test_get_package(self): - package = self.application_catalog_client.get_package( - self.package['id']) - self.assertEqual(self.package['tags'], package['tags']) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('daf5694d-abbf-4ab1-a6df-99540d0efc70') - def test_update_package(self): - post_body = [ - { - "op": "add", - "path": "/tags", - "value": ["im a test"] - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertIn("im a test", result['tags']) - - post_body = [ - { - "op": "replace", - "path": "/tags", - "value": ["im bad:D"] - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertNotIn("im a test", result['tags']) - self.assertIn("im bad:D", result['tags']) - - post_body = [ - { - "op": "remove", - "path": "/tags", - "value": ["im bad:D"] - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertNotIn("im bad:D", result['tags']) - - post_body = [ - { - "op": "replace", - "path": "/is_public", - "value": True - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertTrue(result['is_public']) - - post_body = [ - { - "op": "replace", - "path": "/enabled", - "value": True - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertTrue(result['enabled']) - - post_body = [ - { - "op": "replace", - "path": "/description", - "value": "New description" - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertEqual("New description", result['description']) - - post_body = [ - { - "op": "replace", - "path": "/name", - "value": "New name" - } - ] - - result = self.application_catalog_client.update_package( - self.package['id'], post_body) - self.assertEqual("New name", result['name']) - - @decorators.idempotent_id('fe4711ba-d1ee-4291-8a48-f8efcbd480ab') - def test_download_package(self): - self.application_catalog_client.download_package(self.package['id']) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('9e55ae34-dea4-4db5-be4a-b3b793c9c4a7') - def test_publicize_package(self): - # Given a package that isn't public - application_name = utils.generate_name('test_publicize_package') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - - fetched_package = self.application_catalog_client.get_package( - package['id']) - self.assertFalse(fetched_package['is_public']) - - # When package is publicized - post_body = [ - { - "op": "replace", - "path": "/is_public", - "value": True - } - ] - self.application_catalog_client.update_package(package['id'], - post_body) - - # Then package becomes public - fetched_package = self.application_catalog_client.get_package( - package['id']) - self.assertTrue(fetched_package['is_public']) - - @decorators.idempotent_id('1c017c1b-9efc-4498-95ff-833a9ce565a0') - def test_get_ui_definitions(self): - self.application_catalog_client.get_ui_definition(self.package['id']) - - @decorators.idempotent_id('9f5ee28a-cec7-4d8b-a0fd-affbfceb0fc2') - def test_get_logo(self): - self.application_catalog_client.get_logo(self.package['id']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_repository_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_repository_negative.py deleted file mode 100644 index 12d3af1a0..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_repository_negative.py +++ /dev/null @@ -1,193 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - -CONF = config.CONF - - -class TestRepositoryNegativeNotFound(base.BaseApplicationCatalogTest): - @classmethod - def resource_setup(cls): - if CONF.application_catalog.glare_backend: - msg = ("Murano using GLARE backend. " - "Repository tests will be skipped.") - raise cls.skipException(msg) - super(TestRepositoryNegativeNotFound, cls).resource_setup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('49c557f4-789c-4d9c-8f48-0ba6bea4f234') - def test_update_package_with_incorrect_id(self): - - post_body = [ - { - "op": "add", - "path": "/tags", - "value": ["im a test"] - } - ] - - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.update_package, - utils.generate_uuid(), post_body) - - @decorators.attr(type='negative') - @decorators.idempotent_id('72590141-5046-424a-bed2-17e7b7aabd9a') - def test_get_package_with_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_package, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('09e3f9d9-40ae-4d5c-a488-4137e3abd7a2') - def test_delete_package_with_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_package, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a3cbcb58-7e46-47e9-a633-e3fc296681a9') - def test_download_package_with_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.download_package, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('46799c58-8fe1-4d30-91a9-6067af780b32') - def test_get_ui_definition_with_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_ui_definition, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('062ad8ab-6b5e-43ed-8331-b4bcd849b06e') - def test_get_logo_with_incorrect_id(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_logo, - utils.generate_uuid()) - - -class TestRepositoryNegativeForbidden(base.BaseApplicationCatalogTest): - - # TODO(freerunner): I hope, that we can setup and cleanup resources - # TODO(freerunner): dramatically better. - @classmethod - def resource_setup(cls): - if CONF.application_catalog.glare_backend: - msg = ("Murano using GLARE backend. " - "Repository tests will be skipped.") - raise cls.skipException(msg) - - super(TestRepositoryNegativeForbidden, cls).resource_setup() - - application_name = utils.generate_name('package_test_upload') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - cls.package = cls.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - cls.alt_client = cls.get_client_with_isolated_creds( - type_of_creds='alt') - - @classmethod - def resource_cleanup(cls): - os.remove(cls.abs_archive_path) - cls.application_catalog_client.delete_package(cls.package['id']) - super(TestRepositoryNegativeForbidden, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('29f9b3f1-8e8a-4305-a593-e3055e098666') - def test_update_package_from_another_tenant(self): - post_body = [ - { - "op": "add", - "path": "/tags", - "value": ["im a test"] - } - ] - - self.assertRaises(exceptions.Forbidden, - self.alt_client.update_package, - self.package['id'], - post_body) - - @decorators.attr(type='negative') - @decorators.idempotent_id('75b57ded-6077-436f-97f8-d3087f2f3b77') - def test_get_package_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_package, - self.package['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('1d9f8f74-8aca-4ee8-be0d-ac5b9d5a7dcd') - def test_delete_package_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.delete_package, - self.package['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a1467fed-cd6f-44dd-b79c-ea0f91e082dc') - def test_download_package_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.download_package, - self.package['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('b6074261-f981-4c15-9cd6-5811bd75127a') - def test_get_ui_definition_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_ui_definition, - self.package['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a5a3c2bb-3fde-49cb-ae4c-c454d7eb956b') - def test_get_logo_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_logo, - self.package['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('12928ec7-bd31-415d-9260-5c488aebd4c7') - def test_publicize_package_as_non_admin_user(self): - # Given a package that isn't public - application_name = utils.generate_name('test_publicize_package_' - 'as_non_admin_user') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - - # When package is publicized, then the method throws an exception - post_body = [ - { - "op": "replace", - "path": "/is_public", - "value": True - } - ] - self.assertRaises(exceptions.Forbidden, - self.application_catalog_client.update_package, - package['id'], - post_body) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_services.py b/murano_tempest_tests/tests/api/application_catalog/test_services.py deleted file mode 100644 index f127f9aa5..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_services.py +++ /dev/null @@ -1,134 +0,0 @@ -# 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. - -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestServices(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestServices, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestServices, cls).resource_cleanup() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('6cc9d2da-5aeb-4386-adf3-2ff0b737f363') - def test_get_services_list(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - services_list = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertIsInstance(services_list, list) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('cbdbc025-d673-4fb5-914a-baa0dd896046') - def test_create_and_delete_demo_service(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - services_list = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - services_list_ = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(len(services_list) + 1, len(services_list_)) - self.application_catalog_client.\ - delete_service(self.environment['id'], - session['id'], - service['?']['id']) - services_list_ = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(len(services_list), len(services_list_)) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('431d1842-b25d-4ecd-8837-d56b89c83343') - def test_update_services_via_put(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - put_body = [self._get_demo_app()] - self.application_catalog_client.\ - update_services(self.environment['id'], session['id'], put_body) - services_list = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(1, len(services_list)) - - @decorators.idempotent_id('fc9ef7c7-46e2-44ce-a309-bec2834c6adb') - def test_clear_services_via_put(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - services_list = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - post_body = self._get_demo_app() - self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - services_list_ = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(len(services_list) + 1, len(services_list_)) - self.application_catalog_client.\ - update_services(self.environment['id'], session['id']) - services_list_ = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(0, len(services_list_)) - self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - services_list_ = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(1, len(services_list_)) - - @decorators.idempotent_id('7df86a14-3359-47c2-992e-99eaedb50456') - def test_get_service(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - services_list = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - services_list_ = self.application_catalog_client.\ - get_services_list(self.environment['id'], session['id']) - self.assertEqual(len(services_list) + 1, len(services_list_)) - service_ = self.application_catalog_client.\ - get_service(self.environment['id'], - service['?']['id'], - session['id']) - self.assertEqual(service, service_) - - @decorators.idempotent_id('d64da7cd-9fcd-42c5-9c37-766db902c801') - def test_get_services_without_sess_id(self): - services = self.application_catalog_client.\ - get_services_list(self.environment['id'], None) - self.assertIsInstance(services, list) - self.assertEqual([], services) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_services_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_services_negative.py deleted file mode 100644 index 5b4572868..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_services_negative.py +++ /dev/null @@ -1,272 +0,0 @@ -# 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. - -from tempest.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestServicesNegative(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestServicesNegative, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestServicesNegative, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('5f1dd3f4-170f-4020-bbf6-3d7c277957a8') - def test_get_services_list_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_services_list, - None, - session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('e17972e2-4c5c-4b25-a6cd-82eb2d64897a') - def test_get_services_list_after_delete_env(self): - name = utils.generate_name("get_services_list_after_delete_env") - environment = self.application_catalog_client.create_environment(name) - session = self.application_catalog_client.\ - create_session(environment['id']) - self.application_catalog_client.delete_environment(environment['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_services_list, - environment['id'], - session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('e4ffe0b1-deb0-4f33-9790-6e6dc8bcdecb') - def test_get_services_list_after_delete_session(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.application_catalog_client.\ - delete_session(self.environment['id'], session['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_services_list, - self.environment['id'], - session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('d88880e2-63de-47a0-b29b-a3810b5715e6') - def test_create_service_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.create_service, - None, - session['id'], - post_body) - - @decorators.attr(type='negative') - @decorators.idempotent_id('1d9311af-917a-4a29-b42f-62377369d346') - def test_create_service_without_sess_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.create_service, - self.environment['id'], - "", - post_body) - - @decorators.attr(type='negative') - @decorators.idempotent_id('b22f2232-a6d3-4770-b26e-a1e0ccf62d60') - def test_delete_service_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_service, - "", - session['id'], - service['?']['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('04b4a8b7-3cf6-494a-8741-151305909893') - def test_delete_service_without_session_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.delete_service, - self.environment['id'], - "", - service['?']['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('2d040e59-3af3-47a2-8d87-eef70920cd65') - def test_double_delete_service(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - self.application_catalog_client.\ - delete_service(self.environment['id'], - session['id'], - service['?']['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_service, - self.environment['id'], - session['id'], - service['?']['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a742e411-e572-4aed-ba91-dba8db694039') - def test_get_service_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_service, - None, - session['id'], - service['?']['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('ded0b813-c36e-4108-8be2-c4b1e061f4e9') - def test_put_services_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - put_body = [self._get_demo_app()] - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.update_services, - None, - session['id'], - put_body) - - @decorators.attr(type='negative') - @decorators.idempotent_id('4ab7a7ac-1939-404a-8cb7-feaadc06ae3f') - def test_put_services_without_sess_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - put_body = [self._get_demo_app()] - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.update_services, - self.environment['id'], - "", - put_body) - - -class TestServicesNegativeTenantIsolation(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestServicesNegativeTenantIsolation, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - cls.alt_client = cls.get_client_with_isolated_creds( - type_of_creds='alt') - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestServicesNegativeTenantIsolation, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('014050a1-4f8d-4a9b-8332-3eb03d10ba64') - def test_get_list_services_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_services_list, - self.environment['id'], - session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('b2c70134-0537-4912-a6c7-23d477f62764') - def test_create_service_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - self.assertRaises(exceptions.Forbidden, - self.alt_client.create_service, - self.environment['id'], - session['id'], - post_body) - - @decorators.attr(type='negative') - @decorators.idempotent_id('264f5854-5fce-4186-987a-98d4fbb67093') - def test_delete_service_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - self.assertRaises(exceptions.Forbidden, - self.alt_client.delete_service, - self.environment['id'], - session['id'], - service['?']['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('ff557e1f-a775-4a10-9265-2fa653179c4c') - def test_get_service_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - post_body = self._get_demo_app() - service = self.application_catalog_client.\ - create_service(self.environment['id'], session['id'], post_body) - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_service, - self.environment['id'], - session['id'], - service['?']['id']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_sessions.py b/murano_tempest_tests/tests/api/application_catalog/test_sessions.py deleted file mode 100644 index 2159362d8..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_sessions.py +++ /dev/null @@ -1,93 +0,0 @@ -# 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. - -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestSessions(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestSessions, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestSessions, cls).resource_cleanup() - - @decorators.attr(type='smoke') - @decorators.idempotent_id('9f8ca4dd-1159-4c12-bd97-84ee7f36775e') - def test_create_session(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertEqual(self.environment['id'], session['environment_id']) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('a2782f54-9f9a-443b-97be-edc17039aea5') - def test_delete_session(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.application_catalog_client.delete_session(self.environment['id'], - session['id']) - - @decorators.idempotent_id('0639a8ef-f527-4a5d-b34a-4e2d46f48b30') - def test_get_session(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - session_from_resp = self.application_catalog_client.\ - get_session(self.environment['id'], session['id']) - # Deleting dates from dictionaries to skip it in assert - session.pop('updated', None) - session.pop('created', None) - session_from_resp.pop('updated', None) - session_from_resp.pop('created', None) - self.assertEqual(session, session_from_resp) - - @decorators.idempotent_id('30a63368-e75a-4e00-ac91-c91b17e54a62') - def test_deploy_session(self): - # Given an environment with a session - name = utils.generate_name('_create_and_deploy_env_session') - environment = self.application_catalog_client.create_environment( - name) - self.addCleanup(self.application_catalog_client.delete_environment, - environment['id']) - session = self.application_catalog_client.create_session( - environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - environment['id'], session['id']) - - # When deploy session is called - self.application_catalog_client.deploy_session(environment['id'], - session['id']) - utils.wait_for_environment_deploy(self.application_catalog_client, - environment['id']) - - # Then there is only one deployment and it is in a success state - fetched_deployments = self.application_catalog_client.list_deployments( - environment['id']) - self.assertEqual(1, len(fetched_deployments)) - first_deployment = fetched_deployments[0] - self.assertEqual(environment['id'], first_deployment['environment_id']) - self.assertEqual('success', first_deployment['state']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_sessions_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_sessions_negative.py deleted file mode 100644 index 6cc9a2b1c..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_sessions_negative.py +++ /dev/null @@ -1,146 +0,0 @@ -# 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.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - - -class TestSessionsNegative(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestSessionsNegative, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestSessionsNegative, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('eaf51e99-ff10-45ff-8c9f-416b6a125799') - def test_create_session_before_env(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.create_session, - utils.generate_uuid()) - - @decorators.attr(type='negative') - @decorators.idempotent_id('1269efdf-5586-4119-80e3-e88aa20d3111') - def test_delete_session_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.delete_session, - None, session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('a96f8e67-165c-4a43-92f1-05d28275d576') - def test_get_session_without_env_id(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.get_session, - None, session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('784486ca-9645-4edc-8b23-c7ef781a85ae') - def test_get_session_after_delete_env(self): - name = utils.generate_name('get_session_after_delete_env') - environment = self.application_catalog_client.create_environment(name) - session = self.application_catalog_client.\ - create_session(environment['id']) - self.application_catalog_client.delete_environment(environment['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.get_session, - environment['id'], session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('8e5e1148-0a79-4c5a-bf93-2178ff7a92fe') - def test_double_delete_session(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.application_catalog_client.delete_session(self.environment['id'], - session['id']) - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - - -class TestSessionsNegativeTenantIsolation(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestSessionsNegativeTenantIsolation, cls).resource_setup() - name = utils.generate_name(cls.__name__) - cls.environment = cls.application_catalog_client.\ - create_environment(name) - cls.alt_client = cls.get_client_with_isolated_creds( - type_of_creds='alt') - - @classmethod - def resource_cleanup(cls): - cls.application_catalog_client.\ - delete_environment(cls.environment['id']) - super(TestSessionsNegativeTenantIsolation, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('72108505-3eb1-49b2-a757-a7340d18f52c') - def test_create_session_in_env_from_another_tenant(self): - self.assertRaises(exceptions.Forbidden, - self.alt_client.create_session, - self.environment['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('35ada820-67f1-4a8b-852d-f1a02c11a110') - def test_delete_session_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.Forbidden, - self.alt_client.delete_session, - self.environment['id'], session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('62d469ac-2e91-4e50-bbe8-3f93ab79d903') - def test_get_session_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.Forbidden, - self.alt_client.get_session, - self.environment['id'], session['id']) - - @decorators.attr(type='negative') - @decorators.idempotent_id('d261f060-7189-4234-9ece-06ae46127591') - def test_deploy_session_in_env_from_another_tenant(self): - session = self.application_catalog_client.\ - create_session(self.environment['id']) - self.addCleanup(self.application_catalog_client.delete_session, - self.environment['id'], session['id']) - self.assertRaises(exceptions.Forbidden, - self.alt_client.deploy_session, - self.environment['id'], session['id']) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_static_actions.py b/murano_tempest_tests/tests/api/application_catalog/test_static_actions.py deleted file mode 100644 index 3b714d9df..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_static_actions.py +++ /dev/null @@ -1,76 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - -CONF = config.CONF - - -class TestStaticActions(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestStaticActions, cls).resource_setup() - - application_name = utils.generate_name('test_repository_class') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name, add_class_name=True) - - if CONF.application_catalog.glare_backend: - client = cls.artifacts_client - else: - client = cls.application_catalog_client - - cls.package = client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - - @classmethod - def resource_cleanup(cls): - os.remove(cls.abs_archive_path) - if CONF.application_catalog.glare_backend: - client = cls.artifacts_client - else: - client = cls.application_catalog_client - client.delete_package(cls.package['id']) - super(TestStaticActions, cls).resource_cleanup() - - @decorators.idempotent_id('ac3359e8-8762-417a-95c6-fb2d678850f7') - def test_call_static_action_basic(self): - action_result = self.application_catalog_client.call_static_action( - class_name=self.package['class_definitions'][0], - method_name='staticAction', - args={'myName': 'John'}) - self.assertEqual('"Hello, John"', action_result) - - @decorators.attr(type='smoke') - @decorators.idempotent_id('8b427735-bb73-41ab-8992-c81b3d8ebc42') - def test_call_static_action_full(self): - if CONF.application_catalog.glare_backend: - name_attr = 'name' - else: - name_attr = 'fully_qualified_name' - - action_result = self.application_catalog_client.call_static_action( - class_name=self.package['class_definitions'][0], - method_name='staticAction', - package_name=self.package[name_attr], - class_version="<1", args={'myName': 'John'}) - self.assertEqual('"Hello, John"', action_result) diff --git a/murano_tempest_tests/tests/api/application_catalog/test_static_actions_negative.py b/murano_tempest_tests/tests/api/application_catalog/test_static_actions_negative.py deleted file mode 100644 index adada5f2d..000000000 --- a/murano_tempest_tests/tests/api/application_catalog/test_static_actions_negative.py +++ /dev/null @@ -1,115 +0,0 @@ -# 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 - -from tempest import config -from tempest.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.application_catalog import base -from murano_tempest_tests import utils - -CONF = config.CONF - - -class TestStaticActionsNegative(base.BaseApplicationCatalogTest): - - @classmethod - def resource_setup(cls): - super(TestStaticActionsNegative, cls).resource_setup() - - application_name = utils.generate_name('test_repository_class') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name, add_class_name=True) - - if CONF.application_catalog.glare_backend: - client = cls.artifacts_client - else: - client = cls.application_catalog_client - - cls.package = client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': False}) - - @classmethod - def resource_cleanup(cls): - os.remove(cls.abs_archive_path) - if CONF.application_catalog.glare_backend: - client = cls.artifacts_client - else: - client = cls.application_catalog_client - client.delete_package(cls.package['id']) - super(TestStaticActionsNegative, cls).resource_cleanup() - - @decorators.attr(type='negative') - @decorators.idempotent_id('c6d05273-b6fe-4a33-8a87-c7110c171bc2') - def test_call_static_action_no_args(self): - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.call_static_action) - - @decorators.attr(type='negative') - @decorators.idempotent_id('35440618-6649-40cb-b878-b5cddd4ea0dd') - def test_call_static_action_wrong_class(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.call_static_action, - 'wrong.class', 'staticAction', - args={'myName': 'John'}) - - @decorators.attr(type='negative') - @decorators.idempotent_id('75c6cc5e-0804-45d9-beb2-10c7ab409b70') - def test_call_static_action_wrong_method(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.call_static_action, - class_name=self.package['class_definitions'][0], - method_name='wrongMethod', - args={'myName': 'John'}) - - @decorators.attr(type='negative') - @decorators.idempotent_id('334c828b-3f49-49e0-97a2-534f57596bfb') - def test_call_static_action_session_method(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.call_static_action, - class_name=self.package['class_definitions'][0], - method_name='staticNotAction', - args={'myName': 'John'}) - - @decorators.attr(type='negative') - @decorators.idempotent_id('3ebb5009-2f61-4200-a34c-2bc506d94aed') - def test_call_static_action_wrong_args(self): - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.call_static_action, - class_name=self.package['class_definitions'][0], - method_name='staticAction', - args={'myEmail': 'John'}) - - @decorators.attr(type='negative') - @decorators.idempotent_id('5f4f6edc-2d66-4426-bb81-48e7570d93ef') - def test_call_static_action_wrong_package(self): - self.assertRaises(exceptions.NotFound, - self.application_catalog_client.call_static_action, - class_name=self.package['class_definitions'][0], - method_name='staticAction', - package_name='wrong.package', - args={'myName': 'John'}) - - @decorators.attr(type='negative') - @decorators.idempotent_id('c0854170-700f-4924-9cfe-3bff876b9e63') - def test_call_static_action_wrong_version_format(self): - self.assertRaises(exceptions.BadRequest, - self.application_catalog_client.call_static_action, - class_name=self.package['class_definitions'][0], - method_name='staticAction', - class_version='aaa', - args={'myName': 'John'}) diff --git a/murano_tempest_tests/tests/api/service_broker/__init__.py b/murano_tempest_tests/tests/api/service_broker/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/api/service_broker/base.py b/murano_tempest_tests/tests/api/service_broker/base.py deleted file mode 100644 index 14222ec33..000000000 --- a/murano_tempest_tests/tests/api/service_broker/base.py +++ /dev/null @@ -1,136 +0,0 @@ -# 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. - -import json -import time - -from tempest.common import credentials_factory as common_creds -from tempest import config -from tempest.lib import exceptions -from tempest import test - -from murano_tempest_tests import clients - -CONF = config.CONF - - -class BaseServiceBrokerTest(test.BaseTestCase): - """Base test class for Murano Service Broker API tests.""" - - @classmethod - def skip_checks(cls): - super(BaseServiceBrokerTest, cls).skip_checks() - if not CONF.service_broker.run_service_broker_tests: - skip_msg = "Service Broker API tests are disabled" - raise cls.skipException(skip_msg) - if not CONF.service_available.murano_cfapi: - skip_msg = "Service Broker API is disabled" - raise cls.skipException(skip_msg) - if not CONF.service_available.murano: - skip_msg = "Murano is disabled" - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(BaseServiceBrokerTest, cls).setup_clients() - if not hasattr(cls, "os_primary"): - cls.username = CONF.identity.username - cls.password = CONF.identity.password - cls.tenant_name = CONF.identity.tenant_name - cls.verify_nonempty(cls.username, cls.password, cls.tenant_name) - cls.os_primary = clients.Manager() - cls.service_broker_client = cls.os_primary.service_broker_client - cls.application_catalog_client = \ - cls.os_primary.application_catalog_client - - @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.application_catalog_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.credentials = common_creds.get_credentials_provider( - name=cls.__name__, - force_tenant_isolation=CONF.auth.use_dynamic_credentials, - identity_version=CONF.identity.auth_version) - if type_of_creds == 'primary': - creds = cls.credentials.get_primary_creds() - elif type_of_creds == 'admin': - creds = cls.credentials.get_admin_creds() - elif type_of_creds == 'alt': - creds = cls.credentials.get_alt_creds() - else: - creds = cls.credentials.get_credentials(type_of_creds) - cls.credentials.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) - - def wait_for_result(self, instance_id, timeout): - start_time = time.time() - start_status = self.service_broker_client.get_last_status(instance_id) - while start_status: - status = self.service_broker_client.get_last_status(instance_id) - if status == start_status and time.time() - start_time > timeout: - raise exceptions.TimeoutException - elif status != start_status: - try: - parced_stat = status['state'] - self.assertIn(str(parced_stat), ['succeeded', 'failed']) - result = str(parced_stat) - return result - except KeyError: - parced_stat = json.loads(status) - self.assertIsInstance(parced_stat, dict) - result = parced_stat - return result - else: - time.sleep(2) - - def perform_deprovision(self, instance_id): - self.service_broker_client.deprovision(instance_id) - status = self.wait_for_result(instance_id, 30) - self.assertEqual('succeeded', status) - - -class BaseServiceBrokerAdminTest(BaseServiceBrokerTest): - - @classmethod - def setup_clients(cls): - super(BaseServiceBrokerTest, cls).setup_clients() - if not hasattr(cls, "os_admin"): - cls.username = CONF.identity.username - cls.password = CONF.identity.password - cls.tenant_name = CONF.identity.tenant_name - cls.verify_nonempty(cls.username, cls.password, cls.tenant_name) - cls.os_admin = clients.Manager() - cls.service_broker_client = cls.os_admin.service_broker_client - cls.application_catalog_client = \ - cls.os_admin.application_catalog_client diff --git a/murano_tempest_tests/tests/api/service_broker/test_service_broker_actions.py b/murano_tempest_tests/tests/api/service_broker/test_service_broker_actions.py deleted file mode 100644 index 6a22fe466..000000000 --- a/murano_tempest_tests/tests/api/service_broker/test_service_broker_actions.py +++ /dev/null @@ -1,167 +0,0 @@ -# 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. - -import json -import os - -from tempest.lib import decorators - -from murano_tempest_tests.tests.api.service_broker import base -from murano_tempest_tests import utils - - -class ServiceBrokerActionsTest(base.BaseServiceBrokerAdminTest): - - @decorators.attr(type='gate') - @decorators.idempotent_id('76cadf4b-7143-402c-975e-11d7464dd20e') - def test_applications_listing(self): - app_list = self.service_broker_client.get_applications_list() - self.assertIsInstance(app_list, list) - - @decorators.attr(type=['smoke', 'gate']) - @decorators.idempotent_id('51ad86a2-b8e4-43d1-8099-75e4be293f79') - def test_provision_and_deprovision(self): - application_name = utils.generate_name('cfapi') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': True}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - app_list = self.service_broker_client.get_applications_list() - app = self.service_broker_client.get_application(application_name, - app_list) - post_json = {} - instance_id = utils.generate_uuid() - space_id = utils.generate_uuid() - service = self.service_broker_client.provision( - instance_id, app['id'], app['plans'][0]['id'], - space_id, post_json) - self.wait_for_result(instance_id, 30) - self.addCleanup(self.perform_deprovision, instance_id) - self.assertIsInstance(json.loads(service), dict) - - @decorators.attr(type=['smoke', 'gate']) - @decorators.idempotent_id('d5bd537a-7912-4916-a137-d0601157fb9e') - def test_binding_instance(self): - application_name = utils.generate_name('cfapi') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': True}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - app_list = self.service_broker_client.get_applications_list() - app = self.service_broker_client.get_application(application_name, - app_list) - post_json = {} - instance_id = utils.generate_uuid() - space_id = utils.generate_uuid() - service = self.service_broker_client.provision( - instance_id, app['id'], app['plans'][0]['id'], - space_id, post_json) - self.wait_for_result(instance_id, 30) - self.addCleanup(self.perform_deprovision, instance_id) - self.assertIsInstance(json.loads(service), dict) - binding = self.service_broker_client.create_binding(instance_id) - self.assertIsInstance(binding, dict) - self.assertEqual({'uri': 'localhost'}, binding) - - @decorators.attr(type=['smoke', 'gate']) - @decorators.idempotent_id('f738fdc2-a180-40e5-9aa6-d338d8660b88') - def test_provision_with_incorrect_input(self): - """Test provision with restricted items in object model - - Test will fail on deprovision, if parameters from '?' section - will passed through service-broker. - """ - application_name = utils.generate_name('cfapi') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': True}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - app_list = self.service_broker_client.get_applications_list() - app = self.service_broker_client.get_application(application_name, - app_list) - - # NOTE(freerunner): The '?' section should be cutted off during - # provision action. - post_json = { - '?': { - 'type': 'io.murano.apps.{0}'.format(application_name), - 'id': utils.generate_uuid() - } - } - instance_id = utils.generate_uuid() - space_id = utils.generate_uuid() - service = self.service_broker_client.provision( - instance_id, app['id'], app['plans'][0]['id'], - space_id, post_json) - self.wait_for_result(instance_id, 30) - self.addCleanup(self.perform_deprovision, instance_id) - self.assertIsInstance(json.loads(service), dict) - - @decorators.attr(type=['smoke', 'gate']) - @decorators.idempotent_id('ef9bc7ca-21b7-480d-a3ba-32cb39b33909') - def test_double_provision_to_the_same_space(self): - application_name = utils.generate_name('cfapi') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': True}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - app_list = self.service_broker_client.get_applications_list() - app = self.service_broker_client.get_application(application_name, - app_list) - post_json = {} - instance_id = utils.generate_uuid() - space_id = utils.generate_uuid() - service = self.service_broker_client.provision( - instance_id, app['id'], app['plans'][0]['id'], - space_id, post_json) - self.wait_for_result(instance_id, 30) - self.addCleanup(self.perform_deprovision, instance_id) - self.assertIsInstance(json.loads(service), dict) - application_name = utils.generate_name('cfapi') - abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package(application_name) - self.addCleanup(os.remove, abs_archive_path) - package = self.application_catalog_client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": [], "tags": [], 'is_public': True}) - self.addCleanup(self.application_catalog_client.delete_package, - package['id']) - app_list = self.service_broker_client.get_applications_list() - app = self.service_broker_client.get_application(application_name, - app_list) - post_json = {} - instance_id = utils.generate_uuid() - service = self.service_broker_client.provision( - instance_id, app['id'], app['plans'][0]['id'], - space_id, post_json) - self.wait_for_result(instance_id, 30) - self.addCleanup(self.perform_deprovision, instance_id) - self.assertIsInstance(json.loads(service), dict) diff --git a/murano_tempest_tests/tests/api/service_broker/test_service_broker_negative.py b/murano_tempest_tests/tests/api/service_broker/test_service_broker_negative.py deleted file mode 100644 index bc8ffd91c..000000000 --- a/murano_tempest_tests/tests/api/service_broker/test_service_broker_negative.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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.lib import decorators -from tempest.lib import exceptions - -from murano_tempest_tests.tests.api.service_broker import base -from murano_tempest_tests import utils - - -class ServiceBrokerNegativeTest(base.BaseServiceBrokerAdminTest): - - @decorators.attr(type=['gate', 'negative']) - @decorators.idempotent_id('3c9c14a2-1655-490a-90f0-6cb5dd6dba07') - def test_get_status_with_not_present_instance_id(self): - not_present_instance_id = utils.generate_uuid() - self.assertRaises( - exceptions.Gone, - self.service_broker_client.get_last_status, - not_present_instance_id) diff --git a/murano_tempest_tests/tests/scenario/__init__.py b/murano_tempest_tests/tests/scenario/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/scenario/application_catalog/__init__.py b/murano_tempest_tests/tests/scenario/application_catalog/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/murano_tempest_tests/tests/scenario/application_catalog/base.py b/murano_tempest_tests/tests/scenario/application_catalog/base.py deleted file mode 100644 index 3eb1c5efb..000000000 --- a/murano_tempest_tests/tests/scenario/application_catalog/base.py +++ /dev/null @@ -1,406 +0,0 @@ -# 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 requests -import socket -import time - -from tempest.clients import Manager as services_manager -from tempest.common import credentials_factory as common_creds -from tempest.common import waiters -from tempest import config -from tempest.lib import exceptions -from tempest.services import orchestration -from tempest import test - -from murano_tempest_tests import clients -from murano_tempest_tests import utils - -CONF = config.CONF - - -class BaseApplicationCatalogScenarioTest(test.BaseTestCase): - """Base test class for Murano Application Catalog Scenario tests.""" - - @classmethod - def skip_checks(cls): - super(BaseApplicationCatalogScenarioTest, cls).skip_checks() - if not CONF.service_available.murano: - skip_msg = "Murano is disabled" - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(BaseApplicationCatalogScenarioTest, cls).setup_clients() - if not hasattr(cls, "os_primary"): - creds = cls.get_configured_isolated_creds(type_of_creds='primary') - cls.os_primary = clients.Manager(credentials=creds) - cls.services_manager = services_manager(creds) - - cls.application_catalog_client = \ - cls.os_primary.application_catalog_client - cls.artifacts_client = cls.os_primary.artifacts_client - cls.servers_client = cls.services_manager.servers_client - # NOTE(andreaf) The orchestration client is not initialised in Tempest - # by default anymore. - params = config.service_client_config('orchestration') - cls.orchestration_client = orchestration.OrchestrationClient( - cls.services_manager.auth_provider, **params) - cls.images_client = cls.services_manager.image_client_v2 - - @classmethod - def resource_setup(cls): - super(BaseApplicationCatalogScenarioTest, cls).resource_setup() - cls.linux_image = CONF.application_catalog.linux_image - cls.cirros_image = cls.get_required_image_name() - - @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.application_catalog_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.credentials = common_creds.get_credentials_provider( - name=cls.__name__, - force_tenant_isolation=CONF.auth.use_dynamic_credentials, - identity_version=CONF.identity.auth_version) - if type_of_creds == 'primary': - creds = cls.credentials.get_primary_creds() - elif type_of_creds == 'admin': - creds = cls.credentials.get_admin_creds() - elif type_of_creds == 'alt': - creds = cls.credentials.get_alt_creds() - else: - creds = cls.credentials.get_credentials(type_of_creds) - cls.credentials.type_of_creds = type_of_creds - - return creds.credentials - - @classmethod - def get_required_image_name(cls): - image = cls.images_client.show_image(CONF.compute.image_ref) - return image['name'] - - def environment_delete(self, environment_id, timeout=180): - self.application_catalog_client.delete_environment(environment_id) - - start_time = time.time() - while time.time() - start_time > timeout: - try: - self.application_catalog_client.get_environment(environment_id) - except exceptions.NotFound: - return - - @classmethod - def purge_stacks(cls): - stacks = cls.orchestration_client.list_stacks()['stacks'] - for stack in stacks: - cls.orchestration_client.delete_stack(stack['id']) - cls.orchestration_client.wait_for_stack_status(stack['id'], - 'DELETE_COMPLETE') - - def get_service(self, environment, session, service_name): - for service in self.application_catalog_client.get_services_list( - environment, session): - if service['name'] == service_name: - return service - - def get_stack_id(self, environment_id): - stacks = self.orchestration_client.list_stacks()['stacks'] - for stack in stacks: - if environment_id in self.orchestration_client.show_stack( - stack['id'])['stack']['description']: - return stack['id'] - - def get_stack_template(self, stack): - return self.orchestration_client.show_template(stack) - - def get_instance_id(self, name): - instance_list = self.servers_client.list_servers()['servers'] - for instance in instance_list: - if name in instance['name']: - return instance['id'] - - def apache( - self, attributes=None, userName=None, flavor='m1.tiny'): - post_body = { - "instance": { - "flavor": flavor, - "image": self.linux_image, - "assignFloatingIp": True, - "availabilityZone": "nova", - "volumes": attributes, - "?": { - "type": "io.murano.resources.LinuxMuranoInstance", - "id": utils.generate_uuid() - }, - "name": utils.generate_name("testMurano") - }, - "name": utils.generate_name("ApacheHTTPServer"), - "userName": userName, - "?": { - "_{id}".format(id=utils.generate_uuid()): { - "name": "ApacheHTTPServer" - }, - "type": "io.murano.apps.test.ApacheHttpServerCustom", - "id": utils.generate_uuid() - } - } - return post_body - - def vm_cinder( - self, attributes=None, userName=None, flavor='m1.tiny'): - post_body = { - "instance": { - "flavor": flavor, - "image": self.cirros_image, - "assignFloatingIp": True, - "availabilityZone": "nova", - "volumes": attributes, - "?": { - "type": "io.murano.resources.LinuxMuranoInstance", - "id": utils.generate_uuid() - }, - "name": utils.generate_name("testMurano") - }, - "name": utils.generate_name("VM"), - "userName": userName, - "?": { - "_{id}".format(id=utils.generate_uuid()): { - "name": "VM" - }, - "type": "io.murano.apps.test.VM", - "id": utils.generate_uuid() - } - } - return post_body - - def vm_test(self, **kwargs): - instance = { - "flavor": "m1.tiny", - "image": self.cirros_image, - "assignFloatingIp": True, - "availabilityZone": "nova", - "?": { - "type": "io.murano.resources.LinuxMuranoInstance", - "id": utils.generate_uuid() - }, - "name": utils.generate_name("testMurano") - } - if kwargs.get('securityGroups'): - instance['securityGroups'] = kwargs.get('securityGroups') - return { - "instance": instance, - "name": utils.generate_name("VM"), - "?": { - "_{id}".format(id=utils.generate_uuid()): { - "name": "VM" - }, - "type": "io.murano.apps.test.VM", - "id": utils.generate_uuid() - } - } - - def update_executor(self, flavor='m1.tiny'): - post_body = { - "instance": { - "flavor": flavor, - "image": self.linux_image, - "assignFloatingIp": True, - "?": { - "type": "io.murano.resources.LinuxMuranoInstance", - "id": utils.generate_uuid() - }, - "name": utils.generate_name('testMurano') - }, - "name": utils.generate_name('dummy'), - "?": { - "type": "io.murano.apps.test.UpdateExecutor", - "id": utils.generate_uuid() - } - } - return post_body - - def deploy_environment(self, environment, session): - self.application_catalog_client.deploy_session(environment['id'], - session['id']) - timeout = 1800 - deployed_env = utils.wait_for_environment_deploy( - self.application_catalog_client, environment['id'], - timeout=timeout) - if deployed_env['status'] == 'ready': - return deployed_env - elif deployed_env['status'] == 'deploying': - self.fail('Environment deployment is not finished in {} seconds'. - format(timeout)) - else: - self.fail('Environment has status {}'.format( - deployed_env['status'])) - - def status_check(self, environment_id, configurations): - for configuration in configurations: - inst_name = configuration[0] - ports = configuration[1:] - ip = self.get_ip_by_instance_name(environment_id, inst_name) - if ip and ports: - for port in ports: - self.check_port_access(ip, port) - else: - self.fail('Instance does not have floating IP') - - def check_path(self, environment_id, path, inst_name=None): - environment = self.application_catalog_client.\ - get_environment(environment_id) - if inst_name: - ip = self.get_ip_by_instance_name(environment_id, inst_name) - else: - ip = environment.services[0]['instance']['floatingIpAddress'] - resp = requests.get('http://{0}/{1}'.format(ip, path)) - if resp.status_code == 200: - return resp - else: - self.fail("Service path unavailable") - - def get_ip_by_instance_name(self, environment_id, inst_name): - for service in self.application_catalog_client.\ - get_services_list(environment_id): - if inst_name in service['instance']['name']: - return service['instance']['floatingIpAddress'] - - def check_port_access(self, ip, port): - result = 1 - start_time = time.time() - while time.time() - start_time < 600: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - result = sock.connect_ex((str(ip), port)) - sock.close() - if result == 0: - break - time.sleep(5) - self.assertEqual(0, result, '%s port is closed on instance' % port) - - @classmethod - def create_volume(cls, **kwargs): - volume = cls.volumes_client.create_volume(**kwargs)['volume'] - waiters.wait_for_volume_resource_status(cls.volumes_client, - volume['id'], 'available') - return volume - - @classmethod - def delete_volume(cls, volume_id): - cls.volumes_client.delete_volume(volume_id) - is_volume_deleted = False - while not is_volume_deleted: - is_volume_deleted = cls.volumes_client.\ - is_resource_deleted(volume_id) - time.sleep(1) - - def create_snapshot(self, volume_id): - snapshot = self.snapshots_client.\ - create_snapshot(volume_id=volume_id)['snapshot'] - waiters.wait_for_volume_resource_status(self.snapshots_client, - snapshot['id'], 'available') - return snapshot - - def delete_snapshot(self, snapshot_id): - self.snapshots_client.delete_snapshot(snapshot_id) - is_snapshot_deleted = False - while not is_snapshot_deleted: - is_snapshot_deleted = self.snapshots_client.\ - is_resource_deleted(snapshot_id) - time.sleep(1) - - def create_backup(self, volume_id): - backup = self.backups_client.create_backup( - volume_id=volume_id, - force=True)['backup'] - waiters.wait_for_volume_resource_status(self.backups_client, - backup['id'], 'available') - return backup - - def delete_backup(self, backup_id): - self.backups_client.delete_backup(backup_id) - return self.backups_client.wait_for_resource_deletion(backup_id) - - def get_volume(self, environment_id): - stack = self.get_stack_id(environment_id) - stack_outputs = self.orchestration_client.\ - show_stack(stack)['stack']['outputs'] - for output in stack_outputs: - if (output['output_key'].startswith('vol-') and - output['output_key'].endswith('-id')): - volume_id = output['output_value'] - return self.volumes_client.show_volume(volume_id)['volume'] - - def get_volume_attachments(self, environment_id): - stack = self.get_stack_id(environment_id) - stack_outputs = self.orchestration_client.\ - show_stack(stack)['stack']['outputs'] - for output in stack_outputs: - if (output['output_key'].startswith('vol-') and - output['output_key'].endswith('-attachments')): - return output['output_value'] - - def check_volume_attachments(self, environment_id): - volume_attachments = self.get_volume_attachments(environment_id) - self.assertIsInstance(volume_attachments, list) - self.assertGreater(len(volume_attachments), 0) - instance_id = self.get_instance_id('testMurano') - for attachment in volume_attachments: - self.assertEqual(attachment.get('server_id'), instance_id) - self.assertTrue(attachment.get('device').startswith('/dev/')) - - def check_volume_attached(self, name, volume_id): - instance_id = self.get_instance_id(name) - attached_volumes = self.servers_client.\ - list_volume_attachments(instance_id)['volumeAttachments'] - self.assertEqual(attached_volumes[0]['id'], volume_id) - - -class BaseApplicationCatalogScenarioIsolatedAdminTest( - BaseApplicationCatalogScenarioTest): - - @classmethod - def setup_clients(cls): - super(BaseApplicationCatalogScenarioIsolatedAdminTest, - cls).setup_clients() - if not hasattr(cls, "os_admin"): - creds = cls.get_configured_isolated_creds(type_of_creds='admin') - cls.os_admin = clients.Manager(credentials=creds) - cls.services_manager = services_manager(creds) - - cls.application_catalog_client = \ - cls.os_admin.application_catalog_client - cls.artifacts_client = cls.os_admin.artifacts_client - cls.servers_client = cls.services_manager.servers_client - # NOTE(andreaf) The orchestration client is not initialised in Tempest - # by default anymore. - params = config.service_client_config('orchestration') - cls.orchestration_client = orchestration.OrchestrationClient( - cls.services_manager.auth_provider, **params) - cls.snapshots_client = cls.services_manager.snapshots_v2_client - cls.volumes_client = cls.services_manager.volumes_v2_client - cls.backups_client = cls.services_manager.backups_v2_client - cls.images_client = cls.services_manager.image_client_v2 diff --git a/murano_tempest_tests/tests/scenario/application_catalog/test_cinder_volumes.py b/murano_tempest_tests/tests/scenario/application_catalog/test_cinder_volumes.py deleted file mode 100644 index 4ee0a573e..000000000 --- a/murano_tempest_tests/tests/scenario/application_catalog/test_cinder_volumes.py +++ /dev/null @@ -1,510 +0,0 @@ -# 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 tempest.lib import decorators - -from murano_tempest_tests.tests.scenario.application_catalog import base -from murano_tempest_tests import utils - -CONF = config.CONF - - -class TestCinderVolumes(base.BaseApplicationCatalogScenarioTest): - - @classmethod - def skip_checks(cls): - super(TestCinderVolumes, cls).skip_checks() - if not CONF.service_available.cinder: - msg = "Cinder is not available. Skipping volumes tests" - raise cls.skipException(msg) - if (not CONF.volume_feature_enabled.api_v3 and - not CONF.volume_feature_enabled.api_v2): - msg = ("Neither cinder v2 nor v3 are available. Skipping" - "volumes tests") - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(TestCinderVolumes, cls).setup_clients() - # Prefer volume v3 which is the current version - if CONF.volume_feature_enabled.api_v3: - _volume = cls.services_manager.volume_v3 - elif CONF.volume_feature_enabled.api_v2: - _volume = cls.services_manager.volume_v2 - cls.volumes_client = _volume.VolumesClient() - cls.backups_client = _volume.BackupsClient() - cls.snapshots_client = _volume.SnapshotsClient() - - @classmethod - def resource_setup(cls): - if not CONF.application_catalog.cinder_volume_tests: - msg = "Cinder volumes tests will be skipped." - raise cls.skipException(msg) - super(TestCinderVolumes, cls).resource_setup() - cls.linux = CONF.application_catalog.linux_image - application_name = utils.generate_name('VM') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package( - application_name, - app='io.murano.apps.test.VM', - manifest_required=False) - if CONF.application_catalog.glare_backend: - cls.client = cls.artifacts_client - else: - cls.client = cls.application_catalog_client - cls.package = cls.client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": ["Web"], "tags": ["test"]}) - cls.volume = cls.create_volume(size='1') - - @classmethod - def resource_cleanup(cls): - cls.delete_volume(cls.volume['id']) - cls.client.delete_package(cls.package['id']) - os.remove(cls.abs_archive_path) - super(TestCinderVolumes, cls).resource_cleanup() - - @decorators.idempotent_id('241ace7d-3b6e-413e-8936-a851ff1163f8') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_boot_volume_as_image(self): - """Test app deployment using boot volume as image - - Scenario: - 1. Create environment - 2. Add VM application with ability to boot instance - from Cinder volume - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that instance is not booted from image, volume is attached - to the instance, has size 4GiB and created from image - 7. Delete environment - """ - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - post_body = { - "instance": { - "flavor": "m1.tiny", - "blockDevices": { - "volume": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 4, - "sourceImage": self.cirros_image - }, - "bootIndex": 0, - "deviceName": "vda", - "deviceType": "disk" - }, - "assignFloatingIp": True, - "availabilityZone": "nova", - "?": { - "type": "io.murano.resources.LinuxMuranoInstance", - "id": utils.generate_uuid() - }, - "name": utils.generate_name("testMurano") - }, - "name": utils.generate_name("VM"), - "?": { - "_{id}".format(id=utils.generate_uuid()): { - "name": "VM" - }, - "type": "io.murano.apps.test.VM", - "id": utils.generate_uuid() - } - } - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.assertEqual(volume_data['size'], 4) - self.assertEqual(volume_data['volume_image_metadata']['image_name'], - self.cirros_image) - server = self.get_instance_id('testMurano') - self.assertFalse( - self.servers_client.show_server(server)['server']['image']) - - @decorators.idempotent_id('e10d3bad-7145-46df-8118-4040842883f6') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_existing_volume(self): - """Test app deployment with existing volume - - Scenario: - 1. Create environment - 2. Add VM application with ability to attach existing - Cinder volume to the instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that volume is attached to the instance - 7. Delete environment - """ - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.ExistingCinderVolume" - }, - "openstackId": self.volume['id'] - } - } - post_body = self.vm_cinder(attributes=volume_attributes) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - self.check_volume_attached('testMurano', self.volume['id']) - - @decorators.idempotent_id('6338a496-7415-42a9-a514-61f6f5cb1e65') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_volume_creation(self): - """Test app deployment with volume creation - - Scenario: - 1. Create environment - 2. Add VM application with ability to create and - attach Cinder volume with size 1 GiB to the instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that volume is attached to the instance and has size 1GiB - 7. Check that we can access some attachment info about the volume - 8. Delete environment - """ - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 1 - } - } - post_body = self.vm_cinder(attributes=volume_attributes) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.check_volume_attachments(environment['id']) - self.assertEqual(volume_data['size'], 1) - - @decorators.idempotent_id('1eb9bbe4-9810-408e-86a0-78ff114aadae') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_volume_creation_from_image(self): - """Test app deployment with volume creation from image - - Scenario: - 1. Create environment - 2. Add VM application with ability to create Cinder - volume with size 2 GiB from image and attach it to the instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that volume is attached to the instance, has size 2GiB and - created from image - 7. Delete environment - """ - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 4, - "sourceImage": self.cirros_image - } - } - post_body = self.vm_cinder(volume_attributes) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.assertEqual(volume_data['size'], 4) - self.assertEqual(volume_data['volume_image_metadata']['image_name'], - self.cirros_image) - - @decorators.idempotent_id('bd624a9b-10ae-4079-b515-7b6031d9e725') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_volume_creation_from_volume(self): - """Test app deployment with volume creation from volume - - Scenario: - 1. Create environment - 2. Add VM application with ability to create Cinder - volume with size 1 GiB from existing volume and attach it to the - instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that volume is attached to the instance, has size 1GiB and - created from existing volume - 7. Delete environment - """ - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 1, - "sourceVolume": { - "?": { - "type": "io.murano.resources.ExistingCinderVolume" - }, - "openstackId": self.volume['id'] - } - } - } - post_body = self.vm_cinder(volume_attributes) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.assertEqual(volume_data['size'], 1) - self.assertEqual(volume_data['source_volid'], self.volume['id']) - - @decorators.idempotent_id('7a671222-160d-4594-97bf-ea47f60ad965') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_volume_creation_from_snapshot(self): - """Test app deployment with volume creation from volume snapshot - - Scenario: - 1. Make snapshot from volume - 2. Create environment - 3. Add VM application with ability to create - Cinder volume with size 1 GiB from existing volume snapshot and - attach it to the instance - 4. Deploy environment - 5. Make sure that deployment finished successfully - 6. Check that application is accessible - 7. Check that volume is attached to the instance, has size 1GiB and - created from existing volume snapshot - 8. Delete environment, snapshot - """ - snapshot = self.create_snapshot(self.volume['id']) - self.addCleanup(self.delete_snapshot, snapshot['id']) - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 1, - "sourceSnapshot": { - "?": { - "type": "io.murano.resources.CinderVolumeSnapshot" - }, - "openstackId": snapshot['id'] - } - } - } - post_body = self.vm_cinder(volume_attributes) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.assertEqual(volume_data['size'], 1) - self.assertEqual(volume_data['snapshot_id'], snapshot['id']) - - -class TestCinderVolumeIsolatedAdmin( - base.BaseApplicationCatalogScenarioIsolatedAdminTest): - - @classmethod - def resource_setup(cls): - if not CONF.application_catalog.cinder_volume_tests: - msg = "Cinder volumes attachment tests will be skipped." - raise cls.skipException(msg) - super(TestCinderVolumeIsolatedAdmin, cls).resource_setup() - application_name = utils.generate_name('VM') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package( - application_name, - app='io.murano.apps.test.VM', - manifest_required=False) - if CONF.application_catalog.glare_backend: - cls.client = cls.artifacts_client - else: - cls.client = cls.application_catalog_client - cls.package = cls.client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": ["Web"], "tags": ["test"]}) - cls.volume = cls.create_volume(size='1') - - @classmethod - def resource_cleanup(cls): - cls.delete_volume(cls.volume['id']) - cls.client.delete_package(cls.package['id']) - os.remove(cls.abs_archive_path) - super(TestCinderVolumeIsolatedAdmin, cls).resource_cleanup() - - @decorators.idempotent_id('4111eb94-2636-4d0b-af5c-776ed5a59b87') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_volume_creation_readonly(self): - """Test app deploy with volume creation with readonly - - Scenario: - 1. Create environment - 2. Add VM application with ability to create and - attach Cinder volume with size 1 GiB and readonly - properties to the instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that volume is attached to the instance, has size 1GiB, - and readonly attributes - 7. Delete environment - """ - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.\ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.\ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 1, - "readOnly": True - } - } - post_body = self.vm_cinder(attributes=volume_attributes) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.assertEqual(volume_data['size'], 1) - self.assertEqual(volume_data['metadata']['readonly'], 'True') - - @decorators.idempotent_id('5c134343-11bc-4329-ac30-9b43f32c15e2') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_volume_creation_from_backup(self): - """Test app deployment with volume creation from volume backup - - Scenario: - 1. Make backup from volume - 2. Create environment - 3. Add VM application with ability to create Cinder - volume with size 1 GiB from existing volume backup and attach it to - the instance - 4. Deploy environment - 5. Make sure that deployment finished successfully - 6. Check that application is accessible - 7. Check that volume is attached to the instance, has size 1GiB and - restored from existing volume backup - 8. Delete environment, backup - """ - if not (CONF.volume_feature_enabled.backup and - CONF.service_available.swift): - msg = ("Cinder backup driver and Swift are required. " - "Deploy app with volume restoring from backup test " - "will be skipped.") - raise self.skipException(msg) - - backup = self.create_backup(self.volume['id']) - self.addCleanup(self.delete_backup, backup['id']) - name = utils.generate_name('testMurano') - environment = self.application_catalog_client. \ - create_environment(name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client. \ - create_session(environment['id']) - volume_attributes = { - "/dev/vdb": { - "?": { - "type": "io.murano.resources.CinderVolume" - }, - "size": 1, - "name": "restore_backup_" + backup['id'], - "sourceVolumeBackup": { - "?": { - "type": "io.murano.resources.CinderVolumeBackup" - }, - "openstackId": backup['id'] - } - } - } - post_body = self.vm_cinder(volume_attributes) - self.application_catalog_client. \ - create_service(environment['id'], session['id'], - post_body) - self.deploy_environment(environment, session) - - volume_data = self.get_volume(environment['id']) - self.check_volume_attached('testMurano', volume_data['id']) - self.assertEqual(volume_data['size'], 1) - self.assertIn(backup['id'], volume_data['name']) diff --git a/murano_tempest_tests/tests/scenario/application_catalog/test_deployment.py b/murano_tempest_tests/tests/scenario/application_catalog/test_deployment.py deleted file mode 100644 index 3a3ec679b..000000000 --- a/murano_tempest_tests/tests/scenario/application_catalog/test_deployment.py +++ /dev/null @@ -1,257 +0,0 @@ -# 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 murano_tempest_tests.tests.scenario.application_catalog import base -from murano_tempest_tests import utils - -from tempest import config -from tempest.lib import decorators - -CONF = config.CONF - - -class TestMuranoDeployment(base.BaseApplicationCatalogScenarioTest): - - @classmethod - def resource_setup(cls): - if not CONF.application_catalog.deployment_tests or \ - not CONF.application_catalog.linux_image: - msg = "Application Catalog Scenario Deployment Tests will be " \ - "skipped." - raise cls.skipException(msg) - super(TestMuranoDeployment, cls).resource_setup() - - cls.abs_archive_path = [None]*3 - cls.packages = [None]*3 - - application_name = utils.generate_name('Apache') - cls.abs_archive_path[0], dir_with_archive, archive_name = \ - utils.prepare_package( - application_name, - app='io.murano.apps.test.ApacheHttpServerCustom', - manifest_required=False) - - if CONF.application_catalog.glare_backend: - cls.client = cls.artifacts_client - else: - cls.client = cls.application_catalog_client - - cls.packages[0] = cls.client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": ["Web"], "tags": ["test"]}) - - application_name = utils.generate_name('Lighttpd') - cls.abs_archive_path[1], dir_with_archive, archive_name = \ - utils.prepare_package( - application_name, - app='io.murano.apps.test.Lighttpd', - manifest_required=False) - - cls.packages[1] = cls.client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": ["Web"], "tags": ["test"]}) - - application_name = utils.generate_name('UpdateExecutor') - cls.abs_archive_path[2], dir_with_archive, archive_name = \ - utils.prepare_package( - application_name, - app='io.murano.apps.test.UpdateExecutor', - manifest_required=False) - - cls.packages[2] = cls.client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": ["Web"], "tags": ["test"]}) - - @classmethod - def resource_cleanup(cls): - - cls.purge_stacks() - [cls.client.delete_package(package['id']) for package in cls.packages] - map(os.remove, cls.abs_archive_path) - super(TestMuranoDeployment, cls).resource_cleanup() - - @decorators.idempotent_id('244c7f25-05bb-43f8-af81-563902979109') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_app_deployment(self): - - """Test app deployment - - Scenario: - 1. Create environment - 2. Add ApacheHTTPServer application to the instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Delete environment - """ - - post_body = self.apache() - environment_name = utils.generate_name('Test_Murano') - environment = self.application_catalog_client.create_environment( - name=environment_name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.create_session( - environment['id']) - self.assertEqual(environment['id'], session['environment_id']) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], post_body) - self.deploy_environment(environment, session) - self.status_check(environment['id'], - [[post_body['instance']['name'], 22, 80]]) - - @decorators.idempotent_id('f161ac2f-69b8-4c0b-89ee-225459e7f113') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_resources_deallocation(self): - - """Test resources deallocation - - Scenario: - 1. Create environment - 2. Add ApacheHTTPServer application to the instance - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Remove application from environment - 7. Deploy environment - 8. Check that application is accessible - 9. Check that resources aren't used - 10. Delete environment - """ - - app_1_post_body = self.apache() - app_2_post_body = self.apache() - - environment_name = utils.generate_name('Test_Murano') - environment = self.application_catalog_client.create_environment( - name=environment_name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.create_session( - environment['id']) - self.assertEqual(environment['id'], session['environment_id']) - self.application_catalog_client.create_service( - environment['id'], session['id'], app_1_post_body) - self.application_catalog_client.create_service( - environment['id'], session['id'], app_2_post_body) - self.deploy_environment(environment, session) - self.status_check(environment['id'], - [[app_1_post_body['instance']['name'], 22, 80]]) - - environment = self.application_catalog_client.get_environment( - environment['id']) - app_for_remove = self.get_service( - environment['id'], session['id'], app_1_post_body['name']) - session = self.application_catalog_client.create_session( - environment['id']) - self.application_catalog_client.delete_service( - environment['id'], session['id'], app_for_remove['?']['id']) - environment = self.application_catalog_client.get_environment( - environment['id']) - self.deploy_environment(environment, session) - self.status_check(environment['id'], - [[app_2_post_body['instance']['name'], 22, 80]]) - - instance_name = app_1_post_body['instance']['name'] - stack = self.get_stack_id(environment['id']) - template = self.get_stack_template(stack) - ip_addresses = '{0}-assigned-ip'.format(instance_name) - floating_ip = '{0}-FloatingIPaddress'.format(instance_name) - - self.assertNotIn(ip_addresses, template['outputs']) - self.assertNotIn(floating_ip, template['outputs']) - self.assertNotIn(instance_name, template['resources']) - - @decorators.idempotent_id('5f0f1326-83b4-4ebb-a80d-312a744851b1') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_dependent_app(self): - - """Test dependent application - - Scenario: - 1. Create environment - 2. Add Update Executor application to the instance - 3. Add Dependent application - 4. Deploy environment - 5. Make sure that deployment finished successfully - 6. Check that application is accessible - 7. Delete environment - """ - - post_body = self.update_executor() - environment_name = utils.generate_name('Test_Murano') - environment = self.application_catalog_client.create_environment( - name=environment_name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.create_session( - environment['id']) - self.assertEqual(environment['id'], session['environment_id']) - updater = self.application_catalog_client.\ - create_service(environment['id'], session['id'], post_body) - - post_body = { - "name": utils.generate_name("lighttest"), - "updater": updater, - "?": { - "type": "io.murano.apps.test.Lighttpd", - "id": utils.generate_uuid() - } - } - - self.application_catalog_client.create_service( - environment['id'], session['id'], post_body) - self.deploy_environment(environment, session) - self.status_check(environment['id'], - [[updater['instance']['name'], 22, 80]]) - - @decorators.idempotent_id('3a1fbca7-f5b3-4274-b4dd-3a66822bad77') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_simple_software_configuration(self): - - """Test simple software configuration - - Scenario: - 1. Create environment with name specified - 2. Add ApacheHTTPServer application to the instance with specific - user name - 3. Deploy environment - 4. Make sure that deployment finished successfully - 5. Check that application is accessible - 6. Check that environment deployed with specific user name - 7. Delete environment - """ - - post_body = self.apache(userName=utils.generate_name('user')) - username = post_body["userName"] - environment_name = utils.generate_name('SSC-murano') - environment = self.application_catalog_client.create_environment( - name=environment_name) - self.addCleanup(self.environment_delete, environment['id']) - session = self.application_catalog_client.create_session( - environment['id']) - self.assertEqual(environment['id'], session['environment_id']) - self.application_catalog_client.\ - create_service(environment['id'], session['id'], post_body) - self.deploy_environment(environment, session) - self.status_check(environment['id'], - [[post_body['instance']['name'], 22, 80]]) - resp = self.check_path( - environment['id'], '', post_body['instance']['name']) - self.assertIn(username, resp.text, "Required information not found in " - "response from server") diff --git a/murano_tempest_tests/tests/scenario/application_catalog/test_security_groups.py b/murano_tempest_tests/tests/scenario/application_catalog/test_security_groups.py deleted file mode 100644 index a2cb98d77..000000000 --- a/murano_tempest_tests/tests/scenario/application_catalog/test_security_groups.py +++ /dev/null @@ -1,85 +0,0 @@ -# -# 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 tempest.lib import decorators - -from murano_tempest_tests.tests.scenario.application_catalog import base -from murano_tempest_tests import utils - -CONF = config.CONF - - -class TestSecurityGroups(base.BaseApplicationCatalogScenarioTest): - - @classmethod - def resource_setup(cls): - super(TestSecurityGroups, cls).resource_setup() - cls.linux = CONF.application_catalog.linux_image - application_name = utils.generate_name('VM') - cls.abs_archive_path, dir_with_archive, archive_name = \ - utils.prepare_package( - application_name, - app='io.murano.apps.test.VM', - manifest_required=False) - if CONF.application_catalog.glare_backend: - cls.client = cls.artifacts_client - else: - cls.client = cls.application_catalog_client - cls.package = cls.client.upload_package( - application_name, archive_name, dir_with_archive, - {"categories": ["Web"], "tags": ["test"]}) - - @classmethod - def resource_cleanup(cls): - cls.client.delete_package(cls.package['id']) - os.remove(cls.abs_archive_path) - super(TestSecurityGroups, cls).resource_cleanup() - - @decorators.idempotent_id('1344f041-3f7a-4e75-acfc-36b050ccec82') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_murano_defined_security_group(self): - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.create_environment(name) - session = self.application_catalog_client.create_session( - environment['id']) - self.application_catalog_client.create_service( - environment['id'], session['id'], self.vm_test()) - self.deploy_environment(environment, session) - instance_id = self.get_instance_id('testMurano') - security_groups = self.servers_client.list_security_groups_by_server( - instance_id).get('security_groups') - self.assertEqual(len(security_groups), 1) - self.assertEqual(len(security_groups[0].get('rules')), 4) - - @decorators.idempotent_id('c52cb4a2-53dd-44c3-95d5-7e1606954caa') - @testtools.testcase.attr('smoke') - @testtools.testcase.attr('scenario') - def test_deploy_app_with_user_defined_security_group(self): - name = utils.generate_name('testMurano') - environment = self.application_catalog_client.create_environment(name) - session = self.application_catalog_client.create_session( - environment['id']) - self.application_catalog_client.create_service( - environment['id'], session['id'], - self.vm_test(securityGroups=['default'])) - self.deploy_environment(environment, session) - instance_id = self.get_instance_id('testMurano') - security_groups = self.servers_client.list_security_groups_by_server( - instance_id).get('security_groups') - self.assertEqual(len(security_groups), 1) - self.assertEqual('default', security_groups[0].get('name')) diff --git a/murano_tempest_tests/utils.py b/murano_tempest_tests/utils.py deleted file mode 100644 index 79d628d2f..000000000 --- a/murano_tempest_tests/utils.py +++ /dev/null @@ -1,512 +0,0 @@ -# Copyright (c) 2015 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 collections -import os -import shutil -import tempfile -import time -import uuid -import yaml -import zipfile - -from oslo_log import log as logging -import requests -import six -from six.moves import urllib - -LOG = logging.getLogger(__name__) - -MANIFEST = {'Format': 'MuranoPL/1.0', - 'Type': 'Application', - 'Description': 'MockApp for API tests', - 'Author': 'Mirantis, Inc'} - - -def compose_package(app_name, package_dir, - require=None, archive_dir=None, add_class_name=False, - manifest_required=True, version=None): - """Composes a murano package - - Composes package `app_name` manifest and files from `package_dir`. - Includes `require` section if any in the manifest file. - Puts the resulting .zip file into `archive_dir` if present or in the - `package_dir`. - """ - tmp_package_dir = os.path.join(archive_dir, os.path.basename(package_dir)) - shutil.copytree(package_dir, tmp_package_dir) - package_dir = tmp_package_dir - - if manifest_required: - manifest = os.path.join(package_dir, "manifest.yaml") - with open(manifest, 'w') as f: - fqn = 'io.murano.apps.' + app_name - mfest_copy = MANIFEST.copy() - mfest_copy['FullName'] = fqn - mfest_copy['Name'] = app_name - mfest_copy['Classes'] = {fqn: 'mock_muranopl.yaml'} - if 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: - class_file = os.path.join(package_dir, 'Classes', 'mock_muranopl.yaml') - with open(class_file, 'r') as f: - contents = f.read() - - index = contents.index('Extends') - contents = "{0}Name: {1}\n\n{2}".format(contents[:index], app_name, - contents[index:]) - 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: - archive_dir = os.path.dirname(os.path.abspath(__file__)) - archive_path = os.path.join(archive_dir, name) - - with zipfile.ZipFile(archive_path, 'w') as zip_file: - for root, dirs, files in os.walk(package_dir): - for f in files: - zip_file.write( - os.path.join(root, f), - arcname=os.path.join(os.path.relpath(root, package_dir), f) - ) - - return archive_path, name - - -def prepare_package(name, require=None, add_class_name=False, - app='MockApp', manifest_required=True, - version=None): - """Prepare package. - - :param name: Package name to compose - :param require: Parameter 'require' for manifest - :param add_class_name: Option to write class name to class file - :return: Path to archive, directory with archive, filename of archive - """ - app_dir = acquire_package_directory(app=app) - target_arc_path = tempfile.mkdtemp() - - arc_path, filename = compose_package( - name, app_dir, require=require, archive_dir=target_arc_path, - add_class_name=add_class_name, manifest_required=manifest_required, - version=version) - return arc_path, target_arc_path, filename - - -def generate_uuid(): - """Generate uuid for objects.""" - return uuid.uuid4().hex - - -def generate_name(prefix): - """Generate name for objects.""" - suffix = generate_uuid()[:8] - return '{0}_{1}'.format(prefix, suffix) - - -def acquire_package_directory(app='MockApp'): - """Obtain absolutely directory with package files. - - Should be called inside tests dir. - :return: Package path - """ - top_plugin_dir = os.path.realpath(os.path.join(os.getcwd(), - os.path.dirname(__file__))) - expected_package_dir = '/extras/' + app - app_dir = top_plugin_dir + expected_package_dir - return app_dir - - -def to_url(filename, base_url, version='', path='/', extension=''): - if urllib.parse.urlparse(filename).scheme in ('http', 'https'): - return filename - if not base_url: - raise ValueError("No base_url for repository supplied") - if '/' in filename or filename in ('.', '..'): - raise ValueError("Invalid filename path supplied: {0}".format( - filename)) - version = '.' + version if version else '' - return urllib.parse.urljoin(base_url, - path + filename + version + extension) - -# ----------------------Murano client common functions------------------------- - - -class NoCloseProxy(object): - """A proxy object, that does nothing on close.""" - def __init__(self, obj): - self.obj = obj - - def close(self): - return - - def __getattr__(self, name): - return getattr(self.obj, name) - - -class File(object): - def __init__(self, name, binary=True): - self.name = name - self.binary = binary - - def open(self): - mode = 'rb' if self.binary else 'r' - if hasattr(self.name, 'read'): - # NOTE(kzaitsev) We do not want to close a file object - # passed to File wrapper. The caller should be responsible - # for closing it - return NoCloseProxy(self.name) - else: - if os.path.isfile(self.name): - return open(self.name, mode) - url = urllib.parse.urlparse(self.name) - if url.scheme in ('http', 'https'): - resp = requests.get(self.name, stream=True) - if not resp.ok: - raise ValueError("Got non-ok status({0}) " - "while connecting to {1}".format( - resp.status_code, self.name)) - temp_file = tempfile.NamedTemporaryFile(mode='w+b') - for chunk in resp.iter_content(1024 * 1024): - temp_file.write(chunk) - temp_file.flush() - return open(temp_file.name, mode) - raise ValueError("Can't open {0}".format(self.name)) - - -class FileWrapperMixin(object): - def __init__(self, file_wrapper): - self.file_wrapper = file_wrapper - try: - self._file = self.file_wrapper.open() - except Exception: - # NOTE(kzaitsev): We need to have _file available at __del__ time. - self._file = None - raise - - def file(self): - self._file.seek(0) - return self._file - - def close(self): - if self._file and not self._file.closed: - self._file.close() - - def save(self, dst, binary=True): - file_name = self.file_wrapper.name - - if urllib.parse.urlparse(file_name).scheme: - file_name = file_name.split('/')[-1] - - dst = os.path.join(dst, file_name) - - mode = 'wb' if binary else 'w' - with open(dst, mode) as dst_file: - self._file.seek(0) - shutil.copyfileobj(self._file, dst_file) - - def __del__(self): - self.close() - - -class Package(FileWrapperMixin): - """Represents murano package contents.""" - - @staticmethod - def from_file(file_obj): - if not isinstance(file_obj, File): - file_obj = File(file_obj) - return Package(file_obj) - - @staticmethod - def from_location(name, base_url='', version='', url='', path=None): - """Open file using one of three possible options - - If path is supplied search for name file in the path, otherwise - if url is supplied - open that url and finally search murano - repository for the package. - """ - if path: - pkg_name = os.path.join(path, name) - file_name = None - for f in [pkg_name, pkg_name + '.zip']: - if os.path.exists(f): - file_name = f - if file_name: - return Package.from_file(file_name) - LOG.error("Couldn't find file for package {0}, tried {1}".format( - name, [pkg_name, pkg_name + '.zip'])) - if url: - return Package.from_file(url) - return Package.from_file(to_url( - name, - base_url=base_url, - version=version, - path='apps/', - extension='.zip') - ) - - @property - def contents(self): - """Contents of a package.""" - if not hasattr(self, '_contents'): - try: - self._file.seek(0) - self._zip_obj = zipfile.ZipFile( - six.BytesIO(self._file.read())) - except Exception as e: - LOG.error("Error {0} occurred," - " while parsing the package".format(e)) - raise - return self._zip_obj - - @property - def manifest(self): - """Parsed manifest file of a package.""" - if not hasattr(self, '_manifest'): - try: - self._manifest = yaml.safe_load( - self.contents.open('manifest.yaml')) - except Exception as e: - LOG.error("Error {0} occurred, while extracting " - "manifest from package".format(e)) - raise - return self._manifest - - def images(self): - """Returns a list of required image specifications.""" - if 'images.lst' not in self.contents.namelist(): - return [] - try: - return yaml.safe_load( - self.contents.open('images.lst')).get('Images', []) - except Exception: - return [] - - @property - def classes(self): - if not hasattr(self, '_classes'): - self._classes = {} - for class_name, class_file in ( - self.manifest.get('Classes', {}).items()): - filename = "Classes/%s" % class_file - if filename not in self.contents.namelist(): - continue - klass = yaml.safe_load(self.contents.open(filename)) - self._classes[class_name] = klass - return self._classes - - @property - def ui(self): - if not hasattr(self, '_ui'): - if 'UI/ui.yaml' in self.contents.namelist(): - self._ui = self.contents.open('UI/ui.yaml') - else: - self._ui = None - return self._ui - - @property - def logo(self): - if not hasattr(self, '_logo'): - if 'logo.png' in self.contents.namelist(): - self._logo = self.contents.open('logo.png') - else: - self._logo = None - return self._logo - - def _get_package_order(self, packages_graph): - """Sorts packages according to dependencies between them - - Murano allows cyclic dependencies. It is impossible - to do topological sort for graph with cycles, so at first - graph condensation should be built. - For condensation building Kosaraju's algorithm is used. - Packages in strongly connected components can be situated - in random order to each other. - """ - def topological_sort(graph, start_node): - order = [] - not_seen = set(graph) - - def dfs(node): - not_seen.discard(node) - for dep_node in graph[node]: - if dep_node in not_seen: - dfs(dep_node) - order.append(node) - - dfs(start_node) - return order - - def transpose_graph(graph): - transposed = collections.defaultdict(list) - for node, deps in six.viewitems(graph): - for dep in deps: - transposed[dep].append(node) - return transposed - - order = topological_sort(packages_graph, self.manifest['FullName']) - order.reverse() - transposed = transpose_graph(packages_graph) - - def top_sort_by_components(graph, component_order): - result = [] - seen = set() - - def dfs(node): - seen.add(node) - result.append(node) - for dep_node in graph[node]: - if dep_node not in seen: - dfs(dep_node) - for item in component_order: - if item not in seen: - dfs(item) - return reversed(result) - return top_sort_by_components(transposed, order) - - def requirements(self, base_url, path=None, dep_dict=None): - """Scans Require section of manifests of all the dependencies. - - Returns a dict with FQPNs as keys and respective Package objects - as values, ordered by topological sort. - - :param base_url: url of packages location - :param path: local path of packages location - :param dep_dict: unused. Left for backward compatibility - """ - - unordered_requirements = {} - requirements_graph = collections.defaultdict(list) - dep_queue = collections.deque([(self.manifest['FullName'], self)]) - while dep_queue: - dep_name, dep_file = dep_queue.popleft() - unordered_requirements[dep_name] = dep_file - direct_deps = Package._get_direct_deps(dep_file, base_url, path) - for name, file in direct_deps: - if name not in unordered_requirements: - dep_queue.append((name, file)) - requirements_graph[dep_name] = [dep[0] for dep in direct_deps] - - ordered_reqs_names = self._get_package_order(requirements_graph) - ordered_reqs_dict = collections.OrderedDict() - for name in ordered_reqs_names: - ordered_reqs_dict[name] = unordered_requirements[name] - - return ordered_reqs_dict - - @staticmethod - def _get_direct_deps(package, base_url, path): - result = [] - if 'Require' in package.manifest: - for dep_name, ver in package.manifest['Require'].items(): - try: - req_file = Package.from_location( - dep_name, - version=ver, - path=path, - base_url=base_url, - ) - except Exception as e: - LOG.error("Error {0} occurred while parsing package {1}, " - "required by {2} package".format( - e, dep_name, - package.manifest['FullName'])) - continue - result.append((req_file.manifest['FullName'], req_file)) - return result - - -class NamespaceResolver(object): - """Copied from main murano repo - - original at murano/dsl/namespace_resolver.py - """ - - def __init__(self, namespaces): - self._namespaces = namespaces - self._namespaces[''] = '' - - def resolve_name(self, name, relative=None): - if name is None: - raise ValueError() - if name and name.startswith(':'): - return name[1:] - if ':' in name: - parts = name.split(':') - if len(parts) != 2 or not parts[1]: - raise NameError('Incorrectly formatted name ' + name) - if parts[0] not in self._namespaces: - raise KeyError('Unknown namespace prefix ' + parts[0]) - return '.'.join((self._namespaces[parts[0]], parts[1])) - if not relative and '=' in self._namespaces and '.' not in name: - return '.'.join((self._namespaces['='], name)) - if relative and '.' not in name: - return '.'.join((relative, name)) - return name - - -def get_local_inheritance(classes): - result = {} - for class_name, klass in classes.items(): - if 'Extends' not in klass: - continue - ns = klass.get('Namespaces') - if ns: - resolver = NamespaceResolver(ns) - else: - resolver = None - - if isinstance(klass['Extends'], list): - bases = klass['Extends'] - else: - bases = [klass['Extends']] - for base_class in bases: - if resolver: - base_fqn = resolver.resolve_name(base_class) - else: - 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)