You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by ar...@apache.org on 2017/09/06 17:49:13 UTC
[64/70] incubator-ariatosca-website git commit: Adding Sphinx based
Docs minisite
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/types.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/modeling/types.py b/apache-ariatosca-0.1.1/aria/modeling/types.py
deleted file mode 100644
index c34326e..0000000
--- a/apache-ariatosca-0.1.1/aria/modeling/types.py
+++ /dev/null
@@ -1,318 +0,0 @@
-# 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.
-
-"""
-Allows JSON-serializable collections to be used as SQLAlchemy column types.
-"""
-
-import json
-from collections import namedtuple
-
-from sqlalchemy import (
- TypeDecorator,
- VARCHAR,
- event
-)
-from sqlalchemy.ext import mutable
-from ruamel import yaml
-
-from . import exceptions
-
-
-class _MutableType(TypeDecorator):
- """
- Dict representation of type.
- """
- @property
- def python_type(self):
- raise NotImplementedError
-
- def process_literal_param(self, value, dialect):
- pass
-
- impl = VARCHAR
-
- def process_bind_param(self, value, dialect):
- if value is not None:
- value = json.dumps(value)
- return value
-
- def process_result_value(self, value, dialect):
- if value is not None:
- value = json.loads(value)
- return value
-
-
-class Dict(_MutableType):
- """
- JSON-serializable dict type for SQLAlchemy columns.
- """
- @property
- def python_type(self):
- return dict
-
-
-class List(_MutableType):
- """
- JSON-serializable list type for SQLAlchemy columns.
- """
- @property
- def python_type(self):
- return list
-
-
-class _StrictDictMixin(object):
-
- @classmethod
- def coerce(cls, key, value):
- """
- Convert plain dictionaries to MutableDict.
- """
- try:
- if not isinstance(value, cls):
- if isinstance(value, dict):
- for k, v in value.items():
- cls._assert_strict_key(k)
- cls._assert_strict_value(v)
- return cls(value)
- return mutable.MutableDict.coerce(key, value)
- else:
- return value
- except ValueError as e:
- raise exceptions.ValueFormatException('could not coerce to MutableDict', cause=e)
-
- def __setitem__(self, key, value):
- self._assert_strict_key(key)
- self._assert_strict_value(value)
- super(_StrictDictMixin, self).__setitem__(key, value)
-
- def setdefault(self, key, value):
- self._assert_strict_key(key)
- self._assert_strict_value(value)
- super(_StrictDictMixin, self).setdefault(key, value)
-
- def update(self, *args, **kwargs):
- for k, v in kwargs.items():
- self._assert_strict_key(k)
- self._assert_strict_value(v)
- super(_StrictDictMixin, self).update(*args, **kwargs)
-
- @classmethod
- def _assert_strict_key(cls, key):
- if cls._key_cls is not None and not isinstance(key, cls._key_cls):
- raise exceptions.ValueFormatException('key type was set strictly to {0}, but was {1}'
- .format(cls._key_cls, type(key)))
-
- @classmethod
- def _assert_strict_value(cls, value):
- if cls._value_cls is not None and not isinstance(value, cls._value_cls):
- raise exceptions.ValueFormatException('value type was set strictly to {0}, but was {1}'
- .format(cls._value_cls, type(value)))
-
-
-class _MutableDict(mutable.MutableDict):
- """
- Enables tracking for dict values.
- """
-
- @classmethod
- def coerce(cls, key, value):
- """
- Convert plain dictionaries to MutableDict.
- """
- try:
- return mutable.MutableDict.coerce(key, value)
- except ValueError as e:
- raise exceptions.ValueFormatException('could not coerce value', cause=e)
-
-
-class _StrictListMixin(object):
-
- @classmethod
- def coerce(cls, key, value):
- "Convert plain dictionaries to MutableDict."
- try:
- if not isinstance(value, cls):
- if isinstance(value, list):
- for item in value:
- cls._assert_item(item)
- return cls(value)
- return mutable.MutableList.coerce(key, value)
- else:
- return value
- except ValueError as e:
- raise exceptions.ValueFormatException('could not coerce to MutableDict', cause=e)
-
- def __setitem__(self, index, value):
- """
- Detect list set events and emit change events.
- """
- self._assert_item(value)
- super(_StrictListMixin, self).__setitem__(index, value)
-
- def append(self, item):
- self._assert_item(item)
- super(_StrictListMixin, self).append(item)
-
- def extend(self, item):
- self._assert_item(item)
- super(_StrictListMixin, self).extend(item)
-
- def insert(self, index, item):
- self._assert_item(item)
- super(_StrictListMixin, self).insert(index, item)
-
- @classmethod
- def _assert_item(cls, item):
- if cls._item_cls is not None and not isinstance(item, cls._item_cls):
- raise exceptions.ValueFormatException('key type was set strictly to {0}, but was {1}'
- .format(cls._item_cls, type(item)))
-
-
-class _MutableList(mutable.MutableList):
-
- @classmethod
- def coerce(cls, key, value):
- """
- Convert plain dictionaries to MutableDict.
- """
- try:
- return mutable.MutableList.coerce(key, value)
- except ValueError as e:
- raise exceptions.ValueFormatException('could not coerce to MutableDict', cause=e)
-
-
-_StrictDictID = namedtuple('_StrictDictID', 'key_cls, value_cls')
-_StrictValue = namedtuple('_StrictValue', 'type_cls, listener_cls')
-
-class _StrictDict(object):
- """
- This entire class functions as a factory for strict dicts and their listeners. No type class,
- and no listener type class is created more than once. If a relevant type class exists it is
- returned.
- """
- _strict_map = {}
-
- def __call__(self, key_cls=None, value_cls=None):
- strict_dict_map_key = _StrictDictID(key_cls=key_cls, value_cls=value_cls)
- if strict_dict_map_key not in self._strict_map:
- key_cls_name = getattr(key_cls, '__name__', str(key_cls))
- value_cls_name = getattr(value_cls, '__name__', str(value_cls))
- # Creating the type class itself. this class would be returned (used by the SQLAlchemy
- # Column).
- strict_dict_cls = type(
- 'StrictDict_{0}_{1}'.format(key_cls_name, value_cls_name),
- (Dict, ),
- {}
- )
- # Creating the type listening class.
- # The new class inherits from both the _MutableDict class and the _StrictDictMixin,
- # while setting the necessary _key_cls and _value_cls as class attributes.
- listener_cls = type(
- 'StrictMutableDict_{0}_{1}'.format(key_cls_name, value_cls_name),
- (_StrictDictMixin, _MutableDict),
- {'_key_cls': key_cls, '_value_cls': value_cls}
- )
- yaml.representer.RoundTripRepresenter.add_representer(
- listener_cls, yaml.representer.RoundTripRepresenter.represent_list)
- self._strict_map[strict_dict_map_key] = _StrictValue(type_cls=strict_dict_cls,
- listener_cls=listener_cls)
-
- return self._strict_map[strict_dict_map_key].type_cls
-
-
-StrictDict = _StrictDict()
-"""
-JSON-serializable strict dict type for SQLAlchemy columns.
-
-:param key_cls:
-:param value_cls:
-"""
-
-
-class _StrictList(object):
- """
- This entire class functions as a factory for strict lists and their listeners. No type class,
- and no listener type class is created more than once. If a relevant type class exists it is
- returned.
- """
- _strict_map = {}
-
- def __call__(self, item_cls=None):
-
- if item_cls not in self._strict_map:
- item_cls_name = getattr(item_cls, '__name__', str(item_cls))
- # Creating the type class itself. this class would be returned (used by the SQLAlchemy
- # Column).
- strict_list_cls = type(
- 'StrictList_{0}'.format(item_cls_name),
- (List, ),
- {}
- )
- # Creating the type listening class.
- # The new class inherits from both the _MutableList class and the _StrictListMixin,
- # while setting the necessary _item_cls as class attribute.
- listener_cls = type(
- 'StrictMutableList_{0}'.format(item_cls_name),
- (_StrictListMixin, _MutableList),
- {'_item_cls': item_cls}
- )
- yaml.representer.RoundTripRepresenter.add_representer(
- listener_cls, yaml.representer.RoundTripRepresenter.represent_list)
- self._strict_map[item_cls] = _StrictValue(type_cls=strict_list_cls,
- listener_cls=listener_cls)
-
- return self._strict_map[item_cls].type_cls
-
-
-StrictList = _StrictList()
-"""
-JSON-serializable strict list type for SQLAlchemy columns.
-
-:param item_cls:
-"""
-
-
-def _mutable_association_listener(mapper, cls):
- strict_dict_type_to_listener = \
- dict((v.type_cls, v.listener_cls) for v in _StrictDict._strict_map.values())
-
- strict_list_type_to_listener = \
- dict((v.type_cls, v.listener_cls) for v in _StrictList._strict_map.values())
-
- for prop in mapper.column_attrs:
- column_type = prop.columns[0].type
- # Dict Listeners
- if type(column_type) in strict_dict_type_to_listener: # pylint: disable=unidiomatic-typecheck
- strict_dict_type_to_listener[type(column_type)].associate_with_attribute(
- getattr(cls, prop.key))
- elif isinstance(column_type, Dict):
- _MutableDict.associate_with_attribute(getattr(cls, prop.key))
-
- # List Listeners
- if type(column_type) in strict_list_type_to_listener: # pylint: disable=unidiomatic-typecheck
- strict_list_type_to_listener[type(column_type)].associate_with_attribute(
- getattr(cls, prop.key))
- elif isinstance(column_type, List):
- _MutableList.associate_with_attribute(getattr(cls, prop.key))
-
-
-_LISTENER_ARGS = (mutable.mapper, 'mapper_configured', _mutable_association_listener)
-
-
-def _register_mutable_association_listener():
- event.listen(*_LISTENER_ARGS)
-
-_register_mutable_association_listener()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/modeling/utils.py b/apache-ariatosca-0.1.1/aria/modeling/utils.py
deleted file mode 100644
index 5193cd9..0000000
--- a/apache-ariatosca-0.1.1/aria/modeling/utils.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# 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.
-
-"""
-Miscellaneous modeling utilities.
-"""
-
-import os
-from json import JSONEncoder
-from StringIO import StringIO
-
-from . import exceptions
-from ..parser.consumption import ConsumptionContext
-from ..utils.console import puts
-from ..utils.type import validate_value_type
-from ..utils.collections import OrderedDict
-from ..utils.formatting import string_list_as_string
-
-
-class ModelJSONEncoder(JSONEncoder):
- """
- JSON encoder that automatically unwraps ``value`` attributes.
- """
- def __init__(self, *args, **kwargs):
- # Just here to make sure Sphinx doesn't grab the base constructor's docstring
- super(ModelJSONEncoder, self).__init__(*args, **kwargs)
-
- def default(self, o): # pylint: disable=method-hidden
- from .mixins import ModelMixin
- if isinstance(o, ModelMixin):
- if hasattr(o, 'value'):
- dict_to_return = o.to_dict(fields=('value',))
- return dict_to_return['value']
- else:
- return o.to_dict()
- else:
- return JSONEncoder.default(self, o)
-
-
-class NodeTemplateContainerHolder(object):
- """
- Wrapper that allows using a :class:`~aria.modeling.models.NodeTemplate` model directly as the
- ``container_holder`` input for :func:`~aria.modeling.functions.evaluate`.
- """
-
- def __init__(self, node_template):
- self.container = node_template
- self.service = None
-
- @property
- def service_template(self):
- return self.container.service_template
-
-
-def merge_parameter_values(parameter_values, declared_parameters, model_cls):
- """
- Merges parameter values according to those declared by a type.
-
- Exceptions will be raised for validation errors.
-
- :param parameter_values: provided parameter values or None
- :type parameter_values: {:obj:`basestring`: object}
- :param declared_parameters: declared parameters
- :type declared_parameters: {:obj:`basestring`: :class:`~aria.modeling.models.Parameter`}
- :return: the merged parameters
- :rtype: {:obj:`basestring`: :class:`~aria.modeling.models.Parameter`}
- :raises ~aria.modeling.exceptions.UndeclaredParametersException: if a key in
- ``parameter_values`` does not exist in ``declared_parameters``
- :raises ~aria.modeling.exceptions.MissingRequiredParametersException: if a key in
- ``declared_parameters`` does not exist in ``parameter_values`` and also has no default value
- :raises ~aria.modeling.exceptions.ParametersOfWrongTypeException: if a value in
- ``parameter_values`` does not match its type in ``declared_parameters``
- """
-
- parameter_values = parameter_values or {}
-
- undeclared_names = list(set(parameter_values.keys()).difference(declared_parameters.keys()))
- if undeclared_names:
- raise exceptions.UndeclaredParametersException(
- 'Undeclared parameters have been provided: {0}; Declared: {1}'
- .format(string_list_as_string(undeclared_names),
- string_list_as_string(declared_parameters.keys())))
-
- parameters = OrderedDict()
-
- missing_names = []
- wrong_type_values = OrderedDict()
- for declared_parameter_name, declared_parameter in declared_parameters.iteritems():
- if declared_parameter_name in parameter_values:
- # Value has been provided
- value = parameter_values[declared_parameter_name]
-
- # Validate type
- type_name = declared_parameter.type_name
- try:
- validate_value_type(value, type_name)
- except ValueError:
- wrong_type_values[declared_parameter_name] = type_name
- except RuntimeError:
- # TODO: This error shouldn't be raised (or caught), but right now we lack support
- # for custom data_types, which will raise this error. Skipping their validation.
- pass
-
- # Wrap in Parameter model
- parameters[declared_parameter_name] = model_cls( # pylint: disable=unexpected-keyword-arg
- name=declared_parameter_name,
- type_name=type_name,
- description=declared_parameter.description,
- value=value)
- elif declared_parameter.value is not None:
- # Copy default value from declaration
- parameters[declared_parameter_name] = declared_parameter.instantiate(None)
- else:
- # Required value has not been provided
- missing_names.append(declared_parameter_name)
-
- if missing_names:
- raise exceptions.MissingRequiredParametersException(
- 'Declared parameters {0} have not been provided values'
- .format(string_list_as_string(missing_names)))
-
- if wrong_type_values:
- error_message = StringIO()
- for param_name, param_type in wrong_type_values.iteritems():
- error_message.write('Parameter "{0}" is not of declared type "{1}"{2}'
- .format(param_name, param_type, os.linesep))
- raise exceptions.ParametersOfWrongTypeException(error_message.getvalue())
-
- return parameters
-
-
-def coerce_dict_values(the_dict, report_issues=False):
- if not the_dict:
- return
- coerce_list_values(the_dict.itervalues(), report_issues)
-
-
-def coerce_list_values(the_list, report_issues=False):
- if not the_list:
- return
- for value in the_list:
- value.coerce_values(report_issues)
-
-
-def validate_dict_values(the_dict):
- if not the_dict:
- return
- validate_list_values(the_dict.itervalues())
-
-
-def validate_list_values(the_list):
- if not the_list:
- return
- for value in the_list:
- value.validate()
-
-
-def instantiate_dict(container, the_dict, from_dict):
- if not from_dict:
- return
- for name, value in from_dict.iteritems():
- value = value.instantiate(container)
- if value is not None:
- the_dict[name] = value
-
-
-def instantiate_list(container, the_list, from_list):
- if not from_list:
- return
- for value in from_list:
- value = value.instantiate(container)
- if value is not None:
- the_list.append(value)
-
-
-def dump_list_values(the_list, name):
- if not the_list:
- return
- puts('%s:' % name)
- context = ConsumptionContext.get_thread_local()
- with context.style.indent:
- for value in the_list:
- value.dump()
-
-
-def dump_dict_values(the_dict, name):
- if not the_dict:
- return
- dump_list_values(the_dict.itervalues(), name)
-
-
-def dump_interfaces(interfaces, name='Interfaces'):
- if not interfaces:
- return
- puts('%s:' % name)
- context = ConsumptionContext.get_thread_local()
- with context.style.indent:
- for interface in interfaces.itervalues():
- interface.dump()
-
-
-class classproperty(object): # pylint: disable=invalid-name
- def __init__(self, f):
- self._func = f
- self.__doct__ = f.__doc__
-
- def __get__(self, instance, owner):
- return self._func(owner)
-
-
-def fix_doc(cls):
- """
- Class decorator to use the last base class's docstring and make sure Sphinx doesn't grab the
- base constructor's docstring.
- """
- original_init = cls.__init__
- def init(*args, **kwargs):
- original_init(*args, **kwargs)
-
- cls.__init__ = init
- cls.__doc__ = cls.__bases__[-1].__doc__
-
- return cls
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/context/common.py b/apache-ariatosca-0.1.1/aria/orchestrator/context/common.py
deleted file mode 100644
index f400142..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/context/common.py
+++ /dev/null
@@ -1,200 +0,0 @@
-# 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.
-
-"""
-Common code for contexts.
-"""
-
-import logging
-from contextlib import contextmanager
-from functools import partial
-
-import jinja2
-
-from aria import (
- logger as aria_logger,
- modeling
-)
-from aria.storage import exceptions
-
-from ...utils.uuid import generate_uuid
-
-
-class BaseContext(object):
- """
- Base class for contexts.
- """
-
- INSTRUMENTATION_FIELDS = (
- modeling.models.Node.attributes,
- modeling.models.Node.properties,
- modeling.models.NodeTemplate.attributes,
- modeling.models.NodeTemplate.properties
- )
-
- class PrefixedLogger(object):
- def __init__(self, base_logger, task_id=None):
- self._logger = base_logger
- self._task_id = task_id
-
- def __getattr__(self, attribute):
- if attribute.upper() in logging._levelNames:
- return partial(self._logger_with_task_id, _level=attribute)
- else:
- return getattr(self._logger, attribute)
-
- def _logger_with_task_id(self, *args, **kwargs):
- level = kwargs.pop('_level')
- kwargs.setdefault('extra', {})['task_id'] = self._task_id
- return getattr(self._logger, level)(*args, **kwargs)
-
- def __init__(self,
- name,
- service_id,
- model_storage,
- resource_storage,
- execution_id,
- workdir=None,
- **kwargs):
- super(BaseContext, self).__init__(**kwargs)
- self._name = name
- self._id = generate_uuid(variant='uuid')
- self._model = model_storage
- self._resource = resource_storage
- self._service_id = service_id
- self._workdir = workdir
- self._execution_id = execution_id
- self.logger = None
-
- def _register_logger(self, level=None, task_id=None):
- self.logger = self.PrefixedLogger(
- logging.getLogger(aria_logger.TASK_LOGGER_NAME), task_id=task_id)
- self.logger.setLevel(level or logging.DEBUG)
- if not self.logger.handlers:
- self.logger.addHandler(self._get_sqla_handler())
-
- def _get_sqla_handler(self):
- return aria_logger.create_sqla_log_handler(model=self._model,
- log_cls=modeling.models.Log,
- execution_id=self._execution_id)
-
- def __repr__(self):
- return (
- '{name}(name={self.name}, '
- 'deployment_id={self._service_id}, '
- .format(name=self.__class__.__name__, self=self))
-
- @contextmanager
- def logging_handlers(self, handlers=None):
- handlers = handlers or []
- try:
- for handler in handlers:
- self.logger.addHandler(handler)
- yield self.logger
- finally:
- for handler in handlers:
- self.logger.removeHandler(handler)
-
- @property
- def model(self):
- """
- Storage model API ("MAPI").
- """
- return self._model
-
- @property
- def resource(self):
- """
- Storage resource API ("RAPI").
- """
- return self._resource
-
- @property
- def service_template(self):
- """
- Service template model.
- """
- return self.service.service_template
-
- @property
- def service(self):
- """
- Service instance model.
- """
- return self.model.service.get(self._service_id)
-
- @property
- def name(self):
- """
- Operation name.
- """
- return self._name
-
- @property
- def id(self):
- """
- Operation ID.
- """
- return self._id
-
- def download_resource(self, destination, path=None):
- """
- Download a service template resource from the storage resource API ("RAPI").
- """
- try:
- self.resource.service.download(entry_id=str(self.service.id),
- destination=destination,
- path=path)
- except exceptions.StorageError:
- self.resource.service_template.download(entry_id=str(self.service_template.id),
- destination=destination,
- path=path)
-
- def download_resource_and_render(self, destination, path=None, variables=None):
- """
- Downloads a service template resource from the resource storage and renders its content as a
- Jinja template using the provided variables. ``ctx`` is available to the template without
- providing it explicitly.
- """
- resource_content = self.get_resource(path=path)
- resource_content = self._render_resource(resource_content=resource_content,
- variables=variables)
- with open(destination, 'wb') as f:
- f.write(resource_content)
-
- def get_resource(self, path=None):
- """
- Reads a service instance resource as string from the resource storage.
- """
- try:
- return self.resource.service.read(entry_id=str(self.service.id), path=path)
- except exceptions.StorageError:
- return self.resource.service_template.read(entry_id=str(self.service_template.id),
- path=path)
-
- def get_resource_and_render(self, path=None, variables=None):
- """
- Reads a service instance resource as string from the resource storage and renders it as a
- Jinja template using the provided variables. ``ctx`` is available to the template without
- providing it explicitly.
- """
- resource_content = self.get_resource(path=path)
- return self._render_resource(resource_content=resource_content, variables=variables)
-
- def _render_resource(self, resource_content, variables):
- variables = variables or {}
- variables.setdefault('ctx', self)
- resource_template = jinja2.Template(resource_content)
- return resource_template.render(variables)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/context/exceptions.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/context/exceptions.py b/apache-ariatosca-0.1.1/aria/orchestrator/context/exceptions.py
deleted file mode 100644
index e46e2b1..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/context/exceptions.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.
-
-"""
-Context exceptions.
-"""
-
-from ..exceptions import OrchestratorError
-
-
-class ContextException(OrchestratorError):
- """
- Context based exception
- """
- pass
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/context/operation.py b/apache-ariatosca-0.1.1/aria/orchestrator/context/operation.py
deleted file mode 100644
index 7d5f40c..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/context/operation.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# 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.
-
-"""
-Operation contexts.
-"""
-
-import threading
-from contextlib import contextmanager
-
-import aria
-from aria.utils import file
-from . import common
-
-
-class BaseOperationContext(common.BaseContext):
- """
- Base class for contexts used during operation creation and execution.
- """
-
- def __init__(self, task_id, actor_id, **kwargs):
- self._task_id = task_id
- self._actor_id = actor_id
- self._thread_local = threading.local()
- self._destroy_session = kwargs.pop('destroy_session', False)
- logger_level = kwargs.pop('logger_level', None)
- super(BaseOperationContext, self).__init__(**kwargs)
- self._register_logger(task_id=self.task.id, level=logger_level)
-
- def __repr__(self):
- details = 'function={task.function}; ' \
- 'operation_arguments={task.arguments}'\
- .format(task=self.task)
- return '{name}({0})'.format(details, name=self.name)
-
- @property
- def task(self):
- """
- The task in the model storage
- :return: Task model
- """
- # SQLAlchemy prevents from accessing an object which was created on a different thread.
- # So we retrieve the object from the storage if the current thread isn't the same as the
- # original thread.
-
- if not hasattr(self._thread_local, 'task'):
- self._thread_local.task = self.model.task.get(self._task_id)
- return self._thread_local.task
-
- @property
- def plugin_workdir(self):
- """
- A work directory that is unique to the plugin and the deployment id
- """
- if self.task.plugin is None:
- return None
- plugin_workdir = '{0}/plugins/{1}/{2}'.format(self._workdir,
- self.service.id,
- self.task.plugin.name)
- file.makedirs(plugin_workdir)
- return plugin_workdir
-
- @property
- def serialization_dict(self):
- context_dict = {
- 'name': self.name,
- 'service_id': self._service_id,
- 'task_id': self._task_id,
- 'actor_id': self._actor_id,
- 'workdir': self._workdir,
- 'model_storage': self.model.serialization_dict if self.model else None,
- 'resource_storage': self.resource.serialization_dict if self.resource else None,
- 'execution_id': self._execution_id,
- 'logger_level': self.logger.level
- }
- return {
- 'context_cls': self.__class__,
- 'context': context_dict
- }
-
- @classmethod
- def instantiate_from_dict(cls, model_storage=None, resource_storage=None, **kwargs):
- if model_storage:
- model_storage = aria.application_model_storage(**model_storage)
- if resource_storage:
- resource_storage = aria.application_resource_storage(**resource_storage)
-
- return cls(model_storage=model_storage,
- resource_storage=resource_storage,
- destroy_session=True,
- **kwargs)
-
- def close(self):
- if self._destroy_session:
- self.model.log._session.remove()
- self.model.log._engine.dispose()
-
- @property
- @contextmanager
- def persist_changes(self):
- yield
- self.model.task.update(self.task)
-
-
-class NodeOperationContext(BaseOperationContext):
- """
- Context for node operations.
- """
-
- @property
- def node_template(self):
- """
- the node of the current operation
- :return:
- """
- return self.node.node_template
-
- @property
- def node(self):
- """
- The node instance of the current operation
- :return:
- """
- return self.model.node.get(self._actor_id)
-
-
-class RelationshipOperationContext(BaseOperationContext):
- """
- Context for relationship operations.
- """
-
- @property
- def source_node_template(self):
- """
- The source node
- :return:
- """
- return self.source_node.node_template
-
- @property
- def source_node(self):
- """
- The source node instance
- :return:
- """
- return self.relationship.source_node
-
- @property
- def target_node_template(self):
- """
- The target node
- :return:
- """
- return self.target_node.node_template
-
- @property
- def target_node(self):
- """
- The target node instance
- :return:
- """
- return self.relationship.target_node
-
- @property
- def relationship(self):
- """
- The relationship instance of the current operation
- :return:
- """
- return self.model.relationship.get(self._actor_id)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/context/toolbelt.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/context/toolbelt.py b/apache-ariatosca-0.1.1/aria/orchestrator/context/toolbelt.py
deleted file mode 100644
index a2e1122..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/context/toolbelt.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# 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.
-
-"""
-Tools for operations.
-"""
-
-from . import operation
-
-
-class NodeToolBelt(object):
- """
- Node operation tool belt.
- """
- def __init__(self, operation_context):
- self._op_context = operation_context
-
- @property
- def host_ip(self):
- """
- The host ip of the current node
- :return:
- """
- assert isinstance(self._op_context, operation.NodeOperationContext)
- return self._op_context.node.host.attributes.get('ip')
-
-
-class RelationshipToolBelt(object):
- """
- Relationship operation tool belt.
- """
- def __init__(self, operation_context):
- self._op_context = operation_context
-
-
-def toolbelt(operation_context):
- """
- Get a toolbelt from to the current operation executor.
-
- :param operation_context:
- """
- if isinstance(operation_context, operation.NodeOperationContext):
- return NodeToolBelt(operation_context)
- elif isinstance(operation_context, operation.RelationshipOperationContext):
- return RelationshipToolBelt(operation_context)
- else:
- raise RuntimeError("Operation context not supported")
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/context/workflow.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/context/workflow.py b/apache-ariatosca-0.1.1/aria/orchestrator/context/workflow.py
deleted file mode 100644
index 738d2fd..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/context/workflow.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# 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.
-
-"""
-Workflow context.
-"""
-
-import threading
-from contextlib import contextmanager
-
-from .exceptions import ContextException
-from .common import BaseContext
-
-
-class WorkflowContext(BaseContext):
- """
- Context used during workflow creation and execution.
- """
- def __init__(self,
- workflow_name,
- parameters=None,
- task_max_attempts=1,
- task_retry_interval=0,
- task_ignore_failure=False,
- *args, **kwargs):
- super(WorkflowContext, self).__init__(*args, **kwargs)
- self._workflow_name = workflow_name
- self._parameters = parameters or {}
- self._task_max_attempts = task_max_attempts
- self._task_retry_interval = task_retry_interval
- self._task_ignore_failure = task_ignore_failure
- self._execution_graph = None
- self._register_logger()
-
- def __repr__(self):
- return (
- '{name}(deployment_id={self._service_id}, '
- 'workflow_name={self._workflow_name}, execution_id={self._execution_id})'.format(
- name=self.__class__.__name__, self=self))
-
- @property
- def workflow_name(self):
- return self._workflow_name
-
- @property
- def execution(self):
- """
- Execution model.
- """
- return self.model.execution.get(self._execution_id)
-
- @execution.setter
- def execution(self, value):
- """
- Stores the execution in the storage model API ("MAPI").
- """
- self.model.execution.put(value)
-
- @property
- def node_templates(self):
- """
- Iterates over nodes templates.
- """
- key = 'service_{0}'.format(self.model.node_template.model_cls.name_column_name())
-
- return self.model.node_template.iter(
- filters={
- key: getattr(self.service, self.service.name_column_name())
- }
- )
-
- @property
- def nodes(self):
- """
- Iterates over nodes.
- """
- key = 'service_{0}'.format(self.model.node.model_cls.name_column_name())
- return self.model.node.iter(
- filters={
- key: getattr(self.service, self.service.name_column_name())
- }
- )
-
- @property
- @contextmanager
- def persist_changes(self):
- yield
- self._model.execution.update(self.execution)
-
-
-class _CurrentContext(threading.local):
- """
- Provides a thread-level context, with sugar for the task MAPI.
- """
-
- def __init__(self):
- super(_CurrentContext, self).__init__()
- self._workflow_context = None
-
- def _set(self, value):
- self._workflow_context = value
-
- def get(self):
- """
- Retrieves the current workflow context.
- """
- if self._workflow_context is not None:
- return self._workflow_context
- raise ContextException("No context was set")
-
- @contextmanager
- def push(self, workflow_context):
- """
- Switches the current context to the provided context.
- """
- prev_workflow_context = self._workflow_context
- self._set(workflow_context)
- try:
- yield self
- finally:
- self._set(prev_workflow_context)
-
-current = _CurrentContext()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/decorators.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/decorators.py b/apache-ariatosca-0.1.1/aria/orchestrator/decorators.py
deleted file mode 100644
index 4b163d6..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/decorators.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# 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.
-
-"""
-Workflow and operation decorators.
-"""
-
-from functools import partial, wraps
-
-from ..utils.validation import validate_function_arguments
-from ..utils.uuid import generate_uuid
-
-from . import context
-from .workflows.api import task_graph
-
-
-WORKFLOW_DECORATOR_RESERVED_ARGUMENTS = set(('ctx', 'graph'))
-OPERATION_DECORATOR_RESERVED_ARGUMENTS = set(('ctx', 'toolbelt'))
-
-
-def workflow(func=None, suffix_template=''):
- """
- Workflow decorator.
- """
- if func is None:
- return partial(workflow, suffix_template=suffix_template)
-
- @wraps(func)
- def _wrapper(ctx, **workflow_parameters):
-
- workflow_name = _generate_name(
- func_name=func.__name__,
- suffix_template=suffix_template,
- ctx=ctx,
- **workflow_parameters)
-
- workflow_parameters.setdefault('ctx', ctx)
- workflow_parameters.setdefault('graph', task_graph.TaskGraph(workflow_name))
- validate_function_arguments(func, workflow_parameters)
- with ctx.model.instrument(*ctx.INSTRUMENTATION_FIELDS):
- with context.workflow.current.push(ctx):
- func(**workflow_parameters)
- return workflow_parameters['graph']
- return _wrapper
-
-
-def operation(func=None, toolbelt=False, suffix_template='', logging_handlers=None):
- """
- Operation decorator.
- """
-
- if func is None:
- return partial(operation,
- suffix_template=suffix_template,
- toolbelt=toolbelt,
- logging_handlers=logging_handlers)
-
- @wraps(func)
- def _wrapper(**func_kwargs):
- ctx = func_kwargs['ctx']
- if toolbelt:
- operation_toolbelt = context.toolbelt(ctx)
- func_kwargs.setdefault('toolbelt', operation_toolbelt)
- validate_function_arguments(func, func_kwargs)
- with ctx.model.instrument(*ctx.INSTRUMENTATION_FIELDS):
- return func(**func_kwargs)
- return _wrapper
-
-
-def _generate_name(func_name, ctx, suffix_template, **custom_kwargs):
- return '{func_name}.{suffix}'.format(
- func_name=func_name,
- suffix=suffix_template.format(ctx=ctx, **custom_kwargs) or generate_uuid(variant='uuid'))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/events.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/events.py b/apache-ariatosca-0.1.1/aria/orchestrator/events.py
deleted file mode 100644
index ef84e5d..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/events.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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.
-
-"""
-Orchestrator events.
-"""
-
-from blinker import signal
-
-# workflow engine task signals:
-sent_task_signal = signal('sent_task_signal')
-start_task_signal = signal('start_task_signal')
-on_success_task_signal = signal('success_task_signal')
-on_failure_task_signal = signal('failure_task_signal')
-
-# workflow engine workflow signals:
-start_workflow_signal = signal('start_workflow_signal')
-on_cancelling_workflow_signal = signal('on_cancelling_workflow_signal')
-on_cancelled_workflow_signal = signal('on_cancelled_workflow_signal')
-on_success_workflow_signal = signal('on_success_workflow_signal')
-on_failure_workflow_signal = signal('on_failure_workflow_signal')
-on_resume_workflow_signal = signal('on_resume_workflow_signal')
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/exceptions.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/exceptions.py b/apache-ariatosca-0.1.1/aria/orchestrator/exceptions.py
deleted file mode 100644
index 384458f..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/exceptions.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# 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.
-
-"""
-Orchestrator exceptions.
-"""
-
-from aria.exceptions import AriaError
-
-
-class OrchestratorError(AriaError):
- """
- Orchestrator based exception
- """
- pass
-
-
-class InvalidPluginError(AriaError):
- """
- Raised when an invalid plugin is validated unsuccessfully
- """
- pass
-
-
-class PluginAlreadyExistsError(AriaError):
- """
- Raised when a plugin with the same package name and package version already exists
- """
- pass
-
-
-class TaskRetryException(RuntimeError):
- """
- Used internally when ctx.task.retry is called
- """
- def __init__(self, message, retry_interval=None):
- super(TaskRetryException, self).__init__(message)
- self.retry_interval = retry_interval
-
-
-class TaskAbortException(RuntimeError):
- """
- Used internally when ctx.task.abort is called
- """
- pass
-
-
-class UndeclaredWorkflowError(AriaError):
- """
- Raised when attempting to execute an undeclared workflow
- """
- pass
-
-
-class ActiveExecutionsError(AriaError):
- """
- Raised when attempting to execute a workflow on a service which already has an active execution
- """
- pass
-
-
-class WorkflowImplementationNotFoundError(AriaError):
- """
- Raised when attempting to import a workflow's code but the implementation is not found
- """
- pass
-
-
-class InvalidWorkflowRunnerParams(AriaError):
- """
- Raised when invalid combination of arguments is passed to the workflow runner
- """
- pass
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/common.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/common.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/common.py
deleted file mode 100644
index ce6746c..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/common.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# 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.
-
-"""
-Execution plugin utilities.
-"""
-
-import json
-import os
-import tempfile
-
-import requests
-
-from . import constants
-from . import exceptions
-
-
-def is_windows():
- return os.name == 'nt'
-
-
-def download_script(ctx, script_path):
- split = script_path.split('://')
- schema = split[0]
- suffix = script_path.split('/')[-1]
- file_descriptor, dest_script_path = tempfile.mkstemp(suffix='-{0}'.format(suffix))
- os.close(file_descriptor)
- try:
- if schema in ('http', 'https'):
- response = requests.get(script_path)
- if response.status_code == 404:
- ctx.task.abort('Failed to download script: {0} (status code: {1})'
- .format(script_path, response.status_code))
- content = response.text
- with open(dest_script_path, 'wb') as f:
- f.write(content)
- else:
- ctx.download_resource(destination=dest_script_path, path=script_path)
- except:
- os.remove(dest_script_path)
- raise
- return dest_script_path
-
-
-def create_process_config(script_path, process, operation_kwargs, quote_json_env_vars=False):
- """
- Updates a process with its environment variables, and return it.
-
- Gets a dict representing a process and a dict representing the environment variables. Converts
- each environment variable to a format of::
-
- <string representing the name of the variable>:
- <json formatted string representing the value of the variable>.
-
- Finally, updates the process with the newly formatted environment variables, and return the
- process.
-
- :param process: dict representing a process
- :type process: dict
- :param operation_kwargs: dict representing environment variables that should exist in the
- process's running environment.
- :type operation_kwargs: dict
- :return: process updated with its environment variables
- :rtype: dict
- """
- process = process or {}
- env_vars = operation_kwargs.copy()
- if 'ctx' in env_vars:
- del env_vars['ctx']
- env_vars.update(process.get('env', {}))
- for k, v in env_vars.items():
- if isinstance(v, (dict, list, tuple, bool, int, float)):
- v = json.dumps(v)
- if quote_json_env_vars:
- v = "'{0}'".format(v)
- if is_windows():
- # These <k,v> environment variables will subsequently
- # be used in a subprocess.Popen() call, as the `env` parameter.
- # In some windows python versions, if an environment variable
- # name is not of type str (e.g. unicode), the Popen call will
- # fail.
- k = str(k)
- # The windows shell removes all double quotes - escape them
- # to still be able to pass JSON in env vars to the shell.
- v = v.replace('"', '\\"')
- del env_vars[k]
- env_vars[k] = str(v)
- process['env'] = env_vars
- args = process.get('args')
- command = script_path
- command_prefix = process.get('command_prefix')
- if command_prefix:
- command = '{0} {1}'.format(command_prefix, command)
- if args:
- command = ' '.join([command] + [str(a) for a in args])
- process['command'] = command
- return process
-
-
-def patch_ctx(ctx):
- ctx._error = None
- task = ctx.task
-
- def _validate_legal_action():
- if ctx._error is not None:
- ctx._error = RuntimeError(constants.ILLEGAL_CTX_OPERATION_MESSAGE)
- raise ctx._error
-
- def abort_operation(message=None):
- _validate_legal_action()
- ctx._error = exceptions.ScriptException(message=message, retry=False)
- return ctx._error
- task.abort = abort_operation
-
- def retry_operation(message=None, retry_interval=None):
- _validate_legal_action()
- ctx._error = exceptions.ScriptException(message=message,
- retry=True,
- retry_interval=retry_interval)
- return ctx._error
- task.retry = retry_operation
-
-
-def check_error(ctx, error_check_func=None, reraise=False):
- _error = ctx._error
- # this happens when a script calls task.abort/task.retry more than once
- if isinstance(_error, RuntimeError):
- ctx.task.abort(str(_error))
- # ScriptException is populated by the ctx proxy server when task.abort or task.retry
- # are called
- elif isinstance(_error, exceptions.ScriptException):
- if _error.retry:
- ctx.task.retry(_error.message, _error.retry_interval)
- else:
- ctx.task.abort(_error.message)
- # local and ssh operations may pass an additional logic check for errors here
- if error_check_func:
- error_check_func()
- # if this function is called from within an ``except`` clause, a re-raise maybe required
- if reraise:
- raise # pylint: disable=misplaced-bare-raise
- return _error
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/constants.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/constants.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/constants.py
deleted file mode 100644
index 1953912..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/constants.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# 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.
-
-"""
-Execution plugin constants.
-"""
-import os
-import tempfile
-
-from . import exceptions
-
-# related to local
-PYTHON_SCRIPT_FILE_EXTENSION = '.py'
-POWERSHELL_SCRIPT_FILE_EXTENSION = '.ps1'
-DEFAULT_POWERSHELL_EXECUTABLE = 'powershell'
-
-# related to both local and ssh
-ILLEGAL_CTX_OPERATION_MESSAGE = 'ctx may only abort or retry once'
-
-# related to ssh
-DEFAULT_BASE_DIR = os.path.join(tempfile.gettempdir(), 'aria-ctx')
-FABRIC_ENV_DEFAULTS = {
- 'connection_attempts': 5,
- 'timeout': 10,
- 'forward_agent': False,
- 'abort_on_prompts': True,
- 'keepalive': 0,
- 'linewise': False,
- 'pool_size': 0,
- 'skip_bad_hosts': False,
- 'status': False,
- 'disable_known_hosts': True,
- 'combine_stderr': True,
- 'abort_exception': exceptions.TaskException,
-}
-VALID_FABRIC_GROUPS = set([
- 'status',
- 'aborts',
- 'warnings',
- 'running',
- 'stdout',
- 'stderr',
- 'user',
- 'everything'
-])
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/client.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/client.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/client.py
deleted file mode 100644
index 1310c21..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/client.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#! /usr/bin/env python
-# 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.
-
-"""
-``ctx`` proxy client implementation.
-"""
-
-import argparse
-import json
-import os
-import sys
-import urllib2
-
-
-# Environment variable for the socket url (used by clients to locate the socket)
-CTX_SOCKET_URL = 'CTX_SOCKET_URL'
-
-
-class _RequestError(RuntimeError):
-
- def __init__(self, ex_message, ex_type, ex_traceback):
- super(_RequestError, self).__init__(self, '{0}: {1}'.format(ex_type, ex_message))
- self.ex_type = ex_type
- self.ex_message = ex_message
- self.ex_traceback = ex_traceback
-
-
-def _http_request(socket_url, request, method, timeout):
- opener = urllib2.build_opener(urllib2.HTTPHandler)
- request = urllib2.Request(socket_url, data=json.dumps(request))
- request.get_method = lambda: method
- response = opener.open(request, timeout=timeout)
-
- if response.code != 200:
- raise RuntimeError('Request failed: {0}'.format(response))
- return json.loads(response.read())
-
-
-def _client_request(socket_url, args, timeout, method='POST'):
- response = _http_request(
- socket_url=socket_url,
- request={'args': args},
- method=method,
- timeout=timeout
- )
- payload = response.get('payload')
- response_type = response.get('type')
- if response_type == 'error':
- ex_type = payload['type']
- ex_message = payload['message']
- ex_traceback = payload['traceback']
- raise _RequestError(ex_message, ex_type, ex_traceback)
- elif response_type == 'stop_operation':
- raise SystemExit(payload['message'])
- else:
- return payload
-
-
-def _parse_args(args):
- parser = argparse.ArgumentParser()
- parser.add_argument('-t', '--timeout', type=int, default=30)
- parser.add_argument('--socket-url', default=os.environ.get(CTX_SOCKET_URL))
- parser.add_argument('--json-arg-prefix', default='@')
- parser.add_argument('-j', '--json-output', action='store_true')
- parser.add_argument('args', nargs='*')
- args = parser.parse_args(args=args)
- if not args.socket_url:
- raise RuntimeError('Missing CTX_SOCKET_URL environment variable '
- 'or socket_url command line argument. (ctx is supposed to be executed '
- 'within an operation context)')
- return args
-
-
-def _process_args(json_prefix, args):
- processed_args = []
- for arg in args:
- if arg.startswith(json_prefix):
- arg = json.loads(arg[1:])
- processed_args.append(arg)
- return processed_args
-
-
-def main(args=None):
- args = _parse_args(args)
- response = _client_request(
- args.socket_url,
- args=_process_args(args.json_arg_prefix, args.args),
- timeout=args.timeout)
- if args.json_output:
- response = json.dumps(response)
- else:
- if not response:
- response = ''
- response = str(response)
- sys.stdout.write(response)
-
-if __name__ == '__main__':
- main()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/server.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/server.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/server.py
deleted file mode 100644
index ca910e0..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/ctx_proxy/server.py
+++ /dev/null
@@ -1,260 +0,0 @@
-# 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.
-
-"""
-``ctx`` proxy server implementation.
-"""
-
-import collections
-import json
-import re
-import socket
-import threading
-import traceback
-import Queue
-import StringIO
-import wsgiref.simple_server
-
-import bottle
-from aria import modeling
-
-from .. import exceptions
-
-
-class CtxProxy(object):
-
- def __init__(self, ctx, ctx_patcher=(lambda *args, **kwargs: None)):
- self.ctx = ctx
- self._ctx_patcher = ctx_patcher
- self.port = _get_unused_port()
- self.socket_url = 'http://localhost:{0}'.format(self.port)
- self.server = None
- self._started = Queue.Queue(1)
- self.thread = self._start_server()
- self._started.get(timeout=5)
-
- def _start_server(self):
-
- class BottleServerAdapter(bottle.ServerAdapter):
- proxy = self
-
- def close_session(self):
- self.proxy.ctx.model.log._session.remove()
-
- def run(self, app):
-
- class Server(wsgiref.simple_server.WSGIServer):
- allow_reuse_address = True
- bottle_server = self
-
- def handle_error(self, request, client_address):
- pass
-
- def serve_forever(self, poll_interval=0.5):
- try:
- wsgiref.simple_server.WSGIServer.serve_forever(self, poll_interval)
- finally:
- # Once shutdown is called, we need to close the session.
- # If the session is not closed properly, it might raise warnings,
- # or even lock the database.
- self.bottle_server.close_session()
-
- class Handler(wsgiref.simple_server.WSGIRequestHandler):
- def address_string(self):
- return self.client_address[0]
-
- def log_request(*args, **kwargs): # pylint: disable=no-method-argument
- if not self.quiet:
- return wsgiref.simple_server.WSGIRequestHandler.log_request(*args,
- **kwargs)
- server = wsgiref.simple_server.make_server(
- host=self.host,
- port=self.port,
- app=app,
- server_class=Server,
- handler_class=Handler)
- self.proxy.server = server
- self.proxy._started.put(True)
- server.serve_forever(poll_interval=0.1)
-
- def serve():
- # Since task is a thread_local object, we need to patch it inside the server thread.
- self._ctx_patcher(self.ctx)
-
- bottle_app = bottle.Bottle()
- bottle_app.post('/', callback=self._request_handler)
- bottle.run(
- app=bottle_app,
- host='localhost',
- port=self.port,
- quiet=True,
- server=BottleServerAdapter)
- thread = threading.Thread(target=serve)
- thread.daemon = True
- thread.start()
- return thread
-
- def close(self):
- if self.server:
- self.server.shutdown()
- self.server.server_close()
-
- def _request_handler(self):
- request = bottle.request.body.read() # pylint: disable=no-member
- response = self._process(request)
- return bottle.LocalResponse(
- body=json.dumps(response, cls=modeling.utils.ModelJSONEncoder),
- status=200,
- headers={'content-type': 'application/json'}
- )
-
- def _process(self, request):
- try:
- with self.ctx.model.instrument(*self.ctx.INSTRUMENTATION_FIELDS):
- typed_request = json.loads(request)
- args = typed_request['args']
- payload = _process_ctx_request(self.ctx, args)
- result_type = 'result'
- if isinstance(payload, exceptions.ScriptException):
- payload = dict(message=str(payload))
- result_type = 'stop_operation'
- result = {'type': result_type, 'payload': payload}
- except Exception as e:
- traceback_out = StringIO.StringIO()
- traceback.print_exc(file=traceback_out)
- payload = {
- 'type': type(e).__name__,
- 'message': str(e),
- 'traceback': traceback_out.getvalue()
- }
- result = {'type': 'error', 'payload': payload}
-
- return result
-
- def __enter__(self):
- return self
-
- def __exit__(self, *args, **kwargs):
- self.close()
-
-
-def _process_ctx_request(ctx, args):
- current = ctx
- num_args = len(args)
- index = 0
- while index < num_args:
- arg = args[index]
- attr = _desugar_attr(current, arg)
- if attr:
- current = getattr(current, attr)
- elif isinstance(current, collections.MutableMapping):
- key = arg
- path_dict = _PathDictAccess(current)
- if index + 1 == num_args:
- # read dict prop by path
- value = path_dict.get(key)
- current = value
- elif index + 2 == num_args:
- # set dict prop by path
- value = args[index + 1]
- path_dict.set(key, value)
- current = None
- else:
- raise RuntimeError('Illegal argument while accessing dict')
- break
- elif callable(current):
- kwargs = {}
- remaining_args = args[index:]
- if isinstance(remaining_args[-1], collections.MutableMapping):
- kwargs = remaining_args[-1]
- remaining_args = remaining_args[:-1]
- current = current(*remaining_args, **kwargs)
- break
- else:
- raise RuntimeError('{0} cannot be processed in {1}'.format(arg, args))
- index += 1
- if callable(current):
- current = current()
- return current
-
-
-def _desugar_attr(obj, attr):
- if not isinstance(attr, basestring):
- return None
- if hasattr(obj, attr):
- return attr
- attr = attr.replace('-', '_')
- if hasattr(obj, attr):
- return attr
- return None
-
-
-class _PathDictAccess(object):
- pattern = re.compile(r"(.+)\[(\d+)\]")
-
- def __init__(self, obj):
- self.obj = obj
-
- def set(self, prop_path, value):
- obj, prop_name = self._get_parent_obj_prop_name_by_path(prop_path)
- obj[prop_name] = value
-
- def get(self, prop_path):
- value = self._get_object_by_path(prop_path)
- return value
-
- def _get_object_by_path(self, prop_path, fail_on_missing=True):
- # when setting a nested object, make sure to also set all the
- # intermediate path objects
- current = self.obj
- for prop_segment in prop_path.split('.'):
- match = self.pattern.match(prop_segment)
- if match:
- index = int(match.group(2))
- property_name = match.group(1)
- if property_name not in current:
- self._raise_illegal(prop_path)
- if not isinstance(current[property_name], list):
- self._raise_illegal(prop_path)
- current = current[property_name][index]
- else:
- if prop_segment not in current:
- if fail_on_missing:
- self._raise_illegal(prop_path)
- else:
- current[prop_segment] = {}
- current = current[prop_segment]
- return current
-
- def _get_parent_obj_prop_name_by_path(self, prop_path):
- split = prop_path.split('.')
- if len(split) == 1:
- return self.obj, prop_path
- parent_path = '.'.join(split[:-1])
- parent_obj = self._get_object_by_path(parent_path, fail_on_missing=False)
- prop_name = split[-1]
- return parent_obj, prop_name
-
- @staticmethod
- def _raise_illegal(prop_path):
- raise RuntimeError('illegal path: {0}'.format(prop_path))
-
-
-def _get_unused_port():
- sock = socket.socket()
- sock.bind(('127.0.0.1', 0))
- _, port = sock.getsockname()
- sock.close()
- return port
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/environment_globals.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/environment_globals.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/environment_globals.py
deleted file mode 100644
index 6dec293..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/environment_globals.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# 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.
-
-"""
-Utilities for managing globals for the environment.
-"""
-
-def create_initial_globals(path):
- """
- Emulates a ``globals()`` call in a freshly loaded module.
-
- The implementation of this function is likely to raise a couple of questions. If you read the
- implementation and nothing bothered you, feel free to skip the rest of this docstring.
-
- First, why is this function in its own module and not, say, in the same module of the other
- environment-related functions? Second, why is it implemented in such a way that copies the
- globals, then deletes the item that represents this function, and then changes some other
- entries?
-
- Well, these two questions can be answered with one (elaborate) explanation. If this function was
- in the same module with the other environment-related functions, then we would have had to
- delete more items in globals than just ``create_initial_globals``. That is because all of the
- other function names would also be in globals, and since there is no built-in mechanism that
- return the name of the user-defined objects, this approach is quite an overkill.
-
- *But why do we rely on the copy-existing-globals-and-delete-entries method, when it seems to
- force us to put ``create_initial_globals`` in its own file?*
-
- Well, because there is no easier method of creating globals of a newly loaded module.
-
- *How about hard coding a ``globals`` dict? It seems that there are very few entries:
- ``__doc__``, ``__file__``, ``__name__``, ``__package__`` (but don't forget ``__builtins__``).*
-
- That would be coupling our implementation to a specific ``globals`` implementation. What if
- ``globals`` were to change?
- """
- copied_globals = globals().copy()
- copied_globals.update({
- '__doc__': 'Dynamically executed script',
- '__file__': path,
- '__name__': '__main__',
- '__package__': None
- })
- del copied_globals[create_initial_globals.__name__]
- return copied_globals
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/exceptions.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/exceptions.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/exceptions.py
deleted file mode 100644
index f201fae..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/exceptions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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.
-
-"""
-Execution plugin exceptions.
-"""
-
-class ProcessException(Exception):
- """
- Raised when local scripts and remote SSH commands fail.
- """
-
- def __init__(self, stderr=None, stdout=None, command=None, exit_code=None):
- super(ProcessException, self).__init__(stderr)
- self.command = command
- self.exit_code = exit_code
- self.stdout = stdout
- self.stderr = stderr
-
-
-class TaskException(Exception):
- """
- Raised when remote ssh scripts fail.
- """
-
-
-class ScriptException(Exception):
- """
- Used by the ``ctx`` proxy server when task.retry or task.abort are called by scripts.
- """
-
- def __init__(self, message=None, retry=None, retry_interval=None):
- super(ScriptException, self).__init__(message)
- self.retry = retry
- self.retry_interval = retry_interval
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/instantiation.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/instantiation.py b/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/instantiation.py
deleted file mode 100644
index f55aa50..0000000
--- a/apache-ariatosca-0.1.1/aria/orchestrator/execution_plugin/instantiation.py
+++ /dev/null
@@ -1,228 +0,0 @@
-# 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.
-
-"""
-Instantiation of :class:`~aria.modeling.models.Operation` models.
-"""
-
-# TODO: this module will eventually be moved to a new "aria.instantiation" package
-
-from ...utils.type import full_type_name
-from ...utils.formatting import safe_repr
-from ...utils.collections import OrderedDict
-from ...parser import validation
-from ...parser.consumption import ConsumptionContext
-from ...modeling.functions import Function
-
-
-def configure_operation(operation):
- host = None
- interface = operation.interface
- if interface.node is not None:
- host = interface.node.host
- elif interface.relationship is not None:
- if operation.relationship_edge is True:
- host = interface.relationship.target_node.host
- else: # either False or None (None meaning that edge was not specified)
- host = interface.relationship.source_node.host
-
- _configure_common(operation)
- if host is None:
- _configure_local(operation)
- else:
- _configure_remote(operation)
-
- # Any remaining un-handled configuration parameters will become extra arguments, available as
- # kwargs in either "run_script_locally" or "run_script_with_ssh"
- for key, value in operation.configurations.iteritems():
- if key not in ('process', 'ssh'):
- operation.arguments[key] = value.instantiate(None)
-
-
-def _configure_common(operation):
- """
- Local and remote operations.
- """
-
- from ...modeling.models import Argument
- operation.arguments['script_path'] = Argument.wrap('script_path', operation.implementation,
- 'Relative path to the executable file.')
- operation.arguments['process'] = Argument.wrap('process', _get_process(operation),
- 'Sub-process configuration.')
-
-
-def _configure_local(operation):
- """
- Local operation.
- """
-
- from . import operations
- operation.function = '{0}.{1}'.format(operations.__name__,
- operations.run_script_locally.__name__)
-
-
-def _configure_remote(operation):
- """
- Remote SSH operation via Fabric.
- """
-
- from ...modeling.models import Argument
- from . import operations
-
- ssh = _get_ssh(operation)
-
- # Defaults
- # TODO: find a way to configure these generally in the service template
- default_user = ''
- default_password = ''
- if 'user' not in ssh:
- ssh['user'] = default_user
- if ('password' not in ssh) and ('key' not in ssh) and ('key_filename' not in ssh):
- ssh['password'] = default_password
-
- operation.arguments['use_sudo'] = Argument.wrap('use_sudo', ssh.get('use_sudo', False),
- 'Whether to execute with sudo.')
-
- operation.arguments['hide_output'] = Argument.wrap('hide_output', ssh.get('hide_output', []),
- 'Hide output of these Fabric groups.')
-
- fabric_env = {}
- if 'warn_only' in ssh:
- fabric_env['warn_only'] = ssh['warn_only']
- fabric_env['user'] = ssh.get('user')
- fabric_env['password'] = ssh.get('password')
- fabric_env['key'] = ssh.get('key')
- fabric_env['key_filename'] = ssh.get('key_filename')
- if 'address' in ssh:
- fabric_env['host_string'] = ssh['address']
-
- # Make sure we have a user
- if fabric_env.get('user') is None:
- context = ConsumptionContext.get_thread_local()
- context.validation.report('must configure "ssh.user" for "{0}"'
- .format(operation.implementation),
- level=validation.Issue.BETWEEN_TYPES)
-
- # Make sure we have an authentication value
- if (fabric_env.get('password') is None) and \
- (fabric_env.get('key') is None) and \
- (fabric_env.get('key_filename') is None):
- context = ConsumptionContext.get_thread_local()
- context.validation.report('must configure "ssh.password", "ssh.key", or "ssh.key_filename" '
- 'for "{0}"'
- .format(operation.implementation),
- level=validation.Issue.BETWEEN_TYPES)
-
- operation.arguments['fabric_env'] = Argument.wrap('fabric_env', fabric_env,
- 'Fabric configuration.')
-
- operation.function = '{0}.{1}'.format(operations.__name__,
- operations.run_script_with_ssh.__name__)
-
-
-def _get_process(operation):
- value = (operation.configurations.get('process')._value
- if 'process' in operation.configurations
- else None)
- if value is None:
- return {}
- _validate_type(value, dict, 'process')
- value = OrderedDict(value)
- for k, v in value.iteritems():
- if k == 'eval_python':
- value[k] = _coerce_bool(v, 'process.eval_python')
- elif k == 'cwd':
- _validate_type(v, basestring, 'process.cwd')
- elif k == 'command_prefix':
- _validate_type(v, basestring, 'process.command_prefix')
- elif k == 'args':
- value[k] = _dict_to_list_of_strings(v, 'process.args')
- elif k == 'env':
- _validate_type(v, dict, 'process.env')
- else:
- context = ConsumptionContext.get_thread_local()
- context.validation.report('unsupported configuration parameter: "process.{0}"'
- .format(k),
- level=validation.Issue.BETWEEN_TYPES)
- return value
-
-
-def _get_ssh(operation):
- value = (operation.configurations.get('ssh')._value
- if 'ssh' in operation.configurations
- else None)
- if value is None:
- return {}
- _validate_type(value, dict, 'ssh')
- value = OrderedDict(value)
- for k, v in value.iteritems():
- if k == 'use_sudo':
- value[k] = _coerce_bool(v, 'ssh.use_sudo')
- elif k == 'hide_output':
- value[k] = _dict_to_list_of_strings(v, 'ssh.hide_output')
- elif k == 'warn_only':
- value[k] = _coerce_bool(v, 'ssh.warn_only')
- elif k == 'user':
- _validate_type(v, basestring, 'ssh.user')
- elif k == 'password':
- _validate_type(v, basestring, 'ssh.password')
- elif k == 'key':
- _validate_type(v, basestring, 'ssh.key')
- elif k == 'key_filename':
- _validate_type(v, basestring, 'ssh.key_filename')
- elif k == 'address':
- _validate_type(v, basestring, 'ssh.address')
- else:
- context = ConsumptionContext.get_thread_local()
- context.validation.report('unsupported configuration parameter: "ssh.{0}"'.format(k),
- level=validation.Issue.BETWEEN_TYPES)
- return value
-
-
-def _validate_type(value, the_type, name):
- if isinstance(value, Function):
- return
- if not isinstance(value, the_type):
- context = ConsumptionContext.get_thread_local()
- context.validation.report('"{0}" configuration is not a {1}: {2}'
- .format(name, full_type_name(the_type), safe_repr(value)),
- level=validation.Issue.BETWEEN_TYPES)
-
-
-def _coerce_bool(value, name):
- if value is None:
- return None
- if isinstance(value, bool):
- return value
- _validate_type(value, basestring, name)
- if value == 'true':
- return True
- elif value == 'false':
- return False
- else:
- context = ConsumptionContext.get_thread_local()
- context.validation.report('"{0}" configuration is not "true" or "false": {1}'
- .format(name, safe_repr(value)),
- level=validation.Issue.BETWEEN_TYPES)
-
-
-def _dict_to_list_of_strings(the_dict, name):
- _validate_type(the_dict, dict, name)
- value = []
- for k in sorted(the_dict):
- v = the_dict[k]
- _validate_type(v, basestring, '{0}.{1}'.format(name, k))
- value.append(v)
- return value