Merge pull request #229 from djay87/master

ARIA-438 : Support for storing the common TOSCA YAML files in the res…
diff --git a/aria/__init__.py b/aria/__init__.py
index 980a2bb..6877831 100644
--- a/aria/__init__.py
+++ b/aria/__init__.py
@@ -84,6 +84,7 @@
 
     return storage.ResourceStorage(api_cls=api,
                                    api_kwargs=api_kwargs,
-                                   items=['service_template', 'service', 'plugin'],
+                                   items=['type_definition', 'service_template', 'service',\
+                                          'plugin'],
                                    initiator=initiator,
                                    initiator_kwargs=initiator_kwargs)
diff --git a/aria/cli/commands/__init__.py b/aria/cli/commands/__init__.py
index ba34a43..5cdfbac 100644
--- a/aria/cli/commands/__init__.py
+++ b/aria/cli/commands/__init__.py
@@ -18,6 +18,7 @@
 """
 
 from . import (
+    type_definitions,
     executions,
     logs,
     node_templates,
diff --git a/aria/cli/commands/type_definitions.py b/aria/cli/commands/type_definitions.py
new file mode 100644
index 0000000..fc389e9
--- /dev/null
+++ b/aria/cli/commands/type_definitions.py
@@ -0,0 +1,136 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+"""
+CLI ``type-definitions`` sub-commands.
+"""
+from aria import exceptions
+from ..core import aria
+from .. import service_template_utils
+from .. import table
+
+TYPE_DEFINITION_COLUMNS = \
+    ('id', 'name', 'version', 'main_file_name', 'uploaded_at')
+
+
+@aria.group(name='type-definitions')
+@aria.options.verbose()
+def type_definitions():
+    """
+    Manage type definitions
+    """
+    pass
+
+@type_definitions.command(name='load',
+                          short_help='Parse and load a type definition archive')
+@aria.argument('type-definition-path')
+@aria.options.verbose()
+@aria.pass_type_definition_manager
+@aria.pass_logger
+def load(type_definition_path, type_definition_manager, logger):
+    """
+    Parse and store a type definition archive
+
+    TYPE_DEFINITION_PATH is the path to the type definition archive.
+
+    """
+    logger.info('Loading type definition {0}...'.format(type_definition_path))
+    valid_extension = ('.yaml', '.csar')
+    if not type_definition_path.endswith(valid_extension):
+        raise exceptions.\
+            TypeDefinitionException('Type definition file has invalid extension')
+
+    type_definition_file_path = service_template_utils.get(type_definition_path, None)
+    type_definition = type_definition_manager.load_type_definition(type_definition_file_path)
+    logger.info("Type definition loaded. The type definition's name is {0} and version is {1}".\
+                format(type_definition.name, type_definition.version))
+
+@type_definitions.command(name='list',
+                          short_help='List all stored type definitions')
+@aria.options.sort_by('uploaded_at')
+@aria.options.descending
+@aria.options.verbose()
+@aria.pass_type_definition_manager
+@aria.pass_logger
+def list(sort_by, descending, type_definition_manager, logger):
+    """
+    List all stored type definitions
+    """
+
+    logger.info('Listing all type definitions...')
+    type_definitions_list = type_definition_manager.list_type_definition(sort_by, descending)
+    table.print_data(TYPE_DEFINITION_COLUMNS, type_definitions_list, 'Type definitions:')
+
+@type_definitions.command(name='show',
+                          short_help='Show information for a stored type definition')
+@aria.argument('type-definition-name')
+@aria.argument('type-definition-version')
+@aria.options.verbose()
+@aria.pass_type_definition_manager
+@aria.pass_logger
+def show(type_definition_name, type_definition_version, type_definition_manager, logger):
+    """
+    Show information for a stored type definition
+
+    TYPE_DEFINITION_NAME is name of the stored type definition
+    TYPE_DEFINITION_VERSION is version of the stored type definition
+    """
+    logger.info("Showing type definition name '{0}' version '{1}'...".\
+                format(type_definition_name, type_definition_version))
+    type_definition = type_definition_manager.get_type_definition(type_definition_name,\
+                                                                  type_definition_version)
+    table.print_data(TYPE_DEFINITION_COLUMNS, type_definition, 'Type definition:')
+
+@type_definitions.command(name='delete',
+                          short_help='Delete a stored type definition')
+@aria.argument('type-definition-name')
+@aria.argument('type-definition-version')
+@aria.options.verbose()
+@aria.pass_type_definition_manager
+@aria.pass_logger
+def delete(type_definition_name, type_definition_version, type_definition_manager, logger):
+    """
+    Delete a stored type definition
+
+    TYPE_DEFINITION_NAME is name of the stored type definition
+    TYPE_DEFINITION_VERSION is version of the stored type definition
+    """
+    logger.info("Deleting type definition name '{0}' version '{1}'...".\
+                format(type_definition_name, type_definition_version))
+    type_definition_manager.delete_type_definition(type_definition_name, type_definition_version)
+    logger.info("Type definition name '{0}' version '{1}' deleted".\
+                format(type_definition_name, type_definition_version))
+
+@type_definitions.command(name='validate',
+                          short_help='Validate a type definition archive')
+@aria.argument('type-definition-path')
+@aria.options.verbose()
+@aria.pass_type_definition_manager
+@aria.pass_logger
+def validate(type_definition_path, type_definition_manager, logger):
+    """
+    Validate a type definition archive
+
+    TYPE_DEFINITION_PATH is the path to the type definition archive.
+    """
+    logger.info('Validating type definition: {0}'.format(type_definition_path))
+    valid_extension = ('.yaml', '.csar')
+    if not type_definition_path.endswith(valid_extension):
+        raise exceptions.\
+            TypeDefinitionException('Type definition file has invalid extension')
+
+    type_definition_file_path = service_template_utils.get(type_definition_path, None)
+    type_definition_manager.validate_type_definition(type_definition_file_path)
+    logger.info('Type definition validated successfully')
diff --git a/aria/cli/core/aria.py b/aria/cli/core/aria.py
index b84507c..b16f68e 100644
--- a/aria/cli/core/aria.py
+++ b/aria/cli/core/aria.py
@@ -176,6 +176,17 @@
 
     return wrapper
 
+def pass_type_definition_manager(func):
+    """
+    Simply passes the type definition manager to a command.
+    """
+    # Wraps here makes sure the original docstring propagates to click
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        return func(type_definition_manager=env.type_definition_manager, *args, **kwargs)
+
+    return wrapper
+
 
 def pass_model_storage(func):
     """
