Skip to content

Commit

Permalink
Add options in ecctool to colored output - Issue Ericsson#527
Browse files Browse the repository at this point in the history
  • Loading branch information
Victor Cavichioli committed Mar 25, 2024
1 parent c924e7e commit e3ca625
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 66 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Version 5.0.1

* Colored output in ecctool - Issue #527
* Improve hang preventing task - Issue #544
* Improve Description of unwind_ratio - Issue #628

Expand Down
12 changes: 12 additions & 0 deletions docs/autogenerated/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Schedule'
/repair-management/v2/running-job:
get:
tags:
- Repair-Management
operationId: getCurrentJobStatus
responses:
"200":
description: OK
content:
application/json:
schema:
type: string
/repair-management/v2/repairs/{id}:
get:
tags:
Expand Down
4 changes: 3 additions & 1 deletion ecchronos-binary/generate-ecctool-doc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ fi

pip install sphinx
pip install sphinxcontrib-autoprogram
pip install sphinxnotes-markdown-builder
pip install sphinxnotes-markdown-builder]
pip install colorama
pip install supports-color

sphinx-build -M markdown ${SCRIPT_DIR}/src ${SCRIPT_DIR}/target/
sed -i 's:<:\&lt;:g' ${SCRIPT_DIR}/target/markdown/index.md
Expand Down
36 changes: 29 additions & 7 deletions ecchronos-binary/src/bin/ecctool.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ def add_repairs_subcommand(sub_parsers):
parser_repairs = sub_parsers.add_parser("repairs",
description="Show the status of all manual repairs. This subcommand has "
"no mandatory parameters.")
parser_repairs.add_argument("-c", "--colors", type=str,
help="Allow colored output by ecctool schedules, the option can be auto/on/off.",
default="auto")
parser_repairs.add_argument("-k", "--keyspace", type=str,
help="Show repairs for the specified keyspace. This argument is mutually exclusive "
"with -i and --id.")
Expand All @@ -92,6 +95,9 @@ def add_schedules_subcommand(sub_parsers):
parser_schedules = sub_parsers.add_parser("schedules",
description="Show the status of schedules. This subcommand has no "
"mandatory parameters.")
parser_schedules.add_argument("-c", "--colors", type=str,
help="Allow colored output by ecctool schedules, the option can be auto/on/off.",
default="auto")
parser_schedules.add_argument("-k", "--keyspace", type=str,
help="Show schedules for the specified keyspace. This argument is mutually "
"exclusive with -i and --id.")
Expand Down Expand Up @@ -151,6 +157,9 @@ def add_repair_info_subcommand(sub_parsers):
"specific table using --keyspace and --table, "
"the duration will default to the table's "
"GC_GRACE_SECONDS.")
parser_repair_info.add_argument("-c", "--colors", type=str,
help="Allow colored output by ecctool schedules, the option can be auto/on/off.",
default="auto")
parser_repair_info.add_argument("-k", "--keyspace", type=str,
help="Show repair information for all tables in the specified keyspace.")
parser_repair_info.add_argument("-t", "--table", type=str,
Expand Down Expand Up @@ -214,6 +223,7 @@ def schedules(arguments):
# pylint: disable=too-many-branches
request = rest.V2RepairSchedulerRequest(base_url=arguments.url)
full = False
colors = color_option(arguments.colors)
if arguments.id:
if arguments.full:
result = request.get_schedule(job_id=arguments.id, full=True)
Expand All @@ -222,7 +232,7 @@ def schedules(arguments):
result = request.get_schedule(job_id=arguments.id)

if result.is_successful():
table_printer.print_schedule(result.data, arguments.limit, full)
table_printer.print_schedule(result.data, arguments.limit, full, colors)
else:
print(result.format_exception())
elif arguments.full:
Expand All @@ -234,23 +244,25 @@ def schedules(arguments):
sys.exit(1)
result = request.list_schedules(keyspace=arguments.keyspace, table=arguments.table)
if result.is_successful():
table_printer.print_schedules(result.data, arguments.limit)
table_printer.print_schedules(result.data, arguments.limit, colors)
else:
print(result.format_exception())
else:
result = request.list_schedules(keyspace=arguments.keyspace)
if result.is_successful():
table_printer.print_schedules(result.data, arguments.limit)
table_printer.print_schedules(result.data, arguments.limit, colors)
else:
print(result.format_exception())


def repairs(arguments):
request = rest.V2RepairSchedulerRequest(base_url=arguments.url)
colors = color_option(arguments.colors)

if arguments.id:
result = request.get_repair(job_id=arguments.id, host_id=arguments.hostid)
if result.is_successful():
table_printer.print_repairs(result.data, arguments.limit)
table_printer.print_repairs(result.data, arguments.limit, colors)
else:
print(result.format_exception())
elif arguments.table:
Expand All @@ -259,13 +271,13 @@ def repairs(arguments):
sys.exit(1)
result = request.list_repairs(keyspace=arguments.keyspace, table=arguments.table, host_id=arguments.hostid)
if result.is_successful():
table_printer.print_repairs(result.data, arguments.limit)
table_printer.print_repairs(result.data, arguments.limit, colors)
else:
print(result.format_exception())
else:
result = request.list_repairs(keyspace=arguments.keyspace, host_id=arguments.hostid)
if result.is_successful():
table_printer.print_repairs(result.data, arguments.limit)
table_printer.print_repairs(result.data, arguments.limit, colors)
else:
print(result.format_exception())

Expand All @@ -285,6 +297,7 @@ def run_repair(arguments):

def repair_info(arguments):
request = rest.V2RepairSchedulerRequest(base_url=arguments.url)
colors = color_option(arguments.colors)
if not arguments.keyspace and arguments.table:
print("--keyspace must be specified if table is specified")
sys.exit(1)
Expand All @@ -301,7 +314,7 @@ def repair_info(arguments):
since=arguments.since, duration=duration,
local=arguments.local)
if result.is_successful():
table_printer.print_repair_info(result.data, arguments.limit)
table_printer.print_repair_info(result.data, arguments.limit, colors)
else:
print(result.format_exception())

