Skip to content

Commit

Permalink
feat: add report feature in device
Browse files Browse the repository at this point in the history
  • Loading branch information
guptadev21 committed Oct 18, 2024
1 parent adce386 commit c964a6f
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 5 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ riocli/jsonschema/schemas/json/
*.class

# Compiled Python bytecode
venv/
venv*/
.venv/
build/
*.egg-info/
Expand Down Expand Up @@ -55,4 +55,3 @@ Thumbs.db
.vscode/

.egg-info/
dist/
2 changes: 2 additions & 0 deletions riocli/device/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from riocli.device.list import list_devices
from riocli.device.migrate import migrate_project
from riocli.device.onboard import device_onboard
from riocli.device.report import report_device
from riocli.device.tools import tools
from riocli.device.topic import device_topics
from riocli.device.vpn import toggle_vpn
Expand Down Expand Up @@ -54,6 +55,7 @@ def device():
device.add_command(inspect_device)
device.add_command(list_deployments)
device.add_command(list_devices)
device.add_command(report_device)
device.add_command(tools)
device.add_command(toggle_vpn)
device.add_command(migrate_project)
104 changes: 104 additions & 0 deletions riocli/device/report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Copyright 2024 Rapyuta Robotics
#
# Licensed 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.
import click
from click_help_colors import HelpColorsCommand

from riocli.constants import Colors, Symbols
from riocli.device.util import name_to_guid, generate_shared_url, upload_debug_logs
from riocli.utils.spinner import with_spinner


@click.command(
"report",
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.option(
"--share",
"-s",
is_flag=True,
help="Generate a public URL for sharing",
default=False,
)
@click.option(
"--expiry",
"-e",
help="Expiry time for the shared URL in days",
default=7,
required=False,
show_default=True,
)
@click.argument("device-name", type=str)
@name_to_guid
@with_spinner(text="Upload debugging files...")
def report_device(
device_name: str,
device_guid: str,
force: bool,
share: bool,
expiry: int,
spinner=None,
) -> None:
"""
This function facilitates the reporting of a device by uploading its debug logs.
It also provides an option to share the logs with Rapyuta support by generating
a public URL with a specified expiry time.
Usage Examples:
Report a device with confirmation prompt.
$ rio device report DEVICE_NAME
Report a device without confirmation prompt.
$ rio device report -f DEVICE_NAME
Report a device and generate a public URL for sharing.
$ rio device report -s DEVICE_NAME
Report a device with a custom expiry time for the shared URL.
$ rio device report -s -e 10 DEVICE_NAME
"""
if not force:
with spinner.hidden():
click.confirm(
"Report Device?",
abort=True,
)
try:
# Upload the debug logs
response = upload_debug_logs(device_guid=device_guid)

if share:
spinner.text = click.style("Creating shared URL...", fg=Colors.YELLOW)
public_url = generate_shared_url(
device_guid, response["response"]["data"]["request_uuid"], expiry
)
click.secho(public_url.url, fg=Colors.GREEN)

spinner.text = click.style("Device reported successfully.", fg=Colors.GREEN)
spinner.green.ok(Symbols.SUCCESS)

except Exception as e:
spinner.text = click.style(
"Failed to report device: {}".format(e), fg=Colors.RED
)
spinner.red.fail(Symbols.ERROR)
45 changes: 42 additions & 3 deletions riocli/device/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# 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.
import datetime
import functools
import json
import re
Expand All @@ -21,9 +22,8 @@
import click
from munch import Munch
from rapyuta_io import Client
from rapyuta_io.clients import LogUploads
from rapyuta_io.clients.device import Device
from rapyuta_io.clients.device import DeviceStatus
from rapyuta_io.clients import LogUploads, SharedURL
from rapyuta_io.clients.device import Device, DeviceStatus
from rapyuta_io.utils import RestClient
from rapyuta_io.utils.rest_client import HttpMethod

Expand All @@ -33,6 +33,7 @@
from riocli.exceptions import DeviceNotFound
from riocli.hwil.util import execute_command, find_device_id
from riocli.utils import is_valid_uuid, trim_prefix, trim_suffix
from riocli.v2client.util import handle_server_errors


def name_to_guid(f: typing.Callable) -> typing.Callable:
Expand Down Expand Up @@ -74,6 +75,44 @@ def decorated(**kwargs: typing.Any):
return decorated


def upload_debug_logs(device_guid: str) -> dict:
config = Configuration()
coreapi_host = config.data.get(
"core_api_host", "https://gaapiserver.apps.okd4v2.prod.rapyuta.io"
)

url = "{}/api/device-manager/v0/error_handler/upload_debug_logs/{}".format(
coreapi_host, device_guid
)

headers = config.get_auth_header()
response = (
RestClient(url).method(HttpMethod.POST).headers(headers).execute(payload={})
)

result = handle_server_errors(response)

if result:
return result

return response.json()


def generate_shared_url(device_guid: str, request_id: str, expiry: int, spinner=None):
try:
client = new_client()
device = client.get_device(device_id=device_guid)
expiry_time = datetime.now() + datetime.timedelta(days=expiry)

# Create the shared URL
public_url = device.create_shared_url(
SharedURL(request_id, expiry_time=expiry_time)
)
return public_url
except Exception as e:
raise Exception(f"Failed to create shared URL: {e}")


def get_device_name(client: Client, guid: str) -> str:
device = client.get_device(device_id=guid)
return device.name
Expand Down

0 comments on commit c964a6f

Please sign in to comment.