Make appropriate branch default and updated from global requirements

- Use default value of _BRANCH parameters 'stable/juno' for
  stable/juno release
- Update from global requirements
- Fix lib for using python-muranoclient from stable/juno and openstack
  namespace
- Update .gitreview for using openstack namespace
- Install test-requirements in post_test_hook.sh
- Remove CLI tests
- Update API tests because of tempest updates
- Fix for PEP8 checks after hacking version bump
- Add ignore H233,H405,H904 hacking rules

Change-Id: I7624cba86c7d5612ac32c14e36fb2d020b599e1c
Closes-Bug: #1468746
Closes-Bug: #1469181
This commit is contained in:
Victor Ryzhenkin 2015-06-25 18:19:15 +03:00
parent 4c0c1659c1
commit cba057b84e
57 changed files with 237 additions and 353 deletions

View File

@ -1,5 +1,5 @@
[gerrit]
host=review.openstack.org
port=29418
project=stackforge/murano.git
project=openstack/murano.git
defaultbranch=stable/juno

View File

@ -21,15 +21,11 @@ set -o xtrace
# --------
# Set up default repos
MURANO_REPO=${MURANO_REPO:-${GIT_BASE}/stackforge/murano.git}
MURANO_BRANCH=${MURANO_BRANCH:-master}
MURANO_REPO=${MURANO_REPO:-${GIT_BASE}/openstack/murano.git}
MURANO_BRANCH=${MURANO_BRANCH:-stable/juno}
MURANO_PYTHONCLIENT_REPO=${MURANO_PYTHONCLIENT_REPO:-${GIT_BASE}/stackforge/python-muranoclient.git}
if [[ "${MURANO_PYTHONCLIENT_BRANCH}" == "stable/juno" ]]; then
MURANO_PYTHONCLIENT_BRANCH="0.5.5"
else
MURANO_PYTHONCLIENT_BRANCH=${MURANO_PYTHONCLIENT_BRANCH:-0.5.5}
fi
MURANO_PYTHONCLIENT_REPO=${MURANO_PYTHONCLIENT_REPO:-${GIT_BASE}/openstack/python-muranoclient.git}
MURANO_PYTHONCLIENT_BRANCH=${MURANO_PYTHONCLIENT_BRANCH:-stable/juno}
MURANO_PYTHONCLIENT_DIR=$DEST/python-muranoclient
# Set up default directories

View File

@ -27,8 +27,8 @@ HORIZON_CONFIG=${HORIZON_CONFIG:-$HORIZON_DIR/openstack_dashboard/settings.py}
HORIZON_LOCAL_CONFIG=${HORIZON_LOCAL_CONFIG:-$HORIZON_DIR/openstack_dashboard/local/local_settings.py}
# Set up default repos
MURANO_DASHBOARD_REPO=${MURANO_DASHBOARD_REPO:-${GIT_BASE}/stackforge/murano-dashboard.git}
MURANO_DASHBOARD_BRANCH=${MURANO_DASHBOARD_BRANCH:-master}
MURANO_DASHBOARD_REPO=${MURANO_DASHBOARD_REPO:-${GIT_BASE}/openstack/murano-dashboard.git}
MURANO_DASHBOARD_BRANCH=${MURANO_DASHBOARD_BRANCH:-stable/juno}
MURANO_DASHBOARD_DIR=$DEST/murano-dashboard
# Set up default directories

View File

@ -16,6 +16,7 @@
import argparse
import os
import re
import yaml
@ -119,7 +120,7 @@ class DslPlantUmlNode(DslSpec):
if match:
ns = self.get_ns(match.group(1))
ext_classes.append(self.get_dn(match.group(1)))
if not ns in namespaces:
if ns not in namespaces:
namespaces.append(ns)
uml_class.add_attribute(
name,
@ -178,7 +179,7 @@ class DslPlantUmlGraph():
if level == 0:
for edge in self._edges:
self._file.write('{from_node} {type} {to_node}\n'
.format(**edge))
.format(**edge))
self._file.write('@enduml\n')
self._file.close()
@ -190,7 +191,7 @@ class DslPlantUmlGraph():
def add_edge(self, from_node, to_node, edge_type):
edge = {'from_node': from_node, 'to_node': to_node, 'type': edge_type}
if not edge in self._edges:
if edge not in self._edges:
self._edges.append(edge)
def set_option(self, key, value):

View File

@ -14,6 +14,12 @@
# This script is executed inside post_test_hook function in devstack gate.
# Installing tempest requirements
sudo pip install -r /opt/stack/new/tempest/requirements.txt
# Installing test-requirements
sudo pip install -r /opt/stack/new/murano/test-requirements.txt
cd /opt/stack/new/murano/functionaltests
sudo ./run_tests.sh
RETVAL=$?

View File

