Retire Murano: remove repo content

Murano project is retiring
- https://review.opendev.org/c/openstack/governance/+/919358

this commit remove the content of this project repo

Depends-On: https://review.opendev.org/c/openstack/project-config/+/919359/
Change-Id: I4df568899dadcdf3440e56221b2d4cf74754e058
This commit is contained in:
Ghanshyam Mann 2024-05-10 15:52:41 -07:00
parent d2b794cbf0
commit 528f48107c
121 changed files with 8 additions and 8788 deletions

View File

@ -1,6 +0,0 @@
[run]
branch = True
source = murano_tempest_tests
[report]
ignore_errors = True

58
.gitignore vendored
View File

@ -1,58 +0,0 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg*
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
cover/
.coverage*
!.coveragerc
.tox
nosetests.xml
.testrepository
.venv
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
.*sw?
# Files created by releasenotes build
releasenotes/build

View File

@ -1,3 +0,0 @@
# Format is:
# <preferred e-mail> <other e-mail 1>
# <preferred e-mail> <other e-mail 2>

View File

@ -1,7 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,42 +0,0 @@
- project:
queue: murano
templates:
- check-requirements
- tempest-plugin-jobs
check:
jobs:
- murano-tempest-api:
voting: false
- murano-tempest-api-2023-1:
voting: false
- murano-tempest-api-zed:
voting: false
- murano-tempest-api-yoga:
voting: false
- murano-tempest-api-xena:
voting: false
- murano-tempest-cfapi
- job:
name: murano-tempest-api-2023-1
parent: murano-tempest-api
nodeset: openstack-single-node-jammy
override-checkout: stable/2023.1
- job:
name: murano-tempest-api-zed
parent: murano-tempest-api
nodeset: openstack-single-node-focal
override-checkout: stable/zed
- job:
name: murano-tempest-api-yoga
parent: murano-tempest-api
nodeset: openstack-single-node-focal
override-checkout: stable/yoga
- job:
name: murano-tempest-api-xena
parent: murano-tempest-api
nodeset: openstack-single-node-focal
override-checkout: stable/xena

View File

@ -1,19 +0,0 @@
The source repository for this project can be found at:
https://opendev.org/openstack/muranotempest-plugin
Pull requests submitted through GitHub are not monitored.
To start contributing to OpenStack, follow the steps in the contribution guide
to set up and use Gerrit:
https://docs.openstack.org/contributors/code-and-documentation/quick-start.html
Bugs should be filed on Launchpad:
https://bugs.launchpad.net/murano
For more specific information about contributing to this repository, see the
murano tempest plugin contributor guide:
https://docs.openstack.org/murano/latest/contributor/contributing.html

View File

@ -1,4 +0,0 @@
murano-tempest-plugin Style Commandments
========================================
Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/

176
LICENSE
View File

@ -1,176 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View File

@ -1,42 +1,10 @@
========================
Team and repository tags
========================
This project is no longer maintained.
.. image:: http://governance.openstack.org/tc/badges/murano-tempest-plugin.svg
:target: http://governance.openstack.org/tc/reference/tags/index.html
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
=====================
murano-tempest-plugin
=====================
This directory contains Tempest tests to cover the Murano project, as well
as a plugin to automatically load these tests into tempest.
See the Tempest plugin docs for information on using it:
https://docs.openstack.org/tempest/latest/#using-plugins
* Free software: Apache license
* Documentation: https://docs.openstack.org/murano/latest/
* Release notes: https://docs.openstack.org/releasenotes/murano/
* Source: https://opendev.org/openstack/murano-tempest-plugin
* Bugs: https://bugs.launchpad.net/murano
Running the tests
-----------------
To run all tests from this plugin, install Murano into your environment and
navigate to tempest directory::
$ cd /opt/stack/tempest
Install the murano-tempest-plugin into the tox environment::
$ tox -e venv-tempest -- pip install (path to the murano-tempest-plugin directory)
Run this command::
$ tox -e all -- application_catalog
To run a single test case, run with the test case name, for example::
$ tox -e all -- murano_tempest_tests.tests.api.application_catalog.test_categories.TestCategories.test_list_categories
For any further questions, please email
openstack-discuss@lists.openstack.org or join #openstack-dev on
OFTC.

View File

@ -1,2 +0,0 @@
[python: **.py]

View File

@ -1,5 +0,0 @@
sphinx>=2.0.0,!=2.1.0 # BSD
openstackdocstheme>=2.2.1 # Apache-2.0
# releasenotes
reno>=3.1.0 # Apache-2.0

View File

@ -1,5 +0,0 @@
====================
Administrators guide
====================
Administrators guide of murano-tempest-plugin.

View File

@ -1,5 +0,0 @@
================================
Command line interface reference
================================
CLI reference of murano-tempest-plugin.

View File

@ -1,82 +0,0 @@
# -*- coding: utf-8 -*-
# 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 sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'openstackdocstheme',
#'sphinx.ext.intersphinx',
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'murano-tempest-plugin'
copyright = u'2017, OpenStack Developers'
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/murano-tempest-plugin'
openstackdocs_auto_name = False
openstackdocs_bug_project = 'murano'
openstackdocs_bug_tag = ''
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
html_theme = 'openstackdocs'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Developers', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -1,5 +0,0 @@
=============
Configuration
=============
Configuration of murano-tempest-plugin.

View File

@ -1,4 +0,0 @@
============
Contributing
============
.. include:: ../../../CONTRIBUTING.rst

View File

@ -1,9 +0,0 @@
===========================
Contributor Documentation
===========================
.. toctree::
:maxdepth: 2
contributing

View File

