Fix for functional tests and DB migration unit tests
This commit consists of three parts. We need to merge them both to pass all the CI jobs: 1. Updated functional CLI tests after a change in tempest Also fix contains backported tests from murano-master. 2. Update DB migration tests in respect to new release of Alembic After alembic update output of 'history' command in alembic changed. This commit fixes failing unit tests. commit id (master):1f17868955
3. Fix Murano app names: Names of apps used in CI were changes in murano-incubator. This change updates configuration of functional tests to retrieve apps with respect to their new names. commit id (master):931b2e9d62
Co-authored-by: Ruslan Kamaldinov <rkamaldinov@mirantis.com> Change-Id: I947ed688b44c52ea72211bf630f411ef538fb9b8
This commit is contained in:
parent
65f3cd8826
commit
22a0a109c4
|
@ -19,6 +19,7 @@ import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from tempest import clients
|
from tempest import clients
|
||||||
|
from tempest.common import isolated_creds
|
||||||
from tempest.common import rest_client
|
from tempest.common import rest_client
|
||||||
from tempest import config
|
from tempest import config
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
|
@ -100,6 +101,14 @@ class MuranoClient(rest_client.RestClient):
|
||||||
|
|
||||||
return resp, json.loads(body)
|
return resp, json.loads(body)
|
||||||
|
|
||||||
|
def deploy_session(self, environment_id, session_id):
|
||||||
|
post_body = None
|
||||||
|
url = 'v1/environments/{0}/sessions/{1}/deploy'
|
||||||
|
resp, body = self.post(url.format(environment_id, session_id),
|
||||||
|
post_body)
|
||||||
|
|
||||||
|
return resp, json.loads(body)
|
||||||
|
|
||||||
def create_service(self, environment_id, session_id, post_body):
|
def create_service(self, environment_id, session_id, post_body):
|
||||||
post_body = json.dumps(post_body)
|
post_body = json.dumps(post_body)
|
||||||
|
|
||||||
|
@ -242,7 +251,9 @@ class TestCase(tempest.test.BaseTestCase):
|
||||||
|
|
||||||
return environment
|
return environment
|
||||||
|
|
||||||
def create_demo_service(self, environment_id, session_id):
|
def create_demo_service(self, environment_id, session_id, client=None):
|
||||||
|
if not client:
|
||||||
|
client = self.client
|
||||||
post_body = {
|
post_body = {
|
||||||
"?": {
|
"?": {
|
||||||
"id": uuid.uuid4().hex,
|
"id": uuid.uuid4().hex,
|
||||||
|
@ -261,9 +272,9 @@ class TestCase(tempest.test.BaseTestCase):
|
||||||
"configuration": "standalone"
|
"configuration": "standalone"
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.client.create_service(environment_id,
|
return client.create_service(environment_id,
|
||||||
session_id,
|
session_id,
|
||||||
post_body)
|
post_body)
|
||||||
|
|
||||||
|
|
||||||
class NegativeTestCase(TestCase):
|
class NegativeTestCase(TestCase):
|
||||||
|
@ -273,5 +284,6 @@ class NegativeTestCase(TestCase):
|
||||||
|
|
||||||
# If no credentials are provided, the Manager will use those
|
# If no credentials are provided, the Manager will use those
|
||||||
# in CONF.identity and generate an auth_provider from them
|
# in CONF.identity and generate an auth_provider from them
|
||||||
mgr = clients.Manager()
|
creds = isolated_creds.IsolatedCreds(cls.__name__).get_alt_creds()
|
||||||
|
mgr = clients.Manager(credentials=creds)
|
||||||
cls.alt_client = MuranoClient(mgr.auth_provider)
|
cls.alt_client = MuranoClient(mgr.auth_provider)
|
||||||
|
|
|
@ -100,3 +100,27 @@ class TestEnvironments(base.TestCase):
|
||||||
self.assertRaises(exceptions.NotFound,
|
self.assertRaises(exceptions.NotFound,
|
||||||
self.client.get_environment,
|
self.client.get_environment,
|
||||||
env['id'])
|
env['id'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestEnvironmentsTenantIsolation(base.NegativeTestCase):
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_get_environment_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.get_environment, env['id'])
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_update_environment_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.update_environment, env['id'])
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_delete_environment_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.delete_environment, env['id'])
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import testtools
|
|
||||||
import uuid
|
import uuid
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
|
@ -56,8 +55,6 @@ class TestCaseRepository(base.TestCase):
|
||||||
try:
|
try:
|
||||||
self.client.delete_package(package['id'])
|
self.client.delete_package(package['id'])
|
||||||
except Exception:
|
except Exception:
|
||||||
#except exceptions.NotFound: Need to uncomment after fix the
|
|
||||||
#following bug https://bugs.launchpad.net/murano/+bug/1309413
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -141,7 +138,6 @@ class TestRepositoryNegativeNotFound(base.NegativeTestCase):
|
||||||
self.client.get_package,
|
self.client.get_package,
|
||||||
self.id)
|
self.id)
|
||||||
|
|
||||||
@testtools.skip("https://bugs.launchpad.net/murano/+bug/1309413")
|
|
||||||
@attr(type='negative')
|
@attr(type='negative')
|
||||||
def test_delete_package_with_incorrect_id(self):
|
def test_delete_package_with_incorrect_id(self):
|
||||||
self.assertRaises(exceptions.NotFound,
|
self.assertRaises(exceptions.NotFound,
|
||||||
|
@ -173,9 +169,6 @@ class TestRepositoryNegativeForbidden(base.NegativeTestCase,
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(TestRepositoryNegativeForbidden, cls).setUpClass()
|
super(TestRepositoryNegativeForbidden, cls).setUpClass()
|
||||||
|
|
||||||
raise cls.skipException(
|
|
||||||
"https://bugs.launchpad.net/murano/+bug/1312190")
|
|
||||||
|
|
||||||
cls.categorie = cls.client.list_categories()[1]['categories'][0]
|
cls.categorie = cls.client.list_categories()[1]['categories'][0]
|
||||||
|
|
||||||
packages_list = cls.client.get_list_packages()[1]
|
packages_list = cls.client.get_list_packages()[1]
|
||||||
|
|
|
@ -206,3 +206,44 @@ class TestServices(base.TestCase):
|
||||||
env['id'],
|
env['id'],
|
||||||
"",
|
"",
|
||||||
service['?']['id'])
|
service['?']['id'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestServicesTenantIsolation(base.NegativeTestCase):
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_get_list_services_in_env_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
sess = self.client.create_session(env['id'])[1]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.get_services_list, env['id'],
|
||||||
|
sess['id'])
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_create_service_in_env_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
sess = self.client.create_session(env['id'])[1]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.create_demo_service, env['id'],
|
||||||
|
sess['id'], client=self.alt_client)
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_delete_service_in_env_from_another_tenant(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.alt_client.delete_service, env['id'],
|
||||||
|
sess['id'], service['?']['id'])
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_get_service_in_env_from_another_tenant(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.alt_client.get_service, env['id'],
|
||||||
|
sess['id'], service['?']['id'])
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import testtools
|
||||||
|
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
from tempest.test import attr
|
from tempest.test import attr
|
||||||
|
|
||||||
|
@ -103,3 +105,41 @@ class TestSessions(base.TestCase):
|
||||||
self.client.delete_session,
|
self.client.delete_session,
|
||||||
env['id'],
|
env['id'],
|
||||||
sess['id'])
|
sess['id'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestSessionsTenantIsolation(base.NegativeTestCase):
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_create_session_in_env_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.create_session, env['id'])
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_delete_session_in_env_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
sess = self.client.create_session(env['id'])[1]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.delete_session, env['id'],
|
||||||
|
sess['id'])
|
||||||
|
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_get_session_in_env_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
sess = self.client.create_session(env['id'])[1]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.get_session, env['id'],
|
||||||
|
sess['id'])
|
||||||
|
|
||||||
|
@testtools.skip("https://bugs.launchpad.net/murano/+bug/1382026")
|
||||||
|
@attr(type='negative')
|
||||||
|
def test_deploy_session_in_env_from_another_tenant(self):
|
||||||
|
env = self.create_environment('test')
|
||||||
|
sess = self.client.create_session(env['id'])[1]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.Unauthorized,
|
||||||
|
self.alt_client.deploy_session, env['id'],
|
||||||
|
sess['id'])
|
||||||
|
|
|
@ -12,12 +12,34 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from tempest import cli
|
from tempest_lib.cli import base # noqa
|
||||||
|
|
||||||
|
from tempest import config
|
||||||
|
|
||||||
|
CONF = config.CONF
|
||||||
|
|
||||||
|
|
||||||
class ClientTestBase(cli.ClientTestBase):
|
class ClientTestBase(base.ClientTestBase):
|
||||||
|
|
||||||
def murano(self, action, flags='', params='', admin=True, fail_ok=False):
|
def murano(self, action, flags='', params='', admin=True, fail_ok=False):
|
||||||
"""Executes murano command for the given action."""
|
"""Executes murano command for the given action."""
|
||||||
return self.cmd_with_auth(
|
return self.clients.cmd_with_auth(
|
||||||
'murano', action, flags, params, admin, fail_ok)
|
'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]
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import time
|
||||||
|
import uuid
|
||||||
|
|
||||||
from murano.tests.functional.cli import muranoclient
|
from murano.tests.functional.cli import muranoclient
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,16 +30,100 @@ class SimpleReadOnlyMuranoClientTest(muranoclient.ClientTestBase):
|
||||||
super(SimpleReadOnlyMuranoClientTest, cls).setUpClass()
|
super(SimpleReadOnlyMuranoClientTest, cls).setUpClass()
|
||||||
|
|
||||||
def test_environment_list(self):
|
def test_environment_list(self):
|
||||||
environments = self.parser.listing(self.murano('environment-list'))
|
environments = self.listing('environment-list')
|
||||||
|
|
||||||
self.assertTableStruct(environments,
|
self.assertTableStruct(environments,
|
||||||
['ID', 'Name', 'Created', 'Updated'])
|
['ID', 'Name', 'Created', 'Updated'])
|
||||||
|
|
||||||
def test_package_list(self):
|
def test_package_list(self):
|
||||||
packages = self.parser.listing(self.murano('package-list'))
|
packages = self.listing('package-list')
|
||||||
|
|
||||||
self.assertTableStruct(packages,
|
self.assertTableStruct(packages,
|
||||||
['ID', 'Name', 'FQN', 'Author', 'Is Public'])
|
['ID', 'Name', 'FQN', 'Author', 'Is Public'])
|
||||||
|
|
||||||
def test_category_list(self):
|
def test_category_list(self):
|
||||||
self.murano('category-list')
|
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))
|
||||||
|
|
|
@ -12,19 +12,18 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
import urlparse
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import requests
|
|
||||||
import testresources
|
import testresources
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from heatclient import client as heatclient
|
from heatclient import client as heatclient
|
||||||
from keystoneclient.v2_0 import client as ksclient
|
from keystoneclient.v2_0 import client as ksclient
|
||||||
|
from muranoclient import client as mclient
|
||||||
|
import muranoclient.common.exceptions as exceptions
|
||||||
|
|
||||||
import murano.tests.functional.engine.config as cfg
|
import murano.tests.functional.engine.config as cfg
|
||||||
|
|
||||||
|
@ -32,106 +31,6 @@ import murano.tests.functional.engine.config as cfg
|
||||||
CONF = cfg.cfg.CONF
|
CONF = cfg.cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
|
||||||
def __init__(self, user, password, tenant, auth_url, murano_url):
|
|
||||||
self.auth = ksclient.Client(
|
|
||||||
username=user, password=password,
|
|
||||||
tenant_name=tenant, auth_url=auth_url
|
|
||||||
)
|
|
||||||
self.endpoint = urlparse.urljoin(murano_url, 'v1/')
|
|
||||||
self.headers = {
|
|
||||||
'X-Auth-Token': self.auth.auth_token,
|
|
||||||
'Content-type': 'application/json'
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_url(self, url_part=None):
|
|
||||||
return urlparse.urljoin(self.endpoint, url_part)
|
|
||||||
|
|
||||||
def create_environment(self, name):
|
|
||||||
endpoint = self.get_url('environments')
|
|
||||||
body = json.dumps({'name': name})
|
|
||||||
|
|
||||||
return requests.post(endpoint, data=body, headers=self.headers).json()
|
|
||||||
|
|
||||||
def delete_environment(self, environment_id, timeout=180):
|
|
||||||
endpoint = self.get_url('environments/%s' % environment_id)
|
|
||||||
|
|
||||||
def _is_exist():
|
|
||||||
resp = requests.get(endpoint, headers=self.headers)
|
|
||||||
return resp.status_code == requests.codes.ok
|
|
||||||
|
|
||||||
env_deleted = not _is_exist()
|
|
||||||
requests.delete(endpoint, headers=self.headers)
|
|
||||||
|
|
||||||
start_time = time.time()
|
|
||||||
while env_deleted is not True:
|
|
||||||
if timeout and time.time() - start_time > timeout:
|
|
||||||
raise Exception('Environment was not deleted')
|
|
||||||
time.sleep(5)
|
|
||||||
env_deleted = not _is_exist()
|
|
||||||
|
|
||||||
def get_environment(self, environment_id):
|
|
||||||
endpoint = self.get_url('environments/%s' % environment_id)
|
|
||||||
return requests.get(endpoint, headers=self.headers).json()
|
|
||||||
|
|
||||||
def create_session(self, environment_id):
|
|
||||||
endpoint = self.get_url('environments/%s/configure' % environment_id)
|
|
||||||
return requests.post(endpoint, headers=self.headers).json()
|
|
||||||
|
|
||||||
def deploy_session(self, environment_id, session_id):
|
|
||||||
endpoint = self.get_url('environments/{0}/sessions/{1}/deploy'.format(
|
|
||||||
environment_id, session_id))
|
|
||||||
return requests.post(endpoint, headers=self.headers)
|
|
||||||
|
|
||||||
def create_service(self, environment_id, session_id, json_data):
|
|
||||||
endpoint = self.get_url('environments/%s/services' % environment_id)
|
|
||||||
body = json.dumps(json_data)
|
|
||||||
headers = self.headers.copy()
|
|
||||||
headers['x-configuration-session'] = session_id
|
|
||||||
|
|
||||||
return requests.post(endpoint, data=body, headers=headers).json()
|
|
||||||
|
|
||||||
def delete_service(self, environment_id, session_id, service_id):
|
|
||||||
endpoint = self.get_url('environments/{0}/services/{1}'.format(
|
|
||||||
environment_id, service_id
|
|
||||||
))
|
|
||||||
headers = self.headers.copy()
|
|
||||||
headers['x-configuration-session'] = session_id
|
|
||||||
|
|
||||||
requests.delete(endpoint, headers=headers)
|
|
||||||
|
|
||||||
def wait_for_environment_deploy(self, environment_id):
|
|
||||||
environment = self.get_environment(environment_id)
|
|
||||||
|
|
||||||
start_time = time.time()
|
|
||||||
while environment['status'] != 'ready':
|
|
||||||
if time.time() - start_time > 1200:
|
|
||||||
return
|
|
||||||
time.sleep(5)
|
|
||||||
environment = self.get_environment(environment_id)
|
|
||||||
|
|
||||||
return environment
|
|
||||||
|
|
||||||
def get_ip_list(self, environment):
|
|
||||||
return [service['instance']['ipAddresses']
|
|
||||||
for service in environment['services']]
|
|
||||||
|
|
||||||
def deployments_list(self, environment_id):
|
|
||||||
endpoint = self.get_url('environments/%s/deployments' % environment_id)
|
|
||||||
response = requests.get(endpoint, headers=self.headers)
|
|
||||||
return response.json()['deployments']
|
|
||||||
|
|
||||||
def upload_package(self, name, package, description):
|
|
||||||
endpoint = self.get_url('catalog/packages')
|
|
||||||
body = {'JsonString': json.dumps(description)}
|
|
||||||
files = {name: open(package, 'rb')}
|
|
||||||
headers = self.headers.copy()
|
|
||||||
del headers['Content-type']
|
|
||||||
|
|
||||||
resp = requests.post(endpoint, data=body, files=files, headers=headers)
|
|
||||||
return resp.json()['id']
|
|
||||||
|
|
||||||
|
|
||||||
class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
testresources.ResourcedTestCase):
|
testresources.ResourcedTestCase):
|
||||||
|
|
||||||
|
@ -141,20 +40,26 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
|
|
||||||
cfg.load_config()
|
cfg.load_config()
|
||||||
|
|
||||||
cls.client = Client(user=CONF.murano.user,
|
keystone_client = ksclient.Client(username=CONF.murano.user,
|
||||||
password=CONF.murano.password,
|
password=CONF.murano.password,
|
||||||
tenant=CONF.murano.tenant,
|
tenant_name=CONF.murano.tenant,
|
||||||
auth_url=CONF.murano.auth_url,
|
auth_url=CONF.murano.auth_url)
|
||||||
murano_url=CONF.murano.murano_url)
|
|
||||||
|
|
||||||
cls.linux = CONF.murano.linux_image
|
heat_url = keystone_client.service_catalog.url_for(
|
||||||
cls.windows = CONF.murano.windows_image
|
|
||||||
|
|
||||||
heat_url = cls.client.auth.service_catalog.url_for(
|
|
||||||
service_type='orchestration', endpoint_type='publicURL')
|
service_type='orchestration', endpoint_type='publicURL')
|
||||||
|
|
||||||
cls.heat_client = heatclient.Client('1', endpoint=heat_url,
|
cls.heat_client = heatclient.Client('1', endpoint=heat_url,
|
||||||
token=cls.client.auth.auth_token)
|
token=keystone_client.auth_token)
|
||||||
|
|
||||||
|
url = CONF.murano.murano_url
|
||||||
|
murano_url = url if 'v1' not in url else "/".join(
|
||||||
|
url.split('/')[:url.split('/').index('v1')])
|
||||||
|
|
||||||
|
cls.muranoclient = mclient.Client('1',
|
||||||
|
endpoint=murano_url,
|
||||||
|
token=keystone_client.auth_token)
|
||||||
|
|
||||||
|
cls.linux = CONF.murano.linux_image
|
||||||
|
|
||||||
cls.pkgs_path = os.path.abspath(os.path.join(
|
cls.pkgs_path = os.path.abspath(os.path.join(
|
||||||
os.path.dirname(__file__),
|
os.path.dirname(__file__),
|
||||||
|
@ -162,48 +67,77 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
'murano-app-incubator'
|
'murano-app-incubator'
|
||||||
))
|
))
|
||||||
|
|
||||||
cls.postgre_id = cls.client.upload_package(
|
def upload_package(package_name, body, app):
|
||||||
|
|
||||||
|
files = {'%s' % package_name: open(app, 'rb')}
|
||||||
|
|
||||||
|
return cls.muranoclient.packages.create(body, files)
|
||||||
|
|
||||||
|
upload_package(
|
||||||
'PostgreSQL',
|
'PostgreSQL',
|
||||||
os.path.join(cls.pkgs_path, 'io.murano.apps.PostgreSql.zip'),
|
{"categories": ["Databases"], "tags": ["tag"]},
|
||||||
{'categories': ['Databases'], 'tags': ['tag']}
|
os.path.join(cls.pkgs_path, 'io.murano.databases.PostgreSql.zip')
|
||||||
)
|
)
|
||||||
cls.apache_id = cls.client.upload_package(
|
upload_package(
|
||||||
|
'SqlDatabase',
|
||||||
|
{"categories": ["Databases"], "tags": ["tag"]},
|
||||||
|
os.path.join(cls.pkgs_path, 'io.murano.databases.SqlDatabase.zip')
|
||||||
|
)
|
||||||
|
upload_package(
|
||||||
'Apache',
|
'Apache',
|
||||||
os.path.join(cls.pkgs_path, 'io.murano.apps.apache.Apache.zip'),
|
{"categories": ["Application Servers"], "tags": ["tag"]},
|
||||||
{'categories': ['Application Servers'], 'tags': ['tag']}
|
|
||||||
)
|
|
||||||
cls.tomcat_id = cls.client.upload_package(
|
|
||||||
'Tomcat',
|
|
||||||
os.path.join(cls.pkgs_path, 'io.murano.apps.apache.Tomcat.zip'),
|
|
||||||
{'categories': ['Application Servers'], 'tags': ['tag']}
|
|
||||||
)
|
|
||||||
cls.telnet_id = cls.client.upload_package(
|
|
||||||
'Telnet',
|
|
||||||
os.path.join(cls.pkgs_path, 'io.murano.apps.linux.Telnet.zip'),
|
|
||||||
{'categories': ['Web'], 'tags': ['tag']}
|
|
||||||
)
|
|
||||||
cls.ad_id = cls.client.upload_package(
|
|
||||||
'Active Directory',
|
|
||||||
os.path.join(cls.pkgs_path,
|
os.path.join(cls.pkgs_path,
|
||||||
'io.murano.windows.ActiveDirectory.zip'),
|
'io.murano.apps.apache.ApacheHttpServer.zip')
|
||||||
{'categories': ['Microsoft Services'], 'tags': ['tag']}
|
)
|
||||||
|
upload_package(
|
||||||
|
'Tomcat',
|
||||||
|
{"categories": ["Application Servers"], "tags": ["tag"]},
|
||||||
|
os.path.join(cls.pkgs_path, 'io.murano.apps.apache.Tomcat.zip')
|
||||||
|
)
|
||||||
|
upload_package(
|
||||||
|
'Telnet',
|
||||||
|
{"categories": ["Web"], "tags": ["tag"]},
|
||||||
|
os.path.join(cls.pkgs_path, 'io.murano.apps.linux.Telnet.zip')
|
||||||
)
|
)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(MuranoBase, self).setUp()
|
super(MuranoBase, self).setUp()
|
||||||
|
|
||||||
self.environments = []
|
self.environments = []
|
||||||
self.stack_names = []
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(MuranoBase, self).tearDown()
|
super(MuranoBase, self).tearDown()
|
||||||
|
|
||||||
for env in self.environments:
|
for env in self.environments:
|
||||||
try:
|
try:
|
||||||
self.client.delete_environment(env)
|
self.environment_delete(env)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def environment_delete(self, environment_id, timeout=180):
|
||||||
|
self.muranoclient.environments.delete(environment_id)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
while time.time() - start_time < timeout:
|
||||||
|
try:
|
||||||
|
self.muranoclient.environments.get(environment_id)
|
||||||
|
except exceptions.HTTPNotFound:
|
||||||
|
return
|
||||||
|
raise Exception(
|
||||||
|
'Environment {0} was not deleted in {1} seconds'.format(
|
||||||
|
environment_id, timeout))
|
||||||
|
|
||||||
|
def wait_for_environment_deploy(self, environment):
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
while environment.manager.get(environment.id).status != 'ready':
|
||||||
|
if time.time() - start_time > 1200:
|
||||||
|
self.fail(
|
||||||
|
'Environment deployment is not finished in 1200 seconds')
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
return environment.manager.get(environment.id)
|
||||||
|
|
||||||
def check_port_access(self, ip, port):
|
def check_port_access(self, ip, port):
|
||||||
result = 1
|
result = 1
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
@ -219,15 +153,17 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
self.assertEqual(0, result, '%s port is closed on instance' % port)
|
self.assertEqual(0, result, '%s port is closed on instance' % port)
|
||||||
|
|
||||||
def deployment_success_check(self, environment, port):
|
def deployment_success_check(self, environment, port):
|
||||||
deployments = self.client.deployments_list(environment['id'])
|
deployment = self.muranoclient.deployments.list(environment.id)[-1]
|
||||||
|
|
||||||
for deployment in deployments:
|
self.assertEqual('success', deployment.state,
|
||||||
msg = 'Deployment status is %s' % deployment['state']
|
'Deployment status is {0}'.format(deployment.state))
|
||||||
self.assertEqual('success', deployment['state'], msg)
|
|
||||||
|
|
||||||
instance = environment['services'][0]['instance']
|
ip = environment.services[-1]['instance']['floatingIpAddress']
|
||||||
self.assertTrue(instance['floatingIpAddress'])
|
|
||||||
self.check_port_access(instance['floatingIpAddress'], port)
|
if ip:
|
||||||
|
self.check_port_access(ip, port)
|
||||||
|
else:
|
||||||
|
self.fail('Instance does not have floating IP')
|
||||||
|
|
||||||
def test_deploy_telnet(self):
|
def test_deploy_telnet(self):
|
||||||
post_body = {
|
post_body = {
|
||||||
|
@ -250,16 +186,7 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
|
|
||||||
environment_name = 'Telnetenv' + uuid.uuid4().hex[:5]
|
environment_name = 'Telnetenv' + uuid.uuid4().hex[:5]
|
||||||
|
|
||||||
environment = self.client.create_environment(environment_name)
|
env = self._quick_deploy(environment_name, post_body)
|
||||||
self.environments.append(environment['id'])
|
|
||||||
|
|
||||||
session = self.client.create_session(environment['id'])
|
|
||||||
|
|
||||||
self.client.create_service(environment['id'], session['id'], post_body)
|
|
||||||
self.client.deploy_session(environment['id'], session['id'])
|
|
||||||
|
|
||||||
env = self.client.wait_for_environment_deploy(environment['id'])
|
|
||||||
self.assertIsNotNone(env)
|
|
||||||
|
|
||||||
self.deployment_success_check(env, 23)
|
self.deployment_success_check(env, 23)
|
||||||
|
|
||||||
|
@ -277,24 +204,14 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
},
|
},
|
||||||
"name": "teMurano",
|
"name": "teMurano",
|
||||||
"?": {
|
"?": {
|
||||||
"type": "io.murano.apps.apache.Apache",
|
"type": "io.murano.apps.apache.ApacheHttpServer",
|
||||||
"id": str(uuid.uuid4())
|
"id": str(uuid.uuid4())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
environment_name = 'Apacheenv' + uuid.uuid4().hex[:5]
|
environment_name = 'Apacheenv' + uuid.uuid4().hex[:5]
|
||||||
|
|
||||||
environment = self.client.create_environment(environment_name)
|
env = self._quick_deploy(environment_name, post_body)
|
||||||
self.environments.append(environment['id'])
|
|
||||||
self.stack_names.append(environment_name)
|
|
||||||
|
|
||||||
session = self.client.create_session(environment['id'])
|
|
||||||
|
|
||||||
self.client.create_service(environment['id'], session['id'], post_body)
|
|
||||||
self.client.deploy_session(environment['id'], session['id'])
|
|
||||||
|
|
||||||
env = self.client.wait_for_environment_deploy(environment['id'])
|
|
||||||
self.assertIsNotNone(env)
|
|
||||||
|
|
||||||
self.deployment_success_check(env, 80)
|
self.deployment_success_check(env, 80)
|
||||||
|
|
||||||
|
@ -311,25 +228,18 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
"name": "testMurano"
|
"name": "testMurano"
|
||||||
},
|
},
|
||||||
"name": "teMurano",
|
"name": "teMurano",
|
||||||
|
"database": "test_db",
|
||||||
|
"username": "test_usr",
|
||||||
|
"password": "test_pass",
|
||||||
"?": {
|
"?": {
|
||||||
"type": "io.murano.apps.PostgreSql",
|
"type": "io.murano.databases.PostgreSql",
|
||||||
"id": str(uuid.uuid4())
|
"id": str(uuid.uuid4())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
environment_name = 'Postgreenv' + uuid.uuid4().hex[:5]
|
environment_name = 'Postgreenv' + uuid.uuid4().hex[:5]
|
||||||
|
|
||||||
environment = self.client.create_environment(environment_name)
|
env = self._quick_deploy(environment_name, post_body)
|
||||||
self.environments.append(environment['id'])
|
|
||||||
self.stack_names.append(environment_name)
|
|
||||||
|
|
||||||
session = self.client.create_session(environment['id'])
|
|
||||||
|
|
||||||
self.client.create_service(environment['id'], session['id'], post_body)
|
|
||||||
self.client.deploy_session(environment['id'], session['id'])
|
|
||||||
|
|
||||||
env = self.client.wait_for_environment_deploy(environment['id'])
|
|
||||||
self.assertIsNotNone(env)
|
|
||||||
|
|
||||||
self.deployment_success_check(env, 5432)
|
self.deployment_success_check(env, 5432)
|
||||||
|
|
||||||
|
@ -354,16 +264,7 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
|
|
||||||
environment_name = 'Tomcatenv' + uuid.uuid4().hex[:5]
|
environment_name = 'Tomcatenv' + uuid.uuid4().hex[:5]
|
||||||
|
|
||||||
environment = self.client.create_environment(environment_name)
|
env = self._quick_deploy(environment_name, post_body)
|
||||||
self.environments.append(environment['id'])
|
|
||||||
|
|
||||||
session = self.client.create_session(environment['id'])
|
|
||||||
|
|
||||||
self.client.create_service(environment['id'], session['id'], post_body)
|
|
||||||
self.client.deploy_session(environment['id'], session['id'])
|
|
||||||
|
|
||||||
env = self.client.wait_for_environment_deploy(environment['id'])
|
|
||||||
self.assertIsNotNone(env)
|
|
||||||
|
|
||||||
self.deployment_success_check(env, 8080)
|
self.deployment_success_check(env, 8080)
|
||||||
|
|
||||||
|
@ -386,14 +287,20 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _quick_deploy(self, name, *apps):
|
def _quick_deploy(self, name, *apps):
|
||||||
environment = self.client.create_environment(name)
|
environment = self.muranoclient.environments.create({'name': name})
|
||||||
session = self.client.create_session(environment['id'])
|
self.environments.append(environment.id)
|
||||||
environment_id, session_id = environment['id'], session['id']
|
|
||||||
|
session = self.muranoclient.sessions.configure(environment.id)
|
||||||
|
|
||||||
for app in apps:
|
for app in apps:
|
||||||
self.client.create_service(environment_id, session_id, app)
|
self.muranoclient.services.post(environment.id,
|
||||||
self.client.deploy_session(environment_id, session_id)
|
path='/',
|
||||||
return self.client.wait_for_environment_deploy(environment_id)
|
data=app,
|
||||||
|
session_id=session.id)
|
||||||
|
|
||||||
|
self.muranoclient.sessions.deploy(environment.id, session.id)
|
||||||
|
|
||||||
|
return self.wait_for_environment_deploy(environment)
|
||||||
|
|
||||||
def _get_stack(self, environment_id):
|
def _get_stack(self, environment_id):
|
||||||
|
|
||||||
|
@ -413,17 +320,17 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
application_id = application1['?']['id']
|
application_id = application1['?']['id']
|
||||||
instance_name = application1['instance']['name']
|
instance_name = application1['instance']['name']
|
||||||
apps = [application1, application2]
|
apps = [application1, application2]
|
||||||
environment_id = self._quick_deploy(name, *apps)['id']
|
environment = self._quick_deploy(name, *apps)
|
||||||
# add environment to the list for tear-down clean-up
|
|
||||||
self.environments.append(environment_id)
|
|
||||||
|
|
||||||
# delete telnet application
|
# delete telnet application
|
||||||
session_id = self.client.create_session(environment_id)['id']
|
session = self.muranoclient.sessions.configure(environment.id)
|
||||||
self.client.delete_service(environment_id, session_id, application_id)
|
self.muranoclient.services.delete(environment.id,
|
||||||
self.client.deploy_session(environment_id, session_id)
|
'/' + application_id,
|
||||||
self.client.wait_for_environment_deploy(environment_id)
|
session.id)
|
||||||
|
self.muranoclient.sessions.deploy(environment.id, session.id)
|
||||||
|
self.wait_for_environment_deploy(environment)
|
||||||
|
|
||||||
stack_name = self._get_stack(environment_id).stack_name
|
stack_name = self._get_stack(environment.id).stack_name
|
||||||
template = self.heat_client.stacks.template(stack_name)
|
template = self.heat_client.stacks.template(stack_name)
|
||||||
ip_addresses = '{0}-assigned-ip'.format(instance_name)
|
ip_addresses = '{0}-assigned-ip'.format(instance_name)
|
||||||
floating_ip = '{0}-FloatingIPaddress'.format(instance_name)
|
floating_ip = '{0}-FloatingIPaddress'.format(instance_name)
|
||||||
|
@ -437,17 +344,16 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
|
||||||
|
|
||||||
application = self._get_telnet_app()
|
application = self._get_telnet_app()
|
||||||
environment = self._quick_deploy(name, application)
|
environment = self._quick_deploy(name, application)
|
||||||
self.assertIsNotNone(environment)
|
|
||||||
|
|
||||||
stack = self._get_stack(environment['id'])
|
stack = self._get_stack(environment.id)
|
||||||
self.assertIsNotNone(stack)
|
self.assertIsNotNone(stack)
|
||||||
|
|
||||||
self.client.delete_environment(environment['id'])
|
self.muranoclient.environments.delete(environment.id)
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while stack is not None:
|
while stack is not None:
|
||||||
if time.time() - start_time > 300:
|
if time.time() - start_time > 300:
|
||||||
break
|
break
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
stack = self._get_stack(environment['id'])
|
stack = self._get_stack(environment.id)
|
||||||
self.assertIsNone(stack, 'stack is not deleted')
|
self.assertIsNone(stack, 'stack is not deleted')
|
||||||
|
|
|
@ -29,6 +29,7 @@ import os
|
||||||
from alembic import command
|
from alembic import command
|
||||||
from alembic import config as alembic_config
|
from alembic import config as alembic_config
|
||||||
from alembic import migration
|
from alembic import migration
|
||||||
|
from alembic import script as alembic_script
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
import six.moves.urllib.parse as urlparse
|
import six.moves.urllib.parse as urlparse
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
@ -459,29 +460,20 @@ class BaseWalkMigrationTestCase(BaseMigrationTestCase):
|
||||||
#session.cleanup()
|
#session.cleanup()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _get_alembic_versions(self, engine):
|
def _up_and_down_versions(self):
|
||||||
"""For support of full testing of migrations
|
|
||||||
we should have an opportunity to run command step by step for each
|
|
||||||
version in repo. This method returns list of alembic_versions by
|
|
||||||
historical order.
|
|
||||||
"""
|
|
||||||
full_history = self._alembic_command('history',
|
|
||||||
engine, self.ALEMBIC_CONFIG)
|
|
||||||
# The piece of output data with version can looked as:
|
|
||||||
# 'Rev: 17738166b91 (head)' or 'Rev: 43b1a023dfaa'
|
|
||||||
alembic_history = [r.split(' ')[1] for r in full_history.split("\n")
|
|
||||||
if r.startswith("Rev")]
|
|
||||||
alembic_history.reverse()
|
|
||||||
return alembic_history
|
|
||||||
|
|
||||||
def _up_and_down_versions(self, engine):
|
|
||||||
"""Since alembic version has a random algorithm of generation
|
"""Since alembic version has a random algorithm of generation
|
||||||
(SA-migrate has an ordered autoincrement naming) we should store
|
(SA-migrate has an ordered autoincrement naming) we should store
|
||||||
a tuple of versions (version for upgrade and version for downgrade)
|
a tuple of versions (version for upgrade and version for downgrade)
|
||||||
for successful testing of migrations in up>down>up mode.
|
for successful testing of migrations in up>down>up mode.
|
||||||
"""
|
"""
|
||||||
versions = self._get_alembic_versions(engine)
|
|
||||||
return zip(versions, ['-1'] + versions)
|
env = alembic_script.ScriptDirectory.from_config(self.ALEMBIC_CONFIG)
|
||||||
|
versions = []
|
||||||
|
for rev in env.walk_revisions():
|
||||||
|
versions.append((rev.revision, rev.down_revision or '-1'))
|
||||||
|
|
||||||
|
versions.reverse()
|
||||||
|
return versions
|
||||||
|
|
||||||
def _walk_versions(self, engine=None, snake_walk=False,
|
def _walk_versions(self, engine=None, snake_walk=False,
|
||||||
downgrade=True):
|
downgrade=True):
|
||||||
|
@ -491,7 +483,7 @@ class BaseWalkMigrationTestCase(BaseMigrationTestCase):
|
||||||
# upgrades successfully.
|
# upgrades successfully.
|
||||||
|
|
||||||
self._configure(engine)
|
self._configure(engine)
|
||||||
up_and_down_versions = self._up_and_down_versions(engine)
|
up_and_down_versions = self._up_and_down_versions()
|
||||||
for ver_up, ver_down in up_and_down_versions:
|
for ver_up, ver_down in up_and_down_versions:
|
||||||
# upgrade -> downgrade -> upgrade
|
# upgrade -> downgrade -> upgrade
|
||||||
self._migrate_up(engine, ver_up, with_data=True)
|
self._migrate_up(engine, ver_up, with_data=True)
|
||||||
|
|
Loading…
Reference in New Issue