@ -28,8 +28,5 @@ TEMPEST_DIR=${TEMPEST_DIR:-/opt/stack/new/tempest}
# Add tempest source tree to PYTHONPATH
export PYTHONPATH=$PYTHONPATH:$TEMPEST_DIR
#installing requirements for tempest
pip install -r $TEMPEST_DIR/requirements.txt
nosetests -sv ../murano/tests/functional/api/v1 ../murano/tests/functional/cli/simple_read_only
nosetests -sv ../murano/tests/functional/api/v1

View File

@ -14,10 +14,10 @@
# under the License.
import cgi
import jsonschema
import os
import tempfile
import jsonschema
from oslo.config import cfg
from oslo.db import exception as db_exc
from webob import exc

View File

@ -44,7 +44,7 @@ class Controller(object):
LOG.debug('Environments:List')
policy.check('list_environments', request.context)
#Only environments from same tenant as user should be returned
# Only environments from same tenant as user should be returned
filters = {'tenant_id': request.context.tenant}
environments = envs.EnvironmentServices.get_environments_by(filters)
environments = [env.to_dict() for env in environments]
@ -99,7 +99,7 @@ class Controller(object):
if hasattr(request, 'context') and request.context.session:
session_id = request.context.session
#add services to env
# add services to env
get_data = core_services.CoreServices.get_data
env['services'] = get_data(environment_id, '/services', session_id)

View File

@ -14,10 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import eventlet
import os
import sys
import eventlet
if os.name == 'nt':
# eventlet monkey patching causes subprocess.Popen to fail on Windows
# when using pipes due to missing non blocking I/O support

View File

@ -13,9 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import anyjson
import logging
import anyjson
log = logging.getLogger("murano-common.messaging")

View File

@ -13,11 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import anyjson
import logging
import ssl as ssl_module
import anyjson
from eventlet import patcher
kombu = patcher.import_patched('kombu')
from subscription import Subscription

View File

@ -14,11 +14,13 @@
# Based on designate/policy.py
import murano.openstack.common.log as logging
from murano.openstack.common import policy
from oslo.config import cfg
from webob import exc as exceptions
import murano.openstack.common.log as logging
from murano.openstack.common import policy
LOG = logging.getLogger(__name__)
CONF = cfg.CONF

View File

@ -17,7 +17,6 @@ import uuid
from oslo import messaging
from oslo.messaging.notify import dispatcher as oslo_dispatcher
from oslo.messaging import target
from sqlalchemy import desc
from murano.common import config
@ -70,7 +69,7 @@ class ResultEndpoint(object):
environment.version += 1
environment.save(unit)
#close deployment
# close deployment
deployment = get_last_deployment(unit, environment.id)
deployment.finished = timeutils.utcnow()
@ -93,7 +92,7 @@ class ResultEndpoint(object):
deployment.statuses.append(status)
deployment.save(unit)
#close session
# close session
conf_session = unit.query(models.Session).filter_by(
**{'environment_id': environment.id,
'state': states.SessionState.DEPLOYING if not deleted
@ -106,7 +105,7 @@ class ResultEndpoint(object):
conf_session.state = states.SessionState.DEPLOYED
conf_session.save(unit)
#output application tracking information
# output application tracking information
message = '<EnvId: {0} TenantId: {1} Status: {2} Apps: {3}>'.format(
environment.id,
environment.tenant_id,
@ -174,7 +173,7 @@ def report_notification(report):
status.update(report)
unit = session.get_session()
#connect with deployment
# connect with deployment
with unit.begin():
running_deployment = get_last_deployment(unit,
status.environment_id)

View File

@ -12,16 +12,16 @@
# License for the specific language governing permissions and limitations
# under the License.
import eventlet
import json
import psutil
import socket
import time
import eventlet
import psutil
from murano.api import v1
from murano.api.v1 import request_statistics
from murano.common import config
from murano.db.services import stats as db_stats
from murano.openstack.common.gettextutils import _ # noqa
from murano.openstack.common import log as logging

View File

@ -20,20 +20,20 @@ eventlet.patcher.monkey_patch(all=False, socket=True)
import datetime
import errno
import jsonschema
import re
import socket
import sys
import time
from xml.dom import minidom
from xml.parsers import expat
import eventlet.wsgi
import jsonschema
from oslo.config import cfg
import routes
import routes.middleware
import webob.dec
import webob.exc
from xml.dom import minidom
from xml.parsers import expat
from murano.api.v1 import schemas
from murano.openstack.common import exception
@ -473,7 +473,7 @@ class XMLDictSerializer(DictSerializer):
self._add_xmlns(node, has_atom)
return node.toprettyxml(indent=' ', encoding='UTF-8')
#NOTE (ameade): the has_atom should be removed after all of the
# NOTE (ameade): the has_atom should be removed after all of the
# xml serializers and view builders have been updated to the current
# spec that required all responses include the xmlns:atom, the has_atom
# flag is to prevent current tests from breaking
@ -493,7 +493,7 @@ class XMLDictSerializer(DictSerializer):
if xmlns:
result.setAttribute('xmlns', xmlns)
#TODO(bcwaldon): accomplish this without a type-check
# TODO(bcwaldon): accomplish this without a type-check
if type(data) is list:
collections = metadata.get('list_collections', {})
if nodename in collections:
@ -512,7 +512,7 @@ class XMLDictSerializer(DictSerializer):
for item in data:
node = self._to_xml_node(doc, metadata, singular, item)
result.appendChild(node)
#TODO(bcwaldon): accomplish this without a type-check
# TODO(bcwaldon): accomplish this without a type-check
elif type(data) is dict:
collections = metadata.get('dict_collections', {})
if nodename in collections:

View File

@ -249,7 +249,7 @@ def package_search(filters, context, limit=None):
if context.is_admin:
if not include_disabled:
#NOTE(efedorova): is needed for SA 0.7.9, but could be done
# NOTE(efedorova): is needed for SA 0.7.9, but could be done
# simpler in SA 0.8. See http://goo.gl/9stlKu for a details
query = session.query(pkg).filter(pkg.__table__.c.enabled)
else:

View File

@ -23,10 +23,11 @@ Create Date: 2014-05-29 16:32:33.698760
revision = '001'
down_revision = None
import uuid
from alembic import op
import sqlalchemy as sa
from sqlalchemy.sql.expression import table as sa_table
import uuid
from murano.common import consts
from murano.db.sqla import types as st
@ -252,7 +253,7 @@ def upgrade():
)
_create_default_categories(op)
### end Alembic commands ###
# end Alembic commands #
def downgrade():
@ -272,4 +273,4 @@ def downgrade():
op.drop_table('category')
op.drop_table('tag')
op.drop_table('environment')
### end Alembic commands ###
# end Alembic commands #

View File

@ -40,10 +40,10 @@ def upgrade():
'package',
sa.Column('supplier', sa.types.Text())
)
### end Alembic commands ###
# end Alembic commands #
def downgrade():
op.drop_column('package', 'supplier')
op.drop_column('package', 'supplier_logo')
### end Alembic commands ###
# end Alembic commands #

View File

@ -89,4 +89,4 @@ def downgrade():
)
op.drop_table('task')
### end Alembic commands ###
# end Alembic commands #