diff --git a/aria/cli/env.py b/aria/cli/env.py
index 84bdebe..a99d9a6 100644
--- a/aria/cli/env.py
+++ b/aria/cli/env.py
@@ -19,7 +19,7 @@
 
 import os
 import shutil
-
+from aria.type_definition_manager import TypeDefinitionManager
 from .config import config
 from .logger import Logging
 from .. import (application_model_storage, application_resource_storage)
@@ -44,11 +44,13 @@
         self._model_storage_dir = os.path.join(workdir, 'models')
         self._resource_storage_dir = os.path.join(workdir, 'resources')
         self._plugins_dir = os.path.join(workdir, 'plugins')
+        self._type_definitions_dir = os.path.join(workdir, 'type_definitions')
 
         # initialized lazily
         self._model_storage = None
         self._resource_storage = None
         self._plugin_manager = None
+        self._type_definition_manager = None
 
     @property
     def workdir(self):
@@ -80,6 +82,12 @@
             self._plugin_manager = self._init_plugin_manager()
         return self._plugin_manager
 
+    @property
+    def type_definition_manager(self):
+        if not self._type_definition_manager:
+            self._type_definition_manager = self._init_type_definition_manager()
+        return self._type_definition_manager
+
     def reset(self, reset_config):
         if reset_config:
             shutil.rmtree(self._workdir)
@@ -120,6 +128,11 @@
 
         return PluginManager(self.model_storage, self._plugins_dir)
 
+    def _init_type_definition_manager(self):
+        if not os.path.exists(self._type_definitions_dir):
+            os.makedirs(self._type_definitions_dir)
+
+        return TypeDefinitionManager(self.model_storage, self._type_definitions_dir)
 
 env = _Environment(os.path.join(
     os.environ.get('ARIA_WORKDIR', os.path.expanduser('~')), ARIA_DEFAULT_WORKDIR_NAME))
diff --git a/aria/cli/main.py b/aria/cli/main.py
index 640360b..a0e6b64 100644
--- a/aria/cli/main.py
+++ b/aria/cli/main.py
@@ -44,6 +44,7 @@
     Register the CLI's commands.
     """
 
+    _aria.add_command(commands.type_definitions.type_definitions)
     _aria.add_command(commands.service_templates.service_templates)
     _aria.add_command(commands.node_templates.node_templates)
     _aria.add_command(commands.services.services)
diff --git a/aria/exceptions.py b/aria/exceptions.py
index 5d3e21d..9d5b5f3 100644
--- a/aria/exceptions.py
+++ b/aria/exceptions.py
@@ -71,3 +71,27 @@
 
 class InstantiationError(AriaError):
     pass
+
+
+class TypeDefinitionException(AriaError):
+    """The base exception class of the type definition"""
+    pass
+
+
+class TypeDefinitionNotFoundException(TypeDefinitionException):
+    """The exception class of the type definition thrown
+       if type definition does not exists"""
+    pass
+
+
+class TypeDefinitionAlreadyExistsException(TypeDefinitionException):
+    """The exception class of the type definition thrown
+       if type definition already exists"""
+    pass
+
+
+class InvalidTypeDefinitionException(TypeDefinitionException):
+    """The exception class of the type definition thrown
+       if type definition is not a valid archive or validation error
+       exists during the type definition load"""
+    pass
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index cf84fdb..009717f 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -16,6 +16,14 @@
 """
 Data models.
 
+Type definition models
+-----------------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.modeling.models.TypeDefinition
+
 Service template models
 -----------------------
 
@@ -90,6 +98,7 @@
 )
 
 from . import (
+    type_definition,
     service_template,
     service_instance,
     service_changes,
@@ -107,6 +116,9 @@
 __all__ = (
     'models_to_register',
 
+    # Type definition models
+    'TypeDefinition',
+
     # Service template models
     'ServiceTemplate',
     'NodeTemplate',
@@ -157,6 +169,11 @@
     'Argument'
 )
 
+# region type definition models
+
+@utils.fix_doc
+class TypeDefinition(aria_declarative_base, type_definition.TypeDefinitionBase):
+    pass
 
 # region service template models
 
@@ -376,6 +393,9 @@
 
 # See also __all__ at the top of this file
 models_to_register = (
+    # Type definition models
+    TypeDefinition,
+
     # Service template models
     ServiceTemplate,
     NodeTemplate,
diff --git a/aria/modeling/type_definition.py b/aria/modeling/type_definition.py
new file mode 100644
index 0000000..a8cbccf
--- /dev/null
+++ b/aria/modeling/type_definition.py
@@ -0,0 +1,65 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+"""
+ARIA modeling type definition module
+"""
+
+# pylint: disable=too-many-lines, no-self-argument, no-member, abstract-method
+
+from sqlalchemy import (
+    Column,
+    Text,
+    DateTime,
+    UniqueConstraint
+)
+from . import mixins
+
+class TypeDefinitionBase(mixins.ModelMixin):
+    """
+    Loaded TypeDefinition.
+
+    Usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it can also be
+    created programmatically.
+    """
+
+    __tablename__ = 'type_definition'
+
+    name = Column(Text, nullable=False, index=True, doc="""
+    Name of the type definition
+
+    :type: :obj:`basestring`
+    """)
+
+    version = Column(Text, nullable=False, doc="""
+    Version for the type definition
+
+    :type: :obj:`basestring`
+    """)
+
+    main_file_name = Column(Text, nullable=False, doc="""
+    Filename of CSAR or YAML file from which this type definition was parsed.
+
+    :type: :obj:`basestring`
+    """)
+
+    uploaded_at = Column(DateTime, nullable=False, doc="""
+    Timestamp for when the type definition was loaded.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+    __table_args__ = (UniqueConstraint('name', 'version',
+                                       name='_type_definition_name_version_unique'),)
diff --git a/aria/type_definition_manager.py b/aria/type_definition_manager.py
new file mode 100644
index 0000000..c473725
--- /dev/null
+++ b/aria/type_definition_manager.py
@@ -0,0 +1,225 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+"""
+Type Definition management.
+"""
+from datetime import datetime
+import os
+from distutils import dir_util  # pylint: disable=no-name-in-module
+from aria.utils.yaml import yaml
+from aria.utils import collections
+from aria.exceptions import (
+    ParsingError,
+    TypeDefinitionException,
+    TypeDefinitionAlreadyExistsException,
+    TypeDefinitionNotFoundException,
+    InvalidTypeDefinitionException
+    )
+from aria.parser import consumption
+from aria.parser.loading.location import UriLocation
+
+class TypeDefinitionManager(object):
+    """TypeDefinitionManager class handles the type definition related management"""
+
+    def __init__(self, model_storage, type_definitions_dir):
+        """
+        :param model_storage: model storage object
+        :param type_definitions_dir: root directory in which to load type definitions
+        """
+        self._model_storage = model_storage
+        self._type_definitions_dir = type_definitions_dir
+
+    @property
+    def model_storage(self):
+        """Return model storage object"""
+        return self._model_storage
+
+    def load_type_definition(self, type_definition_path):
+        """
+        Load a type definition into model as well as into file system.
+        """
+        type_definition = self.create_type_definition(type_definition_path)
+
+        return type_definition
+
+    def get_type_definition(self, type_definition_name, type_definition_version):
+        """
+        Get type definition details based on name and version
+        """
+        type_definition_query = self._model_storage.type_definition.\
+        _get_query(None, {'name': type_definition_name, 'version': type_definition_version},\
+                   None)
+        type_definition_id = type_definition_query.value('id')
+        type_definition = self._model_storage.type_definition.get(type_definition_id)
+        return type_definition
+
+    def delete_type_definition(self, type_definition_name, type_definition_version):
+        """
+        Delete a type definition from model as well as from file system
+        """
+        try:
+            type_definition_query = self._model_storage.type_definition.\
+            _get_query(None, {'name': type_definition_name, 'version': type_definition_version},
+                       None)
+            type_definition_id = type_definition_query.value('id')
+
+            if type_definition_id is None:
+                raise TypeDefinitionNotFoundException("Type definition name '{0}' version '{1}' "
+                                                      "does not exist.".\
+                                                      format(type_definition_name,\
+                                                             type_definition_version))
+            else:
+                type_definition = self._model_storage.type_definition.get(type_definition_id)
+                type_def_dir = self.get_type_definition_dir(type_definition)
+
+                if os.path.exists(type_def_dir) and os.path.isdir(type_def_dir):
+                    dir_util.remove_tree(type_def_dir)
+
+                self._model_storage.type_definition.delete(type_definition)
+        except Exception, e:
+            raise e
+
+    def list_type_definition(self, sort_by, descending):
+        """Lists the type definitions that are loaded"""
+        type_definitions_list = self._model_storage.type_definition.list(
+            sort={sort_by: 'desc' if descending else 'asc'})
+        return type_definitions_list
+
+    def get_type_definition_dir(self, type_definition_object):
+        """
+        Get the particular type definition's file system directory.
+        """
+        return os.path.join(self._type_definitions_dir,
+                            '{0}-{1}'.format(type_definition_object.name,
+                                             type_definition_object.version))
+
+    def create_type_definition(self, type_definition_path):
+
+        """validates & stores the type definition file/csar into model & resource storage"""
+
+        context = self.validate_type_definition(type_definition_path)
+        service_template = context.modeling.template
+
+        metadata = service_template.meta_data
+        template_name = metadata['template_name'].value
+        template_version = metadata['template_version'].value.value
+        main_file_name = service_template.main_file_name
+
+        cls = self._model_storage.type_definition.model_cls
+        type_definition = cls(
+            name=template_name,
+            version=template_version,
+            main_file_name=main_file_name,
+            uploaded_at=datetime.now()
+        )
+        number_of_rows_matched = len(self._model_storage.type_definition.list \
+                                     (filters={'name': type_definition.name,
+                                               'version': type_definition.version}))
+        if number_of_rows_matched:
+            raise TypeDefinitionAlreadyExistsException(
+                "Type Definition '{0}' with version '{1}' already exists".format(
+                    type_definition.name, type_definition.version))
+
+        type_definition_directory = self.get_type_definition_dir(type_definition)
+        if os.path.exists(type_definition_directory):
+            raise TypeDefinitionAlreadyExistsException(
+                ("Type Definition '{0}' with version '{1}' already exists").
+                format(type_definition.name, type_definition.version))
+
+        try:
+            os.mkdir(type_definition_directory)
+            type_def_src_dir = os.path.dirname(type_definition_path)
+            dir_util.copy_tree(type_def_src_dir, type_definition_directory)
+        except (IOError, OSError):
+            raise \
+                TypeDefinitionException("Could not store type definition into directory")
+
+        self._model_storage.type_definition.put(type_definition)
+
+        return type_definition
+
+    def validate_type_definition(self, type_definition_path):
+        """ Validates the provided type definition archive"""
+        try:
+            with open(type_definition_path, 'r') as type_definition_yaml_file:
+                type_definition_yaml = yaml.load(type_definition_yaml_file)
+        except (IOError, OSError) as e:
+            raise \
+                TypeDefinitionException("Could not open/load type definition file", e)
+
+        if ('metadata' not in type_definition_yaml) or \
+           ('template_name' not in type_definition_yaml['metadata']) or \
+           ('template_version' not in type_definition_yaml['metadata']):
+            raise InvalidTypeDefinitionException('Type definition is invalid. '
+                                                 'It should have metadata information')
+
+        name = type_definition_yaml['metadata']['template_name']
+        version = type_definition_yaml['metadata']['template_version']
+        try:
+            TypeDefinitionManager._check_topology_template_exists(type_definition_path, \
+                                                                  type_definition_yaml, \
+                                                                  name, version)
+        except InvalidTypeDefinitionException as e:
+            raise e
+        except TypeDefinitionException as e:
+            raise e
+        except Exception as e:
+            raise e
+
+        type_definitions_dir = (self._type_definitions_dir).split()
+        context = consumption.ConsumptionContext()
+        context.presentation.location = UriLocation(type_definition_path)
+        context.loading.prefixes = collections.StrictList(type_definitions_dir)
+        consumption.ConsumerChain(
+            context,
+            (
+                consumption.Read,
+                consumption.Validate,
+                consumption.ServiceTemplate
+            )).consume()
+        if context.validation.dump_issues():
+            raise ParsingError('Failed to parse type definition')
+        return context
+
+    @staticmethod
+    def _check_topology_template_exists(td_path, td_yaml, main_td_name, main_td_version):
+
+        if 'topology_template' in td_yaml:
+            td_file_name = os.path.split(td_path)[1]
+            error_message = ("Type definition '{0}' with version '{1}' is invalid."
+                             " It contains topology template in '{2}'.").\
+                             format(main_td_name, main_td_version, td_file_name)
+            raise InvalidTypeDefinitionException(error_message)
+
+        if 'imports' not in td_yaml:
+            return
+
+        main_type_definition_dir = os.path.dirname(td_path)
+        for td_import_file in td_yaml['imports']:
+            try:
+                td_import_file_path = os.path.join(main_type_definition_dir, td_import_file or ' ')
+                with open(td_import_file_path, 'r') as td_yaml_file:
+                    td_import_yaml = yaml.load(td_yaml_file)
+                    TypeDefinitionManager.\
+                    _check_topology_template_exists(td_import_file_path, td_import_yaml,\
+                                                     main_td_name, main_td_version)
+            except (IOError, OSError) as e:
+                raise TypeDefinitionException("Could not open/load type definition file",\
+                                                     e.message)
+            except InvalidTypeDefinitionException as e:
+                raise e
+            except Exception as e:
+                raise TypeDefinitionException("Failed to parse type definition")
diff --git a/tests/cli/test_type_definitions.py b/tests/cli/test_type_definitions.py
new file mode 100644
index 0000000..92b3156
--- /dev/null
+++ b/tests/cli/test_type_definitions.py
@@ -0,0 +1,228 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+from aria.exceptions import (
+    TypeDefinitionException,
+    TypeDefinitionAlreadyExistsException,
+    TypeDefinitionNotFoundException,
+    AriaException
+    )
+from aria.cli.env import _Environment
+from aria.storage import exceptions as storage_exceptions
+from aria.type_definition_manager import TypeDefinitionManager
+from aria.cli import service_template_utils
+from ..mock import models as mock_models
+from .base_test import ( # pylint: disable=unused-import
+    TestCliBase,
+    assert_exception_raised,
+    raise_exception,
+    mock_storage
+)
+
+class TestTypeDefinitionsLoad(TestCliBase):
+
+    def test_header_string(self, monkeypatch, mock_storage):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        self.invoke('type_definitions load stubpath.csar')
+        assert 'Loading type definition stubpath.csar...' in self.logger_output_string
+
+    def test_load_no_exception(self, monkeypatch, mock_object, mock_storage):
+
+        monkeypatch.setattr(TypeDefinitionManager, 'load_type_definition', mock_object)
+        monkeypatch.setattr(service_template_utils, 'get', mock_object)
+        monkeypatch.setattr(os.path, 'dirname', mock_object)
+        self.invoke('type_definitions load stubpath.csar')
+        assert 'Loading type definition stubpath.csar...' in self.logger_output_string
+        assert 'Type definition loaded.' in self.logger_output_string
+
+    def test_load_relative_path_single_yaml_file(self, monkeypatch, mock_object):
+
+        monkeypatch.setattr(TypeDefinitionManager, 'load_type_definition', mock_object)
+        monkeypatch.setattr(os.path, 'isfile', lambda x: True)
+        monkeypatch.setattr(service_template_utils, '_is_archive', lambda x: False)
+
+        self.invoke('type_definitions load stubpath.yaml')
+
+        mock_object.assert_called_with(os.path.join(os.getcwd(), 'stubpath.yaml'))
+
+    def test_load_raises_exception_resulting_from_name_uniqueness(self, monkeypatch, mock_object):
+
+        monkeypatch.setattr(service_template_utils, 'get', mock_object)
+        monkeypatch.setattr(TypeDefinitionManager,
+                            'load_type_definition',
+                            raise_exception(TypeDefinitionAlreadyExistsException,
+                                            msg=("Type Definition '{0}' with version '{1}'"
+                                                 " already exists.".\
+                                                 format(mock_models.TYPE_DEFINITION_NAME,\
+                                                        mock_models.TYPE_DEFINITION_VERSION))))
+        monkeypatch.setattr(os.path, 'dirname', mock_object)
+
+        assert_exception_raised(
+            self.invoke('type_definitions load stubpath.yaml'),
+            expected_exception=TypeDefinitionAlreadyExistsException,
+            expected_msg=("Type Definition '{0}' with version '{1}' already exists.".\
+            format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION)))
+
+    def test_load_raises_exception(self, monkeypatch, mock_object):
+
+        monkeypatch.setattr(service_template_utils, 'get', mock_object)
+        monkeypatch.setattr(TypeDefinitionManager,
+                            'load_type_definition',
+                            raise_exception(storage_exceptions.NotFoundError))
+        monkeypatch.setattr(os.path, 'dirname', mock_object)
+
+        assert_exception_raised(
+            self.invoke('type_definitions load stubpath.yaml'),
+            expected_exception=storage_exceptions.StorageError)
+
+    def test_load_raises_invalid_format_exception(self):
+
+        assert_exception_raised(
+            self.invoke('type_definitions load stubpath'),
+            expected_exception=TypeDefinitionException,
+            expected_msg='Type definition file has invalid extension')
+
+class TestTypeDefinitionsShow(TestCliBase):
+
+    def test_header_string(self, monkeypatch, mock_storage):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        self.invoke('type_definitions show {0} {1}'.\
+                    format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION))
+        assert "Showing type definition name '{0}' version '{1}'...".\
+        format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION) in \
+        self.logger_output_string
+
+    def test_no_services_no_description(self, monkeypatch, mock_storage):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        self.invoke('type_definitions show {0} {1}'.\
+                    format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION))
+
+        assert "Showing type definition name '{0}' version '{1}'...".\
+        format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION) in \
+        self.logger_output_string
+        assert 'Description:' not in self.logger_output_string
+        assert 'Existing services:' not in self.logger_output_string
+
+    def test_details(self, monkeypatch, mock_storage, mock_object):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        monkeypatch.setattr(mock_storage.type_definition, '_get_query', mock_object)
+        self.invoke('type_definitions show {0} {1}'.\
+                    format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION))
+
+        assert "Showing type definition name '{0}' version '{1}'...".\
+        format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION) in \
+        self.logger_output_string
+        assert 'id' in self.logger_output_string
+        assert 'name' in self.logger_output_string
+        assert 'version' in self.logger_output_string
+        assert 'main_file_name' in self.logger_output_string
+        assert 'uploaded_at' in self.logger_output_string
+
+        assert mock_models.TYPE_DEFINITION_NAME in self.logger_output_string
+        assert mock_models.TYPE_DEFINITION_VERSION in self.logger_output_string
+        assert mock_models.TYPE_DEFINITION_MAIN_FILE_NAME in self.logger_output_string
+
+class TestTypeDefinitionsList(TestCliBase):
+
+    def test_header_string(self, monkeypatch, mock_storage):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        self.invoke('type_definitions list')
+        assert 'Listing all type definitions...' in self.logger_output_string
+
+class TestTypeDefinitionsDelete(TestCliBase):
+
+    def test_header_string(self, monkeypatch, mock_storage):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        self.invoke('type_definitions delete {0} {1}'.\
+                    format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION))
+        assert "Deleting type definition name '{0}' version '{1}'...".\
+        format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION) in \
+        self.logger_output_string
+
+    def test_delete_no_exception(self, monkeypatch, mock_storage, mock_object):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        monkeypatch.setattr(TypeDefinitionManager, 'delete_type_definition', mock_object)
+        self.invoke('type_definitions delete {0} {1}'.\
+                    format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION))
+
+        assert "Type definition name '{0}' version '{1}' deleted".\
+        format(mock_models.TYPE_DEFINITION_NAME, mock_models.TYPE_DEFINITION_VERSION) in \
+        self.logger_output_string
+
+    def test_delete_raises_exception(self, monkeypatch):
+
+        monkeypatch.setattr(TypeDefinitionManager,
+                            'delete_type_definition',
+                            raise_exception(storage_exceptions.StorageError))
+
+        assert_exception_raised(
+            self.invoke('type_definitions delete {0} {1}'.\
+                        format(mock_models.TYPE_DEFINITION_NAME,\
+                               mock_models.TYPE_DEFINITION_VERSION)),
+            expected_exception=storage_exceptions.StorageError,
+            expected_msg='')
+
+    def test_delete_raises_not_found_exception(self, monkeypatch):
+
+        monkeypatch.setattr(TypeDefinitionManager,
+                            'delete_type_definition',
+                            raise_exception(TypeDefinitionNotFoundException,
+                                            msg='Type definition does not exist.'))
+
+        assert_exception_raised(
+            self.invoke('type_definitions delete {0} {1}'.\
+                        format(mock_models.TYPE_DEFINITION_NAME,\
+                               mock_models.TYPE_DEFINITION_VERSION)),
+            expected_exception=TypeDefinitionNotFoundException,
+            expected_msg='Type definition does not exist.')
+
+class TestTypeDefinitionsValidate(TestCliBase):
+
+    def test_header_string(self, monkeypatch, mock_storage):
+
+        monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+        self.invoke('type_definitions validate stubpath.csar')
+        assert 'Validating type definition: stubpath.csar' in self.logger_output_string
+
+    def test_validate_no_exception(self, monkeypatch, mock_object):
+
+        monkeypatch.setattr(TypeDefinitionManager, 'validate_type_definition', mock_object)
+        monkeypatch.setattr(service_template_utils, 'get', mock_object)
+        self.invoke('type_definitions validate stubpath.csar')
+        assert 'Type definition validated successfully' in self.logger_output_string
+
+    def test_validate_raises_exception(self, monkeypatch, mock_object):
+
+        monkeypatch.setattr(TypeDefinitionManager, 'validate_type_definition',\
+                            raise_exception(AriaException))
+        monkeypatch.setattr(service_template_utils, 'get', mock_object)
+        assert_exception_raised(
+            self.invoke('type_definitions validate stubpath.csar'),
+            expected_exception=AriaException)
+
+    def test_validate_raises_invalid_format_exception(self):
+
+        assert_exception_raised(
+            self.invoke('type_definitions load stubpath'),
+            expected_exception=TypeDefinitionException,
+            expected_msg='Type definition file has invalid extension')
diff --git a/tests/cli/utils.py b/tests/cli/utils.py
index a1e0c9a..145f55b 100644
--- a/tests/cli/utils.py
+++ b/tests/cli/utils.py
@@ -62,11 +62,20 @@
 class MockStorage(object):
 
     def __init__(self):
+        self.type_definition = MockTypeDefinitionStorage()
         self.service_template = MockServiceTemplateStorage()
         self.service = MockServiceStorage()
         self.node_template = MockNodeTemplateStorage()
         self.node = MockNodeStorage()
 
+class MockTypeDefinitionStorage(object):
+
+    def __init__(self):
+        self.td = mock_models.load_type_definition()
+        self.list = MagicMock(return_value=[self.td])
+        self.get = MagicMock(return_value=self.td)
+        self._get_query = MagicMock()
+        self.delete = MagicMock()
 
 class MockServiceTemplateStorage(object):
 
diff --git a/tests/fixtures.py b/tests/fixtures.py
index 3b1b9b5..db5f146 100644
--- a/tests/fixtures.py
+++ b/tests/fixtures.py
@@ -21,6 +21,7 @@
     application_model_storage,
     application_resource_storage
 )
+from aria import type_definition_manager as type_definition
 from aria.orchestrator import plugin
 from aria.storage import (
     sql_mapi,
@@ -68,3 +69,16 @@
 @pytest.fixture
 def plugin_manager(model, plugins_dir):
     return plugin.PluginManager(model=model, plugins_dir=plugins_dir)
+
+
+@pytest.fixture
+def type_definitions_dir(tmpdir):
+    result = tmpdir.join('type_definitions')
+    result.mkdir()
+    return str(result)
+
+
+@pytest.fixture
+def type_definition_manager(model, type_definitions_dir):
+    return type_definition.\
+        TypeDefinitionManager(model_storage=model, type_definitions_dir=type_definitions_dir)
diff --git a/tests/helpers.py b/tests/helpers.py
index 4c3194b..a2b881f 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -32,6 +32,10 @@
     return os.path.join(RESOURCES_DIR, 'service-templates', *args)
 
 
+def get_type_definition_uri(*args):
+    return os.path.join(RESOURCES_DIR, 'type-definitions', *args)
+
+
 class FilesystemDataHolder(object):
 
     def __init__(self, path, reset=False):
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 8a3b87e..045f047 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -37,6 +37,9 @@
     NORMATIVE_REMOVE_SOURCE
 )
 
+TYPE_DEFINITION_NAME = 'test_type_definition'
+TYPE_DEFINITION_VERSION = '1.0'
+TYPE_DEFINITION_MAIN_FILE_NAME = 'main_file_name'
 SERVICE_TEMPLATE_NAME = 'test_service_template'
 SERVICE_NAME = 'test_service1'
 NODE_TEMPLATE_NAME = 'test_node_template'
@@ -51,6 +54,17 @@
 DEPENDENT_NODE_NAME = 'dependent_node'
 
 
+def load_type_definition(name=TYPE_DEFINITION_NAME, version=TYPE_DEFINITION_VERSION,\
+                         main_file_name=TYPE_DEFINITION_MAIN_FILE_NAME):
+    now = datetime.now()
+    return models.TypeDefinition(
+        name=name,
+        version=version,
+        main_file_name=main_file_name,
+        uploaded_at=now
+    )
+
+
 def create_service_template(name=SERVICE_TEMPLATE_NAME, description=None, inputs=None):
     now = datetime.now()
     inputs = inputs or {}
diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py
index 25b4080..8ed8500 100644
--- a/tests/modeling/test_models.py
+++ b/tests/modeling/test_models.py
@@ -65,6 +65,13 @@
                                      initiator=init_inmemory_model_storage)
 
 
+def _type_definition_storage():
+    storage = _empty_storage()
+    type_definition = mock.models.load_type_definition()
+    storage.type_definition.put(type_definition)
+    return storage
+
+
 def _service_template_storage():
     storage = _empty_storage()
     service_template = mock.models.create_service_template()
@@ -132,6 +139,12 @@
 
 
 @pytest.fixture
+def type_definition_storage():
+    with sql_storage(_type_definition_storage) as storage:
+        yield storage
+
+
+@pytest.fixture
 def service_template_storage():
     with sql_storage(_service_template_storage) as storage:
         yield storage
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/TOSCA-Metadata/TOSCA.meta b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..cc414a1
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Kowsalya
+Entry-Definitions: definitions/type_definitions_main.yaml
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type1.yaml b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type1.yaml
new file mode 100644
index 0000000..1af6054
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type1.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type2.yaml b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type2.yaml
new file mode 100644
index 0000000..f2c8692
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type2.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type2_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type3.yaml b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type3.yaml
new file mode 100644
index 0000000..0ecee3a
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type3.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type333_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type4.yaml b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type4.yaml
new file mode 100644
index 0000000..418deea
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/custom_types/type4.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type4_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/type_definitions_main.yaml b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/type_definitions_main.yaml
new file mode 100644
index 0000000..889b4ab
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_no_metadata/definitions/type_definitions_main.yaml
@@ -0,0 +1,23 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+metadata:
+  template_name: test10
+  template_author: ekowsalya
+  
+imports:
+  - custom_types/type1.yaml
+  - custom_types/type2.yaml
+  - custom_types/type3.yaml
+  - custom_types/type4.yaml
+  - custom_types/type4.yaml  
+
+node_types:
+    non_normative_type_definition_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/TOSCA-Metadata/TOSCA.meta b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..cc414a1
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Kowsalya
+Entry-Definitions: definitions/type_definitions_main.yaml
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type1.yaml b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type1.yaml
new file mode 100644
index 0000000..1af6054
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type1.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type2.yaml b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type2.yaml
new file mode 100644
index 0000000..f2c8692
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type2.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type2_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type3.yaml b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type3.yaml
new file mode 100644
index 0000000..0ecee3a
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type3.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type333_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type4.yaml b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type4.yaml
new file mode 100644
index 0000000..418deea
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/custom_types/type4.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type4_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/type_definitions_main.yaml b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/type_definitions_main.yaml
new file mode 100644
index 0000000..f6931c6
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_parsing_error/definitions/type_definitions_main.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+metadata:
+  template_name: test10
+  template_author: ekowsalya
+  template_version: 1.0
+  
+imports:
+  - custom_types/type1.yaml
+  - custom_types/type2.yaml
+  - custom_types/type3.yaml
+  - custom_types/type4.yaml
+  - custom_types/type4.yaml  
+
+node_types:
+    non_normative_type_definition_compute:
+        derived_from: tosca.nodes.Compute1
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/TOSCA-Metadata/TOSCA.meta b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..090c2cf
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,5 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Kowsalya
+Entry-Definitions: definitions/type_definitions_main.yaml
+
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/custom_inner_type/inner_type1.yaml b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/custom_inner_type/inner_type1.yaml
new file mode 100644
index 0000000..c0ec1ce
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/custom_inner_type/inner_type1.yaml
@@ -0,0 +1,17 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_inner_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
+
+topology_template:
+    node_templates:
+        test_node:
+            type:non_normative_type_definition_inner_type1_compute
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type1.yaml b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type1.yaml
new file mode 100644
index 0000000..1af6054
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type1.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type2.yaml b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type2.yaml
new file mode 100644
index 0000000..f2c8692
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type2.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type2_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type3.yaml b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type3.yaml
new file mode 100644
index 0000000..0ecee3a
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type3.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type333_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type4.yaml b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type4.yaml
new file mode 100644
index 0000000..c58bfce
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/custom_types/type4.yaml
@@ -0,0 +1,15 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+imports:
+  - custom_inner_type/inner_type1.yaml
+  
+node_types:
+    non_normative_type_definition_type4_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/type_definitions_main.yaml b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/type_definitions_main.yaml
new file mode 100644
index 0000000..9d731f1
--- /dev/null
+++ b/tests/resources/type-definitions/invalid_type_definition_with_topology_template/definitions/type_definitions_main.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+metadata:
+  template_name: test1
+  template_author: ekowsalya
+  template_version: "1.0"
+  
+imports:
+  - custom_types/type1.yaml
+  - custom_types/type2.yaml
+  - custom_types/type3.yaml
+  - custom_types/type4.yaml
+  - custom_types/type4.yaml  
+
+node_types:
+    non_normative_type_definition_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition/TOSCA-Metadata/TOSCA.meta b/tests/resources/type-definitions/valid_type_definition/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..cc414a1
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Kowsalya
+Entry-Definitions: definitions/type_definitions_main.yaml
diff --git a/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type1.yaml b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type1.yaml
new file mode 100644
index 0000000..1af6054
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type1.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type2.yaml b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type2.yaml
new file mode 100644
index 0000000..f2c8692
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type2.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type2_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type3.yaml b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type3.yaml
new file mode 100644
index 0000000..0ecee3a
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type3.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type333_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type4.yaml b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type4.yaml
new file mode 100644
index 0000000..418deea
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition/definitions/custom_types/type4.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type4_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition/definitions/type_definitions_main.yaml b/tests/resources/type-definitions/valid_type_definition/definitions/type_definitions_main.yaml
new file mode 100644
index 0000000..a86cc55
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition/definitions/type_definitions_main.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+metadata:
+  template_name: test10
+  template_author: ekowsalya
+  template_version: "1.0"
+  
+imports:
+  - custom_types/type1.yaml
+  - custom_types/type2.yaml
+  - custom_types/type3.yaml
+  - custom_types/type4.yaml
+  - custom_types/type4.yaml  
+
+node_types:
+    non_normative_type_definition_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition1/TOSCA-Metadata/TOSCA.meta b/tests/resources/type-definitions/valid_type_definition1/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..cc414a1
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition1/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Kowsalya
+Entry-Definitions: definitions/type_definitions_main.yaml
diff --git a/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type1.yaml b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type1.yaml
new file mode 100644
index 0000000..1af6054
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type1.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type2.yaml b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type2.yaml
new file mode 100644
index 0000000..f2c8692
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type2.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type2_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type3.yaml b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type3.yaml
new file mode 100644
index 0000000..0ecee3a
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type3.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type333_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type4.yaml b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type4.yaml
new file mode 100644
index 0000000..418deea
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition1/definitions/custom_types/type4.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type4_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition1/definitions/type_definitions_main.yaml b/tests/resources/type-definitions/valid_type_definition1/definitions/type_definitions_main.yaml
new file mode 100644
index 0000000..4ff3376
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition1/definitions/type_definitions_main.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+metadata:
+  template_name: apple
+  template_author: ekowsalya
+  template_version: "1.0"
+  
+imports:
+  - custom_types/type1.yaml
+  - custom_types/type2.yaml
+  - custom_types/type3.yaml
+  - custom_types/type4.yaml
+  - custom_types/type4.yaml  
+
+node_types:
+    non_normative_type_definition_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition2/TOSCA-Metadata/TOSCA.meta b/tests/resources/type-definitions/valid_type_definition2/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..cc414a1
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition2/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Kowsalya
+Entry-Definitions: definitions/type_definitions_main.yaml
diff --git a/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type1.yaml b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type1.yaml
new file mode 100644
index 0000000..1af6054
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type1.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type1_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type2.yaml b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type2.yaml
new file mode 100644
index 0000000..f2c8692
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type2.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type2_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type3.yaml b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type3.yaml
new file mode 100644
index 0000000..0ecee3a
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type3.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type333_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type4.yaml b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type4.yaml
new file mode 100644
index 0000000..418deea
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition2/definitions/custom_types/type4.yaml
@@ -0,0 +1,12 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+    non_normative_type_definition_type4_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/resources/type-definitions/valid_type_definition2/definitions/type_definitions_main.yaml b/tests/resources/type-definitions/valid_type_definition2/definitions/type_definitions_main.yaml
new file mode 100644
index 0000000..859ed3c
--- /dev/null
+++ b/tests/resources/type-definitions/valid_type_definition2/definitions/type_definitions_main.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+metadata:
+  template_name: ball
+  template_author: ekowsalya
+  template_version: "1.0"
+  
+imports:
+  - custom_types/type1.yaml
+  - custom_types/type2.yaml
+  - custom_types/type3.yaml
+  - custom_types/type4.yaml
+  - custom_types/type4.yaml  
+
+node_types:
+    non_normative_type_definition_compute:
+        derived_from: tosca.nodes.Compute
+        properties:
+            name:
+              type: string
+              required: true
+            password:
+              type: string
+              required: true
diff --git a/tests/storage/test_model_storage.py b/tests/storage/test_model_storage.py
index bc5434a..b70ecdf 100644
--- a/tests/storage/test_model_storage.py
+++ b/tests/storage/test_model_storage.py
@@ -74,7 +74,7 @@
 def test_application_storage_factory():
     storage = application_model_storage(sql_mapi.SQLAlchemyModelAPI,
                                         initiator=tests_storage.init_inmemory_model_storage)
-
+    assert storage.type_definition
     assert storage.service_template
     assert storage.node_template
     assert storage.group_template
diff --git a/tests/test_type_definition_manager.py b/tests/test_type_definition_manager.py
new file mode 100644
index 0000000..5596601
--- /dev/null
+++ b/tests/test_type_definition_manager.py
@@ -0,0 +1,222 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import os
+import pytest
+from tests.fixtures import (# pylint: disable=unused-import
+    inmemory_model as model,
+    type_definition_manager,
+    type_definitions_dir
+)
+from aria.exceptions import(
+    TypeDefinitionException,
+    InvalidTypeDefinitionException,
+    ParsingError,
+    TypeDefinitionNotFoundException
+    )
+from tests.helpers import get_type_definition_uri # pylint: disable=ungrouped-imports
+from aria.storage.exceptions import NotFoundError # pylint: disable=ungrouped-imports
+
+TYPE_DEFINITION_NAME = 'test10'
+TYPE_DEFINITION_VERSION = '1.0'
+TYPE_DEFINITION_MAIN_FILE_NAME = 'type_definitions_main.yaml'
+
+class TestTypeDefinitionManager(object):
+    def test_load_type_definition(self, type_definition_manager, model, type_definitions_dir):
+        type_definition = type_definition_manager.\
+        load_type_definition(get_type_definition_uri('valid_type_definition', 'definitions', \
+                                                     'type_definitions_main.yaml'))
+        assert type_definition.name == TYPE_DEFINITION_NAME
+        assert type_definition.version == TYPE_DEFINITION_VERSION
+        assert type_definition.main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition == model.type_definition.get(type_definition.id)
+        type_definition_dir = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir)
+        assert type_definition_dir == type_definition_manager.\
+        get_type_definition_dir(type_definition)
+
+    def test_invalid_load_type_definition_with_no_file_exist(self, type_definition_manager):
+        with pytest.raises(TypeDefinitionException) as excinfo:
+            type_definition_manager.\
+            load_type_definition(\
+                                 get_type_definition_uri('valid_type_definition',\
+                                                         'definitions', 'invalid'))
+            assert str(excinfo.value) == 'Could not open/load type definition file'
+
+    def test_invalid_load_type_definition_with_topology_template(self, type_definition_manager):
+        with pytest.raises(InvalidTypeDefinitionException) as excinfo:
+            type_definition_manager.\
+            load_type_definition(\
+                                 get_type_definition_uri(('invalid_type_definition_with_'
+                                                          'topology_template'),\
+                                                         'definitions',\
+                                                         'type_definitions_main.yaml'))
+            assert str(excinfo.value) == ("Type definition '{0}' with version '{1}' is invalid."
+                                          " It contains topology template in '{2}'.").\
+                                          format(TYPE_DEFINITION_MAIN_FILE_NAME,\
+                                                 TYPE_DEFINITION_VERSION, 'inner_type1.yaml')
+
+    def test_invalid_load_type_definition_with_no_metadata(self, type_definition_manager):
+        with pytest.raises(InvalidTypeDefinitionException) as excinfo:
+            type_definition_manager.\
+            load_type_definition(\
+                                 get_type_definition_uri('invalid_type_definition_with_no_metadata',
+                                                         'definitions',\
+                                                         'type_definitions_main.yaml'))
+            assert str(excinfo.value) == ('Type definition is invalid.'
+                                          ' It should have metadata information')
+
+    def test_invalid_load_type_definition_with_parsing_error(self, type_definition_manager):
+        with pytest.raises(ParsingError) as excinfo:
+            type_definition_manager.\
+            load_type_definition(\
+                                 get_type_definition_uri(('invalid_type_definition_with_'
+                                                          'parsing_error'),
+                                                         'definitions',\
+                                                         'type_definitions_main.yaml'))
+            assert str(excinfo.value) == 'Failed to parse type definition'
+
+    def test_get_type_definition(self, type_definition_manager, model, type_definitions_dir):
+        type_definition_manager.\
+        load_type_definition(get_type_definition_uri('valid_type_definition', 'definitions', \
+                                                     'type_definitions_main.yaml'))
+        type_definition = type_definition_manager.get_type_definition(TYPE_DEFINITION_NAME, \
+                                                                      TYPE_DEFINITION_VERSION)
+        assert type_definition.name == TYPE_DEFINITION_NAME
+        assert type_definition.version == TYPE_DEFINITION_VERSION
+        assert type_definition.main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition == model.type_definition.get(type_definition.id)
+        type_definition_dir = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir)
+        assert type_definition_dir == type_definition_manager.\
+        get_type_definition_dir(type_definition)
+
+    def test_get_type_definition_not_exist(self, type_definition_manager):
+        with pytest.raises(NotFoundError):
+            type_definition_manager.get_type_definition('test', '1.0')
+
+    def test_delete_type_definition(self, type_definition_manager, model, type_definitions_dir):
+        type_definition_manager.\
+        load_type_definition(get_type_definition_uri('valid_type_definition', 'definitions', \
+                                                     'type_definitions_main.yaml'))
+        type_definition = type_definition_manager.\
+        get_type_definition(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION)
+        assert type_definition.name == TYPE_DEFINITION_NAME
+        assert type_definition.version == TYPE_DEFINITION_VERSION
+        assert type_definition.main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition == model.type_definition.get(type_definition.id)
+        type_definition_dir = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir)
+        assert type_definition_dir == type_definition_manager.\
+        get_type_definition_dir(type_definition)
+        type_definition_manager.\
+        delete_type_definition(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION)
+        with pytest.raises(NotFoundError):
+            type_definition_manager.get_type_definition(TYPE_DEFINITION_NAME,\
+                                                        TYPE_DEFINITION_VERSION)
+
+    def test_delete_type_definition_not_exist(self, type_definition_manager):
+        with pytest.raises(TypeDefinitionNotFoundException) as excinfo:
+            type_definition_manager.delete_type_definition('test', '1.0')
+            assert str(excinfo.value) == "Type definition name 'test' version '1.0' does not exist."
+
+    def test_list_type_definition(self, type_definition_manager, model, type_definitions_dir):
+        type_definition_manager.\
+        load_type_definition(get_type_definition_uri('valid_type_definition', 'definitions', \
+                                                     'type_definitions_main.yaml'))
+        type_definition = type_definition_manager.\
+        get_type_definition(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION)
+        assert type_definition.name == TYPE_DEFINITION_NAME
+        assert type_definition.version == TYPE_DEFINITION_VERSION
+        assert type_definition.main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition == model.type_definition.get(type_definition.id)
+        type_definition_dir = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format(TYPE_DEFINITION_NAME, TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir)
+        assert type_definition_dir == type_definition_manager.\
+        get_type_definition_dir(type_definition)
+        type_definition_list = type_definition_manager.\
+        list_type_definition(sort_by='uploaded_at', descending=False)
+        assert type_definition_list[0].name == TYPE_DEFINITION_NAME
+        assert type_definition_list[0].version == TYPE_DEFINITION_VERSION
+        assert type_definition_list[0].main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition_list[0] == model.type_definition.get(type_definition.id)
+        type_definition_dir = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format(TYPE_DEFINITION_NAME, \
+                                                  TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir)
+        assert type_definition_dir == type_definition_manager.\
+        get_type_definition_dir(type_definition)
+
+    def test_list_type_definition_sort_order(self, type_definition_manager,\
+                                             model, type_definitions_dir):
+        type_definition1 = type_definition_manager.\
+        load_type_definition(get_type_definition_uri('valid_type_definition1', 'definitions', \
+                                                     'type_definitions_main.yaml'))
+        type_definition2 = type_definition_manager.\
+        load_type_definition(get_type_definition_uri('valid_type_definition2', 'definitions', \
+                                                     'type_definitions_main.yaml'))
+
+        type_definition_list = type_definition_manager.\
+        list_type_definition(sort_by='name', descending=True)
+
+        assert type_definition_list[0].name == 'ball'
+        assert type_definition_list[0].version == TYPE_DEFINITION_VERSION
+        assert type_definition_list[0].main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition_list[0] == model.type_definition.get(type_definition2.id)
+        type_definition_dir1 = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format('ball', \
+                                                  TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir1)
+        assert type_definition_dir1 == type_definition_manager.\
+        get_type_definition_dir(type_definition2)
+
+        assert type_definition_list[1].name == 'apple'
+        assert type_definition_list[1].version == TYPE_DEFINITION_VERSION
+        assert type_definition_list[1].main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition_list[1] == model.type_definition.get(type_definition1.id)
+        type_definition_dir2 = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format('apple', \
+                                                  TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir2)
+        assert type_definition_dir2 == type_definition_manager.\
+        get_type_definition_dir(type_definition1)
+
+        type_definition_list = type_definition_manager.\
+        list_type_definition(sort_by='uploaded_at', descending=False)
+
+        assert type_definition_list[0].name == 'apple'
+        assert type_definition_list[0].version == TYPE_DEFINITION_VERSION
+        assert type_definition_list[0].main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition_list[0] == model.type_definition.get(type_definition1.id)
+        type_definition_dir3 = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format('apple', \
+                                                  TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir3)
+        assert type_definition_dir3 == type_definition_manager.\
+        get_type_definition_dir(type_definition1)
+
+        assert type_definition_list[1].name == 'ball'
+        assert type_definition_list[1].version == TYPE_DEFINITION_VERSION
+        assert type_definition_list[1].main_file_name == TYPE_DEFINITION_MAIN_FILE_NAME
+        assert type_definition_list[1] == model.type_definition.get(type_definition2.id)
+        type_definition_dir4 = os.path.join(type_definitions_dir, '{0}-{1}'.\
+                                           format('ball', \
+                                                  TYPE_DEFINITION_VERSION))
+        assert os.path.isdir(type_definition_dir4)
+        assert type_definition_dir4 == type_definition_manager.\
+        get_type_definition_dir(type_definition2)