Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id E1DAB200C61 for ; Tue, 25 Apr 2017 15:27:28 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id E06BD160BB3; Tue, 25 Apr 2017 13:27:28 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id DA164160B9E for ; Tue, 25 Apr 2017 15:27:27 +0200 (CEST) Received: (qmail 95622 invoked by uid 500); 25 Apr 2017 13:27:24 -0000 Mailing-List: contact dev-help@ariatosca.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ariatosca.incubator.apache.org Delivered-To: mailing list dev@ariatosca.incubator.apache.org Received: (qmail 95575 invoked by uid 99); 25 Apr 2017 13:27:24 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Apr 2017 13:27:24 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 2F03E1B08B8 for ; Tue, 25 Apr 2017 13:27:24 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.22 X-Spam-Level: X-Spam-Status: No, score=-4.22 tagged_above=-999 required=6.31 tests=[HK_RANDOM_FROM=0.001, KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id qdbTMZK-nfOe for ; Tue, 25 Apr 2017 13:27:21 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 78CA260E01 for ; Tue, 25 Apr 2017 13:27:17 +0000 (UTC) Received: (qmail 92773 invoked by uid 99); 25 Apr 2017 13:27:16 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Apr 2017 13:27:16 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 89EC6E00C5; Tue, 25 Apr 2017 13:27:16 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mxmrlv@apache.org To: dev@ariatosca.incubator.apache.org Message-Id: <4cdc813cb5c5437e9b55c9680b46f639@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: incubator-ariatosca git commit: wip [Forced Update!] Date: Tue, 25 Apr 2017 13:27:16 +0000 (UTC) archived-at: Tue, 25 Apr 2017 13:27:29 -0000 Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-146-Support-colorful-execution-logging 18046aac3 -> 2dd9830f5 (forced update) wip Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/2dd9830f Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/2dd9830f Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/2dd9830f Branch: refs/heads/ARIA-146-Support-colorful-execution-logging Commit: 2dd9830f5b7ef7deace4fe1ff92e0013212c857f Parents: b69a459 Author: max-orlov Authored: Tue Apr 25 11:02:30 2017 +0300 Committer: max-orlov Committed: Tue Apr 25 16:27:08 2017 +0300 ---------------------------------------------------------------------- aria/cli/color.py | 73 ++++++++++++ aria/cli/config/config_template.yaml | 1 - aria/cli/execution_logging.py | 113 ++++++++++--------- aria/cli/logger.py | 17 --- .../execution_plugin/ssh/operations.py | 5 - 5 files changed, 134 insertions(+), 75 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2dd9830f/aria/cli/color.py ---------------------------------------------------------------------- diff --git a/aria/cli/color.py b/aria/cli/color.py new file mode 100644 index 0000000..77bfe77 --- /dev/null +++ b/aria/cli/color.py @@ -0,0 +1,73 @@ +# 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. +from StringIO import StringIO + +import colorama + +colorama.init() + + +def _get_colors(color_type): + for name in dir(color_type): + if not name.startswith('_'): + yield (name.lower(), getattr(color_type, name)) + + +class Color(object): + Fore = colorama.Fore + Back = colorama.Back + Style = colorama.Style + + _colors = { + 'fore': dict(_get_colors(Fore)), + 'back': dict(_get_colors(Back)), + 'style': dict(_get_colors(Style)) + } + + class Schema(object): + def __init__(self, **kwargs): + """ + It is possible to provide fore, back and style arguments. each could be either + the color is lower case letter, or the actual color from colorama. + + """ + assert all(arg in Color._colors for arg in kwargs) + self._kwargs = kwargs + self._str = StringIO() + for type_, colors in Color._colors.items(): + value = kwargs.pop(type_, None) + # the former case is if the value is a string, the latter is in case of an object. + self._str.write(colors.get(value) or value) + + def __str__(self): + return self._str.getvalue() + + def __add__(self, other): + return str(self) + str(other) + + def __radd__(self, other): + return str(other) + str(self) + + @classmethod + def stylize(cls, str_to_stylize, schema): + return schema + str(str_to_stylize) + cls.Style.RESET_ALL + + @classmethod + def markup(cls, str_to_stylize, matches, schema): + modified_str = str_to_stylize + for group_index in xrange(len(matches.regs)): + match = matches.group(group_index) + modified_str = modified_str.replace(match, schema + match + cls.Back.RESET) + return modified_str http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2dd9830f/aria/cli/config/config_template.yaml ---------------------------------------------------------------------- diff --git a/aria/cli/config/config_template.yaml b/aria/cli/config/config_template.yaml index 13f2cf9..66c606e 100644 --- a/aria/cli/config/config_template.yaml +++ b/aria/cli/config/config_template.yaml @@ -1,4 +1,3 @@ -colors: {{ enable_colors }} logging: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2dd9830f/aria/cli/execution_logging.py ---------------------------------------------------------------------- diff --git a/aria/cli/execution_logging.py b/aria/cli/execution_logging.py index 9631d30..ca966ec 100644 --- a/aria/cli/execution_logging.py +++ b/aria/cli/execution_logging.py @@ -16,9 +16,9 @@ import os import re from StringIO import StringIO from contextlib import contextmanager -from functools import partial from . import logger +from .color import Color from .env import env @@ -29,16 +29,17 @@ IMPLEMENTATION = 'implementation' INPUTS = 'inputs' TRACEBACK = 'traceback' MARKER = 'marker' + FINAL_STATES = 'final_states' SUCCESS_STATE = 'success' CANCEL_STATE = 'cancel' FAIL_STATE = 'fail' -EXECUTION_BASE_PATTERN = "\'.*\' workflow execution " -SUCCESSFUL_EXECUTION_PATTERN = EXECUTION_BASE_PATTERN + "succeeded" -FAILED_EXECUTION_PATTERN = EXECUTION_BASE_PATTERN + "failed" -CANCELED_EXECUTION_PATTERN = EXECUTION_BASE_PATTERN + "canceled" +_EXECUTION_BASE_PATTERN = "\'.*\' workflow execution " +_SUCCESSFUL_EXECUTION_PATTERN = _EXECUTION_BASE_PATTERN + "succeeded" +_FAILED_EXECUTION_PATTERN = _EXECUTION_BASE_PATTERN + "failed" +_CANCELED_EXECUTION_PATTERN = _EXECUTION_BASE_PATTERN + "canceled" DEFAULT_FORMATTING = { logger.NO_VERBOSE: {'message': '{message}'}, @@ -61,44 +62,44 @@ DEFAULT_FORMATTING = { DEFAULT_STYLING = { LEVEL: { - 'info': '{{ FORE.LIGHTMAGENTA_EX }}', - 'debug': '{{ FORE.LIGHTMAGENTA_EX}{STYLE.DIM }}', - 'error': '{{ FORE.RED }}{{ STYLE.BRIGHT }}' + 'info': Color.Fore.LIGHTMAGENTA_EX, + 'debug': Color.Schema(fore=Color.Fore.LIGHTMAGENTA_EX, style=Color.Style.DIM), + 'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT), }, TIMESTAMP: { - 'info': '{{ FORE.LIGHTMAGENTA_EX }}', - 'debug': '{{ FORE.LIGHTMAGENTA_EX }}{{ STYLE.DIM }}', - 'error': '{{ FORE.RED }}{{ STYLE.BRIGHT }}' + 'info': Color.Fore.LIGHTMAGENTA_EX, + 'debug': Color.Schema(fore=Color.Fore.LIGHTMAGENTA_EX, style=Color.Style.DIM), + 'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT), }, MESSAGE: { - 'info': '{{ FORE.LIGHTBLUE_EX }}', - 'debug': '{{ FORE.LIGHTBLUE_EX }}{{ STYLE.DIM }}', - 'error': '{{ FORE.RED }}{{ STYLE.BRIGHT }}' + 'info': Color.Fore.LIGHTBLUE_EX, + 'debug': Color.Schema(fore=Color.Fore.LIGHTBLUE_EX, style=Color.Style.DIM), + 'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT), }, IMPLEMENTATION: { - 'info': '{{ FORE.LIGHTBLACK_EX }}', - 'debug': '{{ FORE.LIGHTBLACK_EX }}{{ STYLE.DIM }}', - 'error': '{{ FORE.RED }}{{ STYLE.BRIGHT }}' + 'info': Color.Fore.LIGHTBLACK_EX, + 'debug': Color.Schema(fore=Color.Fore.LIGHTBLACK_EX, style=Color.Style.DIM), + 'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT), }, INPUTS: { - 'info': '{{ FORE.BLUE }}', - 'debug': '{{ FORE.BLUE }}{{ STYLE.DIM }}', - 'error': '{{ FORE.RED }}{{ STYLE.BRIGHT }}', + 'info': Color.Fore.BLUE, + 'debug': Color.Schema(fore=Color.Fore.BLUE, style=Color.Style.DIM), + 'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT), }, - TRACEBACK: {'error': '{{ FORE.RED }}'}, + TRACEBACK: {'error': Color.Fore.RED}, - MARKER: '{{ BACK.LIGHTYELLOW_EX }}', + MARKER: Color.Back.LIGHTYELLOW_EX, FINAL_STATES: { - SUCCESS_STATE: '{{ FORE.GREEN }}', - CANCEL_STATE: '{{ FORE.YELLOW }}', - FAIL_STATE: '{{ FORE.RED }}', + SUCCESS_STATE: Color.Fore.GREEN, + CANCEL_STATE: Color.Fore.YELLOW, + FAIL_STATE: Color.Fore.RED, } } _PATTERNS = { - SUCCESS_STATE: re.compile(SUCCESSFUL_EXECUTION_PATTERN), - CANCEL_STATE: re.compile(CANCELED_EXECUTION_PATTERN), - FAIL_STATE: re.compile(FAILED_EXECUTION_PATTERN) + SUCCESS_STATE: re.compile(_SUCCESSFUL_EXECUTION_PATTERN), + CANCEL_STATE: re.compile(_CANCELED_EXECUTION_PATTERN), + FAIL_STATE: re.compile(_FAILED_EXECUTION_PATTERN) } @@ -115,32 +116,40 @@ class _StylizedLogs(object): self._formats = formats or self._formats self._mark_pattern = mark_pattern - def __getattr__(self, item): - return partial(self._stylize, msg_type=item[1:]) + def _implementation(self, implementation, log_item): + return self._stylize(implementation, log_item, IMPLEMENTATION) + + def _inputs(self, inputs, log_item): + return self._stylize(inputs, log_item, INPUTS) + + def _timestamp(self, timestamp, log_item): + return self._stylize(timestamp, log_item, TIMESTAMP) + + def _message(self, message, log_item): + return self._stylize(message, log_item, MESSAGE) + + def _traceback(self, traceback, log_item): + return self._stylize(traceback, log_item, TRACEBACK) def _level(self, log_item): return self._stylize(log_item.level[0], log_item, LEVEL) def _stylize(self, msg, log_item, msg_type): - string_marker = (self._final_string_marker(log_item.msg) or - self._styles[msg_type].get(log_item.level.lower(), '')) - return logger.Color.render_str(string_marker + str(msg) + '{{ STYLE.RESET_ALL }}') + schema = (self._final_string_schema(log_item.msg) or + self._styles[msg_type].get(log_item.level.lower(), '')) + return Color.stylize(msg, schema) def _markup(self, str_, original_message): if self._mark_pattern is None: return str_ else: regex_pattern = re.compile(self._mark_pattern) - if not re.match(regex_pattern, original_message): + matches = re.search(regex_pattern, original_message) + if not matches: return str_ - marker = self._styles[MARKER] - return logger.Color.render_str( - marker + - str_.replace(logger.Color.STYLE.RESET_ALL, '{{ STYLE.RESET_ALL }}' + marker) + - '{{ STYLE.RESET_ALL }}' - ) - - def _final_string_marker(self, original_message): + return Color.markup(str_, matches, self._styles[MARKER]) + + def _final_string_schema(self, original_message): for state, pattern in _PATTERNS.items(): if re.match(pattern, original_message): return self._styles[FINAL_STATES][state] @@ -165,8 +174,10 @@ class _StylizedLogs(object): implementation = item.execution.workflow_name inputs = dict(i.unwrap() for i in item.execution.inputs.values()) - formatting_kwargs['implementation'] = self._implementation(implementation, item) - formatting_kwargs['inputs'] = self._inputs(inputs, item) + formatting_kwargs['implementation'] = self._markup( + self._implementation(implementation, item), implementation) + formatting_kwargs['inputs'] = self._markup(self._inputs(inputs, item), str(inputs)) + # timestamp if 'timestamp' in formatting: timestamp = item.created_at.strftime(formatting['timestamp']) @@ -189,20 +200,20 @@ class _StylizedLogs(object): return msg.getvalue() -stylize_log = _StylizedLogs() +_stylize_log = _StylizedLogs() @contextmanager def format(styles=None, formats=None, mark_pattern=None): - original_styles = stylize_log._styles - original_formats = stylize_log._formats - stylize_log._push(styles=styles, formats=formats, mark_pattern=mark_pattern) + original_styles = _stylize_log._styles + original_formats = _stylize_log._formats + _stylize_log._push(styles=styles, formats=formats, mark_pattern=mark_pattern) yield - stylize_log._push(styles=original_styles, formats=original_formats, mark_pattern=None) + _stylize_log._push(styles=original_styles, formats=original_formats, mark_pattern=None) def log(item, *args, **kwargs): - return getattr(env.logging.logger, item.level.lower())(stylize_log(item), *args, **kwargs) + return getattr(env.logging.logger, item.level.lower())(_stylize_log(item), *args, **kwargs) def log_list(iterator): @@ -211,5 +222,3 @@ def log_list(iterator): log(item) any_logs = True return any_logs - - http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2dd9830f/aria/cli/logger.py ---------------------------------------------------------------------- diff --git a/aria/cli/logger.py b/aria/cli/logger.py index cac5d2e..5de3701 100644 --- a/aria/cli/logger.py +++ b/aria/cli/logger.py @@ -19,10 +19,6 @@ import copy import logging from logutils import dictconfig -import colorama -from jinja2.environment import Template - - HIGH_VERBOSE = 3 MEDIUM_VERBOSE = 2 LOW_VERBOSE = 1 @@ -133,16 +129,3 @@ class ModelLogIterator(object): for log in self._model_storage.log.iter(filters=filters, sort=self._sort): self._last_visited_id = log.id yield log - -colorama.init() - - -class Color(object): - FORE = colorama.Fore - BACK = colorama.Back - STYLE = colorama.Style - - @classmethod - def render_str(cls, str_to_stylize): - str_template = Template(str_to_stylize) - return str_template.render(FORE=cls.FORE, BACK=cls.BACK, STYLE=cls.STYLE) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2dd9830f/aria/orchestrator/execution_plugin/ssh/operations.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/execution_plugin/ssh/operations.py b/aria/orchestrator/execution_plugin/ssh/operations.py index 04ae0ea..7147a30 100644 --- a/aria/orchestrator/execution_plugin/ssh/operations.py +++ b/aria/orchestrator/execution_plugin/ssh/operations.py @@ -144,11 +144,6 @@ def _fabric_env(ctx, fabric_env, warn_only): env.update(fabric_env or {}) env.setdefault('warn_only', warn_only) # validations - - env['host_string'] = \ - ctx.model.node_template.get_by_name('virtual_ip').nodes[0].runtime_properties[ - 'floating_ip_address'] - if (not env.get('host_string')) and (ctx.task) and (ctx.task.actor) and (ctx.task.actor.host): env['host_string'] = ctx.task.actor.host.host_address if not env.get('host_string'):