View File

@ -94,7 +94,7 @@ class Session(Base, TimestampMixin):
def to_dict(self):
dictionary = super(Session, self).to_dict()
del dictionary['description']
#object relations may be not loaded yet
# object relations may be not loaded yet
if 'environment' in dictionary:
del dictionary['environment']
return dictionary
@ -138,7 +138,7 @@ class Status(Base, TimestampMixin):
def to_dict(self):
dictionary = super(Status, self).to_dict()
#object relations may be not loaded yet
# object relations may be not loaded yet
if 'deployment' in dictionary:
del dictionary['deployment']
return dictionary
@ -180,7 +180,7 @@ package_to_tag = sa.Table('package_to_tag',
sa.Column('tag_id',
sa.String(36),
sa.ForeignKey('tag.id',
ondelete="CASCADE")))
ondelete="CASCADE")))
class Instance(Base):

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import types
from webob import exc
from murano.common import utils
@ -49,7 +50,7 @@ class CoreServices(object):
if env_description is None:
return None
if not 'services' in env_description:
if 'services' not in env_description:
return []
result = utils.TraverseHelper.get(path, env_description)
@ -70,7 +71,7 @@ class CoreServices(object):
env_description = get_description(environment_id, session_id)
if env_description is None:
raise exc.HTTPMethodNotAllowed
if not 'services' in env_description:
if 'services' not in env_description:
env_description['services'] = []
if path == '/services':

View File

@ -56,7 +56,8 @@ class EnvironmentServices(object):
:param environment_id: Id of environment for which we checking status.
:return: Environment status
"""
#Deploying: there is at least one valid session with status `deploying`
# Deploying: there is at least one valid session with status
# `deploying`
session_list = sessions.SessionServices.get_sessions(environment_id)
has_opened = False
for session in session_list:
@ -77,7 +78,7 @@ class EnvironmentServices(object):
@staticmethod
def create(environment_params, tenant_id):
#tagging environment by tenant_id for later checks
# tagging environment by tenant_id for later checks
"""Creates environment with specified params, in particular - name
:param environment_params: Dict, e.g. {'name': 'env-name'}
@ -106,7 +107,7 @@ class EnvironmentServices(object):
with unit.begin():
unit.add(environment)
#saving environment as Json to itself
# saving environment as Json to itself
environment.update({'description': data})
environment.save(unit)

View File