@ -1,30 +0,0 @@
.. murano-tempest-plugin documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
====================================================
Welcome to the documentation of murano_tempest_tests
====================================================
Contents:
.. toctree::
:maxdepth: 2
readme
install/index
library/index
contributor/index
configuration/index
cli/index
user/index
admin/index
reference/index
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,10 +0,0 @@
2. Edit the ``/etc/murano_tempest_tests/murano_tempest_tests.conf`` file and complete the following
actions:
* In the ``[database]`` section, configure database access:
.. code-block:: ini
[database]
...
connection = mysql+pymysql://murano_tempest_tests:MURANO_TEMPEST_TESTS_DBPASS@controller/murano_tempest_tests

View File

@ -1,75 +0,0 @@
Prerequisites
-------------
Before you install and configure the murano service,
you must create a database, service credentials, and API endpoints.
#. To create the database, complete these steps:
* Use the database access client to connect to the database
server as the ``root`` user:
.. code-block:: console
$ mysql -u root -p
* Create the ``murano_tempest_tests`` database:
.. code-block:: none
CREATE DATABASE murano_tempest_tests;
* Grant proper access to the ``murano_tempest_tests`` database:
.. code-block:: none
GRANT ALL PRIVILEGES ON murano_tempest_tests.* TO 'murano_tempest_tests'@'localhost' \
IDENTIFIED BY 'MURANO_TEMPEST_TESTS_DBPASS';
GRANT ALL PRIVILEGES ON murano_tempest_tests.* TO 'murano_tempest_tests'@'%' \
IDENTIFIED BY 'MURANO_TEMPEST_TESTS_DBPASS';
Replace ``MURANO_TEMPEST_TESTS_DBPASS`` with a suitable password.
* Exit the database access client.
.. code-block:: none
exit;
#. Source the ``admin`` credentials to gain access to
admin-only CLI commands:
.. code-block:: console
$ . admin-openrc
#. To create the service credentials, complete these steps:
* Create the ``murano_tempest_tests`` user:
.. code-block:: console
$ openstack user create --domain default --password-prompt murano_tempest_tests
* Add the ``admin`` role to the ``murano_tempest_tests`` user:
.. code-block:: console
$ openstack role add --project service --user murano_tempest_tests admin
* Create the murano_tempest_tests service entities:
.. code-block:: console
$ openstack service create --name murano_tempest_tests --description "murano" murano
#. Create the murano service API endpoints:
.. code-block:: console
$ openstack endpoint create --region RegionOne \
murano public http://controller:XXXX/vY/%\(tenant_id\)s
$ openstack endpoint create --region RegionOne \
murano internal http://controller:XXXX/vY/%\(tenant_id\)s
$ openstack endpoint create --region RegionOne \
murano admin http://controller:XXXX/vY/%\(tenant_id\)s

View File

@ -1,9 +0,0 @@
=======================
murano service overview
=======================
The murano service provides...
The murano service consists of the following components:
``murano_tempest_tests-api`` service
Accepts and responds to end user compute API calls...

View File

@ -1,17 +0,0 @@
=================================
murano service installation guide
=================================
.. toctree::
:maxdepth: 2
get_started.rst
install.rst
verify.rst
next-steps.rst
The murano service (murano_tempest_tests) provides...
This chapter assumes a working setup of OpenStack following the
`OpenStack Installation Tutorial
<https://docs.openstack.org/project-install-guide/ocata/>`_.

View File

@ -1,34 +0,0 @@
.. _install-obs:
Install and configure for openSUSE and SUSE Linux Enterprise
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the murano service
for openSUSE Leap 42.1 and SUSE Linux Enterprise Server 12 SP1.
.. include:: common_prerequisites.rst
Install and configure components
--------------------------------
#. Install the packages:
.. code-block:: console
# zypper --quiet --non-interactive install
.. include:: common_configure.rst
Finalize installation
---------------------
Start the murano services and configure them to start when
the system boots:
.. code-block:: console
# systemctl enable openstack-murano_tempest_tests-api.service
# systemctl start openstack-murano_tempest_tests-api.service

View File

@ -1,33 +0,0 @@
.. _install-rdo:
Install and configure for Red Hat Enterprise Linux and CentOS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the murano service
for Red Hat Enterprise Linux 7 and CentOS 7.
.. include:: common_prerequisites.rst
Install and configure components
--------------------------------
#. Install the packages:
.. code-block:: console
# yum install
.. include:: common_configure.rst
Finalize installation
---------------------
Start the murano services and configure them to start when
the system boots:
.. code-block:: console
# systemctl enable openstack-murano_tempest_tests-api.service
# systemctl start openstack-murano_tempest_tests-api.service

View File

@ -1,31 +0,0 @@
.. _install-ubuntu:
Install and configure for Ubuntu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the murano
service for Ubuntu 14.04 (LTS).
.. include:: common_prerequisites.rst
Install and configure components
--------------------------------
#. Install the packages:
.. code-block:: console
# apt-get update
# apt-get install
.. include:: common_configure.rst
Finalize installation
---------------------
Restart the murano services:
.. code-block:: console
# service openstack-murano_tempest_tests-api restart

View File

@ -1,20 +0,0 @@
.. _install:
Install and configure
~~~~~~~~~~~~~~~~~~~~~
This section describes how to install and configure the
murano service, code-named murano_tempest_tests, on the controller node.
This section assumes that you already have a working OpenStack
environment with at least the following components installed:
.. (add the appropriate services here and further notes)
Note that installation and configuration vary by distribution.
.. toctree::
:maxdepth: 2
install-obs.rst
install-rdo.rst
install-ubuntu.rst

