From 44a5a1ced136ae7d834a798ec19ac206c5e07ea1 Mon Sep 17 00:00:00 2001 From: Pallab Pain Date: Fri, 26 May 2023 23:11:59 +0530 Subject: [PATCH] feat(project): adds yaspin implementation to project commands --- riocli/project/create.py | 32 +++++++++++++++++------ riocli/project/delete.py | 40 ++++++++++++++++++++--------- riocli/project/features/__init__.py | 5 ++-- riocli/project/features/vpn.py | 30 +++++++++++++++++----- riocli/project/inspect.py | 11 ++++++-- riocli/project/list.py | 19 +++++++++----- riocli/project/model.py | 4 ++- riocli/project/select.py | 28 +++++++++++++++----- riocli/project/util.py | 5 ++-- 9 files changed, 128 insertions(+), 46 deletions(-) diff --git a/riocli/project/create.py b/riocli/project/create.py index f1bc61c4..491323ed 100644 --- a/riocli/project/create.py +++ b/riocli/project/create.py @@ -12,20 +12,33 @@ # See the License for the specific language governing permissions and # limitations under the License. import click -from click_spinner import spinner +from click_help_colors import HelpColorsCommand from riocli.config import new_v2_client +from riocli.constants import Symbols, Colors from riocli.project.util import name_to_organization_guid +from riocli.utils.spinner import with_spinner -@click.command('create') +@click.command( + 'create', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) @click.argument('project-name', type=str) @click.option('--organization', 'organization_name', help='Pass organization name for which project needs to be created. Default will be current organization') @click.pass_context @name_to_organization_guid -def create_project(ctx: click.Context, project_name: str, - organization_guid: str, organization_name: str) -> None: +@with_spinner(text="Creating project...") +def create_project( + ctx: click.Context, + project_name: str, + organization_guid: str, + organization_name: str, + spinner=None, +) -> None: """ Creates a new project """ @@ -45,9 +58,12 @@ def create_project(ctx: click.Context, project_name: str, try: client = new_v2_client(with_project=False) - with spinner(): - client.create_project(payload) - click.secho('Project created successfully!', fg='green') + client.create_project(payload) + spinner.text = click.style( + 'Project created successfully.', fg=Colors.GREEN) + spinner.green.ok(Symbols.SUCCESS) except Exception as e: - click.secho('failed to create project: {}'.format(e), fg='red') + spinner.text = click.style( + 'Failed to create project: {}'.format(e), Colors.RED) + spinner.red.fail(Symbols.ERROR) raise SystemExit(1) diff --git a/riocli/project/delete.py b/riocli/project/delete.py index 16637def..73800679 100644 --- a/riocli/project/delete.py +++ b/riocli/project/delete.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# Copyright 2023 Rapyuta Robotics # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,31 +12,47 @@ # See the License for the specific language governing permissions and # limitations under the License. import click -from click_spinner import spinner +from click_help_colors import HelpColorsCommand from riocli.config import new_v2_client +from riocli.constants import Symbols, Colors from riocli.project.util import name_to_guid +from riocli.utils.spinner import with_spinner -@click.command('delete') +@click.command( + 'delete', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) @click.option('--force', '-f', '--silent', 'force', is_flag=True, help='Skip confirmation') @click.argument('project-name', type=str) @name_to_guid -def delete_project(force: bool, project_name: str, project_guid: str) -> None: +@with_spinner(text="Deleting project...") +def delete_project( + force: bool, + project_name: str, + project_guid: str, + spinner=None, +) -> None: """ - Deletes the project from the Platform + Deletes a project """ if not force: - click.confirm( - 'Deleting project {} ({})'.format(project_name, project_guid), - abort=True) + with spinner.hidden(): + click.confirm('Deleting project {} ({})'.format( + project_name, project_guid), abort=True) try: client = new_v2_client() - with spinner(): - client.delete_project(project_guid) - click.secho('Project deleted successfully!', fg='green') + client.delete_project(project_guid) + spinner.text = click.style( + 'Project deleted successfully.', fg=Colors.GREEN) + spinner.green.ok(Symbols.SUCCESS) except Exception as e: - click.secho('failed to delete project: {}'.format(e), fg='red') + spinner.text = click.style( + 'Failed to delete project: {}'.format(e), Colors.RED) + spinner.red.fail(Symbols.ERROR) raise SystemExit(1) diff --git a/riocli/project/features/__init__.py b/riocli/project/features/__init__.py index d6147e5e..95e011ba 100644 --- a/riocli/project/features/__init__.py +++ b/riocli/project/features/__init__.py @@ -14,14 +14,15 @@ import click from click_help_colors import HelpColorsGroup +from riocli.constants import Colors from riocli.project.features.vpn import vpn @click.group( invoke_without_command=False, cls=HelpColorsGroup, - help_headers_color='yellow', - help_options_color='green', + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, ) def features(): """ diff --git a/riocli/project/features/vpn.py b/riocli/project/features/vpn.py index 07cd7447..bf3fe261 100644 --- a/riocli/project/features/vpn.py +++ b/riocli/project/features/vpn.py @@ -12,16 +12,30 @@ # See the License for the specific language governing permissions and # limitations under the License. import click +from click_help_colors import HelpColorsCommand from riocli.config import new_v2_client +from riocli.constants import Colors, Symbols from riocli.project.util import name_to_guid +from riocli.utils.spinner import with_spinner -@click.command('vpn') +@click.command( + 'vpn', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) @click.argument('project-name', type=str) @click.argument('enable', type=bool) @name_to_guid -def vpn(project_name: str, project_guid: str, enable: bool) -> None: +@with_spinner() +def vpn( + project_name: str, + project_guid: str, + enable: bool, + spinner=None, +) -> None: """ Enable or disable VPN on a project @@ -40,10 +54,14 @@ def vpn(project_name: str, project_guid: str, enable: bool) -> None: } } + state = 'Enabling' if enable else 'Disabling' + spinner.text = click.style('{} VPN...'.format(state), fg=Colors.YELLOW) + try: - r = client.update_project(project_guid, body) + client.update_project(project_guid, body) + spinner.text = click.style('Done', fg=Colors.GREEN) + spinner.green.ok(Symbols.SUCCESS) except Exception as e: - click.secho("❌ Failed: {}".format(e), fg='red') + spinner.text = click.style("Failed: {}".format(e), fg=Colors.RED) + spinner.red.fail(Symbols.ERROR) raise SystemExit(1) from e - - click.secho("✅ VPN has been {}".format("enabled" if enable else "disabled"), fg='green') diff --git a/riocli/project/inspect.py b/riocli/project/inspect.py index fda1f807..6c6426fd 100644 --- a/riocli/project/inspect.py +++ b/riocli/project/inspect.py @@ -12,14 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. import click +from click_help_colors import HelpColorsCommand from munch import unmunchify from riocli.config import new_v2_client +from riocli.constants import Colors from riocli.project.util import name_to_guid from riocli.utils import inspect_with_format -@click.command('inspect') +@click.command( + 'inspect', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) @click.option('--format', '-f', 'format_type', default='yaml', type=click.Choice(['json', 'yaml'], case_sensitive=False)) @click.argument('project-name', type=str) @@ -34,5 +41,5 @@ def inspect_project(format_type: str, project_name: str, project = client.get_project(project_guid) inspect_with_format(unmunchify(project), format_type) except Exception as e: - click.secho(str(e), fg='red') + click.secho(str(e), fg=Colors.RED) raise SystemExit(1) diff --git a/riocli/project/list.py b/riocli/project/list.py index c63955ee..20faa534 100644 --- a/riocli/project/list.py +++ b/riocli/project/list.py @@ -14,15 +14,22 @@ import typing import click +from click_help_colors import HelpColorsCommand from munch import unmunchify from rapyuta_io import Project from riocli.config import new_v2_client +from riocli.constants import Colors from riocli.project.util import name_to_organization_guid from riocli.utils import tabulate_data -@click.command('list') +@click.command( + 'list', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) @click.option('--organization', 'organization_name', help='Pass organization name for which project needs to be created. Default will be current organization') @click.option('--wide', '-w', is_flag=True, default=False, @@ -41,7 +48,7 @@ def list_project(ctx: click.Context = None, organization_guid: str = None, current = ctx.obj.data.get('project_id', None) _display_project_list(projects, current, show_header=True, wide=wide) except Exception as e: - click.secho(str(e), fg='red') + click.secho(str(e), fg=Colors.RED) raise SystemExit(1) @@ -57,14 +64,14 @@ def _display_project_list(projects: typing.List[Project], current: str = None, data = [] for project in projects: metadata = project.metadata - fg = None + fg, bold = None, False if metadata.guid == current: - fg = 'green' - + fg = Colors.GREEN + bold = True row = [metadata.guid, metadata.name, project.status.status] if wide: row.extend([metadata.createdAt, metadata.creatorGUID, unmunchify(project.spec.features)]) - data.append([click.style(v, fg=fg) for v in row]) + data.append([click.style(v, fg=fg, bold=bold) for v in row]) tabulate_data(data, headers) diff --git a/riocli/project/model.py b/riocli/project/model.py index e7af5df5..3b9796b5 100644 --- a/riocli/project/model.py +++ b/riocli/project/model.py @@ -23,6 +23,7 @@ PROJECT_READY_TIMEOUT = 150 + class Project(Model): def __init__(self, *args, **kwargs): @@ -52,7 +53,8 @@ def create_object(self, client: Client) -> typing.Any: r = client.create_project(project) try: - wait(self.is_ready, timeout_seconds=PROJECT_READY_TIMEOUT, sleep_seconds=(1, 30, 2)) + wait(self.is_ready, timeout_seconds=PROJECT_READY_TIMEOUT, + sleep_seconds=(1, 30, 2)) except TimeoutExpired as e: raise e diff --git a/riocli/project/select.py b/riocli/project/select.py index 321cc4d6..4a565c5a 100644 --- a/riocli/project/select.py +++ b/riocli/project/select.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# Copyright 2023 Rapyuta Robotics # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,24 +12,38 @@ # See the License for the specific language governing permissions and # limitations under the License. import click +from click_help_colors import HelpColorsCommand +from riocli.constants import Colors, Symbols from riocli.project.util import name_to_guid from riocli.utils.context import get_root_context -@click.command('select') +@click.command( + 'select', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) @click.argument('project-name', type=str) @name_to_guid @click.pass_context -def select_project(ctx: click.Context, project_name: str, - project_guid: str) -> None: +def select_project( + ctx: click.Context, + project_name: str, + project_guid: str, +) -> None: """ Sets the given project in the CLI context. All other resources use this project to act upon. """ ctx = get_root_context(ctx) + ctx.obj.data['project_id'] = project_guid ctx.obj.data['project_name'] = project_name ctx.obj.save() - click.secho( - 'Project {} ({}) is selected!'.format(project_name, project_guid), - fg='green') + + click.secho('{} Project {} ({}) is selected!'.format( + Symbols.SUCCESS, + project_name, + project_guid), + fg=Colors.GREEN) diff --git a/riocli/project/util.py b/riocli/project/util.py index 75ba5fe9..5c910929 100644 --- a/riocli/project/util.py +++ b/riocli/project/util.py @@ -18,6 +18,7 @@ from rapyuta_io import Client from riocli.config import new_client, new_v2_client +from riocli.constants import Colors from riocli.utils.selector import show_selection from riocli.v2client import Client as v2Client @@ -40,7 +41,7 @@ def decorated(**kwargs: typing.Any): try: guid = find_project_guid(client, name) except Exception as e: - click.secho(str(e), fg='red') + click.secho(str(e), fg=Colors.RED) raise SystemExit(1) kwargs['project_name'] = name @@ -110,7 +111,7 @@ def decorated(*args: typing.Any, **kwargs: typing.Any): else: guid = find_organization_guid(client, name) except Exception as e: - click.secho(str(e), fg='red') + click.secho(str(e), fg=Colors.RED) raise SystemExit(1) kwargs['organization_name'] = name kwargs['organization_guid'] = guid