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:
parent
d2b794cbf0
commit
528f48107c
@ -1,6 +0,0 @@
|
||||
[run]
|
||||
branch = True
|
||||
source = murano_tempest_tests
|
||||
|
||||
[report]
|
||||
ignore_errors = True
|
58
.gitignore
vendored
58
.gitignore
vendored
@ -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
|
3
.mailmap
3
.mailmap
@ -1,3 +0,0 @@
|
||||
# Format is:
|
||||
# <preferred e-mail> <other e-mail 1>
|
||||
# <preferred e-mail> <other e-mail 2>
|
@ -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
|
42
.zuul.yaml
42
.zuul.yaml
@ -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
|
@ -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
|
@ -1,4 +0,0 @@
|
||||
murano-tempest-plugin Style Commandments
|
||||
========================================
|
||||
|
||||
Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/
|
176
LICENSE
176
LICENSE
@ -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.
|
||||
|
48
README.rst
48
README.rst
@ -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.
|
||||
|
@ -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
|
@ -1,5 +0,0 @@
|
||||
====================
|
||||
Administrators guide
|
||||
====================
|
||||
|
||||
Administrators guide of murano-tempest-plugin.
|
@ -1,5 +0,0 @@
|
||||
================================
|
||||
Command line interface reference
|
||||
================================
|
||||
|
||||
CLI reference of murano-tempest-plugin.
|
@ -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}
|
@ -1,5 +0,0 @@
|
||||
=============
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Configuration of murano-tempest-plugin.
|
@ -1,4 +0,0 @@
|
||||
============
|
||||
Contributing
|
||||
============
|
||||
.. include:: ../../../CONTRIBUTING.rst
|
@ -1,9 +0,0 @@
|
||||
===========================
|
||||
Contributor Documentation
|
||||
===========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
contributing
|
||||
|
@ -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`
|
@ -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
|
@ -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
|
@ -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...
|
@ -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/>`_.
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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/.
|
@ -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
|
@ -1,7 +0,0 @@
|
||||
========
|
||||
Usage
|
||||
========
|
||||
|
||||
To use murano-tempest-plugin in a project::
|
||||
|
||||
import murano_tempest_tests
|
@ -1 +0,0 @@
|
||||
.. include:: ../../README.rst
|
@ -1,5 +0,0 @@
|
||||
==========
|
||||
References
|
||||
==========
|
||||
|
||||
References of murano-tempest-plugin.
|
@ -1,5 +0,0 @@
|
||||
===========
|
||||
Users guide
|
||||
===========
|
||||
|
||||
Users guide of murano-tempest-plugin.
|
@ -1,72 +0,0 @@
|
||||
# Copyright (c) 2015 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.common import credentials_factory as common_creds
|
||||
from tempest import config
|
||||
from tempest.lib import auth
|
||||
|
||||
from murano_tempest_tests.services.application_catalog \
|
||||
import application_catalog_client
|
||||
from murano_tempest_tests.services.artifacts import artifacts_client
|
||||
from murano_tempest_tests.services.service_broker import service_broker_client
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class Manager(object):
|
||||
def __init__(self,
|
||||
credentials=None):
|
||||
if credentials is None:
|
||||
credentials = common_creds.\
|
||||
get_configured_admin_credentials('identity_admin')
|
||||
self.auth_provider = get_auth_provider(credentials)
|
||||
self.service_broker_client = service_broker_client.ServiceBrokerClient(
|
||||
self.auth_provider)
|
||||
if CONF.application_catalog.glare_backend:
|
||||
self.artifacts_client = artifacts_client.ArtifactsClient(
|
||||
self.auth_provider)
|
||||
else:
|
||||
self.artifacts_client = None
|
||||
self.application_catalog_client = \
|
||||
application_catalog_client.ApplicationCatalogClient(
|
||||
self.auth_provider)
|
||||
|
||||
|
||||
class AltManager(Manager):
|
||||
def __init__(self, service=None):
|
||||
super(AltManager, self).__init__(
|
||||
common_creds.get_configured_admin_credentials('alt_user'), service)
|
||||
|
||||
|
||||
def get_auth_provider(credentials, scope='project'):
|
||||
default_params = {
|
||||
'disable_ssl_certificate_validation':
|
||||
CONF.identity.disable_ssl_certificate_validation,
|
||||
'ca_certs': CONF.identity.ca_certificates_file,
|
||||
'trace_requests': CONF.debug.trace_requests
|
||||
}
|
||||
|
||||
if isinstance(credentials, auth.KeystoneV3Credentials):
|
||||
auth_provider_class, auth_url = \
|
||||
auth.KeystoneV3AuthProvider, CONF.identity.uri_v3
|
||||
else:
|
||||
auth_provider_class, auth_url = \
|
||||
auth.KeystoneV2AuthProvider, CONF.identity.uri
|
||||
|
||||
_auth_provider = auth_provider_class(credentials, auth_url,
|
||||
scope=scope,
|
||||
**default_params)
|
||||
_auth_provider.set_auth()
|
||||
return _auth_provider
|
@ -1,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.")
|
||||
]
|
@ -1,47 +0,0 @@
|
||||
Namespaces:
|
||||
=: io.murano.apps
|
||||
std: io.murano
|
||||
|
||||
Extends: std:Application
|
||||
|
||||
Properties:
|
||||
|
||||
userName:
|
||||
Contract: $.string()
|
||||
|
||||
greeting:
|
||||
Usage: Static
|
||||
Contract: $.string()
|
||||
Default: 'Hello, '
|
||||
|
||||
Methods:
|
||||
testAction:
|
||||
Scope: Public
|
||||
Body:
|
||||
- $this.find(std:Environment).reporter.report($this, 'Completed')
|
||||
getCredentials:
|
||||
Scope: Public
|
||||
Body:
|
||||
- Return:
|
||||
credentials:
|
||||
uri: localhost
|
||||
deploy:
|
||||
Body:
|
||||
- $this.find(std:Environment).reporter.report($this, 'Follow the white rabbit')
|
||||
|
||||
staticAction:
|
||||
Scope: Public
|
||||
Usage: Static
|
||||
Arguments:
|
||||
- myName:
|
||||
Contract: $.string().notNull()
|
||||
Body:
|
||||
- Return: concat($.greeting, $myName)
|
||||
|
||||
staticNotAction:
|
||||
Usage: Static
|
||||
Arguments:
|
||||
- myName:
|
||||
Contract: $.string().notNull()
|
||||
Body:
|
||||
- Return: concat($.greeting, $myName)
|
@ -1,22 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Version: 2.2
|
||||
|
||||
Forms:
|
||||
- appConfiguration:
|
||||
fields:
|
||||
- name: license
|
||||
type: string
|
||||
description: Apache License, Version 2.0
|
||||
hidden: false
|
||||
required: false
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
@ -1,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)
|
@ -1,8 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title> Hello World</title>
|
||||
</head>
|
||||
<body>Hello world. This is my first web page. My name is %USER_NAME%.
|
||||
</body>
|
||||
</html>
|
@ -1,28 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Format: 1.0
|
||||
Type: Application
|
||||
FullName: io.murano.test.apache.ApacheHttpServerCustom
|
||||
Name: Apache HTTP Server Custom
|
||||
Description: |
|
||||
The Apache HTTP Server Project is an effort to develop and maintain an
|
||||
open-source HTTP server for modern operating systems including UNIX and
|
||||
Windows NT. The goal of this project is to provide a secure, efficient and
|
||||
extensible server that provides HTTP services in sync with the current HTTP
|
||||
standards.
|
||||
Apache httpd has been the most popular web server on the Internet since
|
||||
April 1996, and celebrated its 17th birthday as a project this February.
|
||||
Author: 'Mirantis, Inc'
|
||||
Tags: [HTTP, Server, WebServer, HTML, Apache]
|
||||
Classes:
|
||||
io.murano.apps.test.ApacheHttpServerCustom: ApacheHttpServer.yaml
|
@ -1,55 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Namespaces:
|
||||
=: io.murano.apps.test
|
||||
std: io.murano
|
||||
sys: io.murano.system
|
||||
|
||||
Name: Lighttpd
|
||||
|
||||
Extends: std:Application
|
||||
|
||||
Properties:
|
||||
updater:
|
||||
Contract: $.class(UpdateExecutor).notNull()
|
||||
|
||||
Methods:
|
||||
initialize:
|
||||
Body:
|
||||
- $._environment: $.find(std:Environment).require()
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- If: not $.getAttr(deployed, false)
|
||||
Then:
|
||||
- $securityGroupIngress:
|
||||
- ToPort: 80
|
||||
FromPort: 80
|
||||
IpProtocol: tcp
|
||||
External: true
|
||||
- ToPort: 443
|
||||
FromPort: 443
|
||||
IpProtocol: tcp
|
||||
External: true
|
||||
- $._environment.securityGroupManager.addGroupIngress($securityGroupIngress)
|
||||
- $._environment.reporter.report($this, 'Ensuring Updater is deployed.')
|
||||
- $.updater.deploy()
|
||||
- $resources: new(sys:Resources)
|
||||
- $template: $resources.yaml('DeployLighttpd.template')
|
||||
- $.updater.instance.agent.call($template, $resources)
|
||||
|
||||
- If: $.updater.instance.assignFloatingIp
|
||||
Then:
|
||||
- $address: $.updater.instance.floatingIpAddress
|
||||
- $._environment.reporter.report($this, format('Running at http://{0}', $address))
|
||||
- $.setAttr(deployed, true)
|
@ -1,27 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
FormatVersion: 2.0.0
|
||||
Version: 1.0.0
|
||||
Name: Deploy Lighttpd
|
||||
|
||||
Body: |
|
||||
deploy()
|
||||
|
||||
Scripts:
|
||||
deploy:
|
||||
Type: Application
|
||||
Version: 1.0.0
|
||||
EntryPoint: deployLighttpd.sh
|
||||
Options:
|
||||
captureStdout: true
|
||||
captureStderr: true
|
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
sudo apt-get -y -q install lighttpd
|
@ -1,24 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Format: 1.0
|
||||
Type: Application
|
||||
FullName: io.murano.apps.test.Lighttpd
|
||||
Name: Lighttpd
|
||||
Description: |
|
||||
Lighttpd... :)
|
||||
Author: 'Mirantis, Inc'
|
||||
Tags: [Web]
|
||||
Classes:
|
||||
io.murano.apps.test.Lighttpd: Lighttpd.yaml
|
||||
Require:
|
||||
io.murano.apps.test.UpdateExecutor:
|
@ -1,47 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Namespaces:
|
||||
=: io.murano.apps.test
|
||||
std: io.murano
|
||||
res: io.murano.resources
|
||||
sys: io.murano.system
|
||||
conf: io.murano.configuration
|
||||
|
||||
|
||||
Name: UpdateExecutor
|
||||
|
||||
Extends: std:Application
|
||||
|
||||
Properties:
|
||||
name:
|
||||
Contract: $.string().notNull()
|
||||
|
||||
instance:
|
||||
Contract: $.class(res:Instance).notNull()
|
||||
|
||||
Methods:
|
||||
initialize:
|
||||
Body:
|
||||
- $._environment: $.find(std:Environment).require()
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- If: not $.getAttr(deployed, false)
|
||||
Then:
|
||||
- $._environment.reporter.report($this, 'Creating VM.')
|
||||
- $.instance.deploy()
|
||||
- $._environment.reporter.report($this, 'Starting packages updating.')
|
||||
- $file: sys:Resources.string('scripts/update.sh')
|
||||
- conf:Linux.runCommand($.instance.agent, $file)
|
||||
- $._environment.reporter.report($this, 'Update completed.')
|
||||
- $.setAttr(deployed, true)
|
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
sudo apt-get update
|
@ -1,22 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Format: 1.0
|
||||
Type: Application
|
||||
FullName: io.murano.apps.test.UpdateExecutor
|
||||
Name: Update Executor
|
||||
Description: |
|
||||
Test application, which updates packages on VM
|
||||
Author: 'Mirantis, Inc'
|
||||
Tags: [application]
|
||||
Classes:
|
||||
io.murano.apps.test.UpdateExecutor: UpdateExecutor.yaml
|
@ -1,66 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Namespaces:
|
||||
=: io.murano.apps.test
|
||||
std: io.murano
|
||||
res: io.murano.resources
|
||||
sys: io.murano.system
|
||||
conf: io.murano.configuration
|
||||
|
||||
|
||||
Name: VM
|
||||
|
||||
Extends: std:Application
|
||||
|
||||
Properties:
|
||||
name:
|
||||
Contract: $.string().notNull()
|
||||
|
||||
instance:
|
||||
Contract: $.class(res:Instance).notNull()
|
||||
|
||||
userName:
|
||||
Contract: $.string()
|
||||
|
||||
Methods:
|
||||
initialize:
|
||||
Body:
|
||||
- $._environment: $.find(std:Environment).require()
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- If: not $.getAttr(deployed, false)
|
||||
Then:
|
||||
- $._environment.reporter.report($this, 'Creating VM')
|
||||
- $securityGroupIngress:
|
||||
- ToPort: 80
|
||||
FromPort: 80
|
||||
IpProtocol: tcp
|
||||
External: true
|
||||
- ToPort: 443
|
||||
FromPort: 443
|
||||
IpProtocol: tcp
|
||||
External: true
|
||||
- $._environment.securityGroupManager.addGroupIngress($securityGroupIngress)
|
||||
- $.instance.deploy()
|
||||
- $._environment.reporter.report($this, 'Instance is created.')
|
||||
|
||||
- $resources: new(sys:Resources)
|
||||
- $linux: new(conf:Linux)
|
||||
|
||||
- If: $.instance.assignFloatingIp
|
||||
Then:
|
||||
- $host: $.instance.floatingIpAddress
|
||||
Else:
|
||||
- $host: $.instance.ipAddresses[0]
|
||||
- $.setAttr(deployed, true)
|
@ -1,8 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title> Hello World</title>
|
||||
</head>
|
||||
<body>Hello world. This is my first web page. My name is %USER_NAME%.
|
||||
</body>
|
||||
</html>
|
@ -1,22 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
Format: 1.0
|
||||
Type: Application
|
||||
FullName: io.murano.test.VM.VM
|
||||
Name: VM
|
||||
Description: |
|
||||
application which simply boot a virtual machine
|
||||
Author: 'Mirantis, Inc'
|
||||
Tags: [Server]
|
||||
Classes:
|
||||
io.murano.apps.test.VM: VM.yaml
|
@ -1,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)]
|
@ -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
|
@ -1,157 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib.common import rest_client
|
||||
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class ArtifactsClient(rest_client.RestClient):
|
||||
"""Tempest REST client for Glance Artifacts"""
|
||||
|
||||
def __init__(self, auth_provider):
|
||||
super(ArtifactsClient, self).__init__(
|
||||
auth_provider,
|
||||
CONF.artifacts.catalog_type,
|
||||
CONF.identity.region,
|
||||
endpoint_type=CONF.artifacts.endpoint_type)
|
||||
self.build_interval = CONF.artifacts.build_interval
|
||||
self.build_timeout = CONF.artifacts.build_timeout
|
||||
|
||||
# -----------------------------Artifacts methods-------------------------------
|
||||
|
||||
def list_artifacts(self):
|
||||
uri = 'v0.1/artifacts/murano/v1'
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
parsed = self._parse_resp(body)
|
||||
return parsed['artifacts']
|
||||
|
||||
def list_drafts(self):
|
||||
uri = 'v0.1/artifacts/murano/v1/creating'
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def list_deactivated_drafts(self):
|
||||
uri = 'v0.1/artifacts/murano/v1/deactivated'
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def create_artifact_draft(self, name, version, **kwargs):
|
||||
uri = 'v0.1/artifacts/murano/v1/drafts'
|
||||
kwargs.update({'name': name, 'version': version})
|
||||
resp, body = self.post(uri, body=json.dumps(kwargs))
|
||||
self.expected_success(201, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def publish_artifact(self, artifact_id):
|
||||
uri = 'v0.1/artifacts/murano/v1/{0}/publish'.format(artifact_id)
|
||||
resp, body = self.post(uri, body='')
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def get_artifact(self, artifact_id):
|
||||
uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def update_artifact(self, artifact_id, body):
|
||||
headers = {
|
||||
'Content-Type': 'application/openstack-images-v2.1-json-patch'}
|
||||
uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id)
|
||||
resp, body = self.patch(uri, json.dumps(body), headers=headers)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def delete_artifact(self, artifact_id):
|
||||
uri = 'v0.1/artifacts/murano/v1/{0}'.format(artifact_id)
|
||||
resp, body = self.delete(uri)
|
||||
self.expected_success(204, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def upload_blob(self, artifact_id, blob_type, data):
|
||||
headers = {'Content-Type': 'application/octet-stream'}
|
||||
uri = 'v0.1/artifacts/murano/v1/{0}/{1}'.format(
|
||||
artifact_id, blob_type)
|
||||
resp, body = self.put(uri, data, headers=headers)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def download_blob(self, artifact_id, blob_type):
|
||||
uri = 'v0.1/artifacts/murano/v1/{0}/{1}/download'.format(
|
||||
artifact_id, blob_type)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
# -----------------------------Packages methods-------------------------------
|
||||
|
||||
def get_list_packages(self):
|
||||
return self.list_artifacts()
|
||||
|
||||
def delete_package(self, package_id):
|
||||
return self.delete_artifact(package_id)
|
||||
|
||||
def upload_package(self, package_name, package_path, top_dir, body):
|
||||
files = {package_name: open(os.path.join(top_dir, package_path), 'rb')}
|
||||
is_public = body.pop('is_public', None)
|
||||
if is_public is not None:
|
||||
body['visibility'] = 'public' if is_public else 'private'
|
||||
fqn = list(files.keys())[0]
|
||||
package = utils.Package.from_file(files[fqn])
|
||||
manifest = package.manifest
|
||||
package_draft = {
|
||||
'name': manifest.get('FullName', fqn),
|
||||
'version': manifest.get('Version', '0.0.0'),
|
||||
'description': manifest.get('Description'),
|
||||
'display_name': manifest.get('Name', fqn),
|
||||
'type': manifest.get('Type', 'Application'),
|
||||
'author': manifest.get('Author'),
|
||||
'tags': manifest.get('Tags', []),
|
||||
'class_definitions': package.classes.keys()
|
||||
}
|
||||
for k, v in body.items():
|
||||
package_draft[k] = v
|
||||
|
||||
inherits = utils.get_local_inheritance(package.classes)
|
||||
|
||||
# TODO(kzaitsev): add local and global inheritance information tests
|
||||
package_draft['inherits'] = inherits
|
||||
|
||||
keywords = package_draft['tags']
|
||||
package_draft['keywords'] = keywords
|
||||
|
||||
draft = self.create_artifact_draft(**package_draft)
|
||||
self.upload_blob(draft['id'], 'archive', package.file())
|
||||
|
||||
# TODO(kzaitsev): add logo upload code, currently it's failing for me
|
||||
# with io.UnsupportedOperation: fileno
|
||||
|
||||
# if package.logo is not None:
|
||||
# self.upload_blob(draft['id'], 'logo', package.logo)
|
||||
# if package.ui is not None:
|
||||
# self.client.artifacts.upload_blob(draft['id'], 'ui_definition',
|
||||
# package.ui)
|
||||
self.publish_artifact(draft['id'])
|
||||
return draft
|
@ -1,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
|
@ -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)
|
@ -1,97 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.common import credentials_factory as common_creds
|
||||
from tempest import config
|
||||
from tempest import test
|
||||
|
||||
from murano_tempest_tests import clients
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class BaseArtifactsTest(test.BaseTestCase):
|
||||
"""Base test class for Murano Glare tests."""
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(BaseArtifactsTest, cls).skip_checks()
|
||||
if not CONF.service_available.murano:
|
||||
skip_msg = "Murano is disabled"
|
||||
raise cls.skipException(skip_msg)
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseArtifactsTest, cls).setup_clients()
|
||||
if not hasattr(cls, "os_primary"):
|
||||
creds = cls.get_configured_isolated_creds(type_of_creds='primary')
|
||||
cls.os_primary = clients.Manager(credentials=creds)
|
||||
cls.artifacts_client = cls.os_primary.artifacts_client
|
||||
cls.application_catalog_client = \
|
||||
cls.os_primary.application_catalog_client
|
||||
|
||||
@classmethod
|
||||
def get_client_with_isolated_creds(cls, type_of_creds="admin"):
|
||||
creds = cls.get_configured_isolated_creds(type_of_creds=type_of_creds)
|
||||
|
||||
os = clients.Manager(credentials=creds)
|
||||
client = os.artifacts_client
|
||||
|
||||
return client
|
||||
|
||||
@classmethod
|
||||
def get_configured_isolated_creds(cls, type_of_creds='admin'):
|
||||
identity_version = CONF.identity.auth_version
|
||||
if identity_version == 'v3':
|
||||
cls.admin_role = CONF.identity.admin_role
|
||||
else:
|
||||
cls.admin_role = 'admin'
|
||||
cls.credentials = common_creds.get_credentials_provider(
|
||||
name=cls.__name__,
|
||||
force_tenant_isolation=CONF.auth.use_dynamic_credentials,
|
||||
identity_version=CONF.identity.auth_version)
|
||||
if type_of_creds == 'primary':
|
||||
creds = cls.credentials.get_primary_creds()
|
||||
elif type_of_creds == 'admin':
|
||||
creds = cls.credentials.get_admin_creds()
|
||||
elif type_of_creds == 'alt':
|
||||
creds = cls.credentials.get_alt_creds()
|
||||
else:
|
||||
creds = cls.credentials.get_credentials(type_of_creds)
|
||||
cls.credentials.type_of_creds = type_of_creds
|
||||
|
||||
return creds.credentials
|
||||
|
||||
@classmethod
|
||||
def upload_package(cls, application_name, version=None, require=None):
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name, version=version,
|
||||
add_class_name=True, require=require)
|
||||
package = cls.artifacts_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
return package, abs_archive_path
|
||||
|
||||
@staticmethod
|
||||
def create_obj_model(package):
|
||||
return {
|
||||
"name": package['display_name'],
|
||||
"?": {
|
||||
"type": package['name'],
|
||||
"id": utils.generate_uuid(),
|
||||
"classVersion": package['version']
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog.artifacts import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestRepositorySanity(base.BaseArtifactsTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if not CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano is not using GLARE backend. "
|
||||
"Skipping GLARE tests.")
|
||||
raise cls.skipException(msg)
|
||||
super(TestRepositorySanity, cls).resource_setup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('2818aaa0-6613-4bd9-8abe-02713121357a')
|
||||
def test_get_list_packages(self):
|
||||
package_list = self.artifacts_client.get_list_packages()
|
||||
self.assertIsInstance(package_list, list)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('bc717c98-5f6b-42a6-9131-43a711cfe848')
|
||||
def test_upload_and_delete_package(self):
|
||||
application_name = utils.generate_name('package_test_upload')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.artifacts_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
package_list = self.artifacts_client.get_list_packages()
|
||||
self.assertIn(package['id'], {pkg['id'] for pkg in package_list})
|
||||
self.artifacts_client.delete_package(package['id'])
|
||||
package_list = self.artifacts_client.get_list_packages()
|
||||
self.assertNotIn(package['id'], {pkg['id'] for pkg in package_list})
|
@ -1,166 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog.artifacts import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestVersioning(base.BaseArtifactsTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if not CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano is not using GLARE backend. "
|
||||
"Skipping GLARE tests.")
|
||||
raise cls.skipException(msg)
|
||||
super(TestVersioning, cls).resource_setup()
|
||||
|
||||
application_name = utils.generate_name('package_test')
|
||||
# create first package
|
||||
version1 = '1.0.0'
|
||||
package1, _ = cls.upload_package(application_name,
|
||||
version=version1)
|
||||
|
||||
# create second package
|
||||
version2 = '2.0.0'
|
||||
package2, path1 = cls.upload_package(application_name,
|
||||
version=version2)
|
||||
|
||||
# create package with require >=2.0.0 for 2.0.0 package
|
||||
expected_version = '>=2.0.0'
|
||||
main_app_name = utils.generate_name('main_package_test')
|
||||
require = [(package2['name'], expected_version)]
|
||||
package3, path2 = cls.upload_package(main_app_name, require=require)
|
||||
|
||||
cls.packages = {
|
||||
'1.0.0': package1,
|
||||
'2.0.0': package2,
|
||||
'require_for_2.0.0': package3,
|
||||
}
|
||||
cls.abs_archive_paths = [path1, path2]
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
for pkg in cls.packages.values():
|
||||
cls.artifacts_client.delete_package(pkg['id'])
|
||||
map(os.remove, cls.abs_archive_paths)
|
||||
super(TestVersioning, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('03ee155c-d65f-4ea7-a00a-bdbc7105fc8b')
|
||||
def test_availability_of_packages_with_different_versions(self):
|
||||
"""Test availability of packages with different versions.
|
||||
|
||||
1) Check two packages to have the same names.
|
||||
2) Check two packages to have different ids.
|
||||
3) Check two packages to be in repository.
|
||||
"""
|
||||
self.assertEqual(self.packages['1.0.0']['name'],
|
||||
self.packages['2.0.0']['name'])
|
||||
self.assertNotEqual(self.packages['1.0.0']['id'],
|
||||
self.packages['2.0.0']['id'])
|
||||
|
||||
# check packages availability
|
||||
artifact_packages = {pkg['id'] for pkg in
|
||||
self.artifacts_client.get_list_packages()}
|
||||
|
||||
self.assertIn(self.packages['1.0.0']['id'], artifact_packages)
|
||||
self.assertIn(self.packages['2.0.0']['id'], artifact_packages)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('15c3a52d-cffe-4d03-82c2-31c9be8423d6')
|
||||
def test_deploy_packages_with_different_versions(self):
|
||||
"""Test deployment of packages with different versions.
|
||||
|
||||
1) Create environment.
|
||||
2) Add package with version 1.0.0 to the environment.
|
||||
3) Add package with version 2.0.0 to the environment.
|
||||
4) Deploy environment.
|
||||
5) Check if deployment status ok.
|
||||
"""
|
||||
|
||||
# create environment
|
||||
environment_name = utils.generate_name('create_environment')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
environment_name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
# create session
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
|
||||
# add first application
|
||||
object_model = self.create_obj_model(self.packages['1.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
# add second application
|
||||
object_model = self.create_obj_model(self.packages['2.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
self.application_catalog_client.deploy_session(
|
||||
environment['id'], session['id'])
|
||||
|
||||
deploy_result = utils.wait_for_environment_deploy(
|
||||
self.application_catalog_client, environment['id'])['status']
|
||||
|
||||
self.assertEqual(deploy_result, 'ready')
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('2c472476-f9cd-424b-91ee-cbc770602bf3')
|
||||
def test_deploy_package_with_required_package_version(self):
|
||||
"""Test deployment of package which requires package with present version.
|
||||
|
||||
1) Create environment.
|
||||
2) Add to the environment package which requires version 2.0.0 of the
|
||||
package, which is present with versions 1.0.0 and 2.0.0 in repository.
|
||||
3) Deploy environment.
|
||||
4) Check if deployment status ok.
|
||||
"""
|
||||
|
||||
# create environment
|
||||
environment_name = utils.generate_name('create_environment')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
environment_name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
# create session
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
|
||||
object_model = self.create_obj_model(
|
||||
self.packages['require_for_2.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
self.application_catalog_client.deploy_session(
|
||||
environment['id'], session['id'])
|
||||
|
||||
deploy_result = utils.wait_for_environment_deploy(
|
||||
self.application_catalog_client, environment['id'])['status']
|
||||
|
||||
self.assertEqual(deploy_result, 'ready')
|
@ -1,96 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog.artifacts import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestVersioningNegative(base.BaseArtifactsTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if not CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano is not using GLARE backend. "
|
||||
"Skipping GLARE tests.")
|
||||
raise cls.skipException(msg)
|
||||
super(TestVersioningNegative, cls).resource_setup()
|
||||
|
||||
# create package with version 1.0.0
|
||||
application_name = utils.generate_name('package_test')
|
||||
provided_version = '1.0.0'
|
||||
package1, path1 = cls.upload_package(
|
||||
application_name, version=provided_version)
|
||||
|
||||
# main application
|
||||
expected_version = '2.0.0'
|
||||
main_app_name = utils.generate_name('main_package_test')
|
||||
require = [(package1['name'], expected_version)]
|
||||
package2, path2 = cls.upload_package(main_app_name, require=require)
|
||||
|
||||
cls.packages = {
|
||||
'1.0.0': package1,
|
||||
'require_for_1.0.0': package2
|
||||
}
|
||||
cls.abs_archive_paths = [path1, path2]
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
for pkg in cls.packages.values():
|
||||
cls.artifacts_client.delete_package(pkg['id'])
|
||||
map(os.remove, cls.abs_archive_paths)
|
||||
super(TestVersioningNegative, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type=['negative', 'smoke'])
|
||||
@decorators.idempotent_id('c72fcd24-4694-4479-b550-bdd8cf0bd348')
|
||||
def test_deploy_package_with_no_required_package_version(self):
|
||||
"""Test deployment of package which requires package with absent version.
|
||||
|
||||
1) Create environment.
|
||||
2) Add to the environment package which requires version 2.0.0 of the
|
||||
package, which is present with version 1.0.0 only in repository.
|
||||
3) Deploy environment.
|
||||
4) Check if deployment status failure.
|
||||
"""
|
||||
|
||||
# create environment
|
||||
environment_name = utils.generate_name('create_environment')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
environment_name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
# create session
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
|
||||
object_model = self.create_obj_model(
|
||||
self.packages['require_for_1.0.0'])
|
||||
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], object_model)
|
||||
|
||||
self.application_catalog_client.deploy_session(
|
||||
environment['id'], session['id'])
|
||||
|
||||
deploy_result = utils.wait_for_environment_deploy(
|
||||
self.application_catalog_client, environment['id'])['status']
|
||||
|
||||
self.assertEqual(deploy_result, 'deploy failure')
|
@ -1,110 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.common import credentials_factory as common_creds
|
||||
from tempest import config
|
||||
from tempest import test
|
||||
|
||||
from murano_tempest_tests import clients
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class BaseApplicationCatalogTest(test.BaseTestCase):
|
||||
"""Base test class for Murano Service Broker API tests."""
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(BaseApplicationCatalogTest, cls).skip_checks()
|
||||
if not CONF.service_available.murano:
|
||||
skip_msg = "Murano is disabled"
|
||||
raise cls.skipException(skip_msg)
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseApplicationCatalogTest, cls).setup_clients()
|
||||
if not hasattr(cls, "os_primary"):
|
||||
creds = cls.get_configured_isolated_creds(type_of_creds='primary')
|
||||
cls.os_primary = clients.Manager(credentials=creds)
|
||||
cls.application_catalog_client = \
|
||||
cls.os_primary.application_catalog_client
|
||||
cls.artifacts_client = cls.os_primary.artifacts_client
|
||||
|
||||
@classmethod
|
||||
def get_client_with_isolated_creds(cls, type_of_creds="admin"):
|
||||
creds = cls.get_configured_isolated_creds(type_of_creds=type_of_creds)
|
||||
|
||||
os = clients.Manager(credentials=creds)
|
||||
client = os.application_catalog_client
|
||||
|
||||
return client
|
||||
|
||||
@classmethod
|
||||
def get_configured_isolated_creds(cls, type_of_creds='admin'):
|
||||
identity_version = CONF.identity.auth_version
|
||||
if identity_version == 'v3':
|
||||
cls.admin_role = CONF.identity.admin_role
|
||||
else:
|
||||
cls.admin_role = 'admin'
|
||||
cls.credentials = common_creds.get_credentials_provider(
|
||||
name=cls.__name__,
|
||||
force_tenant_isolation=CONF.auth.use_dynamic_credentials,
|
||||
identity_version=CONF.identity.auth_version)
|
||||
if type_of_creds == 'primary':
|
||||
creds = cls.credentials.get_primary_creds()
|
||||
elif type_of_creds == 'admin':
|
||||
creds = cls.credentials.get_admin_creds()
|
||||
elif type_of_creds == 'alt':
|
||||
creds = cls.credentials.get_alt_creds()
|
||||
else:
|
||||
creds = cls.credentials.get_credentials(type_of_creds)
|
||||
cls.credentials.type_of_creds = type_of_creds
|
||||
|
||||
return creds.credentials
|
||||
|
||||
@staticmethod
|
||||
def _get_demo_app():
|
||||
return {
|
||||
"instance": {
|
||||
"assignFloatingIp": "true",
|
||||
"keyname": "mykeyname",
|
||||
"image": "cloud-fedora-v3",
|
||||
"flavor": "m1.medium",
|
||||
"?": {
|
||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
||||
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||
}
|
||||
},
|
||||
"name": "orion",
|
||||
"port": "8080",
|
||||
"?": {
|
||||
"type": "io.murano.apps.apache.Tomcat",
|
||||
"id": utils.generate_uuid()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class BaseApplicationCatalogIsolatedAdminTest(BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseApplicationCatalogIsolatedAdminTest, cls).setup_clients()
|
||||
if not hasattr(cls, "os_admin"):
|
||||
creds = cls.get_configured_isolated_creds(type_of_creds='admin')
|
||||
cls.os_admin = clients.Manager(credentials=creds)
|
||||
cls.application_catalog_client = \
|
||||
cls.os_admin.application_catalog_client
|
||||
cls.artifacts_client = cls.os_admin.artifacts_client
|
@ -1,113 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestCategories(base.BaseApplicationCatalogIsolatedAdminTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestCategories, cls).resource_setup()
|
||||
application_name = utils.generate_name(cls.__name__)
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
cls.package = cls.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.category = cls.application_catalog_client.create_category(name)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
os.remove(cls.abs_archive_path)
|
||||
cls.application_catalog_client.delete_package(cls.package['id'])
|
||||
cls.application_catalog_client.delete_category(cls.category['id'])
|
||||
super(TestCategories, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('4785781d-4bea-4559-939e-1c2fdf0dbec3')
|
||||
def test_list_categories(self):
|
||||
categories_list = self.application_catalog_client.list_categories()
|
||||
self.assertIsInstance(categories_list, list)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('c02841bc-3305-4e88-a733-696fb8690552')
|
||||
def test_create_and_delete_category(self):
|
||||
name = utils.generate_name('create_and_delete_category')
|
||||
categories_list = self.application_catalog_client.list_categories()
|
||||
category_names = [c['name'] for c in categories_list]
|
||||
self.assertNotIn(name, category_names)
|
||||
|
||||
category = self.application_catalog_client.create_category(name)
|
||||
self.assertEqual(name, category['name'])
|
||||
|
||||
categories_list = self.application_catalog_client.list_categories()
|
||||
category_names = [c['name'] for c in categories_list]
|
||||
self.assertIn(name, category_names)
|
||||
|
||||
self.application_catalog_client.delete_category(category['id'])
|
||||
categories_list = self.application_catalog_client.list_categories()
|
||||
category_names = [c['name'] for c in categories_list]
|
||||
self.assertNotIn(name, category_names)
|
||||
|
||||
@decorators.idempotent_id('c7931b7f-e811-4555-8ecc-84bea7885d96')
|
||||
def test_get_category(self):
|
||||
category = self.application_catalog_client.get_category(
|
||||
self.category['id'])
|
||||
self.assertEqual(self.category['id'], category['id'])
|
||||
self.assertEqual(self.category['name'], category['name'])
|
||||
|
||||
@decorators.idempotent_id('9b92705a-4203-4f02-9d6b-abc797c0eaac')
|
||||
def test_add_package_to_new_category_and_remove_it_from_category(self):
|
||||
category = self.application_catalog_client.get_category(
|
||||
self.category['id'])
|
||||
self.assertEqual(0, category['package_count'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/categories",
|
||||
"value": [category['name']]
|
||||
}
|
||||
]
|
||||
|
||||
package = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertIn(self.category['name'], package['categories'])
|
||||
category = self.application_catalog_client.get_category(
|
||||
self.category['id'])
|
||||
self.assertEqual(1, category['package_count'])
|
||||
self.assertEqual(1, len(category['packages']))
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "remove",
|
||||
"path": "/categories",
|
||||
"value": [category['name']]
|
||||
}
|
||||
]
|
||||
|
||||
package = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertNotIn(self.category['name'], package['categories'])
|
||||
category = self.application_catalog_client.get_category(
|
||||
self.category['id'])
|
||||
self.assertEqual(0, category['package_count'])
|
||||
self.assertEqual(0, len(category['packages']))
|
@ -1,72 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestCategoriesNegative(base.BaseApplicationCatalogIsolatedAdminTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestCategoriesNegative, cls).resource_setup()
|
||||
application_name = utils.generate_name(cls.__name__)
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.category = cls.application_catalog_client.create_category(name)
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
cls.package = cls.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [cls.category['name']],
|
||||
"tags": [], 'is_public': False})
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
os.remove(cls.abs_archive_path)
|
||||
cls.application_catalog_client.delete_package(cls.package['id'])
|
||||
cls.application_catalog_client.delete_category(cls.category['id'])
|
||||
super(TestCategoriesNegative, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('20fe075f-7d07-462e-bfbc-3032b5367207')
|
||||
def test_delete_category_by_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_category,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('e655365b-ec8b-49da-8745-5c80b1f5e65b')
|
||||
def test_get_category_by_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_category,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('c4948d0f-3530-419c-8017-1ee8bbc29dee')
|
||||
def test_create_category_with_same_name(self):
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.application_catalog_client.create_category,
|
||||
self.category['name'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('2bdce780-96dc-46d6-a28e-cdcf768359ae')
|
||||
def test_delete_category_with_package(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.application_catalog_client.delete_category,
|
||||
self.category['id'])
|
@ -1,86 +0,0 @@
|
||||
# Copyright (c) 2017 AT&T Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestDeployments(base.BaseApplicationCatalogTest):
|
||||
|
||||
def _create_and_deploy_env_session(self):
|
||||
name = utils.generate_name('_create_and_deploy_env_session')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
environment['id'], session['id'])
|
||||
self.application_catalog_client.deploy_session(environment['id'],
|
||||
session['id'])
|
||||
utils.wait_for_environment_deploy(self.application_catalog_client,
|
||||
environment['id'])
|
||||
return environment
|
||||
|
||||
@decorators.idempotent_id('ea4f6f21-bd97-4b58-af93-6fe5417543f9')
|
||||
def test_list_all_deployments(self):
|
||||
# Given two environments with deployments
|
||||
environment1 = self._create_and_deploy_env_session()
|
||||
environment2 = self._create_and_deploy_env_session()
|
||||
|
||||
# When list_all_deployments is called
|
||||
deployments = self.application_catalog_client.list_all_deployments()
|
||||
|
||||
# Then both environment's deployments are returned
|
||||
self.assertEqual(2, len(deployments))
|
||||
environment_ids = [d['environment_id'] for d in deployments]
|
||||
self.assertIn(environment1['id'], environment_ids)
|
||||
self.assertIn(environment2['id'], environment_ids)
|
||||
|
||||
@decorators.idempotent_id('d76706f6-9281-4fdc-9758-57da825311b1')
|
||||
def test_list_deployments(self):
|
||||
# Given two environments with deployments
|
||||
environment1 = self._create_and_deploy_env_session()
|
||||
self._create_and_deploy_env_session()
|
||||
|
||||
# When list_deployments is called for first environment
|
||||
deployments = self.application_catalog_client.list_deployments(
|
||||
environment1['id'])
|
||||
|
||||
# Then only the first environment's deployment is returned
|
||||
self.assertEqual(1, len(deployments))
|
||||
first_deployment = deployments[0]
|
||||
self.assertEqual(environment1['id'],
|
||||
first_deployment['environment_id'])
|
||||
|
||||
@decorators.idempotent_id('d6fbba34-92a9-49b3-9c49-e4b7a65eb6e8')
|
||||
def test_list_deployment_statuses(self):
|
||||
# Given an environment with a deployment
|
||||
environment = self._create_and_deploy_env_session()
|
||||
deployment = self.application_catalog_client.list_deployments(
|
||||
environment['id'])[0]
|
||||
|
||||
# When list_deployment_statuses is called
|
||||
statuses = self.application_catalog_client.list_deployment_statuses(
|
||||
environment['id'], deployment['id'])
|
||||
|
||||
# Then the correct statuses for the deployment are returned
|
||||
status_deployment_ids = set([s['task_id'] for s in statuses])
|
||||
self.assertEqual([deployment['id']], list(status_deployment_ids))
|
||||
status_texts = [s['text'] for s in statuses]
|
||||
self.assertEqual(['Action deploy is scheduled', 'Deployment finished'],
|
||||
sorted(status_texts))
|
@ -1,258 +0,0 @@
|
||||
# Copyright (c) 2015 Telefonica I+D.
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestEnvironmentTemplatesSanity(base.BaseApplicationCatalogTest):
|
||||
|
||||
@decorators.idempotent_id('c13f9799-ed80-463f-8275-6bba62933226')
|
||||
def test_list_empty_env_templates(self):
|
||||
templates_list = self.application_catalog_client.\
|
||||
get_env_templates_list()
|
||||
self.assertIsInstance(templates_list, list)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('15363b15-c350-40b9-a96b-de8d7a56a185')
|
||||
def test_create_and_delete_env_template(self):
|
||||
name = utils.generate_name('create_and_delete_env_template')
|
||||
env_template = self.application_catalog_client.\
|
||||
create_env_template(name)
|
||||
self.assertFalse(env_template['is_public'])
|
||||
self.assertEqual(name, env_template['name'])
|
||||
self.assertEqual("description", env_template['description_text'])
|
||||
env_templates_list = self.application_catalog_client.\
|
||||
get_env_templates_list()
|
||||
# Deleting dates from dictionaries to skip it in assert
|
||||
env_template.pop('updated', None)
|
||||
env_template.pop('created', None)
|
||||
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)
|
@ -1,133 +0,0 @@
|
||||
# Copyright (c) 2015 Telefonica I+D.
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestEnvironmentTemplatesNegative(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestEnvironmentTemplatesNegative, cls).resource_setup()
|
||||
cls.name = utils.generate_name(cls.__name__)
|
||||
cls.env_template = cls.application_catalog_client.\
|
||||
create_env_template(cls.name)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(cls.name)
|
||||
cls.alt_client = cls.get_client_with_isolated_creds('alt')
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_env_template(cls.env_template['id'])
|
||||
cls.application_catalog_client.delete_environment(
|
||||
cls.environment['id'])
|
||||
super(TestEnvironmentTemplatesNegative, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('022d0889-c5b3-4853-934f-533b43dfa89f')
|
||||
def test_clone_env_template_private(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.clone_env_template,
|
||||
self.env_template['id'], 'cloned_template')
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('1132afa7-6965-4f48-a4ed-aeedba25ad8c')
|
||||
def test_delete_environment_with_wrong_env_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_env_template,
|
||||
None)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a344b0be-d07d-4dfe-916d-900d93e44425')
|
||||
def test_create_environment_with_wrong_payload(self):
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.create_env_template,
|
||||
' ')
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('fa2efa91-75c0-430f-942d-f52fe208cb16')
|
||||
def test_double_delete_env_template(self):
|
||||
name = utils.generate_name('double_delete_env_template')
|
||||
env_template = self.application_catalog_client.\
|
||||
create_env_template(name)
|
||||
self.application_catalog_client.delete_env_template(
|
||||
env_template['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_env_template,
|
||||
env_template['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('3641cfa9-e74e-4e74-af09-6d0c7d4634fc')
|
||||
def test_get_deleted_env_template(self):
|
||||
name = utils.generate_name('get_deleted_env_template')
|
||||
env_template = self.application_catalog_client.\
|
||||
create_env_template(name)
|
||||
self.application_catalog_client.delete_env_template(
|
||||
env_template['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_env_template,
|
||||
env_template['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('106fe373-8232-4fb4-870f-290ffa3b475b')
|
||||
def test_create_environment_template_with_same_name(self):
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.application_catalog_client.create_env_template,
|
||||
self.name)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('07f56f09-3ca4-4d2a-8713-6306f2c3c4f8')
|
||||
def test_create_env_from_template_witch_existing_name(self):
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.application_catalog_client.
|
||||
create_env_from_template,
|
||||
self.env_template['id'],
|
||||
self.name)
|
||||
|
||||
|
||||
class TestEnvTemplatesTenantIsolation(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestEnvTemplatesTenantIsolation, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.env_template = cls.application_catalog_client.\
|
||||
create_env_template(name)
|
||||
cls.alt_client = cls.get_client_with_isolated_creds('alt')
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_env_template(cls.env_template['id'])
|
||||
super(TestEnvTemplatesTenantIsolation, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('bdf6febf-51aa-4b0a-b0e8-645e4df2531c')
|
||||
def test_get_env_template_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_env_template,
|
||||
self.env_template['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('b664b388-489f-4036-918a-18fa34a2a04e')
|
||||
def test_delete_env_template_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.delete_env_template,
|
||||
self.env_template['id'])
|
@ -1,128 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestEnvironments(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestEnvironments, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestEnvironments, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('32f26f2e-6c55-4e83-9d8c-023d86299d3e')
|
||||
def test_list_environments(self):
|
||||
environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
self.assertIsInstance(environments_list, list)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('a4c0b2fd-2c1b-473c-80cc-d433ceec4c80')
|
||||
def test_create_and_delete_environment(self):
|
||||
environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
name = utils.generate_name('create_and_delete_env')
|
||||
environment = self.application_catalog_client.create_environment(name)
|
||||
self.assertEqual(name, environment['name'])
|
||||
upd_environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
self.assertEqual(len(environments_list) + 1,
|
||||
len(upd_environments_list))
|
||||
self.application_catalog_client.delete_environment(environment['id'])
|
||||
upd_environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
self.assertEqual(len(environments_list),
|
||||
len(upd_environments_list))
|
||||
|
||||
@decorators.idempotent_id('52a06d5f-69e4-4184-a127-1bb13ce6dc7c')
|
||||
def test_create_and_delete_environment_with_unicode_name(self):
|
||||
environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
name = u'$yaql \u2665 unicode'
|
||||
environment = self.application_catalog_client.create_environment(name)
|
||||
self.assertEqual(name, environment['name'])
|
||||
upd_environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
self.assertEqual(len(environments_list) + 1,
|
||||
len(upd_environments_list))
|
||||
self.application_catalog_client.delete_environment(environment['id'])
|
||||
upd_environments_list = self.application_catalog_client.\
|
||||
get_environments_list()
|
||||
self.assertEqual(len(environments_list),
|
||||
len(upd_environments_list))
|
||||
|
||||
@decorators.idempotent_id('2b45d30b-3f1d-4482-805e-7cf15d19fe38')
|
||||
def test_get_environment(self):
|
||||
environment = self.application_catalog_client.\
|
||||
get_environment(self.environment['id'])
|
||||
self.assertEqual(self.environment['name'], environment['name'])
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('950f5bc1-3e5c-48d1-8b05-dc33303ce6f3')
|
||||
def test_update_environment(self):
|
||||
environment = self.application_catalog_client.\
|
||||
update_environment(self.environment['id'])
|
||||
self.assertIsNot(self.environment['name'], environment['name'])
|
||||
|
||||
@decorators.idempotent_id('61001866-e885-4dda-9ac9-5b24c67a0e25')
|
||||
def test_get_environment_model(self):
|
||||
model = self.application_catalog_client.\
|
||||
get_environment_model(self.environment['id'])
|
||||
self.assertIsInstance(model, dict)
|
||||
self.assertIn('defaultNetworks', model)
|
||||
self.assertEqual(self.environment['name'], model['name'])
|
||||
self.assertEqual(model['?']['type'], "io.murano.Environment")
|
||||
|
||||
net_name = self.application_catalog_client.\
|
||||
get_environment_model(self.environment['id'],
|
||||
path='/defaultNetworks/environment/name')
|
||||
self.assertEqual("{0}-network".format(self.environment['name']),
|
||||
net_name)
|
||||
|
||||
@decorators.idempotent_id('23416978-9701-49ff-9bb1-d312292a7f49')
|
||||
def test_update_environment_model(self):
|
||||
session = self.application_catalog_client. \
|
||||
create_session(self.environment['id'])
|
||||
patch = [{
|
||||
"op": "replace",
|
||||
"path": "/defaultNetworks/flat",
|
||||
"value": True
|
||||
}]
|
||||
new_model = self.application_catalog_client. \
|
||||
update_environment_model(self.environment['id'], patch,
|
||||
session['id'])
|
||||
self.assertTrue(new_model['defaultNetworks']['flat'])
|
||||
|
||||
value_draft = self.application_catalog_client. \
|
||||
get_environment_model(self.environment['id'],
|
||||
'/defaultNetworks/flat',
|
||||
session['id'])
|
||||
self.assertTrue(value_draft)
|
||||
|
||||
model_current = self.application_catalog_client. \
|
||||
get_environment_model(self.environment['id'])
|
||||
self.assertIsNone(model_current['defaultNetworks']['flat'])
|
@ -1,104 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestEnvironmentsNegative(base.BaseApplicationCatalogTest):
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('9e245625-ce24-4068-916e-20a5608f6d5a')
|
||||
def test_delete_environment_with_wrong_env_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_environment,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('1dae123c-27f4-4996-871e-31c66f76ee49')
|
||||
def test_double_delete_environment(self):
|
||||
name = utils.generate_name('double_del_negavive')
|
||||
environment = self.application_catalog_client.\
|
||||
create_environment(name)
|
||||
self.application_catalog_client.delete_environment(environment['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a8032052-5a48-48f0-b333-d1cefcfcbf5f')
|
||||
def test_get_deleted_environment(self):
|
||||
name = utils.generate_name('double_del_negavive')
|
||||
environment = self.application_catalog_client.\
|
||||
create_environment(name)
|
||||
self.application_catalog_client.delete_environment(environment['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_environment,
|
||||
environment['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('f0b6102c-dd22-4f4d-9775-ce0a7a53d881')
|
||||
def test_update_environment_with_wrong_env_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.update_environment,
|
||||
None)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('03266970-2f9d-4b82-971f-532fe23d1027')
|
||||
def test_abandon_environment_with_wrong_env_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.abandon_environment,
|
||||
None)
|
||||
|
||||
|
||||
class TestEnvironmentNegativeTenantIsolation(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestEnvironmentNegativeTenantIsolation, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
cls.alt_client = cls.get_client_with_isolated_creds(
|
||||
type_of_creds='alt')
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestEnvironmentNegativeTenantIsolation, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('0fc96a16-5df9-48b9-a681-ba5b3730e95b')
|
||||
def test_get_environment_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_environment,
|
||||
self.environment['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('d3c6dc81-ed60-4346-869c-0a091c2fe5b8')
|
||||
def test_update_environment_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.update_environment,
|
||||
self.environment['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('56aea1db-9314-4558-8b97-5fcd35fd6955')
|
||||
def test_delete_environment_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.delete_environment,
|
||||
self.environment['id'])
|
@ -1,221 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestRepositorySanity(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano using GLARE backend. "
|
||||
"Repository tests will be skipped.")
|
||||
raise cls.skipException(msg)
|
||||
super(TestRepositorySanity, cls).resource_setup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('d0f3ad6c-70b4-4ce0-90c5-e7afb20ace80')
|
||||
def test_get_list_packages(self):
|
||||
package_list = self.application_catalog_client.get_list_packages()
|
||||
self.assertIsInstance(package_list, list)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('53f679d9-955f-4dc1-8cdc-1fcdcfbb07a5')
|
||||
def test_upload_and_delete_package(self):
|
||||
application_name = utils.generate_name('package_test_upload')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
package_list = self.application_catalog_client.get_list_packages()
|
||||
self.assertIn(package['id'], {pkg['id'] for pkg in package_list})
|
||||
self.application_catalog_client.delete_package(package['id'])
|
||||
package_list = self.application_catalog_client.get_list_packages()
|
||||
self.assertNotIn(package['id'], {pkg['id'] for pkg in package_list})
|
||||
|
||||
|
||||
class TestRepository(base.BaseApplicationCatalogIsolatedAdminTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano using GLARE backend. "
|
||||
"Repository tests will be skipped.")
|
||||
raise cls.skipException(msg)
|
||||
|
||||
super(TestRepository, cls).resource_setup()
|
||||
|
||||
application_name = utils.generate_name('test_repository_class')
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
cls.package = cls.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
os.remove(cls.abs_archive_path)
|
||||
cls.application_catalog_client.delete_package(cls.package['id'])
|
||||
super(TestRepository, cls).resource_cleanup()
|
||||
|
||||
@decorators.idempotent_id('5ea58ef1-1a63-403d-a57a-ef4423202993')
|
||||
def test_get_package(self):
|
||||
package = self.application_catalog_client.get_package(
|
||||
self.package['id'])
|
||||
self.assertEqual(self.package['tags'], package['tags'])
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('daf5694d-abbf-4ab1-a6df-99540d0efc70')
|
||||
def test_update_package(self):
|
||||
post_body = [
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/tags",
|
||||
"value": ["im a test"]
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertIn("im a test", result['tags'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/tags",
|
||||
"value": ["im bad:D"]
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertNotIn("im a test", result['tags'])
|
||||
self.assertIn("im bad:D", result['tags'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "remove",
|
||||
"path": "/tags",
|
||||
"value": ["im bad:D"]
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertNotIn("im bad:D", result['tags'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/is_public",
|
||||
"value": True
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertTrue(result['is_public'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/enabled",
|
||||
"value": True
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertTrue(result['enabled'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/description",
|
||||
"value": "New description"
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertEqual("New description", result['description'])
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/name",
|
||||
"value": "New name"
|
||||
}
|
||||
]
|
||||
|
||||
result = self.application_catalog_client.update_package(
|
||||
self.package['id'], post_body)
|
||||
self.assertEqual("New name", result['name'])
|
||||
|
||||
@decorators.idempotent_id('fe4711ba-d1ee-4291-8a48-f8efcbd480ab')
|
||||
def test_download_package(self):
|
||||
self.application_catalog_client.download_package(self.package['id'])
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('9e55ae34-dea4-4db5-be4a-b3b793c9c4a7')
|
||||
def test_publicize_package(self):
|
||||
# Given a package that isn't public
|
||||
application_name = utils.generate_name('test_publicize_package')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
|
||||
fetched_package = self.application_catalog_client.get_package(
|
||||
package['id'])
|
||||
self.assertFalse(fetched_package['is_public'])
|
||||
|
||||
# When package is publicized
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/is_public",
|
||||
"value": True
|
||||
}
|
||||
]
|
||||
self.application_catalog_client.update_package(package['id'],
|
||||
post_body)
|
||||
|
||||
# Then package becomes public
|
||||
fetched_package = self.application_catalog_client.get_package(
|
||||
package['id'])
|
||||
self.assertTrue(fetched_package['is_public'])
|
||||
|
||||
@decorators.idempotent_id('1c017c1b-9efc-4498-95ff-833a9ce565a0')
|
||||
def test_get_ui_definitions(self):
|
||||
self.application_catalog_client.get_ui_definition(self.package['id'])
|
||||
|
||||
@decorators.idempotent_id('9f5ee28a-cec7-4d8b-a0fd-affbfceb0fc2')
|
||||
def test_get_logo(self):
|
||||
self.application_catalog_client.get_logo(self.package['id'])
|
@ -1,193 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestRepositoryNegativeNotFound(base.BaseApplicationCatalogTest):
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano using GLARE backend. "
|
||||
"Repository tests will be skipped.")
|
||||
raise cls.skipException(msg)
|
||||
super(TestRepositoryNegativeNotFound, cls).resource_setup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('49c557f4-789c-4d9c-8f48-0ba6bea4f234')
|
||||
def test_update_package_with_incorrect_id(self):
|
||||
|
||||
post_body = [
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/tags",
|
||||
"value": ["im a test"]
|
||||
}
|
||||
]
|
||||
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.update_package,
|
||||
utils.generate_uuid(), post_body)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('72590141-5046-424a-bed2-17e7b7aabd9a')
|
||||
def test_get_package_with_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_package,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('09e3f9d9-40ae-4d5c-a488-4137e3abd7a2')
|
||||
def test_delete_package_with_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_package,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a3cbcb58-7e46-47e9-a633-e3fc296681a9')
|
||||
def test_download_package_with_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.download_package,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('46799c58-8fe1-4d30-91a9-6067af780b32')
|
||||
def test_get_ui_definition_with_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_ui_definition,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('062ad8ab-6b5e-43ed-8331-b4bcd849b06e')
|
||||
def test_get_logo_with_incorrect_id(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_logo,
|
||||
utils.generate_uuid())
|
||||
|
||||
|
||||
class TestRepositoryNegativeForbidden(base.BaseApplicationCatalogTest):
|
||||
|
||||
# TODO(freerunner): I hope, that we can setup and cleanup resources
|
||||
# TODO(freerunner): dramatically better.
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
if CONF.application_catalog.glare_backend:
|
||||
msg = ("Murano using GLARE backend. "
|
||||
"Repository tests will be skipped.")
|
||||
raise cls.skipException(msg)
|
||||
|
||||
super(TestRepositoryNegativeForbidden, cls).resource_setup()
|
||||
|
||||
application_name = utils.generate_name('package_test_upload')
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
cls.package = cls.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
cls.alt_client = cls.get_client_with_isolated_creds(
|
||||
type_of_creds='alt')
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
os.remove(cls.abs_archive_path)
|
||||
cls.application_catalog_client.delete_package(cls.package['id'])
|
||||
super(TestRepositoryNegativeForbidden, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('29f9b3f1-8e8a-4305-a593-e3055e098666')
|
||||
def test_update_package_from_another_tenant(self):
|
||||
post_body = [
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/tags",
|
||||
"value": ["im a test"]
|
||||
}
|
||||
]
|
||||
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.update_package,
|
||||
self.package['id'],
|
||||
post_body)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('75b57ded-6077-436f-97f8-d3087f2f3b77')
|
||||
def test_get_package_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_package,
|
||||
self.package['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('1d9f8f74-8aca-4ee8-be0d-ac5b9d5a7dcd')
|
||||
def test_delete_package_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.delete_package,
|
||||
self.package['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a1467fed-cd6f-44dd-b79c-ea0f91e082dc')
|
||||
def test_download_package_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.download_package,
|
||||
self.package['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('b6074261-f981-4c15-9cd6-5811bd75127a')
|
||||
def test_get_ui_definition_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_ui_definition,
|
||||
self.package['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a5a3c2bb-3fde-49cb-ae4c-c454d7eb956b')
|
||||
def test_get_logo_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_logo,
|
||||
self.package['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('12928ec7-bd31-415d-9260-5c488aebd4c7')
|
||||
def test_publicize_package_as_non_admin_user(self):
|
||||
# Given a package that isn't public
|
||||
application_name = utils.generate_name('test_publicize_package_'
|
||||
'as_non_admin_user')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
|
||||
# When package is publicized, then the method throws an exception
|
||||
post_body = [
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/is_public",
|
||||
"value": True
|
||||
}
|
||||
]
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.application_catalog_client.update_package,
|
||||
package['id'],
|
||||
post_body)
|
@ -1,134 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestServices(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestServices, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestServices, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('6cc9d2da-5aeb-4386-adf3-2ff0b737f363')
|
||||
def test_get_services_list(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
services_list = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertIsInstance(services_list, list)
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('cbdbc025-d673-4fb5-914a-baa0dd896046')
|
||||
def test_create_and_delete_demo_service(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
services_list = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
services_list_ = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(len(services_list) + 1, len(services_list_))
|
||||
self.application_catalog_client.\
|
||||
delete_service(self.environment['id'],
|
||||
session['id'],
|
||||
service['?']['id'])
|
||||
services_list_ = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(len(services_list), len(services_list_))
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('431d1842-b25d-4ecd-8837-d56b89c83343')
|
||||
def test_update_services_via_put(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
put_body = [self._get_demo_app()]
|
||||
self.application_catalog_client.\
|
||||
update_services(self.environment['id'], session['id'], put_body)
|
||||
services_list = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(1, len(services_list))
|
||||
|
||||
@decorators.idempotent_id('fc9ef7c7-46e2-44ce-a309-bec2834c6adb')
|
||||
def test_clear_services_via_put(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
services_list = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
services_list_ = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(len(services_list) + 1, len(services_list_))
|
||||
self.application_catalog_client.\
|
||||
update_services(self.environment['id'], session['id'])
|
||||
services_list_ = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(0, len(services_list_))
|
||||
self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
services_list_ = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(1, len(services_list_))
|
||||
|
||||
@decorators.idempotent_id('7df86a14-3359-47c2-992e-99eaedb50456')
|
||||
def test_get_service(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
services_list = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
services_list_ = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], session['id'])
|
||||
self.assertEqual(len(services_list) + 1, len(services_list_))
|
||||
service_ = self.application_catalog_client.\
|
||||
get_service(self.environment['id'],
|
||||
service['?']['id'],
|
||||
session['id'])
|
||||
self.assertEqual(service, service_)
|
||||
|
||||
@decorators.idempotent_id('d64da7cd-9fcd-42c5-9c37-766db902c801')
|
||||
def test_get_services_without_sess_id(self):
|
||||
services = self.application_catalog_client.\
|
||||
get_services_list(self.environment['id'], None)
|
||||
self.assertIsInstance(services, list)
|
||||
self.assertEqual([], services)
|
@ -1,272 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestServicesNegative(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestServicesNegative, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestServicesNegative, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('5f1dd3f4-170f-4020-bbf6-3d7c277957a8')
|
||||
def test_get_services_list_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_services_list,
|
||||
None,
|
||||
session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('e17972e2-4c5c-4b25-a6cd-82eb2d64897a')
|
||||
def test_get_services_list_after_delete_env(self):
|
||||
name = utils.generate_name("get_services_list_after_delete_env")
|
||||
environment = self.application_catalog_client.create_environment(name)
|
||||
session = self.application_catalog_client.\
|
||||
create_session(environment['id'])
|
||||
self.application_catalog_client.delete_environment(environment['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_services_list,
|
||||
environment['id'],
|
||||
session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('e4ffe0b1-deb0-4f33-9790-6e6dc8bcdecb')
|
||||
def test_get_services_list_after_delete_session(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.application_catalog_client.\
|
||||
delete_session(self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_services_list,
|
||||
self.environment['id'],
|
||||
session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('d88880e2-63de-47a0-b29b-a3810b5715e6')
|
||||
def test_create_service_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.create_service,
|
||||
None,
|
||||
session['id'],
|
||||
post_body)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('1d9311af-917a-4a29-b42f-62377369d346')
|
||||
def test_create_service_without_sess_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.create_service,
|
||||
self.environment['id'],
|
||||
"",
|
||||
post_body)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('b22f2232-a6d3-4770-b26e-a1e0ccf62d60')
|
||||
def test_delete_service_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_service,
|
||||
"",
|
||||
session['id'],
|
||||
service['?']['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('04b4a8b7-3cf6-494a-8741-151305909893')
|
||||
def test_delete_service_without_session_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.delete_service,
|
||||
self.environment['id'],
|
||||
"",
|
||||
service['?']['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('2d040e59-3af3-47a2-8d87-eef70920cd65')
|
||||
def test_double_delete_service(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
self.application_catalog_client.\
|
||||
delete_service(self.environment['id'],
|
||||
session['id'],
|
||||
service['?']['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_service,
|
||||
self.environment['id'],
|
||||
session['id'],
|
||||
service['?']['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a742e411-e572-4aed-ba91-dba8db694039')
|
||||
def test_get_service_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_service,
|
||||
None,
|
||||
session['id'],
|
||||
service['?']['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('ded0b813-c36e-4108-8be2-c4b1e061f4e9')
|
||||
def test_put_services_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
put_body = [self._get_demo_app()]
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.update_services,
|
||||
None,
|
||||
session['id'],
|
||||
put_body)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('4ab7a7ac-1939-404a-8cb7-feaadc06ae3f')
|
||||
def test_put_services_without_sess_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
put_body = [self._get_demo_app()]
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.update_services,
|
||||
self.environment['id'],
|
||||
"",
|
||||
put_body)
|
||||
|
||||
|
||||
class TestServicesNegativeTenantIsolation(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestServicesNegativeTenantIsolation, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
cls.alt_client = cls.get_client_with_isolated_creds(
|
||||
type_of_creds='alt')
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestServicesNegativeTenantIsolation, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('014050a1-4f8d-4a9b-8332-3eb03d10ba64')
|
||||
def test_get_list_services_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_services_list,
|
||||
self.environment['id'],
|
||||
session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('b2c70134-0537-4912-a6c7-23d477f62764')
|
||||
def test_create_service_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.create_service,
|
||||
self.environment['id'],
|
||||
session['id'],
|
||||
post_body)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('264f5854-5fce-4186-987a-98d4fbb67093')
|
||||
def test_delete_service_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.delete_service,
|
||||
self.environment['id'],
|
||||
session['id'],
|
||||
service['?']['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('ff557e1f-a775-4a10-9265-2fa653179c4c')
|
||||
def test_get_service_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
post_body = self._get_demo_app()
|
||||
service = self.application_catalog_client.\
|
||||
create_service(self.environment['id'], session['id'], post_body)
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_service,
|
||||
self.environment['id'],
|
||||
session['id'],
|
||||
service['?']['id'])
|
@ -1,93 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestSessions(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestSessions, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestSessions, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('9f8ca4dd-1159-4c12-bd97-84ee7f36775e')
|
||||
def test_create_session(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertEqual(self.environment['id'], session['environment_id'])
|
||||
|
||||
@decorators.attr(type='smoke')
|
||||
@decorators.idempotent_id('a2782f54-9f9a-443b-97be-edc17039aea5')
|
||||
def test_delete_session(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.application_catalog_client.delete_session(self.environment['id'],
|
||||
session['id'])
|
||||
|
||||
@decorators.idempotent_id('0639a8ef-f527-4a5d-b34a-4e2d46f48b30')
|
||||
def test_get_session(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
session_from_resp = self.application_catalog_client.\
|
||||
get_session(self.environment['id'], session['id'])
|
||||
# Deleting dates from dictionaries to skip it in assert
|
||||
session.pop('updated', None)
|
||||
session.pop('created', None)
|
||||
session_from_resp.pop('updated', None)
|
||||
session_from_resp.pop('created', None)
|
||||
self.assertEqual(session, session_from_resp)
|
||||
|
||||
@decorators.idempotent_id('30a63368-e75a-4e00-ac91-c91b17e54a62')
|
||||
def test_deploy_session(self):
|
||||
# Given an environment with a session
|
||||
name = utils.generate_name('_create_and_deploy_env_session')
|
||||
environment = self.application_catalog_client.create_environment(
|
||||
name)
|
||||
self.addCleanup(self.application_catalog_client.delete_environment,
|
||||
environment['id'])
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
environment['id'], session['id'])
|
||||
|
||||
# When deploy session is called
|
||||
self.application_catalog_client.deploy_session(environment['id'],
|
||||
session['id'])
|
||||
utils.wait_for_environment_deploy(self.application_catalog_client,
|
||||
environment['id'])
|
||||
|
||||
# Then there is only one deployment and it is in a success state
|
||||
fetched_deployments = self.application_catalog_client.list_deployments(
|
||||
environment['id'])
|
||||
self.assertEqual(1, len(fetched_deployments))
|
||||
first_deployment = fetched_deployments[0]
|
||||
self.assertEqual(environment['id'], first_deployment['environment_id'])
|
||||
self.assertEqual('success', first_deployment['state'])
|
@ -1,146 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class TestSessionsNegative(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestSessionsNegative, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestSessionsNegative, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('eaf51e99-ff10-45ff-8c9f-416b6a125799')
|
||||
def test_create_session_before_env(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.create_session,
|
||||
utils.generate_uuid())
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('1269efdf-5586-4119-80e3-e88aa20d3111')
|
||||
def test_delete_session_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.delete_session,
|
||||
None, session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a96f8e67-165c-4a43-92f1-05d28275d576')
|
||||
def test_get_session_without_env_id(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.get_session,
|
||||
None, session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('784486ca-9645-4edc-8b23-c7ef781a85ae')
|
||||
def test_get_session_after_delete_env(self):
|
||||
name = utils.generate_name('get_session_after_delete_env')
|
||||
environment = self.application_catalog_client.create_environment(name)
|
||||
session = self.application_catalog_client.\
|
||||
create_session(environment['id'])
|
||||
self.application_catalog_client.delete_environment(environment['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.get_session,
|
||||
environment['id'], session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('8e5e1148-0a79-4c5a-bf93-2178ff7a92fe')
|
||||
def test_double_delete_session(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.application_catalog_client.delete_session(self.environment['id'],
|
||||
session['id'])
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
|
||||
|
||||
class TestSessionsNegativeTenantIsolation(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestSessionsNegativeTenantIsolation, cls).resource_setup()
|
||||
name = utils.generate_name(cls.__name__)
|
||||
cls.environment = cls.application_catalog_client.\
|
||||
create_environment(name)
|
||||
cls.alt_client = cls.get_client_with_isolated_creds(
|
||||
type_of_creds='alt')
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.application_catalog_client.\
|
||||
delete_environment(cls.environment['id'])
|
||||
super(TestSessionsNegativeTenantIsolation, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('72108505-3eb1-49b2-a757-a7340d18f52c')
|
||||
def test_create_session_in_env_from_another_tenant(self):
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.create_session,
|
||||
self.environment['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('35ada820-67f1-4a8b-852d-f1a02c11a110')
|
||||
def test_delete_session_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('62d469ac-2e91-4e50-bbe8-3f93ab79d903')
|
||||
def test_get_session_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.get_session,
|
||||
self.environment['id'], session['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('d261f060-7189-4234-9ece-06ae46127591')
|
||||
def test_deploy_session_in_env_from_another_tenant(self):
|
||||
session = self.application_catalog_client.\
|
||||
create_session(self.environment['id'])
|
||||
self.addCleanup(self.application_catalog_client.delete_session,
|
||||
self.environment['id'], session['id'])
|
||||
self.assertRaises(exceptions.Forbidden,
|
||||
self.alt_client.deploy_session,
|
||||
self.environment['id'], session['id'])
|
@ -1,76 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestStaticActions(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestStaticActions, cls).resource_setup()
|
||||
|
||||
application_name = utils.generate_name('test_repository_class')
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name, add_class_name=True)
|
||||
|
||||
if CONF.application_catalog.glare_backend:
|
||||
client = cls.artifacts_client
|
||||
else:
|
||||
client = cls.application_catalog_client
|
||||
|
||||
cls.package = client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
os.remove(cls.abs_archive_path)
|
||||
if CONF.application_catalog.glare_backend:
|
||||
client = cls.artifacts_client
|
||||
else:
|
||||
client = cls.application_catalog_client
|
||||
client.delete_package(cls.package['id'])
|
||||
super(TestStaticActions, cls).resource_cleanup()
|
||||
|
||||
@decorators.idempotent_id('ac3359e8-8762-417a-95c6-fb2d678850f7')
|
||||
def test_call_static_action_basic(self):
|
||||
action_result = self.application_catalog_client.call_static_action(
|
||||
class_name=self.package['class_definitions'][0],
|
||||
method_name='staticAction',
|
||||
args={'myName': 'John'})
|
||||
self.assertEqual(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)
|
@ -1,115 +0,0 @@
|
||||
# Copyright (c) 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestStaticActionsNegative(base.BaseApplicationCatalogTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestStaticActionsNegative, cls).resource_setup()
|
||||
|
||||
application_name = utils.generate_name('test_repository_class')
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name, add_class_name=True)
|
||||
|
||||
if CONF.application_catalog.glare_backend:
|
||||
client = cls.artifacts_client
|
||||
else:
|
||||
client = cls.application_catalog_client
|
||||
|
||||
cls.package = client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': False})
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
os.remove(cls.abs_archive_path)
|
||||
if CONF.application_catalog.glare_backend:
|
||||
client = cls.artifacts_client
|
||||
else:
|
||||
client = cls.application_catalog_client
|
||||
client.delete_package(cls.package['id'])
|
||||
super(TestStaticActionsNegative, cls).resource_cleanup()
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('c6d05273-b6fe-4a33-8a87-c7110c171bc2')
|
||||
def test_call_static_action_no_args(self):
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.call_static_action)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('35440618-6649-40cb-b878-b5cddd4ea0dd')
|
||||
def test_call_static_action_wrong_class(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.call_static_action,
|
||||
'wrong.class', 'staticAction',
|
||||
args={'myName': 'John'})
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('75c6cc5e-0804-45d9-beb2-10c7ab409b70')
|
||||
def test_call_static_action_wrong_method(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.call_static_action,
|
||||
class_name=self.package['class_definitions'][0],
|
||||
method_name='wrongMethod',
|
||||
args={'myName': 'John'})
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('334c828b-3f49-49e0-97a2-534f57596bfb')
|
||||
def test_call_static_action_session_method(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.call_static_action,
|
||||
class_name=self.package['class_definitions'][0],
|
||||
method_name='staticNotAction',
|
||||
args={'myName': 'John'})
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('3ebb5009-2f61-4200-a34c-2bc506d94aed')
|
||||
def test_call_static_action_wrong_args(self):
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.call_static_action,
|
||||
class_name=self.package['class_definitions'][0],
|
||||
method_name='staticAction',
|
||||
args={'myEmail': 'John'})
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('5f4f6edc-2d66-4426-bb81-48e7570d93ef')
|
||||
def test_call_static_action_wrong_package(self):
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.application_catalog_client.call_static_action,
|
||||
class_name=self.package['class_definitions'][0],
|
||||
method_name='staticAction',
|
||||
package_name='wrong.package',
|
||||
args={'myName': 'John'})
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('c0854170-700f-4924-9cfe-3bff876b9e63')
|
||||
def test_call_static_action_wrong_version_format(self):
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.application_catalog_client.call_static_action,
|
||||
class_name=self.package['class_definitions'][0],
|
||||
method_name='staticAction',
|
||||
class_version='aaa',
|
||||
args={'myName': 'John'})
|
@ -1,136 +0,0 @@
|
||||
# Copyright (c) 2015 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import time
|
||||
|
||||
from tempest.common import credentials_factory as common_creds
|
||||
from tempest import config
|
||||
from tempest.lib import exceptions
|
||||
from tempest import test
|
||||
|
||||
from murano_tempest_tests import clients
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class BaseServiceBrokerTest(test.BaseTestCase):
|
||||
"""Base test class for Murano Service Broker API tests."""
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(BaseServiceBrokerTest, cls).skip_checks()
|
||||
if not CONF.service_broker.run_service_broker_tests:
|
||||
skip_msg = "Service Broker API tests are disabled"
|
||||
raise cls.skipException(skip_msg)
|
||||
if not CONF.service_available.murano_cfapi:
|
||||
skip_msg = "Service Broker API is disabled"
|
||||
raise cls.skipException(skip_msg)
|
||||
if not CONF.service_available.murano:
|
||||
skip_msg = "Murano is disabled"
|
||||
raise cls.skipException(skip_msg)
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseServiceBrokerTest, cls).setup_clients()
|
||||
if not hasattr(cls, "os_primary"):
|
||||
cls.username = 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
|
@ -1,167 +0,0 @@
|
||||
# Copyright (c) 2015 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from murano_tempest_tests.tests.api.service_broker import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class ServiceBrokerActionsTest(base.BaseServiceBrokerAdminTest):
|
||||
|
||||
@decorators.attr(type='gate')
|
||||
@decorators.idempotent_id('76cadf4b-7143-402c-975e-11d7464dd20e')
|
||||
def test_applications_listing(self):
|
||||
app_list = self.service_broker_client.get_applications_list()
|
||||
self.assertIsInstance(app_list, list)
|
||||
|
||||
@decorators.attr(type=['smoke', 'gate'])
|
||||
@decorators.idempotent_id('51ad86a2-b8e4-43d1-8099-75e4be293f79')
|
||||
def test_provision_and_deprovision(self):
|
||||
application_name = utils.generate_name('cfapi')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': True})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
app_list = self.service_broker_client.get_applications_list()
|
||||
app = self.service_broker_client.get_application(application_name,
|
||||
app_list)
|
||||
post_json = {}
|
||||
instance_id = utils.generate_uuid()
|
||||
space_id = utils.generate_uuid()
|
||||
service = self.service_broker_client.provision(
|
||||
instance_id, app['id'], app['plans'][0]['id'],
|
||||
space_id, post_json)
|
||||
self.wait_for_result(instance_id, 30)
|
||||
self.addCleanup(self.perform_deprovision, instance_id)
|
||||
self.assertIsInstance(json.loads(service), dict)
|
||||
|
||||
@decorators.attr(type=['smoke', 'gate'])
|
||||
@decorators.idempotent_id('d5bd537a-7912-4916-a137-d0601157fb9e')
|
||||
def test_binding_instance(self):
|
||||
application_name = utils.generate_name('cfapi')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': True})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
app_list = self.service_broker_client.get_applications_list()
|
||||
app = self.service_broker_client.get_application(application_name,
|
||||
app_list)
|
||||
post_json = {}
|
||||
instance_id = utils.generate_uuid()
|
||||
space_id = utils.generate_uuid()
|
||||
service = self.service_broker_client.provision(
|
||||
instance_id, app['id'], app['plans'][0]['id'],
|
||||
space_id, post_json)
|
||||
self.wait_for_result(instance_id, 30)
|
||||
self.addCleanup(self.perform_deprovision, instance_id)
|
||||
self.assertIsInstance(json.loads(service), dict)
|
||||
binding = self.service_broker_client.create_binding(instance_id)
|
||||
self.assertIsInstance(binding, dict)
|
||||
self.assertEqual({'uri': 'localhost'}, binding)
|
||||
|
||||
@decorators.attr(type=['smoke', 'gate'])
|
||||
@decorators.idempotent_id('f738fdc2-a180-40e5-9aa6-d338d8660b88')
|
||||
def test_provision_with_incorrect_input(self):
|
||||
"""Test provision with restricted items in object model
|
||||
|
||||
Test will fail on deprovision, if parameters from '?' section
|
||||
will passed through service-broker.
|
||||
"""
|
||||
application_name = utils.generate_name('cfapi')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': True})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
app_list = self.service_broker_client.get_applications_list()
|
||||
app = self.service_broker_client.get_application(application_name,
|
||||
app_list)
|
||||
|
||||
# NOTE(freerunner): The '?' section should be cutted off during
|
||||
# provision action.
|
||||
post_json = {
|
||||
'?': {
|
||||
'type': 'io.murano.apps.{0}'.format(application_name),
|
||||
'id': utils.generate_uuid()
|
||||
}
|
||||
}
|
||||
instance_id = utils.generate_uuid()
|
||||
space_id = utils.generate_uuid()
|
||||
service = self.service_broker_client.provision(
|
||||
instance_id, app['id'], app['plans'][0]['id'],
|
||||
space_id, post_json)
|
||||
self.wait_for_result(instance_id, 30)
|
||||
self.addCleanup(self.perform_deprovision, instance_id)
|
||||
self.assertIsInstance(json.loads(service), dict)
|
||||
|
||||
@decorators.attr(type=['smoke', 'gate'])
|
||||
@decorators.idempotent_id('ef9bc7ca-21b7-480d-a3ba-32cb39b33909')
|
||||
def test_double_provision_to_the_same_space(self):
|
||||
application_name = utils.generate_name('cfapi')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': True})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
app_list = self.service_broker_client.get_applications_list()
|
||||
app = self.service_broker_client.get_application(application_name,
|
||||
app_list)
|
||||
post_json = {}
|
||||
instance_id = utils.generate_uuid()
|
||||
space_id = utils.generate_uuid()
|
||||
service = self.service_broker_client.provision(
|
||||
instance_id, app['id'], app['plans'][0]['id'],
|
||||
space_id, post_json)
|
||||
self.wait_for_result(instance_id, 30)
|
||||
self.addCleanup(self.perform_deprovision, instance_id)
|
||||
self.assertIsInstance(json.loads(service), dict)
|
||||
application_name = utils.generate_name('cfapi')
|
||||
abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(application_name)
|
||||
self.addCleanup(os.remove, abs_archive_path)
|
||||
package = self.application_catalog_client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": [], "tags": [], 'is_public': True})
|
||||
self.addCleanup(self.application_catalog_client.delete_package,
|
||||
package['id'])
|
||||
app_list = self.service_broker_client.get_applications_list()
|
||||
app = self.service_broker_client.get_application(application_name,
|
||||
app_list)
|
||||
post_json = {}
|
||||
instance_id = utils.generate_uuid()
|
||||
service = self.service_broker_client.provision(
|
||||
instance_id, app['id'], app['plans'][0]['id'],
|
||||
space_id, post_json)
|
||||
self.wait_for_result(instance_id, 30)
|
||||
self.addCleanup(self.perform_deprovision, instance_id)
|
||||
self.assertIsInstance(json.loads(service), dict)
|
@ -1,32 +0,0 @@
|
||||
# Copyright (c) 2015 Mirantis, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from murano_tempest_tests.tests.api.service_broker import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
|
||||
class ServiceBrokerNegativeTest(base.BaseServiceBrokerAdminTest):
|
||||
|
||||
@decorators.attr(type=['gate', 'negative'])
|
||||
@decorators.idempotent_id('3c9c14a2-1655-490a-90f0-6cb5dd6dba07')
|
||||
def test_get_status_with_not_present_instance_id(self):
|
||||
not_present_instance_id = utils.generate_uuid()
|
||||
self.assertRaises(
|
||||
exceptions.Gone,
|
||||
self.service_broker_client.get_last_status,
|
||||
not_present_instance_id)
|
@ -1,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)
|
@ -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)
|
@ -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
|
@ -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())
|
||||
}
|
||||
}
|
@ -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'))
|
@ -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'
|
@ -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
|
@ -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)
|
@ -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
Loading…
Reference in New Issue
Block a user