View File

@ -1,9 +0,0 @@
.. _next-steps:
Next steps
~~~~~~~~~~
Your OpenStack environment now includes the murano_tempest_tests service.
To add additional services, see
https://docs.openstack.org/project-install-guide/ocata/.

View File

@ -1,24 +0,0 @@
.. _verify:
Verify operation
~~~~~~~~~~~~~~~~
Verify operation of the murano service.
.. note::
Perform these commands on the controller node.
#. Source the ``admin`` project credentials to gain access to
admin-only CLI commands:
.. code-block:: console
$ . admin-openrc
#. List service components to verify successful launch and registration
of each process:
.. code-block:: console
$ openstack murano service list

View File

@ -1,7 +0,0 @@
========
Usage
========
To use murano-tempest-plugin in a project::
import murano_tempest_tests

View File

@ -1 +0,0 @@
.. include:: ../../README.rst

View File

@ -1,5 +0,0 @@
==========
References
==========
References of murano-tempest-plugin.

View File

@ -1,5 +0,0 @@
===========
Users guide
===========
Users guide of murano-tempest-plugin.

View File

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

View File

@ -1,160 +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")
orchestration_group = cfg.OptGroup(name='orchestration',
title='Orchestration Service 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.")
]
OrchestrationGroup = [
cfg.StrOpt('catalog_type',
default='orchestration',
help="Catalog type of the Orchestration service."),
cfg.StrOpt('region',
default='',
help="The orchestration 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('endpoint_type',
default='publicURL',
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the orchestration service."),
cfg.StrOpt('stack_owner_role', default='heat_stack_owner',
help='Role required for users to be able to manage stacks'),
cfg.IntOpt('build_interval',
default=1,
help="Time in seconds between build status checks."),
cfg.IntOpt('build_timeout',
default=1200,
help="Timeout in seconds to wait for a stack to build.")
]

View File

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

View File

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

View File

@ -1,82 +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 update')
- $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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,59 +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)
config.register_opt_group(
conf, config_application_catalog.orchestration_group,
config_application_catalog.OrchestrationGroup)
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),
(config_application_catalog.orchestration_group.name,
config_application_catalog.OrchestrationGroup)]

View File

