Remove murano_tempest_tests from murano repo
Change-Id: I5da1c660393df335f8d5e8ab17b23bb21a8e3257
This commit is contained in:
parent
05d95df793
commit
1ea1cda5d4
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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.")
|
||||
]
|
|
@ -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)
|
|
@ -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
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
|
@ -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)
|
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title> Hello World</title>
|
||||
</head>
|
||||
<body>Hello world. This is my first web page. My name is %USER_NAME%.
|
||||
</body>
|
||||
</html>
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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:
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title> Hello World</title>
|
||||
</head>
|
||||
<body>Hello world. This is my first web page. My name is %USER_NAME%.
|
||||
</body>
|
||||
</html>
|
|
@ -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
|
|
@ -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)]
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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']
|
||||
}
|
||||
}
|
|
@ -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})
|
|
@ -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')
|
|
@ -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')
|
|
@ -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
|
|
@ -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']))
|
|
@ -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'])
|
|
@ -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))
|
|
@ -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)
|
|
@ -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'])
|
|
@ -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'])
|
|
@ -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'])
|
|
@ -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'])
|
|
@ -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)
|
|
@ -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)
|
|
@ -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'])
|
|
@ -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'])
|
|
@ -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'])
|
|
@ -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)
|
|
@ -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'})
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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'])
|
|
@ -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")
|
|
@ -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'))
|
|
@ -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)
|
Loading…
Reference in New Issue