Skip to content

Commit

Permalink
feat(parameter): adds spinner and constants
Browse files Browse the repository at this point in the history
This commit updates the parameter commands with the new spinner and
replaces literals with constants wherever applicable.
  • Loading branch information
pallabpain committed Aug 3, 2023
1 parent 8ad2cad commit a4f954e
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 93 deletions.
17 changes: 7 additions & 10 deletions riocli/parameter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import click
from click_help_colors import HelpColorsGroup

from riocli.constants import Colors
from riocli.parameter.apply import apply_configurations
from riocli.parameter.delete import delete_configurations
from riocli.parameter.diff import diff_configurations
Expand All @@ -23,26 +24,22 @@
from riocli.parameter.upload import upload_configurations


# from riocli.parameter.diff import diff_configurations
# from riocli.parameter.download import download_configurations


@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 parameter() -> None:
"""
Define groups of executables to deploy together
Manage configuration parameters for your devices and deployments
"""
pass


parameter.add_command(upload_configurations)
parameter.add_command(download_configurations)
parameter.add_command(diff_configurations)
parameter.add_command(apply_configurations)
parameter.add_command(list_configuration_trees)
parameter.add_command(delete_configurations)
parameter.add_command(upload_configurations)
parameter.add_command(download_configurations)
parameter.add_command(list_configuration_trees)
54 changes: 39 additions & 15 deletions riocli/parameter/apply.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -14,22 +14,35 @@
import typing

import click
from click_help_colors import HelpColorsCommand
from yaspin import kbi_safe_yaspin

from riocli.config import new_client
from riocli.constants import Colors, Symbols
from riocli.utils import tabulate_data, print_separator