@ -1,440 +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)
return self._parse_resp(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)
return self._parse_resp(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)
return self._parse_resp(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

View File

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

View File

@ -1,412 +0,0 @@
# Copyright 2013 IBM Corp.
# 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 re
import time
from urllib import parse as urllib
from oslo_serialization import jsonutils as json
from tempest import exceptions
from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
class OrchestrationClient(rest_client.RestClient):
def list_stacks(self, params=None):
"""Lists all stacks for a user."""
uri = 'stacks'
if params:
uri += '?%s' % urllib.urlencode(params)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def create_stack(self, name, disable_rollback=True, parameters=None,
timeout_mins=60, template=None, template_url=None,
environment=None, files=None):
if parameters is None:
parameters = {}
headers, body = self._prepare_update_create(
name,
disable_rollback,
parameters,
timeout_mins,
template,
template_url,
environment,
files)
uri = 'stacks'
resp, body = self.post(uri, headers=headers, body=body)
self.expected_success(201, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def update_stack(self, stack_identifier, name, disable_rollback=True,
parameters=None, timeout_mins=60, template=None,
template_url=None, environment=None, files=None):
if parameters is None:
parameters = {}
headers, body = self._prepare_update_create(
name,
disable_rollback,
parameters,
timeout_mins,
template,
template_url,
environment)
uri = "stacks/%s" % stack_identifier
resp, body = self.put(uri, headers=headers, body=body)
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)
def _prepare_update_create(self, name, disable_rollback=True,
parameters=None, timeout_mins=60,
template=None, template_url=None,
environment=None, files=None):
if parameters is None:
parameters = {}
post_body = {
"stack_name": name,
"disable_rollback": disable_rollback,
"parameters": parameters,
"timeout_mins": timeout_mins,
"template": "HeatTemplateFormatVersion: '2012-12-12'\n",
"environment": environment,
"files": files
}
if template:
post_body['template'] = template
if template_url:
post_body['template_url'] = template_url
body = json.dumps(post_body)
# Password must be provided on stack create so that heat
# can perform future operations on behalf of the user
headers = self.get_headers()
headers['X-Auth-Key'] = self.password
headers['X-Auth-User'] = self.user
return headers, body
def show_stack(self, stack_identifier):
"""Returns the details of a single stack."""
url = "stacks/%s" % stack_identifier
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def suspend_stack(self, stack_identifier):
"""Suspend a stack."""
url = 'stacks/%s/actions' % stack_identifier
body = {'suspend': None}
resp, body = self.post(url, json.dumps(body))
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp)
def resume_stack(self, stack_identifier):
"""Resume a stack."""
url = 'stacks/%s/actions' % stack_identifier
body = {'resume': None}
resp, body = self.post(url, json.dumps(body))
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp)
def list_resources(self, stack_identifier):
"""Returns the details of a single resource."""
url = "stacks/%s/resources" % stack_identifier
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_resource(self, stack_identifier, resource_name):
"""Returns the details of a single resource."""
url = "stacks/%s/resources/%s" % (stack_identifier, resource_name)
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def delete_stack(self, stack_identifier):
"""Deletes the specified Stack."""
resp, _ = self.delete("stacks/%s" % str(stack_identifier))
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp)
def wait_for_stack_status(self, stack_identifier, status,
failure_pattern='^.*_FAILED$'):
"""Waits for a Stack to reach a given status."""
start = int(time.time())
fail_regexp = re.compile(failure_pattern)
while True:
try:
body = self.show_stack(stack_identifier)['stack']
except lib_exc.NotFound:
if status == 'DELETE_COMPLETE':
return
stack_name = body['stack_name']
stack_status = body['stack_status']
if stack_status == status:
return body
if fail_regexp.search(stack_status):
raise exceptions.StackBuildErrorException(
stack_identifier=stack_identifier,
stack_status=stack_status,
stack_status_reason=body['stack_status_reason'])
if int(time.time()) - start >= self.build_timeout:
message = ('Stack %s failed to reach %s status (current: %s) '
'within the required time (%s s).' %
(stack_name, status, stack_status,
self.build_timeout))
raise lib_exc.TimeoutException(message)
time.sleep(self.build_interval)
def show_resource_metadata(self, stack_identifier, resource_name):
"""Returns the resource's metadata."""
url = ('stacks/{stack_identifier}/resources/{resource_name}'
'/metadata'.format(**locals()))
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_events(self, stack_identifier):
"""Returns list of all events for a stack."""
url = 'stacks/{stack_identifier}/events'.format(**locals())
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_resource_events(self, stack_identifier, resource_name):
"""Returns list of all events for a resource from stack."""
url = ('stacks/{stack_identifier}/resources/{resource_name}'
'/events'.format(**locals()))
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_event(self, stack_identifier, resource_name, event_id):
"""Returns the details of a single stack's event."""
url = ('stacks/{stack_identifier}/resources/{resource_name}/events'
'/{event_id}'.format(**locals()))
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_template(self, stack_identifier):
"""Returns the template for the stack."""
url = ('stacks/{stack_identifier}/template'.format(**locals()))
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def _validate_template(self, post_body):
"""Returns the validation request result."""
post_body = json.dumps(post_body)
resp, body = self.post('validate', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def validate_template(self, template, parameters=None):
"""Returns the validation result for a template with parameters."""
if parameters is None:
parameters = {}
post_body = {
'template': template,
'parameters': parameters,
}
return self._validate_template(post_body)
def validate_template_url(self, template_url, parameters=None):
"""Returns the validation result for a template with parameters."""
if parameters is None:
parameters = {}
post_body = {
'template_url': template_url,
'parameters': parameters,
}
return self._validate_template(post_body)
def list_resource_types(self):
"""List resource types."""
resp, body = self.get('resource_types')
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_resource_type(self, resource_type_name):
"""Return the schema of a resource type."""
url = 'resource_types/%s' % resource_type_name
resp, body = self.get(url)
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, json.loads(body))
def show_resource_type_template(self, resource_type_name):
"""Return the template of a resource type."""
url = 'resource_types/%s/template' % resource_type_name
resp, body = self.get(url)
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, json.loads(body))
def create_software_config(self, name=None, config=None, group=None,
inputs=None, outputs=None, options=None):
headers, body = self._prep_software_config_create(
name, config, group, inputs, outputs, options)
url = 'software_configs'
resp, body = self.post(url, headers=headers, body=body)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_software_config(self, conf_id):
"""Returns a software configuration resource."""
url = 'software_configs/%s' % str(conf_id)
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def delete_software_config(self, conf_id):
"""Deletes a specific software configuration."""
url = 'software_configs/%s' % str(conf_id)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp)
def create_software_deploy(self, server_id=None, config_id=None,
action=None, status=None,
input_values=None, output_values=None,
status_reason=None, signal_transport=None):
"""Creates or updates a software deployment."""
headers, body = self._prep_software_deploy_update(
None, server_id, config_id, action, status, input_values,
output_values, status_reason, signal_transport)
url = 'software_deployments'
resp, body = self.post(url, headers=headers, body=body)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def update_software_deploy(self, deploy_id=None, server_id=None,
config_id=None, action=None, status=None,
input_values=None, output_values=None,
status_reason=None, signal_transport=None):
"""Creates or updates a software deployment."""
headers, body = self._prep_software_deploy_update(
deploy_id, server_id, config_id, action, status, input_values,
output_values, status_reason, signal_transport)
url = 'software_deployments/%s' % str(deploy_id)
resp, body = self.put(url, headers=headers, body=body)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_software_deployments(self):
"""Returns a list of all deployments."""
url = 'software_deployments'
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_software_deployment(self, deploy_id):
"""Returns a specific software deployment."""
url = 'software_deployments/%s' % str(deploy_id)
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_software_deployment_metadata(self, server_id):
"""Return a config metadata for a specific server."""
url = 'software_deployments/metadata/%s' % server_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def delete_software_deploy(self, deploy_id):
"""Deletes a specific software deployment."""
url = 'software_deployments/%s' % str(deploy_id)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp)
def _prep_software_config_create(self, name=None, conf=None, group=None,
inputs=None, outputs=None, options=None):
"""Prepares a software configuration body."""
post_body = {}
if name is not None:
post_body["name"] = name
if conf is not None:
post_body["config"] = conf
if group is not None:
post_body["group"] = group
if inputs is not None:
post_body["inputs"] = inputs
if outputs is not None:
post_body["outputs"] = outputs
if options is not None:
post_body["options"] = options
body = json.dumps(post_body)
headers = self.get_headers()
return headers, body
def _prep_software_deploy_update(self, deploy_id=None, server_id=None,
config_id=None, action=None, status=None,
input_values=None, output_values=None,
status_reason=None,
signal_transport=None):
"""Prepares a deployment create or update (if an id was given)."""
post_body = {}
if deploy_id is not None:
post_body["id"] = deploy_id
if server_id is not None:
post_body["server_id"] = server_id
if config_id is not None:
post_body["config_id"] = config_id
if action is not None:
post_body["action"] = action
if status is not None:
post_body["status"] = status
if input_values is not None:
post_body["input_values"] = input_values
if output_values is not None:
post_body["output_values"] = output_values
if status_reason is not None:
post_body["status_reason"] = status_reason
if signal_transport is not None:
post_body["signal_transport"] = signal_transport
body = json.dumps(post_body)
headers = self.get_headers()
return headers, body