@ -33,13 +33,13 @@ class SessionServices(object):
# Here we duplicate logic for reducing calls to database
# Checks for validation is same as in validate.
query = unit.query(models.Session).filter(
#Get all session for this environment
# Get all session for this environment
models.Session.environment_id == environment_id,
#Only sessions with same version as current env version are valid
# Only sessions with same version as current env version are valid
)
if state:
#in this state, if state is not specified return in all states
# in this state, if state is not specified return in all states
query = query.filter(models.Session.state == state),
return query.order_by(models.Session.version.desc(),
@ -79,17 +79,18 @@ class SessionServices(object):
:param session: Session for validation
"""
#if other session is deploying now current session is invalid
# if other session is deploying now current session is invalid
unit = db_session.get_session()
#if environment version is higher then version on which current session
#is created then other session was already deployed
# if environment version is higher then version on which
# current session
# is created then other session was already deployed
current_env = unit.query(models.Environment).\
get(session.environment_id)
if current_env.version > session.version:
return False
#if other session is deploying now current session is invalid
# if other session is deploying now current session is invalid
other_is_deploying = unit.query(models.Session).filter_by(
environment_id=session.environment_id,
state=states.SessionState.DEPLOYING
@ -109,7 +110,7 @@ class SessionServices(object):
:param token: auth token that is going to be used by orchestration
"""
#Set X-Auth-Token for conductor
# Set X-Auth-Token for conductor
deleted = session.description['Objects'] is None
action_name = None if deleted else 'deploy'

View File

@ -22,7 +22,6 @@ import eventlet
import eventlet.event
import yaql.context
import murano.dsl.attribute_store as attribute_store
import murano.dsl.dsl_exception as dsl_exception
import murano.dsl.expressions as expressions
@ -32,9 +31,9 @@ import murano.dsl.murano_object as murano_object
import murano.dsl.object_store as object_store
import murano.dsl.principal_objects.stack_trace as trace
import murano.dsl.yaql_functions as yaql_functions
from murano.openstack.common import log as logging
LOG = logging.getLogger(__name__)

View File

@ -96,7 +96,7 @@ def _pass1_serialize(value, parent, serialized_objects,
result = value.to_dictionary()
if designer_attributes_getter is not None:
result['?'].update(designer_attributes_getter(value.object_id))
#deserialize and merge list of actions
# deserialize and merge list of actions
actions = _serialize_available_action(value)
result['?']['_actions'] = _merge_actions(
result['?'].get('_actions', {}), actions)

View File

@ -15,12 +15,12 @@
import copy
import datetime
import logging
import os
import types
import uuid
import eventlet.event
import logging
import murano.common.config as config
import murano.common.exceptions as exceptions
@ -30,6 +30,7 @@ import murano.dsl.murano_object as murano_object
import murano.dsl.yaql_expression as yaql_expression
import murano.engine.system.common as common
LOG = logging.getLogger(__name__)

View File

@ -22,9 +22,9 @@ from murano.dsl import helpers
import murano.dsl.murano_class as murano_class
import murano.dsl.murano_object as murano_object
import murano.engine.system.common as common
from murano.openstack.common import log as logging
LOG = logging.getLogger(__name__)

View File

@ -14,11 +14,13 @@
# limitations under the License.
import json as jsonlib
import yaml as yamllib
import murano.dsl.helpers as helpers
import murano.dsl.murano_object as murano_object
if hasattr(yamllib, 'CSafeLoader'):
yaml_loader = yamllib.CSafeLoader
else:

View File

@ -15,13 +15,13 @@
import base64
import collections
import itertools
import random
import re
import string
import time
import types
import itertools
import jsonpatch
import jsonpointer
import yaql.context

View File

@ -16,6 +16,7 @@ import os
import shutil
import sys
import types
import yaml
from murano.dsl import yaql_expression

View File

@ -16,9 +16,10 @@ import os
import shutil
import sys
import tempfile
import yaml
import zipfile
import yaml
from murano.engine import yaql_yaml_loader
import murano.packages.application_package
import murano.packages.exceptions as e

View File

@ -14,6 +14,7 @@
import os
import sys
import yaml
import murano.packages.application_package

View File

@ -18,8 +18,8 @@ import time
import uuid
import requests
from tempest import clients
from tempest.common import cred_provider
from tempest.common import isolated_creds
from tempest import config
from tempest import test
@ -44,9 +44,8 @@ class MuranoClient(rest_client.RestClient):
return resp, json.loads(body)
def create_environment(self, name):
post_body = '{"name": "%s"}' % name
resp, body = self.post('v1/environments', post_body)
body = {'name': name}
resp, body = self.post('v1/environments', json.dumps(body))
return resp, json.loads(body)
@ -110,7 +109,7 @@ class MuranoClient(rest_client.RestClient):
resp, body = self.post(url.format(environment_id, session_id),
post_body)
return resp, json.loads(body)
return resp
def create_service(self, environment_id, session_id, post_body):
post_body = json.dumps(post_body)
@ -142,9 +141,10 @@ class MuranoClient(rest_client.RestClient):
def get_services_list(self, environment_id, session_id):
headers = self.get_headers()
headers.update(
{'X-Configuration-Session': session_id}
)
if session_id:
headers.update(
{'X-Configuration-Session': session_id}
)
resp, body = self.get(
'v1/environments/{0}/services'.format(environment_id),
@ -225,13 +225,16 @@ class MuranoClient(rest_client.RestClient):
class TestCase(test.BaseTestCase):
@classmethod
def setUpClass(cls):
super(TestCase, cls).setUpClass()
# If no credentials are provided, the Manager will use those
# in CONF.identity and generate an auth_provider from them
mgr = clients.Manager()
cls.creds = cred_provider.get_configured_credentials(
credential_type='identity_admin')
mgr = clients.Manager(cls.creds)
cls.client = MuranoClient(mgr.auth_provider)
def setUp(self):
@ -287,7 +290,12 @@ class NegativeTestCase(TestCase):
# If no credentials are provided, the Manager will use those
# in CONF.identity and generate an auth_provider from them
creds = isolated_creds.IsolatedCreds('v2', name=cls.__name__).\
get_alt_creds()
cls.isolated_creds = isolated_creds.IsolatedCreds('v2',
name=cls.__name__)
creds = cls.isolated_creds.get_alt_creds()
mgr = clients.Manager(credentials=creds)
cls.alt_client = MuranoClient(mgr.auth_provider)
@classmethod
def purge_creds(cls):
cls.isolated_creds.clear_isolated_creds()

View File

@ -11,6 +11,7 @@ Templates:
name: generateHostname($.serviceConfiguration.unitNamingPattern, 1)
flavor: $.instanceConfiguration.flavor
image: $.instanceConfiguration.osImage
availabilityZone: $.instanceConfiguration.availabilityZone
secondaryController:
?:

View File

@ -14,15 +14,15 @@
import os
import uuid
import zipfile
from tempest.test import attr
from tempest_lib import exceptions
from murano.tests.functional.api import base
from murano.tests.functional.common import utils as common_utils
class TestCaseRepository(base.TestCase):
class TestCaseRepository(base.TestCase, common_utils.ZipUtilsMixin):
@classmethod
def setUpClass(cls):
@ -32,15 +32,7 @@ class TestCaseRepository(base.TestCase):
cls.location = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
__folderpath__ = os.path.join(cls.location, "DummyTestApp")
__rootlen__ = len(__folderpath__) + 1
with zipfile.ZipFile(os.path.join(cls.location,
"DummyTestApp.zip"), "w") as zf:
for dirname, _, files in os.walk(__folderpath__):
for filename in files:
fn = os.path.join(dirname, filename)
zf.write(fn, fn[__rootlen__:])
cls.zip_dir(cls.location, "DummyTestApp")
def setUp(self):
super(TestCaseRepository, self).setUp()
@ -190,6 +182,7 @@ class TestRepositoryNegativeForbidden(base.NegativeTestCase,
super(TestRepositoryNegativeForbidden, cls).tearDownClass()
cls.client.delete_package(cls.package['id'])
cls.purge_creds()
@attr(type='negative')
def test_update_package_from_another_tenant(self):

View File

@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from tempest.test import attr
from tempest_lib import exceptions
@ -192,20 +190,12 @@ class TestServices(base.TestCase):
sess['id'],
service['?']['id'])
@testtools.skip("https://bugs.launchpad.net/murano/+bug/1295573")
@attr(type='negative')
def test_get_service_without_sess_id(self):
@attr(type='smoke')
def test_get_services_without_sess_id(self):
env = self.create_environment('test')
sess = self.client.create_session(env['id'])[1]
service = self.create_demo_service(env['id'], sess['id'])[1]
self.assertRaises(exceptions.Unauthorized,
self.client.get_service,
env['id'],
"",
service['?']['id'])
resp, body = self.client.get_services_list(env['id'], None)
self.assertEqual(resp.status, 200)
self.assertEqual([], body)
class TestServicesTenantIsolation(base.NegativeTestCase):

View File

@ -12,10 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import testtools
from tempest.test import attr
from tempest_lib import exceptions
import testtools
from murano.tests.functional.api import base

View File

@ -1,45 +0,0 @@
# Copyright (c) 2014 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.cli import base # noqa
from tempest import config
CONF = config.CONF
class ClientTestBase(base.ClientTestBase):
def murano(self, action, flags='', params='', admin=True, fail_ok=False):
"""Executes murano command for the given action."""
return self.clients.cmd_with_auth(
'murano', action, flags, params, admin, fail_ok)
def _get_clients(self):
clients = base.CLIClient(
CONF.identity.admin_username,
CONF.identity.admin_password,
CONF.identity.admin_tenant_name,
CONF.identity.uri,
CONF.cli.cli_dir
)
return clients
def listing(self, command, params=""):
return self.parser.listing(self.murano(command, params=params))
def get_value(self, need_field, known_field, known_value, somelist):
for element in somelist:
if element[known_field] == known_value:
return element[need_field]

View File

@ -1,129 +0,0 @@
# Copyright (c) 2014 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 time
import uuid
from murano.tests.functional.cli import muranoclient
class SimpleReadOnlyMuranoClientTest(muranoclient.ClientTestBase):
"""Basic, read-only tests for Murano CLI client.
Basic smoke test for the Murano CLI commands which do not require
creating or modifying murano objects.
"""
@classmethod
def setUpClass(cls):
super(SimpleReadOnlyMuranoClientTest, cls).setUpClass()
def test_environment_list(self):
environments = self.listing('environment-list')
self.assertTableStruct(environments,
['ID', 'Name', 'Created', 'Updated'])
def test_package_list(self):
packages = self.listing('package-list')
self.assertTableStruct(packages,
['ID', 'Name', 'FQN', 'Author', 'Is Public'])
def test_category_list(self):
self.murano('category-list')
def test_table_struct_of_environment_create(self):
env_name = "gg" + uuid.uuid4().hex
environment = self.listing('environment-create', params=env_name)
self.assertTableStruct(environment,
['ID', 'Name', 'Created', 'Updated'])
def test_table_struct_of_environment_delete(self):
env_name = "gg" + uuid.uuid4().hex
environment = self.listing('environment-create', params=env_name)
ID = self.get_value('ID', 'Name', env_name, environment)
delete_env = self.listing('environment-delete', params=ID)
self.assertTableStruct(delete_env,
['ID', 'Name', 'Created', 'Updated'])
class EnvironmentMuranoClientTest(muranoclient.ClientTestBase):
@classmethod
def setUpClass(cls):
super(EnvironmentMuranoClientTest, cls).setUpClass()
def test_environment_create(self):
env_name = "gg" + uuid.uuid4().hex
environment = self.listing('environment-create', params=env_name)
environment_list = self.listing('environment-list')
self.assertIn(env_name, [env['Name'] for env in environment])
self.assertIn(env_name, [env['Name'] for env in environment_list])
def test_environment_delete(self):
env_name = "gg" + uuid.uuid4().hex
environments = self.listing('environment-create', params=env_name)
ID = self.get_value('ID', 'Name', env_name, environments)
self.listing('environment-delete', params=ID)
start_time = time.time()
while env_name in [env['Name']
for env in self.listing('environment-list')]:
if start_time - time.time() > 60:
self.fail("Environment is not deleted in 60 seconds")
def test_environment_show(self):
env_name = "gg" + uuid.uuid4().hex
environment = self.listing('environment-create', params=env_name)
ID = self.get_value('ID', 'Name', env_name, environment)
created = self.get_value('Created', 'Name', env_name, environment)
updated = self.get_value('Updated', 'Name', env_name, environment)
show_env = self.listing('environment-show', params=ID)
self.assertEqual(env_name, self.get_value('Value', 'Property', 'name',
show_env))
self.assertEqual(created, self.get_value('Value', 'Property',
'created', show_env))
self.assertEqual(updated, self.get_value('Value', 'Property',
'updated', show_env))
def test_environment_rename(self):
env_name = "gg" + uuid.uuid4().hex
environment = self.listing('environment-create', params=env_name)
ID = self.get_value('ID', 'Name', env_name, environment)
new_name = "renamed" + uuid.uuid4().hex
rename_env = self.listing('environment-rename',
params='{id} {name}'.format(id=ID,
name=new_name))
show_env = self.listing('environment-show', params=ID)
self.assertEqual(new_name, self.get_value('Name', 'ID', ID,
rename_env))
self.assertEqual(new_name, self.get_value('Value', 'Property', 'name',
show_env))

View File

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

View File

@ -17,13 +17,12 @@ import socket
import time
import uuid
import testresources
import testtools
from heatclient import client as heatclient
from keystoneclient.v2_0 import client as ksclient
from muranoclient import client as mclient
import muranoclient.common.exceptions as exceptions
import testresources
import testtools
import murano.tests.functional.engine.config as cfg

View File

@ -13,11 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import fixtures
import logging
import urllib
import fixtures
import mock
import routes
import urllib
import webob
from murano.api.v1 import request_statistics
@ -29,6 +30,7 @@ from murano.openstack.common import timeutils
from murano.tests.unit import base
from murano.tests.unit import utils
TEST_DEFAULT_LOGLEVELS = {'migrate': logging.WARN, 'sqlalchemy': logging.WARN}
@ -52,14 +54,14 @@ class FakeLogMixin:
fixtures.FakeLogger(level=logging.DEBUG))
base_list = set([nlog.split('.')[0]
for nlog in logging.Logger.manager.loggerDict])
for base in base_list:
if base in TEST_DEFAULT_LOGLEVELS:
for element in base_list:
if element in TEST_DEFAULT_LOGLEVELS:
self.useFixture(fixtures.FakeLogger(
level=TEST_DEFAULT_LOGLEVELS[base],
name=base))
elif base != 'murano':
level=TEST_DEFAULT_LOGLEVELS[element],
name=element))
elif element != 'murano':
self.useFixture(fixtures.FakeLogger(
name=base))
name=element))
class MuranoApiTestCase(base.MuranoWithDBTestCase, FakeLogMixin):
@ -102,7 +104,7 @@ class ControllerTest(object):
def __init__(self, *args, **kwargs):
super(ControllerTest, self).__init__(*args, **kwargs)
#cfg.CONF.set_default('host', 'server.test')
# cfg.CONF.set_default('host', 'server.test')
self.api_version = '1.0'
self.tenant = 'test_tenant'
self.mock_policy_check = None

