diff --git a/murano/db/migration/alembic_migrations/versions/005_environment-template.py b/murano/db/migration/alembic_migrations/versions/005_environment-template.py new file mode 100644 index 00000000..550d1e4d --- /dev/null +++ b/murano/db/migration/alembic_migrations/versions/005_environment-template.py @@ -0,0 +1,59 @@ +# 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. + +""" +Create the environment-template table for the environment +template functionality. + +Revision ID: 005 +Revises: table template + +""" + +# revision identifiers, used by Alembic. +revision = '005' +down_revision = '004' + +from alembic import op +import sqlalchemy as sa + + +MYSQL_ENGINE = 'InnoDB' +MYSQL_CHARSET = 'utf8' + + +def upgrade(): + """It creates the table environment-template. The name + plus the tenant_id should be unique in the table, since each + tenant cannot duplicate template names. + """ + + op.create_table( + 'environment-template', + sa.Column('created', sa.DateTime(), nullable=False), + sa.Column('updated', sa.DateTime(), nullable=False), + sa.Column('id', sa.String(length=255), nullable=False), + sa.Column('name', sa.String(length=255), nullable=False), + sa.Column('tenant_id', sa.String(length=36), nullable=False), + sa.Column('version', sa.BigInteger(), nullable=False), + sa.Column('description', sa.Text(), nullable=False), + sa.Column('networking', sa.Text(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('tenant_id', 'name'), + mysql_engine=MYSQL_ENGINE, + mysql_charset=MYSQL_CHARSET + ) + + +def downgrade(): + op.drop_table('environment-template') diff --git a/murano/db/models.py b/murano/db/models.py index 393b78b9..989404b3 100644 --- a/murano/db/models.py +++ b/murano/db/models.py @@ -78,6 +78,26 @@ class Environment(Base, TimestampMixin): return dictionary +class EnvironmentTemplate(Base, TimestampMixin): + """Represents a Environment emplate in the metadata-store.""" + __tablename__ = 'environment-template' + + id = sa.Column(sa.String(36), + primary_key=True, + default=uuidutils.generate_uuid) + name = sa.Column(sa.String(255), nullable=False) + tenant_id = sa.Column(sa.String(36), nullable=False) + version = sa.Column(sa.BigInteger, nullable=False, default=0) + description = sa.Column(st.JsonBlob(), nullable=False, default={}) + networking = sa.Column(st.JsonBlob(), nullable=True, default={}) + + def to_dict(self): + dictionary = super(EnvironmentTemplate, self).to_dict() + if 'description' in dictionary: + del dictionary['description'] + return dictionary + + class Session(Base, TimestampMixin): __tablename__ = 'session' diff --git a/murano/db/services/core_services.py b/murano/db/services/core_services.py index e3f02074..87144612 100644 --- a/murano/db/services/core_services.py +++ b/murano/db/services/core_services.py @@ -11,13 +11,19 @@ # 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 types from oslo.utils import timeutils from webob import exc +from murano.common.i18n import _ from murano.common import utils +from murano.db.services import environment_templates as env_temp from murano.db.services import environments as envs +from murano.openstack.common import log as logging + +LOG = logging.getLogger(__name__) class CoreServices(object): @@ -62,6 +68,96 @@ class CoreServices(object): return result + @staticmethod + def get_template_data(env_template_id, path): + """It obtains the data for the template. It includes + all the services. In case the path includes information + such as the env_template_id, the information provided will + be related to the entity specified in the path + + :param env_template_id: The env_template_id to obtain the data + :param path: Id of service for which we checking status. + :return: The template description + """ + temp_description = env_temp.EnvTemplateServices.\ + get_description(env_template_id) + + if temp_description is None: + return None + + if 'services' not in temp_description: + return [] + + result = utils.TraverseHelper.get(path, temp_description) + if result is None: + msg = _('Environment Template is not found').format( + env_template_id) + LOG.error(msg) + raise exc.HTTPNotFound(explanation=msg) + return result + + @staticmethod + def post_env_template_data(env_template_id, data, path): + """It stores the template data inside the template + description. + :param env_template_id: The env_template_id to obtain the data + :param data: the template description + :param path: Id of service for which we checking status. + :return: The template description + """ + get_description = env_temp.EnvTemplateServices.get_description + save_description = env_temp.EnvTemplateServices.save_description + + temp_description = get_description(env_template_id) + if temp_description is None: + msg = _('Environment Template is not found').format( + env_template_id) + LOG.error(msg) + raise exc.HTTPNotFound(explanation=msg) + + if 'services' not in temp_description: + temp_description['services'] = [] + + if path == '/services': + if isinstance(data, types.ListType): + utils.TraverseHelper.extend(path, data, temp_description) + else: + utils.TraverseHelper.insert(path, data, temp_description) + save_description(temp_description) + return data + + @staticmethod + def post_application_data(env_template_id, data, path): + """It stores the application data inside the template + description. + :param env_template_id: The env_template_id to obtain the data + :param data: the template description + :param path: Id of service for which we checking status. + :return: The template description + """ + get_description = env_temp.EnvTemplateServices.get_description + save_description = env_temp.EnvTemplateServices.save_description + + temp_description = get_description(env_template_id) + if temp_description is None: + msg = _('Environment Template is not found').format( + env_template_id) + LOG.error(msg) + raise exc.HTTPNotFound(explanation=msg) + + if 'services' not in temp_description: + temp_description['services'] = [] + + if path == '/services': + if isinstance(data, types.ListType): + utils.TraverseHelper.extend(path, data, temp_description) + else: + utils.TraverseHelper.insert(path, data, temp_description) + + save_description(temp_description, env_template_id) + + return data + @staticmethod def post_data(environment_id, session_id, data, path): get_description = envs.EnvironmentServices.get_environment_description @@ -70,7 +166,11 @@ class CoreServices(object): env_description = get_description(environment_id, session_id) if env_description is None: - raise exc.HTTPMethodNotAllowed + msg = _('Environment is not found').format( + environment_id) + LOG.error(msg) + raise exc.HTTPNotFound(explanation=msg) + if 'services' not in env_description: env_description['services'] = [] @@ -109,3 +209,22 @@ class CoreServices(object): utils.TraverseHelper.remove(path, env_description) save_description(session_id, env_description) + + @staticmethod + def delete_env_template_data(env_template_id, path): + """It deletes a template. + :param env_template_id: The env_template_id to be deleted. + :param path: The path to check. + """ + get_description = env_temp.EnvTemplateServices.get_description + save_description = env_temp.EnvTemplateServices.save_description + + tmp_description = get_description(env_template_id) + if tmp_description is None: + msg = _('Environment Template is not found').format( + env_template_id) + LOG.error(msg) + raise exc.HTTPNotFound(explanation=msg) + + utils.TraverseHelper.remove(path, tmp_description) + save_description(tmp_description, env_template_id) diff --git a/murano/db/services/environment_templates.py b/murano/db/services/environment_templates.py new file mode 100644 index 00000000..fbed3cf4 --- /dev/null +++ b/murano/db/services/environment_templates.py @@ -0,0 +1,167 @@ +# Copyright (c) 2015 Telefonica I+D. +# +# 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 murano.common import uuidutils +from murano.db import models +from murano.db import session as db_session +from murano.openstack.common import log as logging + +from oslo.db import exception as db_exc + +LOG = logging.getLogger(__name__) + + +class EnvTemplateServices(object): + @staticmethod + def get_env_templates_by(filters): + """Returns list of environment-templates. + + :param filters: property filters + :return: Returns list of environment-templates + """ + + unit = db_session.get_session() + templates = unit.query(models.EnvironmentTemplate). \ + filter_by(**filters).all() + + return templates + + @staticmethod + def create(env_template_params, tenant_id): + """Creates environment-template with specified params, in particular - name. + + :param env_template_params: Dict, e.g. {'name': 'temp-name'} + :param tenant_id: Tenant Id + :return: Created Template + """ + + env_template_params['id'] = uuidutils.generate_uuid() + env_template_params['tenant_id'] = tenant_id + env_template = models.EnvironmentTemplate() + env_template.update(env_template_params) + + unit = db_session.get_session() + with unit.begin(): + try: + unit.add(env_template) + except db_exc.DBDuplicateEntry: + msg = 'Environment template specified name already exists' + LOG.exception(msg) + raise db_exc.DBDuplicateEntry(explanation=msg) + env_template.update({'description': env_template_params}) + env_template.save(unit) + + return env_template + + @staticmethod + def delete(env_template_id): + """Deletes template. + + :param env_template_id: Template that is going to be deleted + """ + + env_temp_description = EnvTemplateServices.get_description( + env_template_id) + env_temp_description['description'] = None + EnvTemplateServices.save_description( + env_temp_description, env_template_id) + + @staticmethod + def remove(env_template_id): + """It deletes the environment template from database. + + :param env_template_id: Template Id to be deleted. + """ + + unit = db_session.get_session() + template = unit.query(models.EnvironmentTemplate).get(env_template_id) + if template: + with unit.begin(): + unit.delete(template) + + @staticmethod + def update(env_template_id, body): + """It updates the description of a environment template. + + :param env_template_id: Template Id to be deleted. + :param body: The description to be updated. + :return the template description updated + """ + + unit = db_session.get_session() + template = unit.query(models.EnvironmentTemplate).get(env_template_id) + template.update(body) + template.save(unit) + return template + + @staticmethod + def get_description(env_template_id): + """Returns environment template description for specified template. + + :param env_template_id: Template Id + :return: environment-template Description Object + """ + + template = EnvTemplateServices.get_env_template(env_template_id) + if template is None: + raise ValueError("The environment template does not exists") + return template.description + + @staticmethod + def get_application_description(env_template_id): + """Returns environment template description for specified applications. + + :param env_template_id: Template Id + :return: Template Description Object + """ + + env_temp_desc = EnvTemplateServices.get_description(env_template_id) + if "services" not in env_temp_desc: + return [] + else: + return env_temp_desc['services'] + + @staticmethod + def save_description(env_template_des, env_template_id=None): + """Saves environment template description to specified session. + + :param env_template_des: Template Description + :param env_template_id: The template ID. + """ + unit = db_session.get_session() + template = unit.query(models.EnvironmentTemplate).get(env_template_id) + template.update({'description': env_template_des}) + template.save(unit) + + @staticmethod + def env_template_exist(env_template_id): + """It checks if the environment template exits in database. + + :param env_template_id: The template ID + """ + + template = EnvTemplateServices.get_env_template(env_template_id) + if template is None: + return False + else: + return True + + @staticmethod + def get_env_template(env_template_id): + """It obtains the environment template information from the database. + + :param env_template_id: The template ID + """ + session = db_session.get_session() + return session.query(models.EnvironmentTemplate).get(env_template_id) diff --git a/murano/tests/unit/db/migration/test_migrations.py b/murano/tests/unit/db/migration/test_migrations.py index 4a311b98..c6bdb08d 100644 --- a/murano/tests/unit/db/migration/test_migrations.py +++ b/murano/tests/unit/db/migration/test_migrations.py @@ -129,6 +129,12 @@ class MuranoMigrationsCheckers(object): self.assertColumnExists(engine, 'task', 'action') self.assertColumnExists(engine, 'status', 'task_id') + def _check_005(self, engine, data): + self.assertEqual('005', migration.version(engine)) + self.assertColumnExists(engine, 'environment-template', 'id') + self.assertColumnExists(engine, 'environment-template', 'tenant_id') + self.assertColumnExists(engine, 'environment-template', 'name') + class TestMigrationsMySQL(MuranoMigrationsCheckers, base.BaseWalkMigrationTestCase, diff --git a/murano/tests/unit/db/services/__init__.py b/murano/tests/unit/db/services/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/murano/tests/unit/db/services/environment_templates.py b/murano/tests/unit/db/services/environment_templates.py new file mode 100644 index 00000000..ed262961 --- /dev/null +++ b/murano/tests/unit/db/services/environment_templates.py @@ -0,0 +1,166 @@ +# Copyright (c) 2015 Telefonica I+D. + +# 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 fixtures + + +class EmptyEnvironmentTemplateFixture(fixtures.Fixture): + def setUp(self): + super(EmptyEnvironmentTemplateFixture, self).setUp() + self.environment_template_desc = { + "tenant_id": "tenant_id", + "name": "my_template", + "id": "template_id" + } + self.addCleanup(delattr, self, 'environment_template_desc') + + +class AppEnvTemplateFixture(fixtures.Fixture): + def setUp(self): + super(AppEnvTemplateFixture, self).setUp() + self.env_template_desc = \ + { + "services": [ + { + "instance": { + "assignFloatingIp": "true", + "keyname": "mykeyname", + "image": "cloud-fedora-v3", + "flavor": "m1.medium", + "?": { + "type": "io.murano.resources.LinuxInstance", + "id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e" + } + }, + "name": "orion", + "?": + { + "_26411a1861294160833743e45d0eaad9": { + "name": "tomcat" + }, + "type": "io.murano.apps.apache.Tomcat", + "id": "tomcat_id" + }, + "port": "8080" + }, { + "instance": "ef984a74-29a4-45c0-b1dc-2ab9f075732e", + "password": "XXX", "name": + "mysql", + "?": { + "_26411a1861294160833743e45d0eaad9": { + "name": "mysql" + }, + "type": "io.murano.apps.database.MySQL", + "id": "54aaa43d-5970" + } + } + ], + "tenant_id": "tenant_id", + "name": "template_name", + 'id': 'template_id' + } + self.addCleanup(delattr, self, 'env_template_desc') + + +class ApplicationsFixture(fixtures.Fixture): + + def setUp(self): + super(ApplicationsFixture, self).setUp() + self.applications_desc = [ + { + "instance": { + "assignFloatingIp": "true", + "keyname": "mykeyname", + "image": "cloud-fedora-v3", + "flavor": "m1.medium", + "?": { + "type": "io.murano.resources.LinuxInstance", + "id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e" + } + }, + "name": "orion", + "?": + { + "_26411a1861294160833743e45d0eaad9": { + "name": "tomcat" + }, + "type": "io.murano.apps.apache.Tomcat", + "id": "tomcat_id" + }, + "port": "8080" + }, + { + "instance": "ef984a74-29a4-45c0-b1dc-2ab9f075732e", + "password": "XXX", "name": + "mysql", + "?": { + "_26411a1861294160833743e45d0eaad9": { + "name": "mysql" + }, + "type": "io.murano.apps.database.MySQL", + "id": "54aaa43d-5970" + } + } + ] + self.addCleanup(delattr, self, 'applications_desc') + + +class ApplicationTomcatFixture(fixtures.Fixture): + + def setUp(self): + super(ApplicationTomcatFixture, self).setUp() + self.application_tomcat_desc = { + "instance": { + "assignFloatingIp": "true", + "keyname": "mykeyname", + "image": "cloud-fedora-v3", + "flavor": "m1.medium", + "?": { + "type": "io.murano.resources.LinuxInstance", + "id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e" + } + }, + "name": "orion", + "?": + { + "_26411a1861294160833743e45d0eaad9": { + "name": "tomcat" + }, + "type": "io.murano.apps.apache.Tomcat", + "id": "tomcat_id" + }, + "port": "8080" + } + self.addCleanup(delattr, self, 'application_tomcat_desc') + + +class ApplicationMysqlFixture(fixtures.Fixture): + + def setUp(self): + super(ApplicationMysqlFixture, self).setUp() + self.application_mysql_desc = { + "instance": "ef984a74-29a4-45c0-b1dc-2ab9f075732e", + "password": "XXX", "name": + "mysql", + "?": { + "_26411a1861294160833743e45d0eaad9": { + "name": "mysql" + }, + "type": "io.murano.apps.database.MySQL", + "id": "54aaa43d-5970" + } + } + self.addCleanup(delattr, self, 'application_mysql_desc') diff --git a/murano/tests/unit/db/services/test_core_service.py b/murano/tests/unit/db/services/test_core_service.py new file mode 100644 index 00000000..d600fe43 --- /dev/null +++ b/murano/tests/unit/db/services/test_core_service.py @@ -0,0 +1,134 @@ +# Copyright (c) 2015 Telefonica I+D. + +# 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 mock +from webob import exc + +from murano.db.services import core_services +from murano.tests.unit import base +from murano.tests.unit.db.services import environment_templates as et + + +class TestCoreServices(base.MuranoTestCase): + def setUp(self): + super(TestCoreServices, self).setUp() + self.core_services = core_services.CoreServices + self.addCleanup(mock.patch.stopall) + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_empty_template(self, template_services_mock): + """Check obtaining the template description without services.""" + fixture = self.useFixture(et.EmptyEnvironmentTemplateFixture()) + template_services_mock.get_description.return_value = \ + fixture.environment_template_desc + template_des = self.core_services.get_template_data('any', '/services') + self.assertEqual(template_des, []) + template_services_mock.get_description.assert_is_called() + template_services_mock.get_description.assert_called_with('any') + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_template_services(self, template_services_mock): + """Check obtaining the template description with services.""" + fixture_apps = self.useFixture(et.ApplicationsFixture()) + fixture_env_apps = self.useFixture(et.AppEnvTemplateFixture()) + template_services_mock.get_description.return_value = \ + fixture_env_apps.env_template_desc + template_des = self.core_services.get_template_data('any', '/services') + self.assertEqual(template_des, fixture_apps.applications_desc) + template_services_mock.get_description.assert_is_called() + template_services_mock.get_description.assert_called_with('any') + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_template_get_service(self, template_services_mock): + """Check obtaining the service description.""" + fixture = self.useFixture(et.AppEnvTemplateFixture()) + fixture2 = self.useFixture(et.ApplicationTomcatFixture()) + template_services_mock.get_description.return_value = \ + fixture.env_template_desc + template_des = \ + self.core_services.get_template_data('any', + '/services/tomcat_id') + self.assertEqual(template_des, fixture2.application_tomcat_desc) + template_services_mock.get_description.assert_is_called() + template_services_mock.get_description.assert_called_with('any') + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_template_post_services(self, template_services_mock): + """Check adding a service to a template.""" + fixture = self.useFixture(et.EmptyEnvironmentTemplateFixture()) + fixture2 = self.useFixture(et.AppEnvTemplateFixture()) + template_services_mock.get_description.return_value = \ + fixture.environment_template_desc + template_des = self.core_services.\ + post_env_template_data('any', + fixture2.env_template_desc, + '/services') + self.assertEqual(template_des, fixture2.env_template_desc) + template_services_mock.get_description.assert_is_called() + template_services_mock.\ + get_description.assert_called_with('any') + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_template_delete_services(self, template_services_mock): + """Check deleting a service in a template.""" + fixture2 = self.useFixture(et.AppEnvTemplateFixture()) + fixture = self.useFixture(et.ApplicationTomcatFixture()) + template_services_mock.get_description.return_value = \ + fixture2.env_template_desc + self.core_services.\ + delete_env_template_data('any', + '/services/54aaa43d-5970') + template_des = self.core_services.get_template_data('any', '/services') + self.assertEqual(template_des, [fixture.application_tomcat_desc]) + template_services_mock.get_description.assert_is_called() + template_services_mock.\ + get_description.assert_called_with('any') + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_get_template_no_exists(self, template_services_mock): + """Check obtaining a non-existing service.""" + fixture2 = self.useFixture(et.AppEnvTemplateFixture()) + + template_services_mock.get_description.return_value = \ + fixture2.env_template_desc + self.assertRaises(exc.HTTPNotFound, + self.core_services.get_template_data, + 'any', '/services/noexists') + template_services_mock.get_description.assert_is_called() + template_services_mock.\ + get_description.assert_called_with('any') + + @mock.patch('murano.db.services.environment_templates.EnvTemplateServices') + def test_adding_services(self, template_services_mock): + """Check adding services to a template.""" + ftomcat = self.useFixture(et.ApplicationTomcatFixture()) + fmysql = self.useFixture(et.ApplicationMysqlFixture()) + fixture = self.useFixture(et.EmptyEnvironmentTemplateFixture()) + fservices = self.useFixture(et.ApplicationsFixture()) + template_services_mock.get_description.return_value =\ + fixture.environment_template_desc + self.core_services.\ + post_env_template_data('any', + ftomcat.application_tomcat_desc, + '/services') + self.core_services.\ + post_env_template_data('any', + fmysql.application_mysql_desc, + '/services') + template_des = \ + self.core_services.get_template_data('any', '/services') + self.assertEqual(template_des, fservices.applications_desc) + template_services_mock.get_description.assert_is_called() + template_services_mock.get_description.assert_called_with('any') diff --git a/murano/tests/unit/db/services/test_templates_service.py b/murano/tests/unit/db/services/test_templates_service.py new file mode 100644 index 00000000..99aef501 --- /dev/null +++ b/murano/tests/unit/db/services/test_templates_service.py @@ -0,0 +1,83 @@ +# Copyright (c) 2015 Telefonica I+D. + +# 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 fixtures +import mock + +from murano.db.services import environment_templates as env_temp +from murano.tests.unit import base +from murano.tests.unit.db.services import environment_templates as et + + +class TestTemplateServices(base.MuranoWithDBTestCase, + fixtures.TestWithFixtures): + + def setUp(self): + super(TestTemplateServices, self).setUp() + self.template_services = env_temp.EnvTemplateServices + self.uuids = ['template_id'] + self.mock_uuid = self._stub_uuid(self.uuids) + self.addCleanup(mock.patch.stopall) + + def test_create_template(self): + """Check creating a template without services.""" + fixture = self.useFixture(et.EmptyEnvironmentTemplateFixture()) + """Check the creation of a template.""" + body = { + "name": "my_template" + } + template_des = self.template_services.create(body, 'tenant_id') + self.assertEqual(template_des.description, + fixture.environment_template_desc) + + def test_get_empty_template(self): + """Check obtaining information about a template without services.""" + fixture = self.useFixture(et.EmptyEnvironmentTemplateFixture()) + self.test_create_template() + template = \ + self.template_services.get_description("template_id") + self.assertEqual(template, fixture.environment_template_desc) + + def test_get_template_services(self): + """Check obtaining information about a template with services.""" + fixture = self.useFixture(et.AppEnvTemplateFixture()) + template = self.template_services.create(fixture.env_template_desc, + 'tenant_id') + self.assertEqual(template.description, fixture.env_template_desc) + template_des = \ + self.template_services.get_description("template_id") + self.assertEqual(template_des, fixture.env_template_desc) + + def test_get_template_no_exists(self): + """Check obtaining information about a template which + does not exist. + """ + self.assertRaises(ValueError, + self.template_services.get_description, + 'no_exists') + + def test_delete_template(self): + """Check deleting a template.""" + self.test_create_template() + self.template_services.delete("template_id") + + def _stub_uuid(self, values=[]): + class FakeUUID(object): + def __init__(self, v): + self.hex = v + + mock_uuid4 = mock.patch('uuid.uuid4').start() + mock_uuid4.side_effect = [FakeUUID(v) for v in values] + return mock_uuid4