http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/execution_logging.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/execution_logging.py b/apache-ariatosca-0.1.1/aria/cli/execution_logging.py deleted file mode 100644 index af40e01..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/execution_logging.py +++ /dev/null @@ -1,243 +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. - -""" -Formatting for ``executions`` sub-commands. -""" - -import os -import re -from StringIO import StringIO -from functools import partial - -from . import ( - logger, - color -) -from .env import env - - -FIELD_TYPE = 'field_type' -LEVEL = 'level' -TIMESTAMP = 'timestamp' -MESSAGE = 'message' -IMPLEMENTATION = 'implementation' -INPUTS = 'inputs' -TRACEBACK = 'traceback' -MARKER = 'marker' - -FINAL_STATES = 'final_states' -SUCCESS_STATE = 'succeeded' -CANCEL_STATE = 'canceled' -FAIL_STATE = 'failed' - -_EXECUTION_PATTERN = "\'.*\' workflow execution {0}".format -# In order to be able to format a string into this regex pattern, we need to provide support -# in adding this string into double curly brackets. This is an issue with python format, so we add -# this via format itself. -_FIELD_TYPE_PATTERN = partial('.*({starting}{0}{closing}).*'.format, starting='{', closing='.*?}') - -_PATTERNS = { - FINAL_STATES: { - SUCCESS_STATE: re.compile(_EXECUTION_PATTERN(SUCCESS_STATE)), - CANCEL_STATE: re.compile(_EXECUTION_PATTERN(CANCEL_STATE)), - FAIL_STATE: re.compile(_EXECUTION_PATTERN(FAIL_STATE)), - }, - FIELD_TYPE: { - IMPLEMENTATION: re.compile(_FIELD_TYPE_PATTERN(IMPLEMENTATION)), - LEVEL: re.compile(_FIELD_TYPE_PATTERN(LEVEL)), - MESSAGE: re.compile(_FIELD_TYPE_PATTERN(MESSAGE)), - INPUTS: re.compile(_FIELD_TYPE_PATTERN(INPUTS)), - TIMESTAMP: re.compile(_FIELD_TYPE_PATTERN(TIMESTAMP)) - } -} - -_FINAL_STATES = { - SUCCESS_STATE: color.Colors.Fore.GREEN, - CANCEL_STATE: color.Colors.Fore.YELLOW, - FAIL_STATE: color.Colors.Fore.RED -} - -_DEFAULT_COLORS = { - LEVEL: { - 'default': {'fore': 'lightmagenta_ex'}, - 'error': {'fore': 'red', 'style': 'bright'}, - }, - TIMESTAMP: { - 'default': {'fore': 'lightmagenta_ex'}, - 'error': {'fore': 'red', 'style': 'bright'}, - }, - MESSAGE: { - 'default': {'fore': 'lightblue_ex'}, - 'error': {'fore': 'red', 'style': 'bright'}, - }, - IMPLEMENTATION:{ - 'default': {'fore': 'lightblack_ex'}, - 'error': {'fore': 'red', 'style': 'bright'}, - }, - INPUTS: { - 'default': {'fore': 'blue'}, - 'error': {'fore': 'red', 'style': 'bright'}, - }, - TRACEBACK: {'default': {'fore': 'red'}}, - - MARKER: 'lightyellow_ex' -} - -_DEFAULT_FORMATS = { - logger.NO_VERBOSE: '{message}', - logger.LOW_VERBOSE: '{timestamp:%H:%M:%S} | {level[0]} | {message}', - logger.MEDIUM_VERBOSE: '{timestamp:%H:%M:%S} | {level[0]} | {implementation} | {message}', - logger.HIGH_VERBOSE: - '{timestamp:%H:%M:%S} | {level[0]} | {implementation} | {inputs} | {message}' -} - - -def stylize_log(item, mark_pattern): - - # implementation - if item.task: - # operation task - implementation = item.task.function - inputs = dict(arg.unwrapped for arg in item.task.arguments.values()) - else: - # execution task - implementation = item.execution.workflow_name - inputs = dict(inp.unwrapped for inp in item.execution.inputs.values()) - - stylized_str = color.StringStylizer(_get_format()) - _populate_level(stylized_str, item) - _populate_timestamp(stylized_str, item) - _populate_message(stylized_str, item, mark_pattern) - _populate_inputs(stylized_str, inputs, item, mark_pattern) - _populate_implementation(stylized_str, implementation, item, mark_pattern) - - msg = StringIO() - msg.write(str(stylized_str)) - # Add the exception and the error msg. - if item.traceback and env.logging.verbosity_level >= logger.MEDIUM_VERBOSE: - msg.write(os.linesep) - msg.writelines(_color_traceback('\t' + '|' + line, item, mark_pattern) - for line in item.traceback.splitlines(True)) - - return msg.getvalue() - - -def log(item, mark_pattern=None, *args, **kwargs): - leveled_log = getattr(env.logging.logger, item.level.lower()) - return leveled_log(stylize_log(item, mark_pattern), *args, **kwargs) - - -def log_list(iterator, mark_pattern=None): - any_logs = False - for item in iterator: - log(item, mark_pattern) - any_logs = True - return any_logs - - -def _get_format(): - return (env.config.logging.execution.formats.get(env.logging.verbosity_level) or - _DEFAULT_FORMATS.get(env.logging.verbosity_level)) - - -def _get_styles(field_type): - return env.config.logging.execution.colors[field_type] - - -def _is_color_enabled(): - # If styling is enabled and the current log_item isn't final string - return env.config.logging.execution.colors_enabled - - -def _get_marker_schema(): - return color.ColorSpec(back=_get_styles(MARKER)) - - -def _populate_implementation(str_, implementation, log_item, mark_pattern=None): - _stylize(str_, implementation, log_item, IMPLEMENTATION, mark_pattern) - - -def _populate_inputs(str_, inputs, log_item, mark_pattern=None): - _stylize(str_, inputs, log_item, INPUTS, mark_pattern) - - -def _populate_timestamp(str_, log_item): - _stylize(str_, log_item.created_at, log_item, TIMESTAMP) - - -def _populate_message(str_, log_item, mark_pattern=None): - _stylize(str_, log_item.msg, log_item, MESSAGE, mark_pattern) - - -def _populate_level(str_, log_item): - _stylize(str_, log_item.level[0], log_item, LEVEL) - - -def _stylize(stylized_str, msg, log_item, msg_type, mark_pattern=None): - match = re.match(_PATTERNS[FIELD_TYPE][msg_type], stylized_str._str) - if not match: - return - matched_substr = match.group(1) - - substring = color.StringStylizer(matched_substr) - - # handle format - substring.format(**{msg_type: msg}) - - if _is_color_enabled(): - # handle color - substring.color(_resolve_schema(msg_type, log_item)) - if not _is_end_execution_log(log_item): - # handle highlighting - substring.highlight(mark_pattern, _get_marker_schema()) - - stylized_str.replace(matched_substr, substring) - - -def _color_traceback(traceback, log_item, mark_pattern): - if _is_color_enabled(): - stylized_string = color.StringStylizer(traceback, _resolve_schema(TRACEBACK, log_item)) - stylized_string.highlight(mark_pattern, _get_marker_schema()) - return stylized_string - return traceback - - -def _is_end_execution_log(log_item): - return not log_item.task and bool(_end_execution_schema(log_item)) - - -def _end_execution_schema(log_item): - for state, pattern in _PATTERNS[FINAL_STATES].items(): - if re.match(pattern, log_item.msg): - return _FINAL_STATES[state] - - -def _resolve_schema(msg_type, log_item): - if _is_end_execution_log(log_item): - return _end_execution_schema(log_item) - else: - return color.ColorSpec( - **( - # retrieve the schema from the user config according to the level - _get_styles(msg_type).get(log_item.level.lower()) or - # retrieve the default schema from the user config - _get_styles(msg_type).get('default') or - # retrieve the schema from the aria default config according to the level - _DEFAULT_COLORS[msg_type].get(log_item.level.lower()) or - # retrieve the default schema from the aria default config - _DEFAULT_COLORS[msg_type].get('default') - ) - )
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/helptexts.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/helptexts.py b/apache-ariatosca-0.1.1/aria/cli/helptexts.py deleted file mode 100644 index a5d41e8..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/helptexts.py +++ /dev/null @@ -1,61 +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. - -""" -Gathers all CLI command help texts in one place. -""" - -DEFAULT_MUTUALITY_ERROR_MESSAGE = 'mutually exclusive' -VERBOSE = \ - "Show verbose output; you can supply this up to three times (i.e. -vvv)" - -VERSION = "Display the version and exit" -FORCE_RESET = "Confirmation for resetting ARIA's working directory" -RESET_CONFIG = "Reset ARIA's user configuration" - -SERVICE_TEMPLATE_ID = "The unique identifier for the service template" -SERVICE_ID = "The unique identifier for the service" -EXECUTION_ID = "The unique identifier for the execution" - -SERVICE_TEMPLATE_PATH = "The path to the application's service template file" -SERVICE_TEMPLATE_FILENAME = ( - "The name of the archive's main service template file " - "(only relevant if uploading a non-CSAR archive)") -INPUTS_PARAMS_USAGE = ( - '(can be provided as wildcard based paths ' - '("inp?.yaml", "/my_inputs/", etc.) to YAML files, a JSON string or as ' - '"key1=value1;key2=value2"); this argument can be used multiple times') -SERVICE_INPUTS = "Inputs for the service {0}".format(INPUTS_PARAMS_USAGE) -EXECUTION_INPUTS = "Inputs for the execution {0}".format(INPUTS_PARAMS_USAGE) - -TASK_RETRY_INTERVAL = \ - "How long of a minimal interval should occur between task retry attempts [default: {0}]" -TASK_MAX_ATTEMPTS = \ - "How many times should a task be attempted in case of failures [default: {0}]" -DRY_EXECUTION = "Execute a workflow dry run (prints operations information without causing side " \ - "effects)" -IGNORE_AVAILABLE_NODES = "Delete the service even if it has available nodes" -SORT_BY = "Key for sorting the list" -DESCENDING = "Sort list in descending order [default: False]" -JSON_OUTPUT = "Output logs in JSON format" -MARK_PATTERN = "Mark a regular expression pattern in the logs" - -SHOW_FULL = "Show full information" -SHOW_JSON = "Show in JSON format (implies --full)" -SHOW_YAML = "Show in YAML format (implies --full)" -SHOW_TYPES = "Show only the type hierarchies" -SHOW_GRAPH = "Show only the node graph" -MODE_MUTUALITY_ERROR_MESSAGE = 'only one mode is possible' -FORMAT_MUTUALITY_ERROR_MESSAGE = 'only one format is possible' http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/inputs.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/inputs.py b/apache-ariatosca-0.1.1/aria/cli/inputs.py deleted file mode 100644 index bea3e1a..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/inputs.py +++ /dev/null @@ -1,124 +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. - -""" -Helpers for validating and coercing service template inputs. -""" - -import os -import glob -from ruamel import yaml - -from .env import logger -from .exceptions import AriaCliError - - -def inputs_to_dict(resources): - """ - Returns a dictionary of inputs - - :param resources: can be: - - * list of files - * single file - * directory containing multiple input files - * ``key1=value1;key2=value2`` pairs string. - * string formatted as JSON/YAML - * wildcard based string (e.g. ``*-inputs.yaml``) - """ - if not resources: - return dict() - - parsed_dict = {} - - for resource in resources: - logger.debug('Processing inputs source: {0}'.format(resource)) - # Workflow parameters always pass an empty dictionary. We ignore it - if isinstance(resource, basestring): - try: - parsed_dict.update(_parse_single_input(resource)) - except AriaCliError: - raise AriaCliError( - "Invalid input: {0}. It must represent a dictionary. " - "Valid values can be one of:{1} " - "- A path to a YAML file{1} " - "- A path to a directory containing YAML files{1} " - "- A single quoted wildcard based path " - "(e.g. '*-inputs.yaml'){1} " - "- A string formatted as JSON/YAML{1} " - "- A string formatted as key1=value1;key2=value2".format( - resource, os.linesep)) - return parsed_dict - - -def _parse_single_input(resource): - try: - # parse resource as string representation of a dictionary - return _plain_string_to_dict(resource) - except AriaCliError: - input_files = glob.glob(resource) - parsed_dict = dict() - if os.path.isdir(resource): - for input_file in os.listdir(resource): - parsed_dict.update( - _parse_yaml_path(os.path.join(resource, input_file))) - elif input_files: - for input_file in input_files: - parsed_dict.update(_parse_yaml_path(input_file)) - else: - parsed_dict.update(_parse_yaml_path(resource)) - return parsed_dict - - -def _parse_yaml_path(resource): - - try: - # if resource is a path - parse as a yaml file - if os.path.isfile(resource): - with open(resource) as f: - content = yaml.load(f.read()) - else: - # parse resource content as yaml - content = yaml.load(resource) - except yaml.error.YAMLError as e: - raise AriaCliError("'{0}' is not a valid YAML. {1}".format( - resource, str(e))) - - # Emtpy files return None - content = content or dict() - if not isinstance(content, dict): - raise AriaCliError() - - return content - - -def _plain_string_to_dict(input_string): - input_string = input_string.strip() - input_dict = {} - mapped_inputs = input_string.split(';') - for mapped_input in mapped_inputs: - mapped_input = mapped_input.strip() - if not mapped_input: - continue - split_mapping = mapped_input.split('=') - try: - key = split_mapping[0].strip() - value = split_mapping[1].strip() - except IndexError: - raise AriaCliError( - "Invalid input format: {0}, the expected format is: " - "key1=value1;key2=value2".format(input_string)) - input_dict[key] = value - return input_dict http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/logger.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/logger.py b/apache-ariatosca-0.1.1/aria/cli/logger.py deleted file mode 100644 index 14baae0..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/logger.py +++ /dev/null @@ -1,134 +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. - -""" -Centralized logging configuration and formatting. -""" - -import os -import copy -import logging -from logutils import dictconfig - -HIGH_VERBOSE = 3 -MEDIUM_VERBOSE = 2 -LOW_VERBOSE = 1 -NO_VERBOSE = 0 - -LOGGER_CONFIG_TEMPLATE = { - "version": 1, - "formatters": { - "file": { - "format": "%(asctime)s [%(levelname)s] %(message)s" - }, - "console": { - "format": "%(message)s" - } - }, - "handlers": { - "file": { - "class": "logging.handlers.RotatingFileHandler", - "formatter": "file", - "maxBytes": "5000000", - "backupCount": "20" - }, - "console": { - "class": "logging.StreamHandler", - "stream": "ext://sys.stdout", - "formatter": "console" - } - }, - "disable_existing_loggers": False -} - - -class Logging(object): - - def __init__(self, config): - self._log_file = None - self._verbosity_level = NO_VERBOSE - self._all_loggers_names = [] - self._configure_loggers(config) - self._lgr = logging.getLogger('aria.cli.main') - - @property - def logger(self): - return self._lgr - - @property - def log_file(self): - return self._log_file - - @property - def verbosity_level(self): - return self._verbosity_level - - @verbosity_level.setter - def verbosity_level(self, level): - self._verbosity_level = level - if self.is_high_verbose_level(): - for logger_name in self._all_loggers_names: - logging.getLogger(logger_name).setLevel(logging.DEBUG) - - def is_high_verbose_level(self): - return self.verbosity_level == HIGH_VERBOSE - - def _configure_loggers(self, config): - loggers_config = config.logging.loggers - logfile = config.logging.filename - - logger_dict = copy.deepcopy(LOGGER_CONFIG_TEMPLATE) - if logfile: - # set filename on file handler - logger_dict['handlers']['file']['filename'] = logfile - logfile_dir = os.path.dirname(logfile) - if not os.path.exists(logfile_dir): - os.makedirs(logfile_dir) - self._log_file = logfile - else: - del logger_dict['handlers']['file'] - - # add handlers to all loggers - loggers = {} - for logger_name in loggers_config: - loggers[logger_name] = dict(handlers=list(logger_dict['handlers'].keys())) - self._all_loggers_names.append(logger_name) - logger_dict['loggers'] = loggers - - # set level for all loggers - for logger_name, logging_level in loggers_config.iteritems(): - log = logging.getLogger(logger_name) - level = logging._levelNames[logging_level.upper()] - log.setLevel(level) - - dictconfig.dictConfig(logger_dict) - - -class ModelLogIterator(object): - - def __init__(self, model_storage, execution_id, filters=None, sort=None, offset=0): - self._last_visited_id = offset - self._model_storage = model_storage - self._execution_id = execution_id - self._additional_filters = filters or {} - self._sort = sort or {} - - def __iter__(self): - filters = dict(execution_fk=self._execution_id, id=dict(gt=self._last_visited_id)) - filters.update(self._additional_filters) - - for log in self._model_storage.log.iter(filters=filters, sort=self._sort): - self._last_visited_id = log.id - yield log http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/main.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/main.py b/apache-ariatosca-0.1.1/aria/cli/main.py deleted file mode 100644 index 640360b..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/main.py +++ /dev/null @@ -1,65 +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. - -""" -Executable entry point into the CLI. -""" - -from aria import install_aria_extensions -from aria.cli import commands -from aria.cli.core import aria - - [email protected](name='aria') [email protected]() [email protected] -def _aria(): - """ - ARIA's Command Line Interface. - - To activate bash-completion run:: - - eval "$(_ARIA_COMPLETE=source aria)" - - ARIA's working directory resides by default in "~/.aria". To change it, set the environment - variable ARIA_WORKDIR to something else (e.g. "/tmp/"). - """ - aria.set_cli_except_hook() - - -def _register_commands(): - """ - Register the CLI's commands. - """ - - _aria.add_command(commands.service_templates.service_templates) - _aria.add_command(commands.node_templates.node_templates) - _aria.add_command(commands.services.services) - _aria.add_command(commands.nodes.nodes) - _aria.add_command(commands.workflows.workflows) - _aria.add_command(commands.executions.executions) - _aria.add_command(commands.plugins.plugins) - _aria.add_command(commands.logs.logs) - _aria.add_command(commands.reset.reset) - - -def main(): - install_aria_extensions() - _register_commands() - _aria() - - -if __name__ == '__main__': - main() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/service_template_utils.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/service_template_utils.py b/apache-ariatosca-0.1.1/aria/cli/service_template_utils.py deleted file mode 100644 index 5312522..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/service_template_utils.py +++ /dev/null @@ -1,125 +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. - -""" -Loading mechanism for service templates. -""" - -import os -from urlparse import urlparse - -from . import csar -from . import utils -from .exceptions import AriaCliError -from ..utils import archive as archive_utils - - -def get(source, service_template_filename): - """ - Get a source and return a path to the main service template file - - The behavior based on then source argument content is: - - * local ``.yaml`` file: return the file - * local archive (``.csar``, ``.zip``, ``.tar``, ``.tar.gz``, and ``.tar.bz2``): extract it - locally and return path service template file - * URL: download and get service template from downloaded archive - * GitHub repo: download and get service template from downloaded archive - - :param source: path/URL/GitHub repo to archive/service-template file - :type source: basestring - :param service_template_filename: path to service template if source is a non-CSAR archive - with CSAR archives, this is read from the metadata file) - :type service_template_filename: basestring - :return: path to main service template file - :rtype: basestring - """ - if urlparse(source).scheme: - downloaded_file = utils.download_file(source) - return _get_service_template_file_from_archive( - downloaded_file, service_template_filename) - elif os.path.isfile(source): - if _is_archive(source): - return _get_service_template_file_from_archive(source, service_template_filename) - else: - # Maybe check if yaml. - return os.path.abspath(source) - elif len(source.split('/')) == 2: - url = _map_to_github_url(source) - downloaded_file = utils.download_file(url) - return _get_service_template_file_from_archive( - downloaded_file, service_template_filename) - else: - raise AriaCliError( - 'You must provide either a path to a local file, a remote URL ' - 'or a GitHub `organization/repository[:tag/branch]`') - - -def _get_service_template_file_from_archive(archive, service_template_filename): - """ - Extract archive to temporary location and get path to service template file. - - :param archive: path to archive file - :type archive: basestring - :param service_template_filename: path to service template file relative to archive - :type service_template_filename: basestring - :return: absolute path to service template file - :rtype: basestring - - """ - if csar.is_csar_archive(archive): - service_template_file = _extract_csar_archive(archive) - else: - extract_directory = archive_utils.extract_archive(archive) - service_template_dir = os.path.join( - extract_directory, - os.listdir(extract_directory)[0], - ) - service_template_file = os.path.join(service_template_dir, service_template_filename) - - if not os.path.isfile(service_template_file): - raise AriaCliError( - 'Could not find `{0}`. Please provide the name of the main ' - 'service template file by using the `-n/--service-template-filename` flag' - .format(service_template_filename)) - return service_template_file - - -def _map_to_github_url(source): - """ - Returns a path to a downloaded GitHub archive. - - :param source: GitHub repo: ``org/repo[:tag/branch]`` - :type source: basestring - :return: URL to the archive file for the given repo in GitHub - :rtype: basestring - - """ - source_parts = source.split(':', 1) - repo = source_parts[0] - tag = source_parts[1] if len(source_parts) == 2 else 'master' - url = 'https://github.com/{0}/archive/{1}.tar.gz'.format(repo, tag) - return url - - -def _is_archive(source): - return archive_utils.is_archive(source) or csar.is_csar_archive(source) - - -def _extract_csar_archive(archive): - reader = csar.read(source=archive) - main_service_template_file_name = os.path.basename(reader.entry_definitions) - return os.path.join(reader.destination, - main_service_template_file_name) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/table.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/table.py b/apache-ariatosca-0.1.1/aria/cli/table.py deleted file mode 100644 index 74487ae..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/table.py +++ /dev/null @@ -1,125 +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. - -""" -Tabular formatting utilities. -""" - -import os -from datetime import datetime - -from prettytable import PrettyTable - -from .env import logger - - -def print_data(columns, items, header_text, - column_formatters=None, col_max_width=None, defaults=None): - """ - Prints data in a tabular form. - - :param columns: columns of the table, e.g. ``['id','name']`` - :type columns: iterable of basestring - :param items: each element must have keys or attributes corresponding to the ``columns`` items, - e.g. ``[{'id':'123', 'name':'Pete'}]`` - :type data: [{:obj:`basestring`: :obj:`basestring`}] - :param column_formatters: maps column name to formatter, a function that may manipulate the - string values printed for this column, e.g. ``{'created_at': timestamp_formatter}`` - :type column_formatters: {:obj:`basestring`: :obj:`function`} - :param col_max_width: maximum width of table - :type col_max_width: int - :param defaults: default values for keys that don't exist in the data itself, e.g. - ``{'serviceId':'123'}`` - :type defaults: {:obj:`basestring`: :obj:`basestring`} - """ - if items is None: - items = [] - elif not isinstance(items, list): - items = [items] - - pretty_table = _generate(columns, data=items, column_formatters=column_formatters, - defaults=defaults) - if col_max_width: - pretty_table.max_width = col_max_width - _log(header_text, pretty_table) - - -def _log(title, table): - logger.info('{0}{1}{0}{2}{0}'.format(os.linesep, title, table)) - - -def _generate(cols, data, column_formatters=None, defaults=None): - """ - Return a new PrettyTable instance representing the list. - - :param cols: columns of the table, e.g. ``['id','name']`` - :type cols: iterable of :obj:`basestring` - :param data: each element must have keys or attributes corresponding to the ``cols`` items, - e.g. ``[{'id':'123', 'name':'Pete'}]`` - :type data: [{:obj:`basestring`: :obj:`basestring`}] - :param column_formatters: maps column name to formatter, a function that may manipulate the - string values printed for this column, e.g. ``{'created_at': timestamp_formatter}`` - :type column_formatters: {:obj:`basestring`: :obj:`function`} - :param defaults: default values for keys that don't exist in the data itself, e.g. - ``{'serviceId':'123'}`` - :type defaults: {:obj:`basestring`: :obj:`basestring`} - """ - def get_values_per_column(column, row_data): - if hasattr(row_data, column) or (isinstance(row_data, dict) and column in row_data): - val = row_data[column] if isinstance(row_data, dict) else getattr(row_data, column) - - if val and isinstance(val, list): - val = [str(element) for element in val] - val = ','.join(val) - elif val is None or isinstance(val, list): - # don't print `[]` or `None` (but do print `0`, `False`, etc.) - val = '' - - if column in column_formatters: - # calling the user's column formatter to manipulate the value - val = column_formatters[column](val) - - return val - else: - return defaults.get(column) - - column_formatters = column_formatters or dict() - defaults = defaults or dict() - pretty_table = PrettyTable(list(cols)) - - for datum in data: - values_row = [] - for col in cols: - values_row.append(get_values_per_column(col, datum)) - pretty_table.add_row(values_row) - - return pretty_table - - -def timestamp_formatter(value): - try: - datetime.strptime(value[:10], '%Y-%m-%d') - return value.replace('T', ' ').replace('Z', ' ') - except ValueError: - # not a timestamp - return value - - -def trim_formatter_generator(max_length): - def trim_formatter(value): - if len(value) >= max_length: - value = '{0}..'.format(value[:max_length - 2]) - return value - return trim_formatter http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/cli/utils.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/cli/utils.py b/apache-ariatosca-0.1.1/aria/cli/utils.py deleted file mode 100644 index 697ff37..0000000 --- a/apache-ariatosca-0.1.1/aria/cli/utils.py +++ /dev/null @@ -1,117 +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 CLI utilities. -""" - -import os -import sys -from StringIO import StringIO - -from backports.shutil_get_terminal_size import get_terminal_size - -from .env import logger -from .exceptions import AriaCliError -from ..utils import http - - -def storage_sort_param(sort_by, descending): - return {sort_by: 'desc' if descending else 'asc'} - - -def get_parameter_templates_as_string(parameter_templates): - params_string = StringIO() - - for param_name, param_template in parameter_templates.iteritems(): - params_string.write('\t{0}:{1}'.format(param_name, os.linesep)) - param_dict = param_template.to_dict() - del param_dict['id'] # not interested in printing the id - for k, v in param_dict.iteritems(): - params_string.write('\t\t{0}: {1}{2}'.format(k, v, os.linesep)) - - params_string.write(os.linesep) - return params_string.getvalue() - - -def check_overriding_storage_exceptions(e, model_class, name): - """ - Checks whether the storage exception is a known type where we'd like to override the exception - message; If so, it raises a new error. Otherwise it simply returns. - """ - assert isinstance(e, BaseException) - if 'UNIQUE constraint failed' in e.message: - new_message = \ - 'Could not store {model_class} `{name}`{linesep}' \ - 'There already a exists a {model_class} with the same name' \ - .format(model_class=model_class, name=name, linesep=os.linesep) - trace = sys.exc_info()[2] - raise type(e), type(e)(new_message), trace # pylint: disable=raising-non-exception - - -def download_file(url): - progress_bar = generate_progress_handler(url, 'Downloading') - try: - destination = http.download_file(url, logger=logger, progress_handler=progress_bar) - except Exception as e: - raise AriaCliError( - 'Failed to download {0}. ({1})'.format(url, str(e))) - return destination - - -def generate_progress_handler(file_path, action='', max_bar_length=80): - """ - Returns a function that prints a progress bar in the terminal. - - :param file_path: the name of the file being transferred - :param action: uploading/downloading - :param max_bar_length: maximum allowed length of the bar - :return: configured ``print_progress`` function - """ - # We want to limit the maximum line length to 80, but allow for a smaller terminal size. We also - # include the action string, and some extra chars - terminal_width = get_terminal_size().columns - - # This takes care of the case where there is no terminal (e.g. unittest) - terminal_width = terminal_width or max_bar_length - bar_length = min(max_bar_length, terminal_width) - len(action) - 12 - - # Shorten the file name if it's too long - file_name = os.path.basename(file_path) - if len(file_name) > (bar_length / 4) + 3: - file_name = file_name[:bar_length / 4] + '...' - - bar_length -= len(file_name) - - def print_progress(read_bytes, total_bytes): - """ - Print upload/download progress on a single line. - - Call this function in a loop to create a progress bar in the terminal. - - :param read_bytes: number of bytes already processed - :param total_bytes: total number of bytes in the file - """ - - filled_length = min(bar_length, int(round(bar_length * read_bytes / float(total_bytes)))) - percents = min(100.00, round(100.00 * (read_bytes / float(total_bytes)), 2)) - bar = '#' * filled_length + '-' * (bar_length - filled_length) # pylint: disable=blacklisted-name - - # The \r caret makes sure the cursor moves back to the beginning of the line - sys.stdout.write('\r{0} {1} |{2}| {3}%'.format(action, file_name, bar, percents)) - if read_bytes >= total_bytes: - sys.stdout.write(os.linesep) - - return print_progress http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/core.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/core.py b/apache-ariatosca-0.1.1/aria/core.py deleted file mode 100644 index a8d5245..0000000 --- a/apache-ariatosca-0.1.1/aria/core.py +++ /dev/null @@ -1,134 +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. - -""" -ARIA core module. -""" - -from . import exceptions -from .parser import consumption -from .parser.loading.location import UriLocation - - -class Core(object): - - def __init__(self, - model_storage, - resource_storage, - plugin_manager): - self._model_storage = model_storage - self._resource_storage = resource_storage - self._plugin_manager = plugin_manager - - @property - def model_storage(self): - return self._model_storage - - @property - def resource_storage(self): - return self._resource_storage - - @property - def plugin_manager(self): - return self._plugin_manager - - def validate_service_template(self, service_template_path): - self._parse_service_template(service_template_path) - - def create_service_template(self, service_template_path, service_template_dir, - service_template_name): - context = self._parse_service_template(service_template_path) - service_template = context.modeling.template - service_template.name = service_template_name - self.model_storage.service_template.put(service_template) - self.resource_storage.service_template.upload( - entry_id=str(service_template.id), source=service_template_dir) - - def delete_service_template(self, service_template_id): - service_template = self.model_storage.service_template.get(service_template_id) - if service_template.services: - raise exceptions.DependentServicesError( - 'Can\'t delete service template `{0}` - service template has existing services' - .format(service_template.name)) - - self.model_storage.service_template.delete(service_template) - self.resource_storage.service_template.delete(entry_id=str(service_template.id)) - - def create_service(self, service_template_id, inputs, service_name=None): - - service_template = self.model_storage.service_template.get(service_template_id) - - # creating an empty ConsumptionContext, initiating a threadlocal context - context = consumption.ConsumptionContext() - - storage_session = self.model_storage._all_api_kwargs['session'] - # setting no autoflush for the duration of instantiation - this helps avoid dependency - # constraints as they're being set up - with storage_session.no_autoflush: - service = service_template.instantiate(None, self.model_storage, inputs=inputs) - - consumption.ConsumerChain( - context, - ( - consumption.CoerceServiceInstanceValues, - consumption.ValidateServiceInstance, - consumption.SatisfyRequirements, - consumption.CoerceServiceInstanceValues, - consumption.ValidateCapabilities, - consumption.FindHosts, - consumption.ConfigureOperations, - consumption.CoerceServiceInstanceValues - )).consume() - if context.validation.dump_issues(): - raise exceptions.InstantiationError('Failed to instantiate service template `{0}`' - .format(service_template.name)) - - storage_session.flush() # flushing so service.id would auto-populate - service.name = service_name or '{0}_{1}'.format(service_template.name, service.id) - self.model_storage.service.put(service) - return service - - def delete_service(self, service_id, force=False): - service = self.model_storage.service.get(service_id) - - active_executions = [e for e in service.executions if e.is_active()] - if active_executions: - raise exceptions.DependentActiveExecutionsError( - 'Can\'t delete service `{0}` - there is an active execution for this service. ' - 'Active execution ID: {1}'.format(service.name, active_executions[0].id)) - - if not force: - available_nodes = [str(n.id) for n in service.nodes.values() if n.is_available()] - if available_nodes: - raise exceptions.DependentAvailableNodesError( - 'Can\'t delete service `{0}` - there are available nodes for this service. ' - 'Available node IDs: {1}'.format(service.name, ', '.join(available_nodes))) - - self.model_storage.service.delete(service) - - @staticmethod - def _parse_service_template(service_template_path): - context = consumption.ConsumptionContext() - context.presentation.location = UriLocation(service_template_path) - consumption.ConsumerChain( - context, - ( - consumption.Read, - consumption.Validate, - consumption.ServiceTemplate - )).consume() - if context.validation.dump_issues(): - raise exceptions.ParsingError('Failed to parse service template') - return context http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/exceptions.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/exceptions.py b/apache-ariatosca-0.1.1/aria/exceptions.py deleted file mode 100644 index 5d3e21d..0000000 --- a/apache-ariatosca-0.1.1/aria/exceptions.py +++ /dev/null @@ -1,73 +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. - -""" -Base exception classes and other common exceptions used throughout ARIA. -""" - -import sys - - -class AriaError(Exception): - """ - Base class for ARIA errors. - """ - pass - - -class AriaException(Exception): - """ - Base class for ARIA exceptions. - """ - - def __init__(self, message=None, cause=None, cause_traceback=None): - super(AriaException, self).__init__(message) - self.cause = cause - self.issue = None - if cause_traceback is None: - _, e, traceback = sys.exc_info() - if cause == e: - # Make sure it's our traceback - cause_traceback = traceback - self.cause_traceback = cause_traceback - - -class DependentServicesError(AriaError): - """ - Raised when attempting to delete a service template which has existing services. - """ - pass - - -class DependentActiveExecutionsError(AriaError): - """ - Raised when attempting to delete a service which has active executions. - """ - pass - - -class DependentAvailableNodesError(AriaError): - """ - Raised when attempting to delete a service which has available nodes. - """ - pass - - -class ParsingError(AriaError): - pass - - -class InstantiationError(AriaError): - pass http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/extension.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/extension.py b/apache-ariatosca-0.1.1/aria/extension.py deleted file mode 100644 index e90750d..0000000 --- a/apache-ariatosca-0.1.1/aria/extension.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. - -""" -Mechanism for registering and loading ARIA extensions. -""" - -# pylint: disable=no-self-use - -from .utils import collections - - -class _Registrar(object): - - def __init__(self, registry): - if not isinstance(registry, (dict, list)): - raise RuntimeError('Unsupported registry type') - self._registry = registry - - def register(self, function): - result = function() - if isinstance(self._registry, dict): - for key in result: - if key in self._registry: - raise RuntimeError('Re-definition of {0} in {1}'.format(key, function.__name__)) - self._registry.update(result) - elif isinstance(self._registry, list): - if not isinstance(result, (list, tuple, set)): - result = [result] - self._registry += list(result) - else: - raise RuntimeError('Illegal state') - - def __call__(self): - return self._registry - - -def _registrar(function): - function._registrar_function = True - return function - - -class _ExtensionRegistration(object): - """ - Base class for extension class decorators. - """ - - def __init__(self): - self._registrars = {} - self._registered_classes = [] - for attr, value in vars(self.__class__).items(): - try: - is_registrar_function = value._registrar_function - except AttributeError: - is_registrar_function = False - if is_registrar_function: - registrar = _Registrar(registry=getattr(self, attr)()) - setattr(self, attr, registrar) - self._registrars[attr] = registrar - - def __call__(self, cls): - self._registered_classes.append(cls) - return cls - - def init(self): - """ - Initialize all registrars by calling all registered functions. - """ - registered_instances = [cls() for cls in self._registered_classes] - for name, registrar in self._registrars.items(): - for instance in registered_instances: - registrating_function = getattr(instance, name, None) - if registrating_function: - registrar.register(registrating_function) - - -class _ParserExtensionRegistration(_ExtensionRegistration): - """ - Parser extensions class decorator. - """ - - @_registrar - def presenter_class(self): - """ - Presentation class registration. - - Implementing functions can return a single class or a list/tuple of classes. - """ - return [] - - @_registrar - def specification_package(self): - """ - Specification package registration. - - Implementing functions can return a package name or a list/tuple of names. - """ - return [] - - @_registrar - def specification_url(self): - """ - Specification URL registration. - - Implementing functions should return a dictionary from names to URLs. - """ - return {} - - @_registrar - def uri_loader_prefix(self): - """ - URI loader prefix registration. - - Implementing functions can return a single prefix or a list/tuple of prefixes. - """ - return collections.StrictList(value_class=basestring) - -parser = _ParserExtensionRegistration() - - -class _ProcessExecutorExtensionRegistration(_ExtensionRegistration): - """ - Process executor extension class decorator. - """ - - @_registrar - def decorate(self): - """ - The operation function executed by the process executor will be decorated with the function - returned from ``decorate()``. - """ - return [] - -process_executor = _ProcessExecutorExtensionRegistration() - - -def init(): - """ - Initialize all registrars by calling all registered functions. - """ - parser.init() - process_executor.init() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/logger.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/logger.py b/apache-ariatosca-0.1.1/aria/logger.py deleted file mode 100644 index f4f6ec9..0000000 --- a/apache-ariatosca-0.1.1/aria/logger.py +++ /dev/null @@ -1,186 +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. - -""" -Mix-ins and functions for logging, supporting multiple backends (such as SQL) and consistent -formatting. -""" - -import logging -from logging import handlers as logging_handlers -# NullHandler doesn't exist in < 27. this workaround is from -# http://docs.python.org/release/2.6/library/logging.html#configuring-logging-for-a-library -try: - from logging import NullHandler # pylint: disable=unused-import -except ImportError: - class NullHandler(logging.Handler): - def emit(self, record): - pass -from datetime import datetime - - -TASK_LOGGER_NAME = 'aria.executions.task' - - -_base_logger = logging.getLogger('aria') - - -class LoggerMixin(object): - """ - Provides logging functionality to a class. - - :ivar logger_name: logger name; default to the class name - :ivar logger_level: logger level; defaults to ``logging.DEBUG`` - :ivar base_logger: child loggers are created from this; defaults to the root logger - """ - logger_name = None - logger_level = logging.DEBUG - - def __init__(self, *args, **kwargs): - self.logger_name = self.logger_name or self.__class__.__name__ - self.logger = logging.getLogger('{0}.{1}'.format(_base_logger.name, self.logger_name)) - # Set the logger handler of any object derived from LoggerMixing to NullHandler. - # This is since the absence of a handler shows up while using the CLI in the form of: - # `No handlers could be found for logger "..."`. - self.logger.addHandler(NullHandler()) - self.logger.setLevel(self.logger_level) - super(LoggerMixin, self).__init__(*args, **kwargs) - - @classmethod - def with_logger( - cls, - logger_name=None, - logger_level=logging.DEBUG, - base_logger=logging.getLogger(), - **kwargs): - """ - Set the logger used by the consuming class. - """ - cls.logger_name = logger_name - cls.logger_level = logger_level - cls.base_logger = base_logger - return cls(**kwargs) - - def __getstate__(self): - obj_dict = vars(self).copy() - del obj_dict['logger'] - return obj_dict - - def __setstate__(self, obj_dict): - vars(self).update( - logger=logging.getLogger('{0}.{1}'.format(_base_logger.name, obj_dict['logger_name'])), - **obj_dict) - - -def create_logger(logger=_base_logger, handlers=(), **configs): - """ - :param logger: logger name; defaults to ARIA logger - :type logger: logging.Logger - :param handlers: logger handlers - :type handlers: [] - :param configs: logger configurations - :type configs: [] - :return: logger - """ - logger.handlers = [] - for handler in handlers: - logger.addHandler(handler) - - logger.setLevel(configs.get('level', logging.DEBUG)) - logger.debug('Logger {0} configured'.format(logger.name)) - return logger - - -def create_console_log_handler(level=logging.DEBUG, formatter=None): - """ - :param level: - :param formatter: - """ - console = logging.StreamHandler() - console.setLevel(level) - console.formatter = formatter or _DefaultConsoleFormat() - return console - - -def create_sqla_log_handler(model, log_cls, execution_id, level=logging.DEBUG): - - # This is needed since the engine and session are entirely new we need to reflect the db - # schema of the logging model into the engine and session. - return _SQLAlchemyHandler(model=model, log_cls=log_cls, execution_id=execution_id, level=level) - - -class _DefaultConsoleFormat(logging.Formatter): - """ - Info level log format: ``%(message)s``. - - Every other log level is formatted: ``%(levelname)s: %(message)s``. - """ - def format(self, record): - try: - if hasattr(record, 'prefix'): - self._fmt = '<%(asctime)s: [%(levelname)s] @%(prefix)s> %(message)s' - else: - self._fmt = '<%(asctime)s: [%(levelname)s]> %(message)s' - - except AttributeError: - return record.message - return logging.Formatter.format(self, record) - - -def create_file_log_handler( - file_path, - level=logging.DEBUG, - max_bytes=5 * 1000 * 1024, - backup_count=10, - formatter=None): - """ - Create a :class:`logging.handlers.RotatingFileHandler`. - """ - rotating_file = logging_handlers.RotatingFileHandler( - filename=file_path, - maxBytes=max_bytes, - backupCount=backup_count, - delay=True, - ) - rotating_file.setLevel(level) - rotating_file.formatter = formatter or _default_file_formatter - return rotating_file - - -class _SQLAlchemyHandler(logging.Handler): - def __init__(self, model, log_cls, execution_id, **kwargs): - logging.Handler.__init__(self, **kwargs) - self._model = model - self._cls = log_cls - self._execution_id = execution_id - - def emit(self, record): - created_at = datetime.strptime(logging.Formatter('%(asctime)s').formatTime(record), - '%Y-%m-%d %H:%M:%S,%f') - log = self._cls( - execution_fk=self._execution_id, - task_fk=record.task_id, - level=record.levelname, - msg=str(record.msg), - created_at=created_at, - - # Not mandatory. - traceback=getattr(record, 'traceback', None) - ) - self._model.log.put(log) - - -_default_file_formatter = logging.Formatter( - '%(asctime)s [%(name)s:%(levelname)s] %(message)s <%(pathname)s:%(lineno)d>') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/constraints.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/modeling/constraints.py b/apache-ariatosca-0.1.1/aria/modeling/constraints.py deleted file mode 100644 index 8ed33d5..0000000 --- a/apache-ariatosca-0.1.1/aria/modeling/constraints.py +++ /dev/null @@ -1,31 +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. - -""" -Constraints for the requirements-and-capabilities matching mechanism. -""" - -class NodeTemplateConstraint(object): - """ - Used to constrain requirements for node templates. - - Must be serializable. - """ - - def matches(self, source_node_template, target_node_template): - """ - Returns ``True`` if the target matches the constraint for the source. - """ - raise NotImplementedError http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/exceptions.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/modeling/exceptions.py b/apache-ariatosca-0.1.1/aria/modeling/exceptions.py deleted file mode 100644 index 573efaf..0000000 --- a/apache-ariatosca-0.1.1/aria/modeling/exceptions.py +++ /dev/null @@ -1,63 +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. - -""" -Modeling exceptions. -""" - -from ..exceptions import AriaException - - -class ModelingException(AriaException): - """ - ARIA modeling exception. - """ - - -class ParameterException(ModelingException): - """ - ARIA parameter exception. - """ - pass - - -class ValueFormatException(ModelingException): - """ - ARIA modeling exception: the value is in the wrong format. - """ - - -class CannotEvaluateFunctionException(ModelingException): - """ - ARIA modeling exception: cannot evaluate the function at this time. - """ - - -class MissingRequiredParametersException(ParameterException): - """ - ARIA modeling exception: Required parameters have been omitted. - """ - - -class ParametersOfWrongTypeException(ParameterException): - """ - ARIA modeling exception: Parameters of the wrong types have been provided. - """ - - -class UndeclaredParametersException(ParameterException): - """ - ARIA modeling exception: Undeclared parameters have been provided. - """ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/functions.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/modeling/functions.py b/apache-ariatosca-0.1.1/aria/modeling/functions.py deleted file mode 100644 index 6544adf..0000000 --- a/apache-ariatosca-0.1.1/aria/modeling/functions.py +++ /dev/null @@ -1,139 +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. - -""" -Mechanism for evaluating intrinsic functions. -""" - -from ..parser.consumption import ConsumptionContext -from ..parser.exceptions import InvalidValueError -from ..utils.collections import OrderedDict -from . import exceptions - - -class Function(object): - """ - Base class for intrinsic functions. Serves as a placeholder for a value that should eventually - be derived by "evaluating" (calling) the function. - - Note that this base class is provided as a convenience and you do not have to inherit it: any - object with an ``__evaluate__`` method would be treated similarly. - """ - - @property - def as_raw(self): - raise NotImplementedError - - def __evaluate__(self, container_holder): - """ - Evaluates the function if possible. - - :rtype: :class:`Evaluation` (or any object with ``value`` and ``final`` properties) - :raises CannotEvaluateFunctionException: if cannot be evaluated at this time (do *not* just - return ``None``) - """ - - raise NotImplementedError - - def __deepcopy__(self, memo): - # Circumvent cloning in order to maintain our state - return self - - -class Evaluation(object): - """ - An evaluated :class:`Function` return value. - - :ivar value: evaluated value - :ivar final: whether the value is final - :vartype final: boolean - """ - - def __init__(self, value, final=False): - self.value = value - self.final = final - - -def evaluate(value, container_holder, report_issues=False): # pylint: disable=too-many-branches - """ - Recursively attempts to call ``__evaluate__``. If an evaluation occurred will return an - :class:`Evaluation`, otherwise it will be ``None``. If any evaluation is non-final, then the - entire evaluation will also be non-final. - - The ``container_holder`` argument should have three properties: ``container`` should return - the model that contains the value, ``service`` should return the containing - :class:`~aria.modeling.models.Service` model or None, and ``service_template`` should return the - containing :class:`~aria.modeling.models.ServiceTemplate` model or ``None``. - """ - - evaluated = False - final = True - - if hasattr(value, '__evaluate__'): - try: - evaluation = value.__evaluate__(container_holder) - - # Verify evaluation structure - if (evaluation is None) \ - or (not hasattr(evaluation, 'value')) \ - or (not hasattr(evaluation, 'final')): - raise InvalidValueError('bad __evaluate__ implementation') - - evaluated = True - value = evaluation.value - final = evaluation.final - - # The evaluated value might itself be evaluable - evaluation = evaluate(value, container_holder, report_issues) - if evaluation is not None: - value = evaluation.value - if not evaluation.final: - final = False - except exceptions.CannotEvaluateFunctionException: - pass - except InvalidValueError as e: - if report_issues: - context = ConsumptionContext.get_thread_local() - context.validation.report(e.issue) - - elif isinstance(value, list): - evaluated_list = [] - for v in value: - evaluation = evaluate(v, container_holder, report_issues) - if evaluation is not None: - evaluated_list.append(evaluation.value) - evaluated = True - if not evaluation.final: - final = False - else: - evaluated_list.append(v) - if evaluated: - value = evaluated_list - - elif isinstance(value, dict): - evaluated_dict = OrderedDict() - for k, v in value.iteritems(): - evaluation = evaluate(v, container_holder, report_issues) - if evaluation is not None: - evaluated_dict[k] = evaluation.value - evaluated = True - if not evaluation.final: - final = False - else: - evaluated_dict[k] = v - if evaluated: - value = evaluated_dict - - return Evaluation(value, final) if evaluated else None http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/mixins.py ---------------------------------------------------------------------- diff --git a/apache-ariatosca-0.1.1/aria/modeling/mixins.py b/apache-ariatosca-0.1.1/aria/modeling/mixins.py deleted file mode 100644 index 883ff4a..0000000 --- a/apache-ariatosca-0.1.1/aria/modeling/mixins.py +++ /dev/null @@ -1,373 +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. - -""" -ARIA modeling mix-ins module -""" - -from sqlalchemy.ext import associationproxy -from sqlalchemy import ( - Column, - Integer, - Text, - PickleType -) - -from ..parser.consumption import ConsumptionContext -from ..utils import console, collections, caching, formatting -from ..utils.type import canonical_type_name, full_type_name -from . import utils, functions - - -class ModelMixin(object): - - @utils.classproperty - def __modelname__(cls): # pylint: disable=no-self-argument - return getattr(cls, '__mapiname__', cls.__tablename__) - - @classmethod - def id_column_name(cls): - raise NotImplementedError - - @classmethod - def name_column_name(cls): - raise NotImplementedError - - def to_dict(self, fields=None, suppress_error=False): - """ - Create a dict representation of the model. - - :param suppress_error: if set to ``True``, sets ``None`` to attributes that it's unable to - retrieve (e.g., if a relationship wasn't established yet, and so it's impossible to access - a property through it) - """ - - res = dict() - fields = fields or self.fields() - for field in fields: - try: - field_value = getattr(self, field) - except AttributeError: - if suppress_error: - field_value = None - else: - raise - if isinstance(field_value, list): - field_value = list(field_value) - elif isinstance(field_value, dict): - field_value = dict(field_value) - elif isinstance(field_value, ModelMixin): - field_value = field_value.to_dict() - res[field] = field_value - - return res - - @classmethod - def fields(cls): - """ - List of field names for this table. - - Mostly for backwards compatibility in the code (that uses ``fields``). - """ - - fields = set(cls._iter_association_proxies()) - fields.update(cls.__table__.columns.keys()) - return fields - set(getattr(cls, '__private_fields__', ())) - - @classmethod - def _iter_association_proxies(cls): - for col, value in vars(cls).items(): - if isinstance(value, associationproxy.AssociationProxy): - yield col - - def __repr__(self): - return '<{cls} id=`{id}`>'.format( - cls=self.__class__.__name__, - id=getattr(self, self.name_column_name())) - - -class ModelIDMixin(object): - id = Column(Integer, primary_key=True, autoincrement=True, doc=""" - Unique ID. - - :type: :obj:`int` - """) - - name = Column(Text, index=True, doc=""" - Model name. - - :type: :obj:`basestring` - """) - - @classmethod - def id_column_name(cls): - return 'id' - - @classmethod - def name_column_name(cls): - return 'name' - - -class InstanceModelMixin(ModelMixin): - """ - Mix-in for service instance models. - - All models support validation, diagnostic dumping, and representation as raw data (which can be - translated into JSON or YAML) via :meth:`as_raw`. - """ - - @property - def as_raw(self): - raise NotImplementedError - - def validate(self): - pass - - def coerce_values(self, report_issues): - pass - - def dump(self): - pass - - -class TemplateModelMixin(InstanceModelMixin): - """ - Mix-in for service template models. - - All model models can be instantiated into service instance models. - """ - - def instantiate(self, container): - raise NotImplementedError - - -class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods): #pylint: disable=abstract-method - """ - Mix-in for typed values. The value can contain nested intrinsic functions. - - This model can be used as the ``container_holder`` argument for - :func:`~aria.modeling.functions.evaluate`. - """ - - __tablename__ = 'parameter' - - type_name = Column(Text, doc=""" - Type name. - - :type: :obj:`basestring` - """) - - description = Column(Text, doc=""" - Human-readable description. - - :type: :obj:`basestring` - """) - - _value = Column(PickleType) - - @property - def value(self): - value = self._value - if value is not None: - evaluation = functions.evaluate(value, self) - if evaluation is not None: - value = evaluation.value - return value - - @value.setter - def value(self, value): - self._value = value - - @property - @caching.cachedmethod - def owner(self): - """ - The sole owner of this parameter, which is another model that relates to it. - - *All* parameters should have an owner model. - - :raises ~exceptions.ValueError: if failed to find an owner, which signifies an abnormal, - orphaned parameter - """ - - # Find first non-null relationship - for the_relationship in self.__mapper__.relationships: - v = getattr(self, the_relationship.key) - if v: - return v - - raise ValueError('orphaned {class_name}: does not have an owner: {name}'.format( - class_name=type(self).__name__, name=self.name)) - - @property - @caching.cachedmethod - def container(self): # pylint: disable=too-many-return-statements,too-many-branches - """ - The logical container for this parameter, which would be another model: service, node, - group, or policy (or their templates). - - The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in - TOSCA. - - *All* parameters should have a container model. - - :raises ~exceptions.ValueError: if failed to find a container model, which signifies an - abnormal, orphaned parameter - """ - - from . import models - - container = self.owner - - # Extract interface from operation - if isinstance(container, models.Operation): - container = container.interface - elif isinstance(container, models.OperationTemplate): - container = container.interface_template - - # Extract from other models - if isinstance(container, models.Interface): - container = container.node or container.group or container.relationship - elif isinstance(container, models.InterfaceTemplate): - container = container.node_template or container.group_template \ - or container.relationship_template - elif isinstance(container, models.Capability) or isinstance(container, models.Artifact): - container = container.node - elif isinstance(container, models.CapabilityTemplate) \ - or isinstance(container, models.ArtifactTemplate): - container = container.node_template - elif isinstance(container, models.Task): - container = container.actor - - # Extract node from relationship - if isinstance(container, models.Relationship): - container = container.source_node - elif isinstance(container, models.RelationshipTemplate): - container = container.requirement_template.node_template - - if container is not None: - return container - - raise ValueError('orphaned parameter: does not have a container: {0}'.format(self.name)) - - @property - @caching.cachedmethod - def service(self): - """ - The :class:`~aria.modeling.models.Service` model containing this parameter, or ``None`` if - not contained in a service. - - :raises ~exceptions.ValueError: if failed to find a container model, which signifies an - abnormal, orphaned parameter - """ - - from . import models - container = self.container - if isinstance(container, models.Service): - return container - elif hasattr(container, 'service'): - return container.service - return None - - @property - @caching.cachedmethod - def service_template(self): - """ - The :class:`~aria.modeling.models.ServiceTemplate` model containing this parameter, or - ``None`` if not contained in a service template. - - :raises ~exceptions.ValueError: if failed to find a container model, which signifies an - abnormal, orphaned parameter - """ - - from . import models - container = self.container - if isinstance(container, models.ServiceTemplate): - return container - elif hasattr(container, 'service_template'): - return container.service_template - return None - - @property - def as_raw(self): - return collections.OrderedDict(( - ('name', self.name), - ('type_name', self.type_name), - ('value', self.value), - ('description', self.description))) - - def instantiate(self, container): - return self.__class__(name=self.name, # pylint: disable=unexpected-keyword-arg - type_name=self.type_name, - _value=self._value, - description=self.description) - - def coerce_values(self, report_issues): - value = self._value - if value is not None: - evaluation = functions.evaluate(value, self, report_issues) - if (evaluation is not None) and evaluation.final: - # A final evaluation can safely replace the existing value - self._value = evaluation.value - - def dump(self): - context = ConsumptionContext.get_thread_local() - if self.type_name is not None: - console.puts('{0}: {1} ({2})'.format( - context.style.property(self.name), - context.style.literal(formatting.as_raw(self.value)), - context.style.type(self.type_name))) - else: - console.puts('{0}: {1}'.format( - context.style.property(self.name), - context.style.literal(formatting.as_raw(self.value)))) - if self.description: - console.puts(context.style.meta(self.description)) - - @property - def unwrapped(self): - return self.name, self.value - - @classmethod - def wrap(cls, name, value, description=None): - """ - Wraps an arbitrary value as a parameter. The type will be guessed via introspection. - - For primitive types, we will prefer their TOSCA aliases. See the `TOSCA Simple Profile v1.0 - cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01 - /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__ - - :param name: parameter name - :type name: basestring - :param value: parameter value - :param description: human-readable description (optional) - :type description: basestring - """ - - type_name = canonical_type_name(value) - if type_name is None: - type_name = full_type_name(value) - return cls(name=name, # pylint: disable=unexpected-keyword-arg - type_name=type_name, - value=value, - description=description) - - def as_other_parameter_model(self, other_model_cls): - name, value = self.unwrapped - return other_model_cls.wrap(name, value) - - def as_argument(self): - from . import models - return self.as_other_parameter_model(models.Argument)