View File

@ -1,109 +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
auth = '{0}:{1}'.format(uname, pwd)
encoded_auth = base64.b64encode(auth.encode('utf-8'))
headers = {"Authorization": "Basic " + encoded_auth.decode('utf-8'),
'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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
list(map(lambda x: x.pop('updated', None), env_templates_list))
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
list(map(lambda x: x.pop('updated', None),
public_env_templates + [public_env_template] +
[private_env_template] + [private_alt_env_template]))
list(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
list(map(lambda x: x.pop('updated', None), private_env_templates))
list(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
list(map(lambda x: x.pop('updated', None), env_templates))
list(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
list(map(lambda x: x.pop('updated', None), alt_pub_templates))
list(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
list(map(lambda x: x.pop('updated', None), alt_priv_templates))
list(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
list(map(lambda x: x.pop('updated', None), alt_env_templates))
list(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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(b'"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(b'"Hello, John"', action_result)

View File

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

View File

@ -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 = cls.os_primary.credentials.username
cls.password = cls.os_primary.credentials.password
cls.tenant_name = cls.os_primary.credentials.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.auth.admin_username
cls.password = CONF.auth.admin_password
cls.tenant_name = CONF.auth.admin_project_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

View File

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

View File

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

View File

@ -1,32 +0,0 @@
# Copyright (c) 2015 OpenStack Foundation
#
# 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 keystoneclient.v3 as ksclient
from tempest import config
import murano_tempest_tests.tests.functional.common.utils as common_utils
CONF = config.CONF
class TempestDeployTestMixin(common_utils.DeployTestMixin):
"""Overrides methods to use tempest configuration."""
@staticmethod
@common_utils.memoize
def keystone_client():
return ksclient.Client(username=CONF.auth.admin_username,
password=CONF.auth.admin_password,
tenant_name=CONF.auth.admin_project_name,
auth_url=CONF.identity.uri_v3)

View File

@ -1,550 +0,0 @@
# Copyright (c) 2015 OpenStack Foundation
#
# 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 contextlib
import json
import os
import random
import socket
import telnetlib
import time
from heatclient import client as heatclient
from keystoneclient import exceptions as ks_exceptions
import keystoneclient.v3 as ksclient
from muranoclient import client as mclient
import muranoclient.common.exceptions as exceptions
from muranoclient.glance import client as glare_client
from oslo_log import log as logging
from tempest import config
import yaml
import murano_tempest_tests.tests.functional.common.zip_utils_mixin \
as zip_utils
CONF = config.CONF
LOG = logging.getLogger(__name__)
SessionState = collections.namedtuple('SessionState', [
'OPENED', 'DEPLOYING', 'DEPLOYED', 'DEPLOY_FAILURE', 'DELETING',
'DELETE_FAILURE'
])(
OPENED='opened',
DEPLOYING='deploying',
DEPLOYED='deployed',
DEPLOY_FAILURE='deploy failure',
DELETING='deleting',
DELETE_FAILURE='delete failure'
)
@contextlib.contextmanager
def ignored(*exceptions):
try:
yield
except exceptions:
pass
def memoize(f):
"""Saves result of decorated function to cache
Decorator, which saves result of a decorated function
to cache.
TTL for cache is 1800 sec
:param f: decorated function
:return: saved result of a decorated function
"""
cache = {}
def decorated_function(*args):
if args in cache:
if time.time() - cache[args][1] < 1800:
return cache[args][0]
else:
cache[args] = (f(*args), time.time())
return cache[args][0]
else:
cache[args] = (f(*args), time.time())
return cache[args][0]
return decorated_function
class DeployTestMixin(zip_utils.ZipUtilsMixin):
@staticmethod
@memoize
def keystone_client():
return ksclient.Client(username=CONF.auth.admin_username,
password=CONF.auth.admin_password,
tenant_name=CONF.auth.admin_project_name,
auth_url=CONF.identity.uri_v3)
@classmethod
@memoize
def heat_client(cls):
heat_url = cls.keystone_client().service_catalog.url_for(
service_type='orchestration', endpoint_type='publicURL')
return heatclient.Client('1',
endpoint=heat_url,
token=cls.keystone_client().auth_token)
@classmethod
@memoize
def murano_client(cls):
murano_url = cls.get_murano_url()
if CONF.application_catalog.glare_backend:
glare_endpoint = "http://127.0.0.1:9494"
artifacts_client = glare_client.Client(
endpoint=glare_endpoint,
token=cls.keystone_client().auth_token,
insecure=False, key_file=None, ca_file=None, cert_file=None,
type_name="murano", type_version=1)
else:
artifacts_client = None
return mclient.Client('1',
artifacts_client=artifacts_client,
endpoint=murano_url,
token=cls.keystone_client().auth_token)
# --------------------------Specific test methods------------------------------
@classmethod
def deploy_apps(cls, name, *apps):
"""Create and deploy environment.
:param name: Murano environment name
:param apps: App(s), described in JSON format
:return: Murano environment
"""
environment = cls.murano_client().environments.create({'name': name})
cls.init_list("_environments")
cls._environments.append(environment)
session = cls.murano_client().sessions.configure(environment.id)
for app in apps:
cls.murano_client().services.post(
environment.id,
path='/',
data=app,
session_id=session.id)
cls.murano_client().sessions.deploy(environment.id, session.id)
return environment
@classmethod
def wait_for_final_status(cls, environment, timeout=300):
"""Function for wait final status of environment.
:param environment: Murano environment.
:param timeout: Timeout for waiting environment to get any status
excluding DEPLOYING state
"""
start_time = time.time()
status = environment.manager.get(environment.id).status
while SessionState.DEPLOYING == status:
if time.time() - start_time > timeout:
err_msg = ('Deployment not finished in {amount} seconds'
.format(amount=timeout))
LOG.error(err_msg)
raise RuntimeError(err_msg)
time.sleep(5)
status = environment.manager.get(environment.id).status
dep = cls.murano_client().deployments.list(environment.id)
reports = cls.murano_client().deployments.reports(environment.id,
dep[0].id)
return status, ", ".join([r.text for r in reports])
# -----------------------------Reports methods---------------------------------
@classmethod
def get_last_deployment(cls, environment):
"""Gets last deployment of Murano environment.
:param environment: Murano environment
:return:
"""
deployments = cls.murano_client().deployments.list(environment.id)
return deployments[0]
@classmethod
def get_deployment_report(cls, environment, deployment):
"""Gets reports for environment with specific deployment.
:param environment: Murano environment.
:param deployment: Murano deployment for certain environment
:return:
"""
history = ''
report = cls.murano_client().deployments.reports(
environment.id, deployment.id)
for status in report:
history += '\t{0} - {1}\n'.format(status.created, status.text)
return history
@classmethod
def _log_report(cls, environment):
"""Used for logging reports on failures.
:param environment: Murano environment.
"""
deployment = cls.get_last_deployment(environment)
try:
details = deployment.result['result']['details']
LOG.warning('Details:\n {details}'.format(details=details))
except Exception as e:
LOG.error(e)
report = cls.get_deployment_report(environment, deployment)
LOG.debug('Report:\n {report}\n'.format(report=report))
# -----------------------------Service methods---------------------------------
@classmethod
def add_service(cls, environment, data, session, to_dict=False):
"""This function adds a specific service to environment.
:param environment: Murano environment
:param data: JSON with specific servive to add into
:param session: Session that is open for environment
:param to_dict: If True - returns a JSON object with service
If False - returns a specific class <Service>
"""
LOG.debug('Added service:\n {data}'.format(data=data))
service = cls.murano_client().services.post(environment.id,
path='/', data=data,
session_id=session.id)
if to_dict:
return cls._convert_service(service)
else:
return service
@classmethod
def services_list(cls, environment):
"""Get a list of environment services.
:param environment: Murano environment
:return: List of <Service> objects
"""
return cls.murano_client().services.list(environment.id)
@classmethod
def get_service(cls, environment, service_name, to_dict=True):
"""Get a service with specific name from environment.
:param to_dict: Convert service to JSON or not to convert
:param environment: Murano environment
:param service_name: Service name
:return: JSON or <Service> object
"""
for service in cls.services_list(environment):
if service.name == service_name:
return cls._convert_service(service) if to_dict else service
@classmethod
def _convert_service(cls, service):
"""Converts a <Service> to JSON object.
:param service: <Service> object
:return: JSON object
"""
component = service.to_dict()
component = json.dumps(component)
return yaml.safe_load(component)
@classmethod
def get_service_id(cls, service):
"""Gets id on <Service> object.
:param service: <Service> object
:return: ID of the Service
"""
serv = cls._convert_service(service)
serv_id = serv['?']['id']
return serv_id
@classmethod
def delete_service(cls, environment, session, service):
"""This function removes a specific service from environment.
:param environment: Murano environment
:param session: Session fir urano environment
:param service: <Service> object
:return: Updated murano environment
"""
cls.murano_client().services.delete(
environment.id, path='/{0}'.format(cls.get_service_id(service)),
session_id=session.id)
LOG.debug('Service with name {0} from environment {1} successfully '
'removed'.format(environment.name, service.name))
updated_env = cls.get_environment(environment)
return updated_env
# -----------------------------Packages methods--------------------------------
@classmethod
def upload_package(cls, package_name, body, app):
"""Uploads a .zip package with parameters to Murano.
:param package_name: Package name in Murano repository
:param body: Categories, tags, etc.
e.g. {
"categories": ["Application Servers"],
"tags": ["tag"]
}
:param app: Correct .zip archive with the application
:return: Package
"""
files = {'{0}'.format(package_name): open(app, 'rb')}
package = cls.murano_client().packages.create(body, files)
cls.init_list("_packages")
cls._packages.append(package)
return package
# ------------------------------Common methods---------------------------------
@classmethod
def rand_name(cls, name='murano'):
"""Generates random string.
:param name: Basic name
:return:
"""
return name + str(random.randint(1, 0x7fffffff))
@classmethod
def init_list(cls, list_name):
if not hasattr(cls, list_name):
setattr(cls, list_name, [])
@classmethod
def get_murano_url(cls):
try:
url = cls.keystone_client().service_catalog.url_for(
service_type='application-catalog', endpoint_type='publicURL')
except ks_exceptions.EndpointNotFound:
url = CONF.murano.murano_url
LOG.warning("Murano endpoint not found in Keystone. "
"Using CONF.")
return url if 'v1' not in url else "/".join(
url.split('/')[:url.split('/').index('v1')])
@classmethod
def verify_connection(cls, ip, port):
"""Try to connect to specific ip:port with telnet.
:param ip: Ip that you want to check
:param port: Port that you want to check
:return: :raise RuntimeError:
"""
tn = telnetlib.Telnet(ip, port)
tn.write('GET / HTTP/1.0\n\n')
try:
buf = tn.read_all()
LOG.debug('Data:\n {data}'.format(data=buf))
if len(buf) != 0:
tn.sock.sendall(telnetlib.IAC + telnetlib.NOP)
return
else:
raise RuntimeError('Resource at {0}:{1} not exist'.
format(ip, port))
except socket.error as e:
LOG.error('Socket Error: {error}'.format(error=e))
@classmethod
def get_ip_by_appname(cls, environment, appname):
"""Returns ip of instance with a deployed application using app name.
:param environment: Murano environment
:param appname: Application name or substring of application name
:return:
"""
for service in environment.services:
if appname in service['name']:
return service['instance']['floatingIpAddress']
@classmethod
def get_ip_by_instance_name(cls, environment, inst_name):
"""Returns ip of instance using instance name.
:param environment: Murano environment
:param name: String, which is substring of name of instance or name of
instance
:return:
"""
for service in environment.services:
if inst_name in service['instance']['name']:
return service['instance']['floatingIpAddress']
@classmethod
def get_k8s_ip_by_instance_name(cls, environment, inst_name, service_name):
"""Returns ip of specific kubernetes node (gateway, master, minion).
Search depends on service name of kubernetes and names of spawned
instances
:param environment: Murano environment
:param inst_name: Name of instance or substring of instance name
:param service_name: Name of Kube Cluster application in Murano
environment
:return: Ip of Kubernetes instances
"""
for service in environment.services:
if service_name in service['name']:
if "gateway" in inst_name:
for gateway in service['gatewayNodes']:
if inst_name in gateway['instance']['name']:
LOG.debug(gateway['instance']['floatingIpAddress'])
return gateway['instance']['floatingIpAddress']
elif "master" in inst_name:
LOG.debug(service['masterNode']['instance'][
'floatingIpAddress'])
return service['masterNode']['instance'][
'floatingIpAddress']
elif "minion" in inst_name:
for minion in service['minionNodes']:
if inst_name in minion['instance']['name']:
LOG.debug(minion['instance']['floatingIpAddress'])
return minion['instance']['floatingIpAddress']
# -----------------------------Cleanup methods---------------------------------
@classmethod
def purge_uploaded_packages(cls):
"""Cleanup for uploaded packages."""
cls.init_list("_packages")
try:
for pkg in cls._packages:
with ignored(Exception):
cls.murano_client().packages.delete(pkg.id)
finally:
cls._packages = []
cls.init_list("_package_files")
try:
for pkg_file in cls._package_files:
os.remove(pkg_file)
finally:
cls._package_files = []
@classmethod
def purge_environments(cls):
"""Cleanup for created environments."""
cls.init_list("_environments")
try:
for env in cls._environments:
with ignored(Exception):
LOG.debug('Processing cleanup for environment {0} ({1})'.
format(env.name, env.id))
cls.environment_delete(env.id)
cls.purge_stacks(env.id)
time.sleep(5)
finally:
cls._environments = []
@classmethod
def purge_stacks(cls, environment_id):
stack = cls._get_stack(environment_id)
if not stack:
return
else:
cls.heat_client().stacks.delete(stack.id)
# -----------------------Methods for environment CRUD--------------------------
@classmethod
def create_environment(cls, name=None):
"""Creates Murano environment with random name.
:param name: Environment name
:return: Murano environment
"""
if not name:
name = cls.rand_name('MuranoTe')
environment = cls.murano_client().environments.create({'name': name})
cls._environments.append(environment)
return environment
@classmethod
def get_environment(cls, environment):
"""Refresh <Environment> variable.
:param environment: Murano environment.
:return: Murano environment.
"""
return cls.murano_client().environments.get(environment.id)
@classmethod
def environment_delete(cls, environment_id, timeout=180):
"""Remove Murano environment.
:param environment_id: ID of Murano environment
:param timeout: Timeout to environment get deleted
:return: :raise RuntimeError:
"""
try:
cls.murano_client().environments.delete(environment_id)
start_time = time.time()
while time.time() - start_time < timeout:
try:
cls.murano_client().environments.get(environment_id)
except exceptions.HTTPNotFound:
LOG.debug('Environment with id {0} successfully deleted.'.
format(environment_id))
return
err_msg = ('Environment {0} was not deleted in {1} seconds'.
format(environment_id, timeout))
LOG.error(err_msg)
raise RuntimeError(err_msg)
except Exception as exc:
LOG.debug('Environment with id {0} going to be abandoned.'.
format(environment_id))
LOG.exception(exc)
cls.murano_client().environments.delete(environment_id,
abandon=True)
# -----------------------Methods for session actions---------------------------
@classmethod
def create_session(cls, environment):
return cls.murano_client().sessions.configure(environment.id)
@classmethod
def delete_session(cls, environment, session):
return cls.murano_client().sessions.delete(environment.id, session.id)
# -------------------------------Heat methods----------------------------------
@classmethod
def _get_stack(cls, environment_id):
for stack in cls.heat_client().stacks.list():
stack_description = (
cls.heat_client().stacks.get(stack.id).description)
if not stack_description:
err_msg = ("Stack {0} description is empty".format(stack.id))
LOG.error(err_msg)
raise RuntimeError(err_msg)
if environment_id in stack_description:
return stack
@classmethod
def get_stack_template(cls, stack):
return cls.heat_client().stacks.template(stack.stack_name)

View File

@ -1,30 +0,0 @@
# Copyright (c) 2015 OpenStack Foundation
#
# 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 zipfile
class ZipUtilsMixin(object):
@staticmethod
def zip_dir(parent_dir, dir):
abs_path = os.path.join(parent_dir, dir)
path_len = len(abs_path) + 1
zip_file = abs_path + ".zip"
with zipfile.ZipFile(zip_file, "w") as zf:
for dir_name, _, files in os.walk(abs_path):
for filename in files:
fn = os.path.join(dir_name, filename)
zf.write(fn, fn[path_len:])
return zip_file

View File

@ -1,72 +0,0 @@
# Copyright (c) 2015 OpenStack Foundation, 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 uuid
import mistralclient.api.client as mistralclient
import testresources
import testtools
import murano_tempest_tests.tests.functional.common.tempest_utils \
as tempest_utils
import murano_tempest_tests.tests.functional.common.utils as utils
class MistralIntegration(testtools.TestCase, testtools.testcase.WithAttributes,
testresources.ResourcedTestCase,
tempest_utils.TempestDeployTestMixin):
@classmethod
@utils.memoize
def mistral_client(cls):
keystone_client = cls.keystone_client()
endpoint_type = 'publicURL'
service_type = 'workflowv2'
mistral_url = keystone_client.service_catalog.url_for(
service_type=service_type,
endpoint_type=endpoint_type)
auth_token = keystone_client.auth_token
return mistralclient.client(mistral_url=mistral_url,
auth_url=keystone_client.auth_url,
project_id=keystone_client.tenant_id,
endpoint_type=endpoint_type,
service_type=service_type,
auth_token=auth_token,
user_id=keystone_client.user_id)
@classmethod
def upload_mistral_showcase_app(cls):
app_dir = 'io.murano.apps.test.MistralShowcaseApp'
zip_file_path = cls.zip_dir(os.path.dirname(__file__), app_dir)
cls.init_list("_package_files")
cls._package_files.append(zip_file_path)
return cls.upload_package(
'MistralShowcaseApp',
{"categories": ["Web"], "tags": ["tag"]},
zip_file_path)
@staticmethod
def _create_env_body():
return {
"name": "Mistral_environment",
"?": {
"type": "io.murano.apps.test.MistralShowcaseApp",
"id": str(uuid.uuid4())
}
}

View File

@ -1,32 +0,0 @@
Namespaces:
=: io.murano.apps.test
std: io.murano
sys: io.murano.system
Name: MistralShowcaseApp
Extends: std:Application
Properties:
name:
Contract: $.string().notNull()
mistralClient:
Contract: $.class(sys:MistralClient)
Usage: Runtime
Methods:
initialize:
Body:
- $environment: $.find(std:Environment).require()
- $this.mistralClient: new(sys:MistralClient, $environment)
deploy:
Body:
- $resources: new('io.murano.system.Resources')
- $workflow: $resources.string('TestEcho_MistralWorkflow.yaml')
- $.mistralClient.upload(definition => $workflow)
- $output: $.mistralClient.run(name => 'test_echo', inputs => dict(input_1 => input_1_value))
- $this.find(std:Environment).reporter.report($this, $output.get('out_3'))

View File

@ -1,24 +0,0 @@
version: '2.0'
test_echo:
type: direct
input:
- input_1
output:
out_1: <% $.task1_output_1 %>
out_2: <% $.task2_output_2 %>
out_3: <% $.input_1 %>
tasks:
my_echo_test:
action: std.echo output='just a string'
publish:
task1_output_1: 'task1_output_1_value'
task1_output_2: 'task1_output_2_value'
on-success:
- my_echo_test_2
my_echo_test_2:
action: std.echo output='just a string'
publish:
task2_output_1: 'task2_output_1_value'
task2_output_2: 'task2_output_2_value'

View File

@ -1,10 +0,0 @@
Format: 1.0
Type: Application
FullName: io.murano.apps.test.MistralShowcaseApp
Name: MistralShowcaseApp
Description: |
MistralShowcaseApp.
Author: 'Mirantis, Inc'
Tags: [Servlets, Server, Pages, Java]
Classes:
io.murano.apps.test.MistralShowcaseApp: MistralShowcaseApp.yaml

View File

@ -1,48 +0,0 @@
Namespaces:
=: io.murano.apps.test
std: io.murano
res: io.murano.resources
sys: io.murano.system
Name: PolicyEnforcementTestApp
Extends: std:Application
Properties:
name:
Contract: $.string().notNull()
instance:
Contract: $.class(res:Instance).notNull()
host:
Contract: $.string()
Usage: Out
user:
Contract: $.string()
Usage: Out
Methods:
initialize:
Body:
- $._environment: $.find(std:Environment).require()
deploy:
Body:
- If: not $.getAttr(deployed, false)
Then:
- $._environment.reporter.report($this, 'Creating VM')
- $securityGroupIngress:
- ToPort: 22
FromPort: 22
IpProtocol: tcp
External: true
- $._environment.securityGroupManager.addGroupIngress($securityGroupIngress)
- $.instance.deploy()
- $resources: new(sys:Resources)
- $._environment.reporter.report($this, 'Test VM is installed')
- $.host: $.instance.ipAddresses[0]
- $.user: 'root'
- $.setAttr(deployed, true)

View File

@ -1,10 +0,0 @@
Format: 1.0
Type: Application
FullName: io.murano.apps.test.PolicyEnforcementTestApp
Name: PolicyEnforcementTestApp
Description: |
This is a simple test app with a single VM for policy enforcement testing purposes.
Author: 'Hewlett-Packard'
Tags: [test]
Classes:
io.murano.apps.test.PolicyEnforcementTestApp: PolicyEnforcementTestApp.yaml

Some files were not shown because too many files have changed in this diff Show More