View File

@ -64,11 +64,21 @@ class TestActionsApi(tb.ControllerTest, tb.MuranoApiTestCase):
rpc_task = {
'tenant_id': self.tenant,
'model': {'Objects': {'applications': [], '?':
{
'_actions': {'actionsID_action': {
'name': 'Testaction', 'enabled': True}},
'id': '12345'}}, 'Attributes': {}},
'model': {
'Objects': {
'applications': [],
'?': {
'_actions': {
'actionsID_action': {
'name': 'Testaction',
'enabled': True
}
},
'id': '12345'
}
},
'Attributes': {}
},
'action': {
'method': 'Testaction',
'object_id': '12345',

View File

@ -16,9 +16,10 @@
import cgi
import cStringIO
import imghdr
import mock
import os
import mock
from murano.api.v1 import catalog
from murano.common import policy
from murano.db.catalog import api as db_catalog_api

View File

@ -394,7 +394,7 @@ class BaseWalkMigrationTestCase(BaseMigrationTestCase):
database functionality (reset default settings and session cleanup).
"""
CONF.set_override('connection', str(engine.url), group='database')
#session.cleanup()
# session.cleanup()
def _test_mysql_opportunistically(self):
# Test that table creation on mysql only builds InnoDB tables
@ -453,11 +453,11 @@ class BaseWalkMigrationTestCase(BaseMigrationTestCase):
"""
self.ALEMBIC_CONFIG.stdout = buf = io.StringIO()
CONF.set_override('connection', str(engine.url), group='database')
#session.cleanup()
# session.cleanup()
getattr(command, alembic_command)(*args, **kwargs)
res = buf.getvalue().strip()
LOG.debug('Alembic command `%s` returns: %s' % (alembic_command, res))
#session.cleanup()
# session.cleanup()
return res
def _up_and_down_versions(self):

View File

@ -14,6 +14,7 @@
import fnmatch
import os.path
import yaml
from murano.dsl import class_loader

View File

@ -13,8 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
import mock
import yaql.context
from murano.common import exceptions as exc

View File

@ -16,7 +16,6 @@
from testtools import matchers
from murano.dsl import exceptions
from murano.tests.unit.dsl.foundation import object_model as om
from murano.tests.unit.dsl.foundation import test_case

View File

@ -11,9 +11,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import imghdr
import os
import murano.packages.load_utils as load_utils
import murano.tests.unit.base as test_base
import os
class TestHotV1(test_base.MuranoTestCase):

View File

@ -14,10 +14,10 @@
# limitations under the License.
import mock
from murano.tests.unit import base
from murano.dsl import murano_object
from murano.engine.system import heat_stack
from murano.tests.unit import base
MOD_NAME = 'murano.engine.system.heat_stack'

View File

@ -38,7 +38,7 @@ class SysLogHandlersTestCase(base.MuranoTestCase):
self.logger.binary_name = 'Foo_application'
def test_rfc_format(self):
"""Ensure syslog msg contains APP-NAME for RFC wrapped handler"""
"""Ensure syslog msg contains APP-NAME for RFC wrapped handler."""
logrecord = logging.LogRecord('name', 'WARN', '/tmp', 1,
'Message', None, None)
expected = logging.LogRecord('name', 'WARN', '/tmp', 1,
@ -47,7 +47,7 @@ class SysLogHandlersTestCase(base.MuranoTestCase):
expected.getMessage())
def test_standard_format(self):
"""Ensure syslog msg isn't modified for standard handler"""
"""Ensure syslog msg isn't modified for standard handler."""
logrecord = logging.LogRecord('name', 'WARN', '/tmp', 1,
'Message', None, None)
expected = logrecord

View File

@ -23,7 +23,7 @@ def dummy_context(user='test_username', tenant_id='test_tenant_id',
return context.RequestContext.from_dict({
'tenant': tenant_id,
'user': user,
#'roles': roles, # Commented until policy check changes land
# 'roles': roles, # Commented until policy check changes land
'is_admin': is_admin,
})

View File

@ -2,42 +2,42 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=0.6,!=0.7,<1.0
Babel>=1.3
Babel>=1.3,<=1.3
SQLAlchemy>=0.8.4,<=0.9.99,!=0.9.0,!=0.9.1,!=0.9.2,!=0.9.3,!=0.9.4,!=0.9.5,!=0.9.6
alembic>=0.6.4
anyjson>=0.3.3
eventlet>=0.15.1
PasteDeploy>=1.5.0
Routes>=1.12.3,!=2.0
WebOb>=1.2.3
alembic>=0.6.4,<=0.7.4
anyjson>=0.3.3,<=0.3.3
eventlet>=0.15.1,<=0.15.2
PasteDeploy>=1.5.0,<=1.5.2
Routes>=1.12.3,!=2.0,<=2.1
WebOb>=1.2.3,<=1.3.1
wsgiref>=0.1.2
argparse
ordereddict
kombu>=2.5.0
lockfile>=0.8
pycrypto>=2.6
ordereddict<=1.1
kombu>=2.5.0,<=3.0.7
lockfile>=0.8,<=0.8
pycrypto>=2.6,<=2.6.1
psutil>=1.1.1,<2.0.0
iso8601>=0.1.9
six>=1.7.0
netaddr>=0.7.12
PyYAML>=3.1.0
jsonpatch>=1.1
keystonemiddleware>=1.0.0
iso8601>=0.1.9,<=0.1.10
six>=1.7.0,<=1.9.0
netaddr>=0.7.12,<=0.7.13
PyYAML>=3.1.0,<=3.10
jsonpatch>=1.1,<=1.3
keystonemiddleware>=1.0.0,<1.4.0
# For paste.util.template used in keystone.common.template
Paste
passlib
passlib<=1.6.2
jsonschema>=2.0.0,<3.0.0
python-keystoneclient>=0.10.0
python-heatclient>=0.2.9
python-neutronclient>=2.3.6,<3
oslo.db>=1.0.0 # Apache-2.0
oslo.config>=1.4.0 # Apache-2.0
oslo.messaging>=1.4.0,!=1.5.0,<1.6.0
oslo.utils>=1.0.0 # Apache-2.0
python-keystoneclient>=0.10.0,<1.2.0
python-heatclient>=0.2.9,<0.3.0
python-neutronclient>=2.3.6,<2.4.0
oslo.db>=1.0.0,<1.1 # Apache-2.0
oslo.config>=1.4.0,<=1.6.0 # Apache-2.0
oslo.messaging>=1.4.0,<1.5.0
oslo.utils>=1.4.0,<1.5.0 # Apache-2.0
# not listed in global requirements
yaql>=0.2.3,<0.3
python-muranoclient>=0.5.5
python-muranoclient>=0.5.5, <0.5.6

View File

@ -1,23 +1,26 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking>=0.8.0,<0.9
coverage>=3.6
discover
fixtures>=0.3.14
mock>=1.0
posix_ipc
sqlalchemy-migrate>=0.9.1,!=0.9.2
testrepository>=0.0.18
testresources>=0.2.4
testscenarios>=0.4
testtools>=0.9.34,!=1.4.0
unittest2
hacking>=0.9.2,<0.10
nose<=1.3.1
coverage>=3.6,<=3.7.1
discover<=0.4.0
fixtures>=0.3.14,<=1.0.0
mock>=1.0,<=1.0.1
posix_ipc<=0.9.9
sqlalchemy-migrate==0.9.1
testrepository>=0.0.18,<=0.0.20
testresources>=0.2.4,<=0.2.7
testscenarios>=0.4,<=0.4
testtools>=0.9.34,!=1.4.0,<=1.5.0
unittest2<=0.8.0
# Some of the tests use real MySQL and Postgres databases
MySQL-python
psycopg2
MySQL-python<=1.2.3
psycopg2<=2.6
# doc build requirements
sphinx>=1.1.2,!=1.2.0,<1.3
# Tempest reqs override
oslo.i18n<=1.3.1

View File

@ -38,7 +38,10 @@ commands = flake8
# H501 Do not use locals() for string formatting
# H702 Argument to _ must be just a string
# H902 Use the 'not in' operator for collection membership evaluation
ignore =H501,H702,H902
# H233 Python 3.x incompatible use of print operator
# H405 Multi line docstring summary not separated with an empty line
# H904 Wrap long lines in parentheses instead of a backslash
ignore =H501,H702,H902,H233,H405,H904
show-source = true
builtins = _
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools