ariatosca-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mxm...@apache.org
Subject [13/14] incubator-ariatosca git commit: ARIA-61 Initial version of CLI "workflow" command
Date Mon, 30 Jan 2017 14:15:11 GMT
ARIA-61 Initial version of CLI "workflow" command


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/44478293
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/44478293
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/44478293

Branch: refs/heads/ARIA-66-Convert-custom-parser-fields-into-sqla-based-fields
Commit: 44478293c0f16ed1c60fb5c8b8b12e73954fddfe
Parents: 8469917
Author: Tal Liron <tal.liron@gmail.com>
Authored: Wed Jan 25 16:30:16 2017 +0200
Committer: Tal Liron <tal.liron@gmail.com>
Committed: Thu Jan 26 12:38:16 2017 +0200

----------------------------------------------------------------------
 aria/cli/args_parser.py                         | 141 +++++----
 aria/cli/cli.py                                 |  10 +-
 aria/cli/commands.py                            | 313 ++++++++++++-------
 aria/cli/csar.py                                |   2 +-
 aria/orchestrator/__init__.py                   |   2 +-
 aria/orchestrator/decorators.py                 |   3 +
 aria/parser/modeling/__init__.py                |   4 +-
 aria/parser/modeling/types.py                   |  28 +-
 .../simple_v1_0/modeling/__init__.py            |   1 +
 9 files changed, 313 insertions(+), 191 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/cli/args_parser.py
----------------------------------------------------------------------
diff --git a/aria/cli/args_parser.py b/aria/cli/args_parser.py
index 8eacf05..e661620 100644
--- a/aria/cli/args_parser.py
+++ b/aria/cli/args_parser.py
@@ -68,6 +68,7 @@ def config_parser(parser=None):
     add_init_parser(sub_parser)
     add_execute_parser(sub_parser)
     add_parse_parser(sub_parser)
+    add_workflow_parser(sub_parser)
     add_spec_parser(sub_parser)
     add_csar_create_parser(sub_parser)
     add_csar_open_parser(sub_parser)
@@ -76,6 +77,73 @@ def config_parser(parser=None):
 
 
 @sub_parser_decorator(
+    name='parse',
+    help='Parse a blueprint',
+    formatter_class=SmartFormatter)
+def add_parse_parser(parse):
+    """
+    ``parse`` command parser configuration
+    """
+    parse.add_argument(
+        'uri',
+        help='URI or file path to service template')
+    parse.add_argument(
+        'consumer',
+        nargs='?',
+        default='validate',
+        help='"validate" (default), "presentation", "model", "types", "instance", or consumer
'
+             'class name (full class path or short name)')
+    parse.add_argument(
+        '--loader-source',
+        default='aria.parser.loading.DefaultLoaderSource',
+        help='loader source class for the parser')
+    parse.add_argument(
+        '--reader-source',
+        default='aria.parser.reading.DefaultReaderSource',
+        help='reader source class for the parser')
+    parse.add_argument(
+        '--presenter-source',
+        default='aria.parser.presentation.DefaultPresenterSource',
+        help='presenter source class for the parser')
+    parse.add_argument(
+        '--presenter',
+        help='force use of this presenter class in parser')
+    parse.add_argument(
+        '--prefix', nargs='*',
+        help='prefixes for imports')
+    parse.add_flag_argument(
+        'debug',
+        help_true='print debug info',
+        help_false='don\'t print debug info')
+    parse.add_flag_argument(
+        'cached-methods',
+        help_true='enable cached methods',
+        help_false='disable cached methods',
+        default=True)
+
+
+@sub_parser_decorator(
+    name='workflow',
+    help='Run a workflow on a blueprint',
+    formatter_class=SmartFormatter)
+def add_workflow_parser(workflow):
+    """
+    ``workflow`` command parser configuration
+    """
+    workflow.add_argument(
+        'uri',
+        help='URI or file path to service template')
+    workflow.add_argument(
+        '-w', '--workflow',
+        default='install',
+        help='The workflow name')
+    workflow.add_argument(
+        '-d', '--deployment-id',
+        required=False,
+        help='A unique ID for the deployment')
+
+
+@sub_parser_decorator(
     name='init',
     help='Initialize environment',
     formatter_class=SmartFormatter)
@@ -146,65 +214,6 @@ def add_execute_parser(execute):
 
 
 @sub_parser_decorator(
-    name='parse',
-    help='Parse a blueprint',
-    formatter_class=SmartFormatter)
-def add_parse_parser(parse):
-    """
-    ``parse`` command parser configuration
-    """
-    parse.add_argument(
-        'uri',
-        help='URI or file path to profile')
-    parse.add_argument(
-        'consumer',
-        nargs='?',
-        default='instance',
-        help='consumer class name (full class path or short name)')
-    parse.add_argument(
-        '--loader-source',
-        default='aria.parser.loading.DefaultLoaderSource',
-        help='loader source class for the parser')
-    parse.add_argument(
-        '--reader-source',
-        default='aria.parser.reading.DefaultReaderSource',
-        help='reader source class for the parser')
-    parse.add_argument(
-        '--presenter-source',
-        default='aria.parser.presentation.DefaultPresenterSource',
-        help='presenter source class for the parser')
-    parse.add_argument(
-        '--presenter',
-        help='force use of this presenter class in parser')
-    parse.add_argument(
-        '--prefix', nargs='*',
-        help='prefixes for imports')
-    parse.add_flag_argument(
-        'debug',
-        help_true='print debug info',
-        help_false='don\'t print debug info')
-    parse.add_flag_argument(
-        'cached-methods',
-        help_true='enable cached methods',
-        help_false='disable cached methods',
-        default=True)
-
-
-@sub_parser_decorator(
-    name='spec',
-    help='Specification tool',
-    formatter_class=SmartFormatter)
-def add_spec_parser(spec):
-    """
-    ``spec`` command parser configuration
-    """
-    spec.add_argument(
-        '--csv',
-        action='store_true',
-        help='output as CSV')
-
-
-@sub_parser_decorator(
     name='csar-create',
     help='Create a CSAR file from a TOSCA service template directory',
     formatter_class=SmartFormatter)
@@ -243,3 +252,17 @@ def add_csar_validate_parser(parse):
     parse.add_argument(
         'source',
         help='CSAR file location')
+
+
+@sub_parser_decorator(
+    name='spec',
+    help='Specification tool',
+    formatter_class=SmartFormatter)
+def add_spec_parser(spec):
+    """
+    ``spec`` command parser configuration
+    """
+    spec.add_argument(
+        '--csv',
+        action='store_true',
+        help='output as CSV')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/cli/cli.py
----------------------------------------------------------------------
diff --git a/aria/cli/cli.py b/aria/cli/cli.py
index c5830d5..20ace2c 100644
--- a/aria/cli/cli.py
+++ b/aria/cli/cli.py
@@ -29,13 +29,14 @@ from ..logger import (
 from ..utils.exceptions import print_exception
 from .args_parser import config_parser
 from .commands import (
+    ParseCommand,
+    WorkflowCommand,
     InitCommand,
     ExecuteCommand,
-    ParseCommand,
-    SpecCommand,
     CSARCreateCommand,
     CSAROpenCommand,
     CSARValidateCommand,
+    SpecCommand,
 )
 
 __version__ = '0.1.0'
@@ -49,13 +50,14 @@ class AriaCli(LoggerMixin):
     def __init__(self, *args, **kwargs):
         super(AriaCli, self).__init__(*args, **kwargs)
         self.commands = {
+            'parse': ParseCommand.with_logger(base_logger=self.logger),
+            'workflow': WorkflowCommand.with_logger(base_logger=self.logger),
             'init': InitCommand.with_logger(base_logger=self.logger),
             'execute': ExecuteCommand.with_logger(base_logger=self.logger),
-            'parse': ParseCommand.with_logger(base_logger=self.logger),
-            'spec': SpecCommand.with_logger(base_logger=self.logger),
             'csar-create': CSARCreateCommand.with_logger(base_logger=self.logger),
             'csar-open': CSAROpenCommand.with_logger(base_logger=self.logger),
             'csar-validate': CSARValidateCommand.with_logger(base_logger=self.logger),
+            'spec': SpecCommand.with_logger(base_logger=self.logger),
         }
 
     def __enter__(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/cli/commands.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands.py b/aria/cli/commands.py
index 1cd765f..0890cd1 100644
--- a/aria/cli/commands.py
+++ b/aria/cli/commands.py
@@ -26,15 +26,10 @@ import tempfile
 from glob import glob
 from importlib import import_module
 
-from yaml import safe_load, YAMLError
+from ruamel import yaml # @UnresolvedImport
 
 from .. import extension
-from .. import (application_model_storage, application_resource_storage)
 from ..logger import LoggerMixin
-from ..storage import (FileSystemModelDriver, FileSystemResourceDriver)
-from ..orchestrator.context.workflow import WorkflowContext
-from ..orchestrator.workflows.core.engine import Engine
-from ..orchestrator.workflows.executor.process import ProcessExecutor
 from ..parser import iter_specifications
 from ..parser.consumption import (
     ConsumptionContext,
@@ -47,29 +42,27 @@ from ..parser.consumption import (
     Instance
 )
 from ..parser.loading import LiteralLocation, UriLocation
+from ..parser.modeling import initialize_storage
 from ..utils.application import StorageManager
 from ..utils.caching import cachedmethod
 from ..utils.console import (puts, Colored, indent)
 from ..utils.imports import (import_fullname, import_modules)
-from . import csar
+from ..utils.collections import OrderedDict
+from ..orchestrator import WORKFLOW_DECORATOR_RESERVED_ARGUMENTS
+from ..orchestrator.runner import Runner
+from ..orchestrator.workflows.builtin import BUILTIN_WORKFLOWS
+
 from .exceptions import (
     AriaCliFormatInputsError,
     AriaCliYAMLInputsError,
     AriaCliInvalidInputsError
 )
-from .storage import (
-    local_resource_storage,
-    create_local_storage,
-    local_model_storage,
-    create_user_space,
-    user_space,
-    local_storage,
-)
+from . import csar
 
 
 class BaseCommand(LoggerMixin):
     """
-    Base class for CLI commands
+    Base class for CLI commands.
     """
 
     def __repr__(self):
@@ -101,9 +94,9 @@ class BaseCommand(LoggerMixin):
                 try:
                     parsed_dict.update(json.loads(input_string))
                 except BaseException:
-                    parsed_dict.update((input.split('=')
-                                        for input in input_string.split(';')
-                                        if input))
+                    parsed_dict.update((i.split('=')
+                                        for i in input_string.split(';')
+                                        if i))
             except Exception as exc:
                 raise AriaCliFormatInputsError(str(exc), inputs=input_string)
 
@@ -111,8 +104,8 @@ class BaseCommand(LoggerMixin):
             self.logger.info('Processing inputs source: {0}'.format(input_path))
             try:
                 with open(input_path) as input_file:
-                    content = safe_load(input_file)
-            except YAMLError as exc:
+                    content = yaml.safe_load(input_file)
+            except yaml.YAMLError as exc:
                 raise AriaCliYAMLInputsError(
                     '"{0}" is not a valid YAML. {1}'.format(input_path, str(exc)))
             if isinstance(content, dict):
@@ -136,9 +129,153 @@ class BaseCommand(LoggerMixin):
         return parsed_dict
 
 
+class ParseCommand(BaseCommand):
+    """
+    :code:`parse` command.
+    
+    Given a blueprint, emits information in human-readable, JSON, or YAML format from various
phases
+    of the ARIA parser.
+    """
+    
+    def __call__(self, args_namespace, unknown_args):
+        super(ParseCommand, self).__call__(args_namespace, unknown_args)
+
+        if args_namespace.prefix:
+            for prefix in args_namespace.prefix:
+                extension.parser.uri_loader_prefix().append(prefix)
+
+        cachedmethod.ENABLED = args_namespace.cached_methods
+
+        context = ParseCommand.create_context_from_namespace(args_namespace)
+        context.args = unknown_args
+
+        consumer = ConsumerChain(context, (Read, Validate))
+
+        consumer_class_name = args_namespace.consumer
+        dumper = None
+        if consumer_class_name == 'validate':
+            dumper = None
+        elif consumer_class_name == 'presentation':
+            dumper = consumer.consumers[0]
+        elif consumer_class_name == 'model':
+            consumer.append(Model)
+        elif consumer_class_name == 'types':
+            consumer.append(Model, Types)
+        elif consumer_class_name == 'instance':
+            consumer.append(Model, Inputs, Instance)
+        else:
+            consumer.append(Model, Inputs, Instance)
+            consumer.append(import_fullname(consumer_class_name))
+
+        if dumper is None:
+            # Default to last consumer
+            dumper = consumer.consumers[-1]
+
+        consumer.consume()
+
+        if not context.validation.dump_issues():
+            dumper.dump()
+            exit(1)
+
+    @staticmethod
+    def create_context_from_namespace(namespace, **kwargs):
+        args = vars(namespace).copy()
+        args.update(kwargs)
+        return ParseCommand.create_context(**args)
+
+    @staticmethod
+    def create_context(uri,
+                       loader_source,
+                       reader_source,
+                       presenter_source,
+                       presenter,
+                       debug,
+                       **kwargs):
+        context = ConsumptionContext()
+        context.loading.loader_source = import_fullname(loader_source)()
+        context.reading.reader_source = import_fullname(reader_source)()
+        context.presentation.location = UriLocation(uri) if isinstance(uri, basestring) else
uri
+        context.presentation.presenter_source = import_fullname(presenter_source)()
+        context.presentation.presenter_class = import_fullname(presenter)
+        context.presentation.print_exceptions = debug
+        return context
+
+
+class WorkflowCommand(BaseCommand):
+    """
+    :code:`workflow` command.
+    """
+
+    WORKFLOW_POLICY_INTERNAL_PROPERTIES = ('function', 'implementation', 'dependencies')
+    
+    def __call__(self, args_namespace, unknown_args):
+        super(WorkflowCommand, self).__call__(args_namespace, unknown_args)
+
+        deployment_id = args_namespace.deployment_id or 1 
+        context = self._parse(args_namespace.uri)
+        workflow_fn, inputs = self._get_workflow(context, args_namespace.workflow)
+        self._run(context, args_namespace.workflow, workflow_fn, inputs, deployment_id)
+    
+    def _parse(self, uri):
+        # Parse
+        context = ConsumptionContext()
+        context.presentation.location = UriLocation(uri)
+        consumer = ConsumerChain(context, (Read, Validate, Model, Inputs, Instance))
+        consumer.consume()
+
+        if context.validation.dump_issues():
+            exit(1)
+        
+        return context
+    
+    def _get_workflow(self, context, workflow_name):
+        if workflow_name in BUILTIN_WORKFLOWS:
+            workflow_fn = import_fullname('aria.orchestrator.workflows.builtin.%s' % workflow_name)
+            inputs = {}
+        else:
+            try:
+                policy = context.modeling.instance.policies[workflow_name]
+            except KeyError:
+                raise AttributeError('workflow policy does not exist: "%s"' % workflow_name)
+            if context.modeling.policy_types.get_role(policy.type_name) != 'workflow':
+                raise AttributeError('policy is not a workflow: "%s"' % workflow_name)
+    
+            try:
+                sys.path.append(policy.properties['implementation'].value)
+            except KeyError:
+                pass
+    
+            workflow_fn = import_fullname(policy.properties['function'].value)
+    
+            for k in policy.properties:
+                if k in WORKFLOW_DECORATOR_RESERVED_ARGUMENTS:
+                    raise AttributeError('workflow policy "%s" defines a reserved property:
"%s"' %
+                                         (workflow_name, k))
+    
+            inputs = OrderedDict([
+                (k, v.value) for k, v in policy.properties.iteritems()
+                if k not in WorkflowCommand.WORKFLOW_POLICY_INTERNAL_PROPERTIES
+            ])
+        
+        return workflow_fn, inputs
+    
+    def _run(self, context, workflow_name, workflow_fn, inputs, deployment_id):
+        # Storage
+        def _initialize_storage(model_storage):
+            initialize_storage(context, model_storage, deployment_id)
+
+        # Create runner
+        runner = Runner(workflow_name, workflow_fn, inputs, _initialize_storage, deployment_id)
+        
+        # Run
+        runner.run()
+   
+
 class InitCommand(BaseCommand):
     """
-    ``init`` command implementation
+    :code:`init` command.
+    
+    Broken. Currently maintained for reference.
     """
 
     _IN_VIRTUAL_ENV = hasattr(sys, 'real_prefix')
@@ -216,7 +353,9 @@ class InitCommand(BaseCommand):
 
 class ExecuteCommand(BaseCommand):
     """
-    ``execute`` command implementation
+    :code:`execute` command.
+
+    Broken. Currently maintained for reference.
     """
 
     def __call__(self, args_namespace, unknown_args):
@@ -310,98 +449,7 @@ class ExecuteCommand(BaseCommand):
             raise
 
 
-class ParseCommand(BaseCommand):
-    def __call__(self, args_namespace, unknown_args):
-        super(ParseCommand, self).__call__(args_namespace, unknown_args)
-
-        if args_namespace.prefix:
-            for prefix in args_namespace.prefix:
-                extension.parser.uri_loader_prefix().append(prefix)
-
-        cachedmethod.ENABLED = args_namespace.cached_methods
-
-        context = ParseCommand.create_context_from_namespace(args_namespace)
-        context.args = unknown_args
-
-        consumer = ConsumerChain(context, (Read, Validate))
-
-        consumer_class_name = args_namespace.consumer
-        dumper = None
-        if consumer_class_name == 'presentation':
-            dumper = consumer.consumers[0]
-        elif consumer_class_name == 'model':
-            consumer.append(Model)
-        elif consumer_class_name == 'types':
-            consumer.append(Model, Types)
-        elif consumer_class_name == 'instance':
-            consumer.append(Model, Inputs, Instance)
-        else:
-            consumer.append(Model, Inputs, Instance)
-            consumer.append(import_fullname(consumer_class_name))
-
-        if dumper is None:
-            # Default to last consumer
-            dumper = consumer.consumers[-1]
-
-        consumer.consume()
-
-        if not context.validation.dump_issues():
-            dumper.dump()
-
-    @staticmethod
-    def create_context_from_namespace(namespace, **kwargs):
-        args = vars(namespace).copy()
-        args.update(kwargs)
-        return ParseCommand.create_context(**args)
-
-    @staticmethod
-    def create_context(uri,
-                       loader_source,
-                       reader_source,
-                       presenter_source,
-                       presenter,
-                       debug,
-                       **kwargs):
-        context = ConsumptionContext()
-        context.loading.loader_source = import_fullname(loader_source)()
-        context.reading.reader_source = import_fullname(reader_source)()
-        context.presentation.location = UriLocation(uri) if isinstance(uri, basestring) else
uri
-        context.presentation.presenter_source = import_fullname(presenter_source)()
-        context.presentation.presenter_class = import_fullname(presenter)
-        context.presentation.print_exceptions = debug
-        return context
-
-
-class SpecCommand(BaseCommand):
-    def __call__(self, args_namespace, unknown_args):
-        super(SpecCommand, self).__call__(args_namespace, unknown_args)
-
-        # Make sure that all @dsl_specification decorators are processed
-        for pkg in extension.parser.specification_package():
-            import_modules(pkg)
-
-        # TODO: scan YAML documents as well
-
-        if args_namespace.csv:
-            writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL)
-            writer.writerow(('Specification', 'Section', 'Code', 'URL'))
-            for spec, sections in iter_specifications():
-                for section, details in sections:
-                    writer.writerow((spec, section, details['code'], details['url']))
-
-        else:
-            for spec, sections in iter_specifications():
-                puts(Colored.cyan(spec))
-                with indent(2):
-                    for section, details in sections:
-                        puts(Colored.blue(section))
-                        with indent(2):
-                            for k, v in details.iteritems():
-                                puts('%s: %s' % (Colored.magenta(k), v))
-
-
 class BaseCSARCommand(BaseCommand):
-
     @staticmethod
     def _parse_and_dump(reader):
         context = ConsumptionContext()
@@ -439,7 +487,6 @@ class BaseCSARCommand(BaseCommand):
 
 
 class CSARCreateCommand(BaseCSARCommand):
-
     def __call__(self, args_namespace, unknown_args):
         super(CSARCreateCommand, self).__call__(args_namespace, unknown_args)
         csar.write(
@@ -451,7 +498,6 @@ class CSARCreateCommand(BaseCSARCommand):
 
 
 class CSAROpenCommand(BaseCSARCommand):
-
     def __call__(self, args_namespace, unknown_args):
         super(CSAROpenCommand, self).__call__(args_namespace, unknown_args)
         self._read(
@@ -460,7 +506,40 @@ class CSAROpenCommand(BaseCSARCommand):
 
 
 class CSARValidateCommand(BaseCSARCommand):
-
     def __call__(self, args_namespace, unknown_args):
         super(CSARValidateCommand, self).__call__(args_namespace, unknown_args)
         self._validate(args_namespace.source)
+
+
+class SpecCommand(BaseCommand):
+    """
+    :code:`spec` command.
+    
+    Emits all uses of :code:`@dsl_specification` in the codebase, in human-readable or CSV
format.
+    """
+    
+    def __call__(self, args_namespace, unknown_args):
+        super(SpecCommand, self).__call__(args_namespace, unknown_args)
+
+        # Make sure that all @dsl_specification decorators are processed
+        for pkg in extension.parser.specification_package():
+            import_modules(pkg)
+
+        # TODO: scan YAML documents as well
+
+        if args_namespace.csv:
+            writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL)
+            writer.writerow(('Specification', 'Section', 'Code', 'URL'))
+            for spec, sections in iter_specifications():
+                for section, details in sections:
+                    writer.writerow((spec, section, details['code'], details['url']))
+
+        else:
+            for spec, sections in iter_specifications():
+                puts(Colored.cyan(spec))
+                with indent(2):
+                    for section, details in sections:
+                        puts(Colored.blue(section))
+                        with indent(2):
+                            for k, v in details.iteritems():
+                                puts('%s: %s' % (Colored.magenta(k), v))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/cli/csar.py
----------------------------------------------------------------------
diff --git a/aria/cli/csar.py b/aria/cli/csar.py
index 933df17..b185f46 100644
--- a/aria/cli/csar.py
+++ b/aria/cli/csar.py
@@ -19,7 +19,7 @@ import tempfile
 import zipfile
 
 import requests
-from ruamel import yaml
+from ruamel import yaml # @UnresolvedImport
 
 
 META_FILE = 'TOSCA-Metadata/TOSCA.meta'

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/orchestrator/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/__init__.py b/aria/orchestrator/__init__.py
index 90d6442..097ee1d 100644
--- a/aria/orchestrator/__init__.py
+++ b/aria/orchestrator/__init__.py
@@ -15,7 +15,7 @@
 """
 Aria orchestrator
 """
-from .decorators import workflow, operation
+from .decorators import workflow, operation, WORKFLOW_DECORATOR_RESERVED_ARGUMENTS
 
 from . import (
     context,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/orchestrator/decorators.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/decorators.py b/aria/orchestrator/decorators.py
index 6e8ab39..bbe43f4 100644
--- a/aria/orchestrator/decorators.py
+++ b/aria/orchestrator/decorators.py
@@ -26,6 +26,9 @@ from . import context
 from .workflows.api import task_graph
 
 
+WORKFLOW_DECORATOR_RESERVED_ARGUMENTS = ('ctx', 'graph')
+
+
 def workflow(func=None, suffix_template=''):
     """
     Workflow decorator

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/parser/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/__init__.py b/aria/parser/modeling/__init__.py
index bc4373c..a1efd9f 100644
--- a/aria/parser/modeling/__init__.py
+++ b/aria/parser/modeling/__init__.py
@@ -24,6 +24,7 @@ from .model_elements import (ServiceModel, NodeTemplate, RequirementTemplate,
Ca
                              GroupPolicyTemplate, GroupPolicyTriggerTemplate, MappingTemplate,
                              SubstitutionTemplate, InterfaceTemplate, OperationTemplate)
 from .types import TypeHierarchy, Type, RelationshipType, PolicyType, PolicyTriggerType
+from .storage import initialize_storage
 
 __all__ = (
     'CannotEvaluateFunctionException',
@@ -65,4 +66,5 @@ __all__ = (
     'Type',
     'RelationshipType',
     'PolicyType',
-    'PolicyTriggerType')
+    'PolicyTriggerType',
+    'initialize_storage')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/aria/parser/modeling/types.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/types.py b/aria/parser/modeling/types.py
index e6249ef..0a232fc 100644
--- a/aria/parser/modeling/types.py
+++ b/aria/parser/modeling/types.py
@@ -29,6 +29,7 @@ class Type(object):
 
         self.name = name
         self.description = None
+        self.role = None
         self.children = StrictList(value_class=Type)
 
     def get_parent(self, name):
@@ -40,6 +41,13 @@ class Type(object):
                 return parent
         return None
 
+    def is_descendant(self, base_name, name):
+        base = self.get_descendant(base_name)
+        if base is not None:
+            if base.get_descendant(name) is not None:
+                return True
+        return False
+
     def get_descendant(self, name):
         if self.name == name:
             return self
@@ -49,24 +57,28 @@ class Type(object):
                 return found
         return None
 
-    def is_descendant(self, base_name, name):
-        base = self.get_descendant(base_name)
-        if base is not None:
-            if base.get_descendant(name) is not None:
-                return True
-        return False
-
     def iter_descendants(self):
         for child in self.children:
             yield child
             for descendant in child.iter_descendants():
                 yield descendant
 
+    def get_role(self, name):
+        def _get_role(the_type):
+            if the_type is None:
+                return None
+            elif the_type.role is None:
+                return _get_role(self.get_parent(the_type.name))
+            return the_type.role
+
+        return _get_role(self.get_descendant(name))
+
     @property
     def as_raw(self):
         return OrderedDict((
             ('name', self.name),
-            ('description', self.description)))
+            ('description', self.description),
+            ('role', self.role)))
 
     def dump(self, context):
         if self.name:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/44478293/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index 5c3206b..811da19 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -330,6 +330,7 @@ def create_types(context, root, types, normalize=None):
                     model = Type(the_type._name)
                 if the_type.description:
                     model.description = the_type.description.value
+                model.role = the_type._get_extension('role')
                 if parent_type is None:
                     root.children.append(model)
                 else:


Mime
View raw message