@click.command('apply')
@click.command(
'apply',
cls=HelpColorsCommand,
help_headers_color=Colors.YELLOW,
help_options_color=Colors.GREEN,
)
@click.option('--devices', type=click.STRING, multiple=True, default=(),
help='Device names to apply configurations')
@click.option('--tree-names', type=click.STRING, multiple=True, default=None,
help='Tree names to apply')
@click.option('--retry-limit', type=click.INT, default=0,
help='Retry limit')
@click.option('-f', '--force', '--silent', 'silent', is_flag=True, type=click.BOOL, default=False,
@click.option('-f', '--force', '--silent', 'silent', is_flag=True,
type=click.BOOL, default=False,
help="Skip confirmation")
def apply_configurations(devices: typing.List, tree_names: str = None, retry_limit: int = 0,
silent: bool = False) -> None:
def apply_configurations(
devices: typing.List,
tree_names: str = None,
retry_limit: int = 0,
silent: bool = False,
) -> None:
"""
Apply a set of configurations to a list of devices
"""
Expand All @@ -40,27 +53,38 @@ def apply_configurations(devices: typing.List, tree_names: str = None, retry_lim
device_map = {d.name: d for d in online_devices}

if devices:
device_ids = {device_map[d].uuid: d for d in devices if d in device_map}
device_ids = {device_map[d].uuid: d for d in devices if
d in device_map}
else:
device_ids = {v.uuid: k for k, v in device_map.items()}

if not device_ids:
click.secho("invalid devices or no device is currently online", fg='red')
click.secho(
"{} Invalid devices or no device is currently online".format(
Symbols.ERROR),
fg=Colors.RED)
raise SystemExit(1)

click.secho('Online Devices: {}'.format(','.join(device_ids.values())), fg='green')
click.secho('Online Devices: {}'.format(','.join(device_ids.values())),
fg=Colors.GREEN)

printable_tree_names = ','.join(tree_names) if tree_names != "" else "*all*"
click.secho('Config Trees: {}'.format(printable_tree_names), fg='green')
printable_tree_names = ','.join(
tree_names) if tree_names != "" else "*all*"

click.secho('Config Trees: {}'.format(printable_tree_names),
fg=Colors.GREEN)

if not silent:
click.confirm(
"Do you want to apply the configurations?",
default=True, abort=True)

response = client.apply_parameters(list(device_ids.keys()),
list(tree_names),
retry_limit)
with kbi_safe_yaspin(text='Applying parameters...') as spinner:
response = client.apply_parameters(
list(device_ids.keys()),
list(tree_names),
retry_limit
)

print_separator()

Expand All @@ -72,6 +96,6 @@ def apply_configurations(devices: typing.List, tree_names: str = None, retry_lim

tabulate_data(result, headers=["Device", "Success"])
except IOError as e:
click.secho(str(e.__traceback__), fg='red')
click.secho(str(e), fg='red')
click.secho(str(e.__traceback__), fg=Colors.RED)
click.secho(str(e), fg=Colors.RED)
raise SystemExit(1) from e
43 changes: 30 additions & 13 deletions riocli/parameter/delete.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -13,30 +13,47 @@
# limitations under the License.

import click
from click_help_colors import HelpColorsCommand
from rapyuta_io.utils.rest_client import HttpMethod
from yaspin import kbi_safe_yaspin

from riocli.constants import Colors, Symbols
from riocli.parameter.utils import _api_call


@click.command('delete')
@click.option('-f', '--force', '--silent', 'silent', is_flag=True, default=False,
@click.command(
'delete',
cls=HelpColorsCommand,
help_headers_color=Colors.YELLOW,
help_options_color=Colors.GREEN,
)
@click.option('-f', '--force', '--silent', 'silent', is_flag=True,
default=False,
help="Skip confirmation")
@click.argument('tree', type=click.STRING)
def delete_configurations(tree: str, silent: bool = False) -> None:
def delete_configurations(
tree: str,
silent: bool = False
) -> None:
"""
Deletes the Configuration Parameter Tree.
Deletes the configuration parameter tree.
"""
click.secho('Configuration Parameter {} will be deleted'.format(tree))

if not silent:
click.confirm('Do you want to proceed?', default=True, abort=True)

try:
data = _api_call(HttpMethod.DELETE, name=tree)
if data.get('data') != 'ok':
raise Exception('Something went wrong!')
with kbi_safe_yaspin(text='Deleting...', timer=True) as spinner:
try:
data = _api_call(HttpMethod.DELETE, name=tree)
if data.get('data') != 'ok':
raise Exception('Failed to delete configuration')

except IOError as e:
click.secho(str(e.__traceback__), fg='red')
click.secho(str(e), fg='red')
raise SystemExit(1)
spinner.text = click.style(
'Configuration deleted successfully.',
fg=Colors.GREEN)
spinner.green.ok(Symbols.SUCCESS)
except IOError as e:
spinner.text = click.style(e, fg=Colors.RED)
spinner.red.fail(Symbols.ERROR)
raise SystemExit(1)
39 changes: 29 additions & 10 deletions riocli/parameter/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,48 +24,65 @@
from typing import Tuple

import click
from click_help_colors import HelpColorsCommand
from rapyuta_io.utils.error import APIError, InternalServerError
from yaspin import kbi_safe_yaspin

from riocli.config import new_client
from riocli.constants import Colors
from riocli.parameter.utils import filter_trees


@click.command('diff')
@click.command(
'diff',
cls=HelpColorsCommand,
help_headers_color=Colors.YELLOW,
help_options_color=Colors.GREEN,
)
@click.option('--tree-names', type=click.STRING, multiple=True, default=None,
help='Tree names to fetch')
@click.argument('path', type=click.Path(exists=True), required=False)
def diff_configurations(path: str, tree_names: Tuple = None) -> None:
"""
Diff between the Local and Cloud Configuration Trees.
Diff between the local and cloud configuration trees.
"""
trees = filter_trees(path, tree_names)

try:
client = new_client()
with TemporaryDirectory(prefix='riocli-') as tmp_path:
client.download_configurations(tmp_path, tree_names=list(tree_names))
with kbi_safe_yaspin(
text="Fetching configurations from the cloud..."):
client.download_configurations(
tmp_path,
tree_names=list(tree_names)
)

for tree in trees:
left_tree, right_tree = os.path.join(tmp_path, tree), os.path.join(path, tree)
left_tree = os.path.join(tmp_path, tree)
right_tree = os.path.join(path, tree)
diff_tree(left_tree, right_tree)
except (APIError, InternalServerError) as e:
click.secho(str(e), fg='red')
click.secho(str(e), fg=Colors.RED)
raise SystemExit(1)


def diff_tree(left: str, right: str) -> None:
comp = dircmp(left, right)

for f in comp.diff_files:
remote_file, local_file = os.path.join(comp.left, f), os.path.join(comp.right, f)
remote_file, local_file = os.path.join(comp.left, f), os.path.join(
comp.right, f)
diff_file(remote_file, local_file)

for f in comp.right_only:
remote_file, local_file = os.path.join(comp.left, f), os.path.join(comp.right, f)
remote_file, local_file = os.path.join(comp.left, f), os.path.join(
comp.right, f)
changed_file(remote_file, local_file, right_only=True)

for f in comp.left_only:
remote_file, local_file = os.path.join(comp.left, f), os.path.join(comp.right, f)
remote_file, local_file = os.path.join(comp.left, f), os.path.join(
comp.right, f)
changed_file(remote_file, local_file, left_only=True)


Expand All @@ -80,13 +97,15 @@ def diff_file(left: str, right: str):
changed_file(left, right, binary=True)
return

diff = unified_diff(left_lines, right_lines, fromfile=left, tofile=right, lineterm='')
diff = unified_diff(left_lines, right_lines, fromfile=left, tofile=right,
lineterm='')

for line in diff:
click.secho(line)


def changed_file(left: str, right: str, left_only: bool = False, right_only: bool = False, binary: bool = False):
def changed_file(left: str, right: str, left_only: bool = False,
right_only: bool = False, binary: bool = False):
click.secho('--- {}'.format(left))
click.secho('+++ {}'.format(right))

Expand Down
50 changes: 35 additions & 15 deletions riocli/parameter/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import typing
from os.path import abspath
from tempfile import mkdtemp
from xmlrpc.client import Boolean

import click
from click_spinner import spinner
from click_help_colors import HelpColorsCommand

from riocli.config import new_client
from riocli.parameter.utils import display_trees
from riocli.constants import Symbols, Colors
from riocli.utils.spinner import with_spinner


# -----------------------------------------------------------------------------
Expand All @@ -30,29 +31,48 @@
# -----------------------------------------------------------------------------


@click.command('download')
@click.option('--tree-names', type=click.STRING, multiple=True, default=None, help='Tree names to fetch')
@click.option('--overwrite', '--delete-existing', 'delete_existing', is_flag=True,
@click.command(
'download',
cls=HelpColorsCommand,
help_headers_color=Colors.YELLOW,
help_options_color=Colors.GREEN,
)
@click.option('--tree-names', type=click.STRING, multiple=True, default=None,
help='Tree names to fetch')
@click.option('--overwrite', '--delete-existing', 'delete_existing',
is_flag=True,
help='Overwrite existing parameter tree')
@click.argument('path', type=click.Path(exists=True), required=False)
def download_configurations(path: str, tree_names: typing.Tuple[str] = None, delete_existing: Boolean = False) -> None:
@with_spinner(text='Download configurations...', timer=True)
def download_configurations(
path: str,
tree_names: typing.Tuple[str] = None,
delete_existing: bool = False,
spinner=None
) -> None:
"""
Download the Configuration Parameter trees.
Download configuration parameter trees from rapyuta.io
"""
if path is None:
# Not using the Context Manager because we need to persist the Temporary directory.
# Not using the Context Manager because
# we need to persist the temporary directory.
path = mkdtemp()

click.secho('Downloading at {}'.format(path))
spinner.write('Downloading at {}'.format(abspath(path)))

try:
client = new_client()

with spinner():
client.download_configurations(path, tree_names=list(tree_names),
delete_existing_trees=delete_existing)
client.download_configurations(
path,
tree_names=list(tree_names),
delete_existing_trees=delete_existing
)

click.secho('✅ Configuration Parameters downloaded successfully', fg='green')
spinner.text = click.style("Configurations downloaded successfully.",
fg=Colors.GREEN)
spinner.green.ok(Symbols.SUCCESS)
except Exception as e:
click.secho(e, fg='red')
spinner.text = click.style(e, fg=Colors.RED)
spinner.red.fail(Symbols.ERROR)
raise SystemExit(1)
Loading

0 comments on commit a4f954e

Please sign in to comment.