Expand Down Expand Up @@ -382,7 +395,16 @@ def running_job(arguments):
result = request.running_job()
print(result)

def color_option(color_arg):
colors = "auto"

if color_arg in ["auto", "on", "off"]:
if color_arg != colors:
colors = color_arg
else:
print(f"'{color_arg}' is not an valid option, it should be auto/on/off.")
print("Using 'auto' as a color option.")
return colors

def run_subcommand(arguments):
if arguments.subcommand == "repairs":
Expand Down
80 changes: 80 additions & 0 deletions ecchronos-binary/src/pylib/ecchronoslib/displaying.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from colorama import Fore, init
from supports_color import supportsColor

init(autoreset=True)

RED = Fore.RED
GREEN = Fore.GREEN
BLUE = Fore.BLUE
YELLOW = Fore.YELLOW
MAGENTA = Fore.MAGENTA
CYAN = Fore.CYAN
RESET = Fore.RESET
DARK_MAGENTA = '\033[0;35m'

color_map = {
"Id": RED,
"Host Id": RED,
"Keyspace": CYAN,
"Table": CYAN,
"Status": MAGENTA,
"Repaired(%)": MAGENTA,
"Completed at": MAGENTA,
"Next repair": MAGENTA,
"Repair type": MAGENTA,
"Start token": GREEN,
"End token": RED,
"Replicas": CYAN,
"Repaired at": GREEN,
"Repaired": CYAN,
"Repair time taken": GREEN,
"Config": MAGENTA,
"UUID": GREEN,
"FLOAT": CYAN,
"DATETIME": GREEN,
"INT": YELLOW,
"TEXT": YELLOW,
"COMPLETED": GREEN,
"IN_QUEUE": CYAN,
"BLOCKED": MAGENTA,
"WARNING": YELLOW,
"ERROR": RED,
"ON_TIME": BLUE,
"LATE": YELLOW,
"OVERDUE": YELLOW,
"Collection": MAGENTA
}

def color_str(field, color, field_type):
if should_color(color):
colored_str = color_map[field_type] + str(field) + RESET
return colored_str
return field

def color_key(key, color):
if should_color(color):
colored_str = color_map[key] + str(key) + RESET
return colored_str
return key

def color_index(summary, color):
if should_color(color):
colored_summary = []
for collum in summary:
colored_collum = color_map[collum] + collum + RESET
colored_summary.append(colored_collum)
return colored_summary
return summary

def verify_system_compatibility() -> bool:
if supportsColor.stdout:
return True
return False

def should_color(color) -> bool:
should_colorize = False
if color == "auto":
should_colorize = verify_system_compatibility()
if color == "on":
should_colorize = True
return should_colorize
8 changes: 5 additions & 3 deletions ecchronos-binary/src/pylib/ecchronoslib/table_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

from __future__ import print_function


def calculate_max_len(data, i):
max_len = 0
for array in data:
Expand All @@ -24,17 +23,20 @@ def calculate_max_len(data, i):
return max_len


def format_table(data):
def format_table(data, colors):
if len(data) <= 0:
return

print_format = "| "
total_length = 2

for idx, _ in enumerate(data[0]):
remove_str = 0
if colors:
remove_str = 10 # remove ANSI extra strings
max_len = calculate_max_len(data, idx)
print_format = "{0}{{{1}:{2}s}} | ".format(print_format, idx, max_len)
total_length += max_len + 3
total_length += max_len + 3 - remove_str
total_length -= 1 # Last space is not counted

print("-" * total_length)
Expand Down
Loading

0 comments on commit e3ca625

Please sign in to comment.