diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..61c48441 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# Contribution Guidelines +## Setup your development environment + +The project uses [pipenv](https://pipenv.pypa.io/en/latest/) for +development. It needs to be installed to setup the development environment. + +``` bash +pip install pipenv +``` + +Once Pipenv is installed, a Python virtual environment can be quickly +bootstrapped by running the following commands in the root of the repository. + +``` bash +pipenv install --dev +``` + +This will create a virtual environment in the Pipenv's preconfigured location +(if one doesn't already exists). It will also install all the dependencies and +`riocli` package in the location. + +To run the CLI (or any command) under the context of Pipenv's virtual +environment, prepend the commands with `pipenv run` + +```bash +pipenv run rio +``` + +To run the RIO CLI from the source directly, you can use `riocli` module +directly. + +``` bash +pipenv run python -m riocli +``` + +New dependencies can be installed directly using `pipenv`. This modifies the +`Pipfile` and `Pipfile.lock`. + +``` bash +pipenv install {dependency} +``` + +But using the `pipenv` directly doesn't sync the dependencies in the +`setup.py` file. For this, the project uses a utility called `pipenv-setup` +which allows us to sync the dependencies. + +``` bash +pipenv run pipenv-setup sync +``` diff --git a/README.md b/README.md index 631e00cb..4bb699d3 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,61 @@ -# Rapyuta CLI +# rapyuta.io CLI -Rapyuta CLI exposes features of Rapyuta.io platform on the command-line. +The rapyuta.io CLI exposes features of the rapyuta.io cloud platform on the command-line. -The application is written in Python 3 and it is distributed through PyPI for -Python 3 environments. +The application is written in Python 3, and it is distributed through PyPI for Python 3 environments. For Reference on directory structure please refer Please have a look at the corresponding article: http://gehrcke.de/2014/02/distributing-a-python-command-line-application/ -## Install +## Installation -Rio CLI is available on PyPI index and can be installed directly by running the -following command. +### Installing the `AppImage` -``` bash -pip install rapyuta-io-cli +You can install the latest `AppImage` using the following command. + +```bash +curl -fSsL https://cli.rapyuta.io/install.sh | bash ``` +> Note: The `AppImage` is a self-contained executable that can be run on any Linux distribution. +However, it is not supported for non-Linux systems. + +### Installing via `pip` + +```bash +pip install rapyuta-io-cli +``` On Unix-like systems it places the `rio` executable in the user's PATH. On Windows it places the `rio.exe` in the centralized `Scripts` directory which should be in the user's PATH. +### Installing from source + To install the CLI from source, you can use the `setup.py` script directly. Clone the repository and from the root of the directory, run the following command. -``` bash +```bash +git clone git@github.com:rapyuta-robotics/rapyuta-io-cli.git +cd rapyuta-io-cli python setup.py install ``` ## Getting Started -To begin using the CLI, it must be authenticated with the Platform. - -``` bash -rio auth login -``` - -The Email and Password can either be given through flags (for scripting -purposes) or interactively through the Prompts. - -NOTE: Entering password as a Flag is not recommended because it leaves the -Traces. +To begin using the CLI, it must be authenticated with rapyuta.io. -## Development - -Rio CLI project uses [Pipenv](https://pipenv.pypa.io/en/latest/) for -development. It needs to be installed to setup the development environment. - -``` bash -pip install pipenv -``` - -Once Pipenv is installed, a Python virtual environment can be quickly -bootstrapped by running the following commands in the root of the repository. - -``` bash -pipenv install --dev -``` - -This will create a virtual environment in the Pipenv's preconfigured location -(if one doesn't already exists). It will also install all the dependencies and -`riocli` package in the location. - -To run the CLI (or any command) under the context of Pipenv's virtual -environment, prepend the commands with `pipenv run` - ```bash -pipenv run rio -``` - -To run the RIO CLI from the source directly, you can use `riocli` module -directly. - -``` bash -pipenv run python -m riocli +rio auth login ``` -New dependencies can be installed directly using `pipenv`. This modifies the -`Pipfile` and `Pipfile.lock`. +The `email` and `password` can either be given through flags (for scripting purposes) or interactively through the prompt. -``` bash -pipenv install {dependency} -``` +> Note: Entering the password as a flag is not recommended because it leaves the traces. -But using the `pipenv` directly doesn't sync the dependencies in the -`setup.py` file. For this, the project uses a utility called `pipenv-setup` -which allows us to sync the dependencies. +Once set up, run `rio --help` to see the available commands. -``` bash -pipenv run pipenv-setup sync -``` +## References +* [Development Guide](CONTRIBUTING.md) \ No newline at end of file diff --git a/docs/source/_static/logo-dark-mode.png b/docs/source/_static/logo-dark-mode.png deleted file mode 100644 index f34585f1..00000000 Binary files a/docs/source/_static/logo-dark-mode.png and /dev/null differ diff --git a/docs/source/_static/logo-dark-mode.svg b/docs/source/_static/logo-dark-mode.svg new file mode 100644 index 00000000..b9d62180 --- /dev/null +++ b/docs/source/_static/logo-dark-mode.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/source/_static/logo-light-mode.png b/docs/source/_static/logo-light-mode.png deleted file mode 100644 index 4639835f..00000000 Binary files a/docs/source/_static/logo-light-mode.png and /dev/null differ diff --git a/docs/source/_static/logo-light-mode.svg b/docs/source/_static/logo-light-mode.svg new file mode 100644 index 00000000..63bea6ea --- /dev/null +++ b/docs/source/_static/logo-light-mode.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/source/_static/riocli-logo-dark.png b/docs/source/_static/riocli-logo-dark.png new file mode 100644 index 00000000..7a4e41f2 Binary files /dev/null and b/docs/source/_static/riocli-logo-dark.png differ diff --git a/docs/source/_static/riocli-logo-light.png b/docs/source/_static/riocli-logo-light.png new file mode 100644 index 00000000..51ce5070 Binary files /dev/null and b/docs/source/_static/riocli-logo-light.png differ diff --git a/docs/source/conf.py b/docs/source/conf.py index 32253d15..181a85e4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -2,7 +2,7 @@ import os import sys -project = u'rapyuta.io CLI' +project = u'CLI' copyright = u'2024, Rapyuta Robotics' author = u'Rapyuta Robotics' @@ -26,8 +26,8 @@ html_favicon = 'favicon.ico' html_static_path = ['_static'] html_theme_options = { - "light_logo": "logo-light-mode.png", - "dark_logo": "logo-dark-mode.png", + "light_logo": "logo-light-mode.svg", + "dark_logo": "logo-dark-mode.svg", } html_css_files = ['css/rio-sphinx.css'] html_js_files = ['js/rio-sphinx.js'] diff --git a/docs/source/index.rst b/docs/source/index.rst index 4bde6f42..0b56bc12 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,7 +1,7 @@ -Welcome to Rapyuta.io CLI documentation! +Welcome to rapyuta.io CLI documentation! ======================================== -Rapyuta CLI exposes features of Rapyuta.io platform on the command-line. +The rapyuta.io CLI (aka riocli) exposes features of Rapyuta.io platform on the command-line. The application is written in Python 3 and it is distributed through PyPI for Python 3 environments. @@ -9,45 +9,58 @@ Python 3 environments. Installation -------------- -It is recommended you install the latest Python SDK using pip +Installing the ``AppImage`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can install the latest ``AppImage`` on your Linux systems using the following command. .. code:: bash - pip install rapyuta-io + curl -fSsL https://cli.rapyuta.io/install.sh | bash + +Installing via ``pip`` +~~~~~~~~~~~~~~~~~~~~~~ -Rio CLI is available on PyPI index and can be installed directly by running the -following command. +Alternatively, you can install the CLI using ``pip``. .. code:: bash pip install rapyuta-io-cli + On Unix-like systems it places the ``rio`` executable in the user's PATH. On Windows it places the ``rio.exe`` in the centralized ``Scripts`` directory which should be in the user's PATH. +Installing from source +~~~~~~~~~~~~~~~~~~~~~~~ + To install the CLI from source, you can use the ``setup.py`` script directly. Clone the repository and from the root of the directory, run the following command. .. code:: bash + git clone git@github.com:rapyuta-robotics/rapyuta-io-cli.git + cd rapyuta-io-cli python setup.py install + Getting Started --------------- -To begin using the CLI, it must be authenticated with the Platform. +To begin using the CLI, it must be authenticated with rapyuta.io. .. code:: bash rio auth login -The Email and Password can either be given through flags (for scripting +The ``email`` and ``password`` can either be given through flags (for scripting purposes) or interactively through the Prompts. -NOTE: Entering password as a Flag is not recommended because it leaves the -Traces. +.. note:: + + Entering ``password`` as a flag is not recommended because it leaves the traces. Commands -------- @@ -66,7 +79,6 @@ Rapyuta CLI has commands for all rapyuta.io resources. You can read more about t Device Disk Hardware-in-Loop - ManagedService Network Organization Package diff --git a/docs/source/managedservice.rst b/docs/source/managedservice.rst deleted file mode 100644 index 47571069..00000000 --- a/docs/source/managedservice.rst +++ /dev/null @@ -1,10 +0,0 @@ -Managed Service -=============== - -.. toctree:: - :maxdepth: 3 - :caption: Contents: - -.. click:: riocli.managedservice:managedservice - :prog: rio managedservice - :nested: full diff --git a/riocli/__init__.py b/riocli/__init__.py index ecff8f22..dd6b3e1a 100644 --- a/riocli/__init__.py +++ b/riocli/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/apply/__init__.py b/riocli/apply/__init__.py index 86401a92..7a202ca7 100644 --- a/riocli/apply/__init__.py +++ b/riocli/apply/__init__.py @@ -32,19 +32,19 @@ help_options_color=Colors.GREEN, ) @click.option('--dryrun', '-d', is_flag=True, default=False, - help='dry run the yaml files without applying any change') + help='Dry run the yaml files without applying any change') @click.option('--show-graph', '-g', is_flag=True, default=False, help='Opens a mermaid.live dependency graph') @click.option('--values', '-v', - help="path to values yaml file. key/values " + help="Path to values yaml file. Key/values " "specified in the values file can be " "used as variables in template YAMLs") @click.option('--secrets', '-s', - help="secret files are sops encoded value files. " + help="Secret files are sops encoded value files. " "rio-cli expects sops to be authorized for " "decoding files on this computer") @click.option('--workers', '-w', - help="number of parallel workers while running apply " + help="Number of parallel workers while running apply " "command. defaults to 6.", type=int) @click.option('-f', '--force', '--silent', 'silent', is_flag=True, type=click.BOOL, default=False, @@ -65,8 +65,46 @@ def apply( silent: bool = False, show_graph: bool = False, ) -> None: - """ - Apply resource manifests + """Apply resource manifests. + + The apply command provides the mechanism to create or update + resources on rapyuta.io defined in YAML manifests making the + process declarative and repeatable. The command can take multiple + files, paths or globs as arguments and parse the manifests to + create or update resources. It also supports Jinja templating + and secret management with sops. + + You can provide a values file with the ``--values`` option and a + sops encrypted secret file with ``--secret`` option. Currently, the + command supports only one values and secret file. + + You can use the ``--show-graph`` option to visualize the + dependency graph of the resources defined in the manifests. + + The --dryrun option can be used to execute the manifests without + actually creating the resources. This is useful to validate the + manifests before applying them. + + You can specify the number of parallel workers with the ``--workers`` + option. The default value is ``6``. + + The ``--silent``, ``--force`` or ``-f`` option lets you skip the confirmation + prompt before applying the manifests. This is particularly useful + in CI/CD pipelines. + + Usage Examples: + + Apply a single manifest file with secret and values file. + + $ rio apply -v values.yaml -s secrets.yaml manifest.yaml + + Apply manifests from a directory with secret and values file. + + $ rio apply -v values.yaml -s secrets.yaml templates/ + + Apply manifests from a directory without confirmation prompt. + + $ rio apply -f templates/ """ glob_files, abs_values, abs_secrets = process_files_values_secrets( files, values, secrets) @@ -105,7 +143,7 @@ def apply( help_options_color=Colors.GREEN, ) @click.option('--dryrun', '-d', is_flag=True, default=False, - help='dry run the yaml files without applying any change') + help='Dry run the yaml files without applying any change') @click.option('--values', '-v', help="Path to values yaml file. key/values specified in the" " values file can be used as variables in template YAMLs") @@ -116,7 +154,7 @@ def apply( type=click.BOOL, default=False, help="Skip confirmation") @click.option('--workers', '-w', - help="number of parallel workers while running apply " + help="Number of parallel workers while running apply " "command. defaults to 6.", type=int) @click.option('--retry-count', '-rc', type=int, default=50, help="Number of retries before a resource creation times out status, defaults to 50") @@ -133,8 +171,41 @@ def delete( workers: int = 6, silent: bool = False ) -> None: - """ - Removes resources defined in the manifest + """Removes resources via manifests + + The delete command provides the mechanism to remove resources on + rapyuta.io defined in YAML manifests making the process declarative + and repeatable. The command can take multiple files, paths or globs + as arguments and parse the manifests to remove resources. It also + supports Jinja templating and secret management with sops. You can + provide a values file with the --values option and a sops encrypted + secret file with ``--secret`` option. Currently, the command supports + only one values and secret file. + + The ``--dryrun`` option can be used to execute the manifests without + actually deleting the resources. This is useful to validate the + manifests before applying them. + + You can specify the number of parallel workers with the ``--workers`` + option. The default value is ``6``. + + The ``--silent``, ``--force`` or ``-f`` option lets you skip the confirmation + prompt before applying the manifests. This is particularly useful + in CI/CD pipelines. + + Usage Examples: + + Delete a single manifest file with secret and values file. + + $ rio delete -v values.yaml -s secrets.yaml manifest.yaml + + Delete manifests from a directory with secret and values file. + + $ rio delete -v values.yaml -s secrets.yaml templates/ + + Delete manifests from a directory without confirmation prompt. + + $ rio delete -f templates/ """ glob_files, abs_values, abs_secrets = process_files_values_secrets( files, values, secrets) diff --git a/riocli/apply/explain.py b/riocli/apply/explain.py index 90f04e8f..af909559 100644 --- a/riocli/apply/explain.py +++ b/riocli/apply/explain.py @@ -29,6 +29,7 @@ help='List all examples supported in rio explain command' ) def list_examples() -> None: + """List all examples supported in rio explain command.""" path = Path(__file__).parent.joinpath('manifests') examples = [] @@ -49,6 +50,24 @@ def list_examples() -> None: default=None) @click.argument('resource') def explain(resource: str, templates: str = None) -> None: + """Explain a resource manifest for the given type. + + The explain command can be used to generate a sample + resource manifest using the examples that are shown + in the output. This is particularly useful to understand + the structure of the manifest and the fields that are + required for the resource. + + Usage Examples: + + View examples for deployment + + $ rio explain deployment + + View examples for usergroup + + $ rio explain usergroup + """ if templates: path = Path(templates) else: diff --git a/riocli/apply/template.py b/riocli/apply/template.py index 417c45ad..062bcae6 100644 --- a/riocli/apply/template.py +++ b/riocli/apply/template.py @@ -36,8 +36,22 @@ 'expects sops to be authorized for decoding files on this computer') @click.argument('files', nargs=-1) def template(values: str, secrets: str, files: Iterable[str]) -> None: - """ - Print manifests with filled values + """Print manifests with values and secrets applied + + The template command can be used to preview the manifests + with values and secrets applied. This is particularly useful + to check if the values and secrets are correctly substituted + in the manifests before applying them. + + Just like the apply command, the template command also accepts + a list of files as arguments. You can specify one or more files, + directories or glob pattern. + + However, it will only accept on values and secrets file as input. + + Usage Examples: + + rio template manifests/*.yaml -v values.yaml -s secrets.yaml """ glob_files, abs_values, abs_secrets = process_files_values_secrets( files, values, secrets) diff --git a/riocli/auth/__init__.py b/riocli/auth/__init__.py index 7211d180..ecaf03e0 100644 --- a/riocli/auth/__init__.py +++ b/riocli/auth/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -32,9 +32,7 @@ help_options_color=Colors.GREEN, ) def auth(): - """ - Account and Login on Rapyuta.io - """ + """Login and token management""" pass diff --git a/riocli/auth/login.py b/riocli/auth/login.py index 892c9924..c2bdc539 100644 --- a/riocli/auth/login.py +++ b/riocli/auth/login.py @@ -57,12 +57,51 @@ def login( interactive: bool, auth_token: str, ) -> None: - """ - Log into your rapyuta.io account using the CLI. This is required to - use most commands of the CLI. + """Log into your rapyuta.io account. + + This is the first step to start using the CLI. - You can log in with your email and password or just with and auth token - if you already have one. + You can log in with your email and password or + just with and auth token if you already have one. + The command works in an interactive mode by default + and will prompt you to enter your credentials and + select the organization and project you want to work + with. + + You can also use the command in non-interactive mode + by providing the email and password as arguments and + setting the --no-interactive or --silent flag. In this + mode, you can also set the organization and project + using the --organization and --project flags. If you + do not provide the organization and project, you will + have to set them later using the `rio organization select` + and `rio project select` commands. + + Note: If you have special characters in your password, then + consider putting them in quotes to avoid the terminal from + interpreting them otherwise. + + Usage Examples: + + Login interactively + + $ rio auth login + + Login interactively with email and password + + $ rio auth login --email YOUR_EMAIL --password YOUR_PASSWORD + + Login non-interactively with email and password + + $ rio auth login --email YOUR_EMAIL --password YOUR_PASSWORD --no-interactive + + Login non-interactively with email, password, organization and project + + $ rio auth login --email YOUR_EMAIL --password YOUR_PASSWORD --organization YOUR_ORG --project YOUR_PROJECT --silent + + Login with auth token + + $ rio auth login --auth-token YOUR_AUTH_TOKEN """ ctx = get_root_context(ctx) diff --git a/riocli/auth/logout.py b/riocli/auth/logout.py index 548a593e..998dd697 100644 --- a/riocli/auth/logout.py +++ b/riocli/auth/logout.py @@ -25,9 +25,7 @@ ) @click.pass_context def logout(ctx: click.Context): - """ - Log out from the Rapyuta.io account using the CLI. - """ + """Log out from your rapyuta.io account.""" if not ctx.obj.exists: return diff --git a/riocli/auth/refresh_token.py b/riocli/auth/refresh_token.py index 86c968d9..260682fd 100644 --- a/riocli/auth/refresh_token.py +++ b/riocli/auth/refresh_token.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -27,17 +27,15 @@ help_options_color=Colors.GREEN, ) @click.pass_context -@click.option( - '--password', - type=str, - help='Password for the rapyuta.io account', -) +@click.option('--password', type=str, help='Password for the rapyuta.io account') @click.option('--interactive/--no-interactive', '--interactive/--silent', is_flag=True, type=bool, default=True, help='Make login interactive') def refresh_token(ctx: click.Context, password: str, interactive: bool): - """ - Refreshes the authentication token after it expires + """Refreshes the authentication token. + + If the stores auth token has expired, this command will prompt the + user to enter the password to refresh the token. """ config = get_config_from_context(ctx) email = config.data.get('email_id', None) @@ -55,7 +53,8 @@ def refresh_token(ctx: click.Context, password: str, interactive: bool): refreshed = api_refresh_token(existing_token) if not refreshed: if not interactive and password is None: - click.secho('existing token expired, re-run rio auth refresh-token in interactive mode or pass the password using the flag') + click.secho('The existing token has expired, re-run rio auth refresh-token ' + 'in interactive mode or pass the password using the flag.') raise SystemExit(1) password = password or click.prompt('Password', hide_input=True) diff --git a/riocli/auth/status.py b/riocli/auth/status.py index 7844be4e..5d404a55 100644 --- a/riocli/auth/status.py +++ b/riocli/auth/status.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -25,9 +25,7 @@ ) @click.pass_context def status(ctx: click.Context): - """ - Shows the login status of the CLI - """ + """Shows the current login status.""" if not ctx.obj.exists: click.secho('🔒You are logged out', fg=Colors.YELLOW) raise SystemExit(1) diff --git a/riocli/auth/token.py b/riocli/auth/token.py index 30d0356c..def9fe65 100644 --- a/riocli/auth/token.py +++ b/riocli/auth/token.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -32,8 +32,17 @@ @click.option("--level", default=0, help="Level of the token. 0 = low, 1 = med, 2 = high") def token(email: str, password: str, level: int = 0): - """ - Generates a fresh rapyuta.io auth token + """Generates a new rapyuta.io auth token. + + There may be times when you just need a new auth token. + This command will generate a new token for you based on + the level you specify. The default level is 0. You will + have to specify a valid email and password. + + The token levels are as follows: + 0 = low, 24 hours + 1 = medium, 7 days + 2 = high, 30 days """ config = Configuration() diff --git a/riocli/bootstrap.py b/riocli/bootstrap.py index 371c280c..e9a8a5c6 100644 --- a/riocli/bootstrap.py +++ b/riocli/bootstrap.py @@ -24,7 +24,7 @@ from click_plugins import with_plugins from pkg_resources import iter_entry_points -from riocli.apply import apply, explain, delete, template, list_examples +from riocli.apply import apply, delete, explain, list_examples, template from riocli.auth import auth from riocli.chart import chart from riocli.completion import completion @@ -44,15 +44,10 @@ from riocli.project import project from riocli.rosbag import rosbag from riocli.secret import secret -from riocli.shell import shell, deprecated_repl +from riocli.shell import deprecated_repl, shell from riocli.static_route import static_route from riocli.usergroup import usergroup -from riocli.utils import ( - check_for_updates, - pip_install_cli, - is_pip_installation, - update_appimage, -) +from riocli.utils import (check_for_updates, is_pip_installation, pip_install_cli, update_appimage) from riocli.vpn import vpn @@ -65,6 +60,7 @@ ) @click.pass_context def cli(ctx: Context, config: str = None): + """Manage rapyuta.io features on the command-line""" ctx.obj = Configuration(filepath=config) @@ -78,22 +74,18 @@ def safe_cli(): else: cli() + @cli.command("help") @click.pass_context def cli_help(ctx): - """ - Prints the help message - """ + """Print the help message.""" click.echo(cli.get_help(ctx)) @cli.command() def version(): - """ - Version of the CLI/SDK - """ - click.echo("rio {} / SDK {}".format(__version__, rapyuta_io.__version__)) - return + """View installed CLI and SDK versions.""" + click.echo(f'rio {__version__} / SDK {rapyuta_io.__version__}') @cli.command('update') @@ -101,8 +93,15 @@ def version(): type=click.BOOL, default=False, help="Skip confirmation") def update(silent: bool) -> None: - """ - Update the CLI to the latest version + """Update the CLI to the latest version. + + You can update your existing installation of the CLI to + its latest version. Based on the installation method, i.e. + pip or AppImage, the command will update the right + installation. + + You can skip the confirmation prompt by using the --silent or + --force or -f flag. """ available, latest = check_for_updates(__version__) if not available: diff --git a/riocli/chart/__init__.py b/riocli/chart/__init__.py index 72e93fd8..0aa658cf 100644 --- a/riocli/chart/__init__.py +++ b/riocli/chart/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -29,9 +29,13 @@ help_options_color=Colors.GREEN, ) def chart() -> None: - """ - Rapyuta Charts is a way to package the complete Application for - Rapyuta.io Platform. + """Rapyuta chart is a way to package applications. + + With rapyuta chart, you can create, install, and manage applications + that are a collection of one or more deployments and other resources. + A chart comprises a collection of manifest files that define the + resources to be created. It may also offer customization by means of + values or secrets. """ pass diff --git a/riocli/chart/apply.py b/riocli/chart/apply.py index bf83dbed..c16d4585 100644 --- a/riocli/chart/apply.py +++ b/riocli/chart/apply.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -56,7 +56,34 @@ def apply_chart( retry_count: int = 50, retry_interval: int = 6, silent: bool = False) -> None: - """Install a chart from the rapyuta-charts repository.""" + """Install a chart from the rapyuta-charts repository. + + This command is based on the ``rio apply`` command. However, + the manifests are pulled from rapyuta-charts repository on + GitHub. A rapyuta chart is collection of manifest files with + default values. + + The chart can be customized by providing custom values and + secrets files using the ``--values`` and ``--secrets`` flags respectively. + + The ``--workers`` flag can be used to specify the number of parallel + workers while running the apply command. The default value is 6. + + The ``--dryrun`` flag can be used to test the installation process + without actually installing the chart. + + Repository: https://github.com/rapyuta-robotics/rapyuta-charts + + Usage Examples: + + Apply a chart with values and secrets files + + $ rio chart apply ioconfig-syncer -v values.yaml -s secrets.yaml + + Apply a chart with values and secrets files without confirmation + + $ rio chart apply ioconfig-syncer -v values.yaml -s secrets.yaml -f + """ versions = find_chart(chart) if len(versions) > 1: click.secho( diff --git a/riocli/chart/chart.py b/riocli/chart/chart.py index 6418a680..16f63f9d 100644 --- a/riocli/chart/chart.py +++ b/riocli/chart/chart.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/chart/delete.py b/riocli/chart/delete.py index c3ba804f..bff8a0a5 100644 --- a/riocli/chart/delete.py +++ b/riocli/chart/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -44,7 +44,33 @@ def delete_chart( secrets: str, dryrun: bool = False, silent: bool = False) -> None: - """Uninstall a chart.""" + """Delete a chart. + + The delete command is based on the `rio delete` command + and is used to delete a chart that you have installed + using the `rio chart apply` command. The manifest files + are pulled from the rapyuta-charts repository. The command + accepts custom values and secrets files that you may have + used while installing the chart. + + You can skip confirmation by using the `--silent` or `--force` + or the `-f` flag. + + The `--dryrun` flag can be used to test the deletion process + without actually deleting the chart. + + Repository: https://github.com/rapyuta-robotics/rapyuta-charts + + Usage Examples: + + Delete a chart + + $ rio chart delete postgres + + Delete a chart without confirmation + + $ rio chart delete postgres --silent + """ versions = find_chart(chart) if len(versions) > 1: click.secho('More than one charts are available, ' diff --git a/riocli/chart/info.py b/riocli/chart/info.py index 492a8c55..cc9bda71 100644 --- a/riocli/chart/info.py +++ b/riocli/chart/info.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/chart/list.py b/riocli/chart/list.py index 1f55a910..c4339440 100644 --- a/riocli/chart/list.py +++ b/riocli/chart/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/chart/search.py b/riocli/chart/search.py index d8d747f9..0e85d19f 100644 --- a/riocli/chart/search.py +++ b/riocli/chart/search.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/completion/__init__.py b/riocli/completion/__init__.py index ef451a46..56c693ed 100644 --- a/riocli/completion/__init__.py +++ b/riocli/completion/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/config/__init__.py b/riocli/config/__init__.py index c3da6ee6..7b407d72 100644 --- a/riocli/config/__init__.py +++ b/riocli/config/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/constants/__init__.py b/riocli/constants/__init__.py index 31975eff..f10bda61 100644 --- a/riocli/constants/__init__.py +++ b/riocli/constants/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/constants/colors.py b/riocli/constants/colors.py index e2be344e..1b35d4ba 100644 --- a/riocli/constants/colors.py +++ b/riocli/constants/colors.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/constants/symbols.py b/riocli/constants/symbols.py index 3bc16ed5..cda687e0 100644 --- a/riocli/constants/symbols.py +++ b/riocli/constants/symbols.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/deployment/__init__.py b/riocli/deployment/__init__.py index 246fbe06..0291ba47 100644 --- a/riocli/deployment/__init__.py +++ b/riocli/deployment/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/deployment/delete.py b/riocli/deployment/delete.py index 06d95948..224989bc 100644 --- a/riocli/deployment/delete.py +++ b/riocli/deployment/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -20,8 +20,7 @@ from riocli.config import new_v2_client from riocli.constants import Colors, Symbols from riocli.deployment.model import Deployment -from riocli.deployment.util import fetch_deployments -from riocli.deployment.util import print_deployments_for_confirmation +from riocli.deployment.util import fetch_deployments, print_deployments_for_confirmation from riocli.utils import tabulate_data from riocli.utils.execute import apply_func_with_result from riocli.utils.spinner import with_spinner @@ -50,8 +49,34 @@ def delete_deployment( workers: int = 10, spinner=None, ) -> None: - """ - Deletes one or more deployments given a name or a pattern + """Delete one or more deployments with a name or a regex pattern. + + You can specify a deployment name or a regex pattern to delete one + or more deployment. + + If you want to delete all the deployments, then + simply use the ``--all`` flag. + + If you want to delete deployments without confirmation, then use the + ``--force`` or ``--silent`` or ``-f`` + + Usage Examples: + + Delete a deployment by name + + $ rio deployment delete DEPLOYMENT_NAME + + Delete a deployment without confirmation + + $ rio deployment delete DEPLOYMENT_NAME --force + + Delete all deployments in the project + + $ rio deployment delete --all + + Delete deployments using regex pattern + + $ rio deployment delete "DEPLOYMENT.*" """ client = new_v2_client() if not (deployment_name_or_regex or delete_all): diff --git a/riocli/deployment/execute.py b/riocli/deployment/execute.py index 32d6aeb2..d1556720 100644 --- a/riocli/deployment/execute.py +++ b/riocli/deployment/execute.py @@ -47,8 +47,31 @@ def execute_command( deployment_name: str, command: typing.List[str] ) -> None: - """ - Execute commands on a device deployment + """Execute a command on a device deployment + + You can execute a command on a deployment running on a device. + In case there are more than one executable in the deployment, + you can specify the executable name using the ``--exec`` option. + If you do not specify the executable name, you will be prompted + to select one from the list of executables. If the deployment + only has one executable, it will be selected automatically. + + You can specify the shell using the ``--shell`` option. The default + shell is ``/bin/bash``. You can also specify the user using the ``--user`` + option. The default user is ``root``. + + Please ensure that you enclose the command in quotes to avoid + any issues with the command parsing. + + Usage Examples: + + Execute a command on a device deployment with one executable + + $ rio deployment execute DEPLOYMENT_NAME 'ls -l' + + Execute a command on a device deployment with multiple executables + + $ rio deployment execute DEPLOYMENT_NAME --exec EXECUTABLE_NAME 'ls -l' """ try: client = new_v2_client() diff --git a/riocli/deployment/inspect.py b/riocli/deployment/inspect.py index f65751a7..86dedea8 100644 --- a/riocli/deployment/inspect.py +++ b/riocli/deployment/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -37,8 +37,10 @@ def inspect_deployment( format_type: str, deployment_name: str, ) -> None: - """ - Inspect the deployment resource + """Inspect the deployment resource + + Prints the deployment resource in the specified format. + The supported formats are ``json`` and ``yaml``. Default is ``yaml``. """ try: client = new_v2_client() diff --git a/riocli/deployment/list.py b/riocli/deployment/list.py index e9b087dc..f49c7dec 100644 --- a/riocli/deployment/list.py +++ b/riocli/deployment/list.py @@ -60,8 +60,21 @@ def list_deployments( labels: typing.List[str], wide: bool = False, ) -> None: - """ - List the deployments in the selected project + """List the deployments in the current project + + You can filter the deployments by phase and labels. + + The -w or --wide flag prints more details about the deployments. + + Usage Examples: + + Filter by phase + + $ rio deployment list --phase InProgress --phase Stopped + + Filter by labels + + $ rio deployment list --label key1=value1 --label key2=value2 """ query = { 'phases': phase, diff --git a/riocli/deployment/logs.py b/riocli/deployment/logs.py index 480113c6..8044b215 100644 --- a/riocli/deployment/logs.py +++ b/riocli/deployment/logs.py @@ -35,8 +35,18 @@ def deployment_logs( exec_name: str, deployment_name: str, ) -> None: - """ - Stream live logs from cloud deployments (not supported for device deployments) + """Stream live logs from cloud deployments. + + You can stream logs from a deployment running on the cloud. + In case there are more than one executable in the deployment, + you can specify the executable name using the --exec option. + + If there are multiple replicas of the deployment, you can specify + the replica number using the --replica option. The default replica + number is 0. + + Note: The logs are streamed in real-time. Press Ctrl+C to stop the + log streaming. Also, device deployments do not support log streaming. """ try: # TODO(pallab): when no exec name is given, implement the logic to set default or prompt a selection. diff --git a/riocli/deployment/status.py b/riocli/deployment/status.py index 6c248521..2261b084 100644 --- a/riocli/deployment/status.py +++ b/riocli/deployment/status.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -26,8 +26,11 @@ ) @click.argument('deployment-name', type=str) def status(deployment_name: str) -> None: - """ - Current status of the deployment + """Print the current status of a deployment. + + The command simply prints the current status of the deployment. + This is useful in scripts and automation where you need to check + the status of a deployment. """ try: client = new_v2_client() diff --git a/riocli/deployment/update.py b/riocli/deployment/update.py index 049ffc1f..16c6d6b7 100644 --- a/riocli/deployment/update.py +++ b/riocli/deployment/update.py @@ -53,7 +53,7 @@ def update_deployment( update_all: bool = False, spinner: Yaspin = None, ) -> None: - """Updates one or more deployments""" + """Use the restart command instead""" _update(force, workers, deployment_name_or_regex, update_all, spinner) @@ -81,19 +81,19 @@ def restart_deployment( ) -> None: """Restarts one or more deployments by name or regex. - Examples: + Usage Examples: Restart a specific deployment - >> rio deployment restart amr01 + $ rio deployment restart amr01 Restart all deployments in the project - >> rio deployment restart --all + $ rio deployment restart --all Restart deployments matching a regex. - >> rio deployment restart amr.* + $ rio deployment restart amr.* """ _update(force, workers, deployment_name_or_regex, update_all, spinner) diff --git a/riocli/deployment/util.py b/riocli/deployment/util.py index a45e255f..61079646 100644 --- a/riocli/deployment/util.py +++ b/riocli/deployment/util.py @@ -16,14 +16,12 @@ import typing import click -from rapyuta_io import DeploymentPhaseConstants from rapyuta_io.clients.deployment import Deployment -from riocli.config import new_client, new_v2_client +from riocli.config import new_v2_client from riocli.constants import Colors from riocli.deployment.list import DEFAULT_PHASES from riocli.utils import tabulate_data -from riocli.utils.selector import show_selection from riocli.v2client import Client from riocli.v2client.enums import DeploymentPhaseConstants @@ -77,10 +75,11 @@ def get_deployment_guid(client: Client, name: str) -> str: def get_deployment_name(client: Client, guid: str) -> str: deployments = client.list_deployments(query={'guids': [guid]}) if len(deployments) == 0: - raise DeploymentNotFound + raise Exception('deployment not found') return deployments[0].metadata.name + def fetch_deployments( client: Client, deployment_name_or_regex: str, diff --git a/riocli/deployment/wait.py b/riocli/deployment/wait.py index 92b010f4..f5b6c791 100644 --- a/riocli/deployment/wait.py +++ b/riocli/deployment/wait.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -32,8 +32,10 @@ def wait_for_deployment( deployment_name: str, spinner=None, ) -> None: - """ - Wait until the deployment succeeds/fails + """Wait until the deployment succeeds/fails + + This command is useful in scripts or automation when you + explicitly want to wait for the deployment to complete. """ try: client = new_v2_client() @@ -55,4 +57,4 @@ def wait_for_deployment( except Exception as e: spinner.text = click.style(str(e), fg=Colors.RED) spinner.red.fail(Symbols.ERROR) - raise SystemExit(1) \ No newline at end of file + raise SystemExit(1) diff --git a/riocli/device/config.py b/riocli/device/config.py index 09d9cf21..7bb95901 100644 --- a/riocli/device/config.py +++ b/riocli/device/config.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/device/create.py b/riocli/device/create.py index 146e8a26..4b2cde38 100644 --- a/riocli/device/create.py +++ b/riocli/device/create.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/device/delete.py b/riocli/device/delete.py index 822aaa35..90f1459b 100644 --- a/riocli/device/delete.py +++ b/riocli/device/delete.py @@ -22,7 +22,7 @@ from yaspin.api import Yaspin from riocli.config import new_client -from riocli.constants import Symbols, Colors +from riocli.constants import Colors, Symbols from riocli.device.util import fetch_devices from riocli.utils import tabulate_data from riocli.utils.execute import apply_func_with_result @@ -50,8 +50,34 @@ def delete_device( delete_all: bool = False, spinner: Yaspin = None, ) -> None: - """ - Deletes one more devices + """Delete one or more devices with a name or a regex pattern. + + You can specify a name or a regex pattern to delete one + or more devices. + + If you want to delete all the device, then + simply use the --all flag. + + If you want to delete devices without confirmation, then + use the --force or --silent or -f + + Usage Examples: + + Delete a device by name + + $ rio device delete DEVICE_NAME + + Delete a device without confirmation + + $ rio device delete DEVICE_NAME --force + + Delete all device in the project + + $ rio device delete --all + + Delete devices using regex pattern + + $ rio device delete "DISK.*" """ client = new_client() if not (device_name_or_regex or delete_all): diff --git a/riocli/device/deployment.py b/riocli/device/deployment.py index 1926a229..53ddffc2 100644 --- a/riocli/device/deployment.py +++ b/riocli/device/deployment.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/device/execute.py b/riocli/device/execute.py index 0d4505a2..4fe3ce15 100644 --- a/riocli/device/execute.py +++ b/riocli/device/execute.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -39,8 +39,18 @@ def execute_command( shell: str, command: typing.List[str] ) -> None: - """ - Execute commands on the Device + """Execute commands on a device. + + You can specify the user and shell to run the command in. + To specify the user, use the --user flag. The default is + root. To specify the shell, use the --shell flag. The default + shell is /bin/bash. + + Make sure you put your command in quotes to avoid any issues. + + Usage Examples: + + $ rio device execute DEVICE_NAME "ls -l" """ try: response = run_on_device( diff --git a/riocli/device/files.py b/riocli/device/files.py index 85d3b8c1..9c9a31e8 100644 --- a/riocli/device/files.py +++ b/riocli/device/files.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -14,9 +14,8 @@ from datetime import datetime, timedelta import click -from click_help_colors import HelpColorsCommand -from click_help_colors import HelpColorsGroup -from rapyuta_io.clients import LogsUploadRequest, LogUploads, SharedURL +from click_help_colors import HelpColorsCommand, HelpColorsGroup +from rapyuta_io.clients import LogUploads, LogsUploadRequest, SharedURL from riocli.config import new_client from riocli.constants import Colors, Symbols @@ -33,8 +32,10 @@ help_options_color=Colors.RED, ) def device_uploads() -> None: - """ - Uploaded files from the Device + """Manage file uploads from a device. + + Provides a convenient way to upload from a device to the cloud + and later download, share and perform operations on the uploaded files. """ pass @@ -46,6 +47,11 @@ def device_uploads() -> None: @click.argument('device-name', type=str) @name_to_guid def list_uploads(device_name: str, device_guid: str) -> None: + """List all files uploaded from a device. + + Lists all the files uploaded from a device along + with their size and status. + """ try: client = new_client() device = client.get_device(device_id=device_guid) @@ -81,6 +87,34 @@ def create_upload( purge: bool, spinner=None, ) -> None: + """Upload a file from a device to the cloud. + + You can set the maximum upload rate for the upload operation + --max-upload-rate flag. The default rate is 1MB/s. + + If there already exists a file upload with the same name, you + can override it using the --override flag. The default is set + to false. + + Setting the --purge flag will delete the file from the device + once it is uploaded. The default is set to false. This option + is useful when you want to free up space on the device after + uploading the file. + + Usage Examples: + + Upload a file from a device with a max upload rate of 2MB/s + + $ rio device uploads create DEVICE_NAME FILE_NAME FILE_PATH --max-upload-rate 2097152 + + Upload a file from the device and delete it after it uploads + + $ rio device uploads create DEVICE_NAME FILE_NAME FILE_PATH --purge + + Upload a file from the device and override the existing file on the cloud + + $ rio device uploads create DEVICE_NAME FILE_NAME FILE_PATH --override + """ try: client = new_client() device = client.get_device(device_id=device_guid) @@ -116,6 +150,7 @@ def upload_status( file_name: str, request_id: str, ) -> None: + """Check the status of a file upload.""" try: client = new_client() device = client.get_device(device_id=device_guid) @@ -144,6 +179,7 @@ def delete_upload( request_id: str, spinner=None ) -> None: + """Delete an uploaded file.""" try: client = new_client() device = client.get_device(device_id=device_guid) @@ -174,6 +210,7 @@ def download_log( request_id: str, spinner=None ) -> None: + """Download a file from the device.""" try: client = new_client() device = client.get_device(device_id=device_guid) @@ -204,6 +241,7 @@ def cancel_upload( request_id: str, spinner=None ) -> None: + """Cancel an ongoing upload operation.""" try: client = new_client() device = client.get_device(device_id=device_guid) @@ -236,6 +274,21 @@ def shared_url( expiry: int, spinner=None ) -> None: + """Share a URL for an uploaded file. + + The command creates a shared public URL for the file + uploaded from the device. The URl can be used to download + the file later from any location. + + Optionally, you can set an expiry on the URL using the + --expiry flag. The default expiry is 7 days. + + Usage Examples: + + Share a URL for an uploaded file with 10 day expiry + + $ rio device uploads share DEVICE_NAME FILE_NAME --expiry 10 + """ try: client = new_client() device = client.get_device(device_id=device_guid) diff --git a/riocli/device/inspect.py b/riocli/device/inspect.py index 98046767..a37e1557 100644 --- a/riocli/device/inspect.py +++ b/riocli/device/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -32,8 +32,10 @@ @click.argument('device-name', type=str) @name_to_guid def inspect_device(format_type: str, device_name: str, device_guid: str) -> None: - """ - Inspect the device resource + """Print the details of a device. + + You can specify the format of the output using the --format flag. + The default format is yaml. You can choose between json and yaml. """ try: client = new_client() diff --git a/riocli/device/label.py b/riocli/device/label.py index 889b4b0e..cbe25936 100644 --- a/riocli/device/label.py +++ b/riocli/device/label.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -32,8 +32,9 @@ help_options_color=Colors.GREEN, ) def device_labels() -> None: - """ - Device Labels + """Manage device labels. + + Labels a key-value pair that you can attach to a device. """ pass @@ -42,9 +43,7 @@ def device_labels() -> None: @click.argument('device-name', type=str) @name_to_guid def list_labels(device_name: str, device_guid: str) -> None: - """ - List all the labels for the Device - """ + """List all the labels for a device.""" try: client = new_client() device = client.get_device(device_id=device_guid) @@ -61,9 +60,7 @@ def list_labels(device_name: str, device_guid: str) -> None: @click.argument('value', type=str) @name_to_guid def create_label(device_name: str, device_guid: str, key: str, value: str) -> None: - """ - Create a label for the Device - """ + """Create a new label on a device""" try: with spinner(): client = new_client() @@ -81,9 +78,7 @@ def create_label(device_name: str, device_guid: str, key: str, value: str) -> No @click.argument('value', type=str) @name_to_guid def update_label(device_name: str, device_guid: str, key: str, value: str) -> None: - """ - Update the label for the Device - """ + """Update a label on a device""" try: with spinner(): _update_label(device_guid, key, value) @@ -98,9 +93,7 @@ def update_label(device_name: str, device_guid: str, key: str, value: str) -> No @click.argument('key', type=str) @name_to_guid def delete_label(device_name: str, device_guid: str, key: str) -> None: - """ - Delete the label for the Device - """ + """Delete a label on a device.""" try: with spinner(): _delete_label(device_guid, key) diff --git a/riocli/device/list.py b/riocli/device/list.py index 85e62808..bb3ad384 100644 --- a/riocli/device/list.py +++ b/riocli/device/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -29,9 +29,7 @@ help_options_color=Colors.GREEN, ) def list_devices() -> None: - """ - List all the devices in the selected Project - """ + """List all the devices in the current project.""" try: client = new_client() devices = client.get_all_devices() diff --git a/riocli/device/metric.py b/riocli/device/metric.py index aef9978f..3946af22 100644 --- a/riocli/device/metric.py +++ b/riocli/device/metric.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -32,8 +32,10 @@ help_options_color='green', ) def device_metrics(): - """ - Device Metrics + """Interact with device metrics. + + You can list, subscribe or unsubscribe to metrics for a device + conveniently from the CLI. """ pass @@ -42,9 +44,7 @@ def device_metrics(): @click.argument('device-name', type=str) @name_to_guid def list_metrics(device_name: str, device_guid: str) -> None: - """ - Lists all the available metrics for the Device - """ + """Lists all the available metrics for a device.""" try: client = new_client() device = client.get_device(device_id=device_guid) @@ -60,9 +60,7 @@ def list_metrics(device_name: str, device_guid: str) -> None: @click.argument('metric', type=click.Choice(['cpu', 'memory', 'disk', 'diskio', 'network', 'wireless'])) @name_to_guid def subscribe_metrics(device_name: str, device_guid: str, metric: str) -> None: - """ - Subscribes the metrics to start collecting it - """ + """Subscribe to a metric to start collecting it.""" try: client = new_client() with spinner(): @@ -79,9 +77,7 @@ def subscribe_metrics(device_name: str, device_guid: str, metric: str) -> None: @click.argument('metric', type=click.Choice(['cpu', 'memory', 'disk', 'diskio', 'network', 'wireless'])) @name_to_guid def unsubscribe_metrics(device_name: str, device_guid: str, metric: str) -> None: - """ - Un-subscribes the metrics to stop collecting it - """ + """Unsubscribe a metric to stop collecting it.""" try: client = new_client() with spinner(): diff --git a/riocli/device/migrate.py b/riocli/device/migrate.py index bc09b005..20b28f9c 100644 --- a/riocli/device/migrate.py +++ b/riocli/device/migrate.py @@ -16,10 +16,9 @@ from yaspin.core import Yaspin from riocli.config import new_client +from riocli.constants import Colors, Symbols from riocli.device.util import migrate_device_to_project, name_to_guid from riocli.project.util import name_to_guid as project_name_to_guid - -from riocli.constants import Colors, Symbols from riocli.utils.spinner import with_spinner @@ -45,8 +44,16 @@ def migrate_project(ctx: click.Context, device_name: str, device_guid: str, project_name: str, project_guid: str, enable_vpn: bool, advertise_routes: bool, spinner: Yaspin) -> None: - """ - Migrate the device from current project to the target project. + """Migrate a device from current project to the target project. + + This process may take some time since it involves multiple steps. + + Optionally, you can enable VPN on the device after migration. Use + the --enable-vpn flag to enable VPN on the device. + + If you want to advertise the subnets configured in the project to VPN peers, + use the --advertise-routes flag. This is usually applicable for edge devices + that are configured as subnet routers. """ try: migrate_device_to_project(ctx, device_guid, project_guid) @@ -58,12 +65,14 @@ def migrate_project(ctx: click.Context, device_name: str, device_guid: str, spinner.text = 'Enabling VPN on device...' client = new_client() client.set_project(project_guid) - client.toggle_features(device_id=device_guid, features=[('vpn', True)], - config={'vpn': {'advertise_routes': advertise_routes}}) + client.toggle_features( + device_id=device_guid, + features=[('vpn', True)], + config={'vpn': {'advertise_routes': advertise_routes}}, + ) spinner.write(click.style('{} Enabled VPN on the device.'.format(Symbols.SUCCESS), fg=Colors.GREEN)) except Exception as e: spinner.text = click.style( 'Failed to migrate device: {}'.format(e), Colors.RED) spinner.red.fail(Symbols.ERROR) raise SystemExit(1) from e - diff --git a/riocli/device/onboard.py b/riocli/device/onboard.py index fc1e5383..77adf7e2 100644 --- a/riocli/device/onboard.py +++ b/riocli/device/onboard.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -21,12 +21,11 @@ @click.argument('device-name', type=str) @name_to_guid def device_onboard(device_name: str, device_guid: str) -> None: - """ - Generates the on-boarding script for the Device - - To onboard the current device, run the following + """Generates the on-boarding script for a device. - exec $(rio device onboard {device-name}) + You are supposed to run the script on the device to onboard it. + Copy the script to the device and run it. The device will be + onboarded to the rapyuta.io in the selected project. """ try: client = new_client() diff --git a/riocli/device/tools/__init__.py b/riocli/device/tools/__init__.py index 67e29e77..cd3e2200 100644 --- a/riocli/device/tools/__init__.py +++ b/riocli/device/tools/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -17,7 +17,7 @@ from riocli.device.tools.device_init import device_init from riocli.device.tools.forward import port_forward from riocli.device.tools.rapyuta_logs import rapyuta_agent_logs -from riocli.device.tools.ssh import ssh_authorize_key, device_ssh +from riocli.device.tools.ssh import device_ssh, ssh_authorize_key from .scp import scp from .service import service @@ -29,6 +29,13 @@ help_options_color='green', ) def tools(): + """Tools for managing devices. + + A collection of commands that provide a way + to conveniently interact with devices and services + running on them. The commands also enable you to + script and automate tasks on devices. + """ pass diff --git a/riocli/device/tools/device_init.py b/riocli/device/tools/device_init.py index dc1dfeef..348fe01e 100644 --- a/riocli/device/tools/device_init.py +++ b/riocli/device/tools/device_init.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -16,7 +16,7 @@ import click from riocli.config import Configuration -from riocli.constants import Symbols, Colors +from riocli.constants import Colors, Symbols from riocli.device.util import name_to_guid from riocli.utils import run_bash from riocli.utils.execute import run_on_device @@ -28,8 +28,11 @@ @with_spinner(text="Initializing device...", timer=True) @name_to_guid def device_init(device_name: str, device_guid: str, spinner=None) -> None: - """ - Initialize device for use with device tools. This is required to be executed first before all tools sub-commands. + """Initialize a device for use with device tools. + + This is required to be executed first before all tools sub-commands. + The command will install the necessary tools on the device and locally + on the machine you are running this command on. """ try: _setup_device(device_guid=device_guid, spinner=spinner) diff --git a/riocli/device/tools/forward.py b/riocli/device/tools/forward.py index 712c30aa..bfb98f9b 100644 --- a/riocli/device/tools/forward.py +++ b/riocli/device/tools/forward.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -32,9 +32,7 @@ @click.argument('local-port', type=int, default=0, required=False) @name_to_guid def port_forward(device_name: str, device_guid: str, remote_port: int, local_port: int) -> None: - """ - Forwards the port on the Device to local machine - """ + """Forwards a port on the device to local machine.""" try: path = random_string(8, 5) if local_port == 0: diff --git a/riocli/device/tools/rapyuta_logs.py b/riocli/device/tools/rapyuta_logs.py index 158940fc..59f1207b 100644 --- a/riocli/device/tools/rapyuta_logs.py +++ b/riocli/device/tools/rapyuta_logs.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -25,6 +25,11 @@ @click.argument('device-name', type=str) @name_to_guid def rapyuta_agent_logs(device_name: str, device_guid: str) -> None: + """Stream rapyuta agent logs from the device. + + This is useful for debugging issues with the rapyuta + agent running on the device. + """ try: path = random_string(8, 5) local_port = get_free_tcp_port() diff --git a/riocli/device/tools/scp.py b/riocli/device/tools/scp.py index 9ca49a51..5baf0205 100644 --- a/riocli/device/tools/scp.py +++ b/riocli/device/tools/scp.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -16,7 +16,7 @@ from yaspin.api import Yaspin from riocli.config import new_client -from riocli.constants import Symbols, Colors +from riocli.constants import Colors, Symbols from riocli.device.tools.util import copy_from_device, copy_to_device from riocli.device.util import is_remote_path from riocli.utils.spinner import with_spinner @@ -32,8 +32,17 @@ @click.argument('destination', nargs=1) @with_spinner(text='Copying files...') def scp(source: str, destination: str, spinner: Yaspin = None) -> None: - """ - An scp like interface to copy files to and from the device + """SCP like interface to copy files to and from a device. + + Usage Examples: + + Copy a file from local filesystem to the device + + $ rio device tools scp /path/to/local/file :/path/to/remote/file + + Copy a file from the device to the local filesystem + + $ rio device tools scp :/path/to/remote/file /path/to/local/file """ try: client = new_client() diff --git a/riocli/device/tools/service.py b/riocli/device/tools/service.py index 20ad26cb..1bb22801 100644 --- a/riocli/device/tools/service.py +++ b/riocli/device/tools/service.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -21,6 +21,7 @@ @click.argument('device-name', type=str) @name_to_guid def status_all(device_name: str, device_guid: str) -> None: + """Get the status of all services on the device.""" try: remote_service_cmd_list = ['service', '--status-all'] response = run_on_device(device_guid=device_guid, command=remote_service_cmd_list) @@ -31,6 +32,7 @@ def status_all(device_name: str, device_guid: str) -> None: def run_service_cmd(device_guid, service_name, service_cmd=""): + """Run a service command on the device.""" try: remote_service_cmd_list = ['service', service_name, service_cmd] response = run_on_device(device_guid=device_guid, command=remote_service_cmd_list) @@ -45,6 +47,7 @@ def run_service_cmd(device_guid, service_name, service_cmd=""): @click.argument('service-name', nargs=1) @name_to_guid def status(device_name: str, device_guid: str, service_name) -> None: + """Get the status of a service on the device.""" run_service_cmd(device_guid, service_name, 'status') @@ -53,6 +56,7 @@ def status(device_name: str, device_guid: str, service_name) -> None: @click.argument('service-name', nargs=1) @name_to_guid def start(device_name: str, device_guid: str, service_name) -> None: + """Start a service on the device.""" run_service_cmd(device_guid, service_name, 'start') @@ -61,6 +65,7 @@ def start(device_name: str, device_guid: str, service_name) -> None: @click.argument('service-name', nargs=1) @name_to_guid def stop(device_name: str, device_guid: str, service_name) -> None: + """Stop a service on the device.""" run_service_cmd(device_guid, service_name, 'stop') @@ -69,6 +74,7 @@ def stop(device_name: str, device_guid: str, service_name) -> None: @click.argument('service-name', nargs=1) @name_to_guid def reload(device_name: str, device_guid: str, service_name) -> None: + """Reload a service on the device.""" run_service_cmd(device_guid, service_name, 'reload') @@ -77,6 +83,7 @@ def reload(device_name: str, device_guid: str, service_name) -> None: @click.argument('service-name', nargs=1) @name_to_guid def force_reload(device_name: str, device_guid: str, service_name) -> None: + """Force reload a service on the device.""" run_service_cmd(device_guid, service_name, 'force_reload') @@ -85,13 +92,17 @@ def force_reload(device_name: str, device_guid: str, service_name) -> None: @click.argument('service-name', nargs=1) @name_to_guid def restart(device_name: str, device_guid: str, service_name) -> None: + """Restart a service on the device.""" run_service_cmd(device_guid, service_name, 'restart') -@click.group() +@click.group( + hidden=True +) def service(): - """ - System manager commands + """System management commands for services on the device. + + Offers a set of commands to manage services on the device. """ pass diff --git a/riocli/device/tools/ssh.py b/riocli/device/tools/ssh.py index 45e51e52..dd78e1d8 100644 --- a/riocli/device/tools/ssh.py +++ b/riocli/device/tools/ssh.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -17,11 +17,7 @@ from click_help_colors import HelpColorsCommand from riocli.constants import Colors, Symbols -from riocli.device.tools.util import ( - run_tunnel_on_device, - run_tunnel_on_local, - copy_to_device, -) +from riocli.device.tools.util import (copy_to_device, run_tunnel_on_device, run_tunnel_on_local) from riocli.device.util import name_to_guid from riocli.utils import random_string from riocli.utils.execute import run_on_device @@ -52,12 +48,27 @@ def device_ssh( remote_port: int, x_forward: bool, ) -> None: - """ - SSH to the Device + """SSH into a device. + + Note: Make sure that you have executed the `rio device tools init` + command before trying to SSH. + + You can select the user to SSH into the device with the `--user` flag. + The default user is `root`. + + You can also specify the local port to forward the SSH connection to + using the `--local-port` flag. If not specified, a random port will be + selected. + + You can also specify the remote port on the device on which the SSH server + is listening using the `--remote-port` flag. The default port is 22. + + You can enable X Forwarding over SSH using the `--x-forward` flag. """ extra_args = "" if not x_forward: extra_args = extra_args + " -X " + try: path = random_string(8, 5) if not local_port: @@ -88,8 +99,23 @@ def device_ssh( @name_to_guid def ssh_authorize_key(device_name: str, device_guid: str, user: str, public_key_file: click.Path, spinner=None) -> None: - """ - Authorize Public SSH Key + """Authorize your local machine's public SSH key + + This command will add the public SSH key of your local machine to the + authorized keys of the specified device. This will allow you to SSH into + the device without a password. + + You can specify the user for which the SSH keys are added using the `--user` + flag. The default user is `root`. + + You can also specify the path to the public key file using the `public-key-file` + argument. The default path is `~/.ssh/id_rsa.pub`. + + Usage Examples: + + Authorize the default public key for the root user + + $ rio device tools ssh-authorize DEVICE_NAME """ try: temp_path = "/tmp/{}".format(random_string(8, 5)) diff --git a/riocli/device/tools/util.py b/riocli/device/tools/util.py index 6a1f946b..567db8b1 100644 --- a/riocli/device/tools/util.py +++ b/riocli/device/tools/util.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/device/topic.py b/riocli/device/topic.py index e401424a..3dd3f804 100644 --- a/riocli/device/topic.py +++ b/riocli/device/topic.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/device/vpn.py b/riocli/device/vpn.py index 1dda61fe..5066f037 100644 --- a/riocli/device/vpn.py +++ b/riocli/device/vpn.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -42,10 +42,25 @@ @click.option('--advertise-routes', is_flag=True, type=click.BOOL, default=False, help="Advertise subnets configured in project to VPN peers") -def toggle_vpn(devices: typing.List, enable: bool, - silent: bool = False, advertise_routes: bool = False) -> None: - """ - Enable or disable VPN client on the device +def toggle_vpn( + devices: typing.List, + enable: bool, + silent: bool = False, + advertise_routes: bool = False, +) -> None: + """Enable or disable VPN client on the device. + + Optionally, you can configure the device to advertise a subnet + if the project is configured with a subnet range. Please note + that --advertise-routes is only a flag and does not provide you + an option to specify the subnet range. + + You can specify the devices using their names or UUIDs using the + --devices flag. If you do not specify any devices, the state will + be applied to all online devices in the project. + + If you want to skip the confirmation prompt, use the --silent or + --force or -f flag. Examples: diff --git a/riocli/disk/__init__.py b/riocli/disk/__init__.py index d6c4cedf..9d9c42fa 100644 --- a/riocli/disk/__init__.py +++ b/riocli/disk/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -27,8 +27,9 @@ help_options_color=Colors.GREEN, ) def disk() -> None: - """ - Persistent disks + """Manage cloud disks. + + Create, list, and delete cloud disks. """ pass diff --git a/riocli/disk/create.py b/riocli/disk/create.py index e5197564..1c0cfb11 100644 --- a/riocli/disk/create.py +++ b/riocli/disk/create.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -15,10 +15,10 @@ from click_help_colors import HelpColorsCommand from yaspin.api import Yaspin -from riocli.constants import Colors, Symbols, Regions +from riocli.config import new_v2_client +from riocli.constants import Colors, Regions, Symbols from riocli.disk.enum import DiskCapacity from riocli.utils.spinner import with_spinner -from riocli.config import new_v2_client SUPPORTED_CAPACITIES = [ DiskCapacity.GiB_4.value, @@ -55,8 +55,17 @@ def create_disk( region: str = 'jp', spinner: Yaspin = None ) -> None: - """ - Creates a new disk + """Creates a new cloud disk. + + You can create a disk with a specific capacity and region. + The command will create a disk and wait until it is ready + to use. + + Usage Examples: + + Create a new 4GB disk in the JP region + + $ rio disk create DISK_NAME --capacity 4 --region jp """ client = new_v2_client() payload = { diff --git a/riocli/disk/delete.py b/riocli/disk/delete.py index 097e87a4..404fc2ae 100644 --- a/riocli/disk/delete.py +++ b/riocli/disk/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -19,9 +19,9 @@ from yaspin.api import Yaspin from riocli.config import new_v2_client -from riocli.constants import Symbols, Colors +from riocli.constants import Colors, Symbols from riocli.disk.model import Disk -from riocli.disk.util import fetch_disks, display_disk_list +from riocli.disk.util import display_disk_list, fetch_disks from riocli.utils import tabulate_data from riocli.utils.execute import apply_func_with_result from riocli.utils.spinner import with_spinner @@ -37,7 +37,7 @@ @click.option('--force', '-f', is_flag=True, default=False, help='Skip confirmation', type=bool) @click.option('-a', '--all', 'delete_all', is_flag=True, default=False, - help='Deletes all deployments in the project') + help='Deletes all disks in the project') @click.option('--workers', '-w', help="Number of parallel workers while running deleting disks. Defaults to 10", type=int, default=10) @@ -50,8 +50,34 @@ def delete_disk( workers: int = 10, spinner: Yaspin = None ) -> None: - """ - Deletes a disk + """Delete one or more disks with a name or a regex pattern. + + You can specify a name or a regex pattern to delete one + or more disks. + + If you want to delete all the disks, then + simply use the ``--all`` flag. + + If you want to delete disks without confirmation, then use the + ``--force`` or ``--silent`` or ``-f``. + + Usage Examples: + + Delete a disk by name + + $ rio disk delete DISK_NAME + + Delete a disk without confirmation + + $ rio disk delete DISK_NAME --force + + Delete all disks in the project + + $ rio disk delete --all + + Delete disks using regex pattern + + $ rio disk delete "DISK.*" """ client = new_v2_client() diff --git a/riocli/disk/list.py b/riocli/disk/list.py index 20a8892b..3b84776f 100644 --- a/riocli/disk/list.py +++ b/riocli/disk/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -28,10 +28,16 @@ help_options_color=Colors.GREEN, ) @click.option('--label', '-l', 'labels', multiple=True, type=click.STRING, - default=(), help='Filter the deployment list by labels') + default=(), help='Filter the disk list by labels') def list_disks(labels: typing.List[str]) -> None: - """ - List the disks in the selected project + """List the disks in the current project. + + Additionally, you can filter the list by labels using the + ``--label`` or ``-l`` flag. + + Usage Examples: + + $ rio disk list -l app=postgres """ try: client = new_v2_client(with_project=True) diff --git a/riocli/disk/util.py b/riocli/disk/util.py index 1c6a7279..824fbd41 100644 --- a/riocli/disk/util.py +++ b/riocli/disk/util.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/exceptions/__init__.py b/riocli/exceptions/__init__.py index fb53854d..b956b5bc 100644 --- a/riocli/exceptions/__init__.py +++ b/riocli/exceptions/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/hwil/__init__.py b/riocli/hwil/__init__.py index ddb2c866..01d57435 100644 --- a/riocli/hwil/__init__.py +++ b/riocli/hwil/__init__.py @@ -32,7 +32,12 @@ help_options_color=Colors.GREEN, ) def hwildevice(): - """Manage Hardware-in-the-Loop (HWIL) devices""" + """Manage Hardware-in-the-Loop (HWIL) devices. + + Hardware-in-the-Loop (HWIL) devices are virtual devices that + can be used to test devices on rapyuta.io. The set of commands + provide a convenient way to manage these devices and access them. + """ pass diff --git a/riocli/hwil/create.py b/riocli/hwil/create.py index 91edf7fa..1e9d30a3 100644 --- a/riocli/hwil/create.py +++ b/riocli/hwil/create.py @@ -45,7 +45,35 @@ def create_device( codename: str, spinner: Yaspin = None, ) -> None: - """Create a new hardware-in-the-loop device.""" + """Create a new hardware-in-the-loop device. + + You can specify the parameters to create the kind of device + you want using the --arch, --os and the --codename flags. + + The --arch defines the architecture of the device, which + can be either amd64 or arm64. + + The --os defines the type of the OS, which can be either + debian or ubuntu. + + The --codename defines the code name of the OS, which can + be either bionic, focal, jammy or bullseye. + + Usage Example: + + Create a new device with the name 'my-device' and the default + + $ rio hwil create my-device + + Create a new device with the name 'my-device' and custom + parameters for example, arm64 architecture, debian OS and + bullseye codename. + + $ rio hwil create my-device --arch arm64 --os debian --codename bullseye + + Note: All combinations of the --arch, --os and --codename flags may not always + work. Please contact io-support for more information. + """ info = click.style(f'{Symbols.INFO} Device configuration = {os}:{codename}:{arch}', fg=Colors.CYAN, bold=True) spinner.write(info) diff --git a/riocli/hwil/delete.py b/riocli/hwil/delete.py index ad967dc0..26806e46 100644 --- a/riocli/hwil/delete.py +++ b/riocli/hwil/delete.py @@ -37,8 +37,26 @@ def delete_device( force: bool, spinner: Yaspin = None, ) -> None: - """Delete one or more devices""" + """Delete one or more devices. + You can specify the device names to delete using the + device names as arguments. If you want to delete multiple + devices, you can specify multiple device names separated + by spaces. + + You can skip confirmation by using the ``--force`` or ``-f`` + or the ``--silent`` flag. + + Usage Examples: + + Delete a single device by name + + $ rio hwil delete my-device + + Delete multiple devices by name + + $ rio hwil delete my-device1 my-device2 my-device3 + """ if not devices: spinner.text = click.style('No device names provided', fg=Colors.RED) spinner.red.fail(Symbols.ERROR) diff --git a/riocli/hwil/execute.py b/riocli/hwil/execute.py index 54edc77a..a02293a1 100644 --- a/riocli/hwil/execute.py +++ b/riocli/hwil/execute.py @@ -31,7 +31,10 @@ @click.argument('command', required=True, type=str) @name_to_id def execute(device_name: str, device_id: str, command: str) -> None: - """Execute a command on a hardware-in-the-loop device.""" + """Execute a command on a hardware-in-the-loop device. + + Ensure that you wrap the command in quotes to avoid any issues. + """ try: code, stdout, stderr = execute_command(new_hwil_client(), device_id, command) sys.stdout.write(stdout) diff --git a/riocli/hwil/inspect.py b/riocli/hwil/inspect.py index a38e536e..3ca188ed 100644 --- a/riocli/hwil/inspect.py +++ b/riocli/hwil/inspect.py @@ -37,9 +37,7 @@ def inspect_device( device_name: str, device_id: str ) -> None: - """ - Inspect the hardware-in-the-loop device. - """ + """Print the details of a hardware-in-the-loop device.""" client = new_hwil_client() try: diff --git a/riocli/hwil/login.py b/riocli/hwil/login.py index e53a1970..130804d1 100644 --- a/riocli/hwil/login.py +++ b/riocli/hwil/login.py @@ -45,7 +45,15 @@ def login( password: str, interactive: bool = True, ) -> None: - """Log in to HWIL.""" + """Authenticate with HWIL API. + + This is mandatory to use the HWIL commands and also + to create virtual devices with the device manifest. + + You can choose to login non-interactively by providing + --username and --password flags or interactively by + not providing any flags. + """ ctx = get_root_context(ctx) if interactive: diff --git a/riocli/hwil/ssh.py b/riocli/hwil/ssh.py index 05cebc42..ffa9cb82 100644 --- a/riocli/hwil/ssh.py +++ b/riocli/hwil/ssh.py @@ -30,7 +30,14 @@ @click.argument('device-name', required=True, type=str) @name_to_id def ssh(device_name: str, device_id: str, spinner=None) -> None: - """SSH into the hardware-in-the-loop device.""" + """SSH into a hardware-in-the-loop device. + + This command acts as a wrapper on top of the ``ssh`` command. + It fetches the static IP address of the device and logs you in + using the username configured for the device at the time of its + creation. You will be prompted for the password which is also + presented to you on the terminal. + """ try: device = new_hwil_client().get_device(device_id) diff --git a/riocli/jsonschema/validate.py b/riocli/jsonschema/validate.py index 2c5f24cf..55fa3bb2 100644 --- a/riocli/jsonschema/validate.py +++ b/riocli/jsonschema/validate.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/managedservice/__init__.py b/riocli/managedservice/__init__.py index f47b74e3..c15cd8a6 100644 --- a/riocli/managedservice/__init__.py +++ b/riocli/managedservice/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. @@ -25,6 +25,7 @@ cls=HelpColorsGroup, help_headers_color='yellow', help_options_color='green', + hidden=True, ) def managedservice() -> None: """ diff --git a/riocli/managedservice/delete.py b/riocli/managedservice/delete.py index 7601f187..94cb9383 100644 --- a/riocli/managedservice/delete.py +++ b/riocli/managedservice/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/managedservice/inspect.py b/riocli/managedservice/inspect.py index 2ff7567a..50136a42 100644 --- a/riocli/managedservice/inspect.py +++ b/riocli/managedservice/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. diff --git a/riocli/managedservice/list.py b/riocli/managedservice/list.py index efddcee8..c1a4488f 100644 --- a/riocli/managedservice/list.py +++ b/riocli/managedservice/list.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. diff --git a/riocli/managedservice/list_providers.py b/riocli/managedservice/list_providers.py index 92ab3b11..7ea22553 100644 --- a/riocli/managedservice/list_providers.py +++ b/riocli/managedservice/list_providers.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. diff --git a/riocli/network/__init__.py b/riocli/network/__init__.py index 865de419..20b55111 100644 --- a/riocli/network/__init__.py +++ b/riocli/network/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/network/delete.py b/riocli/network/delete.py index 88ed4620..858dc6ec 100644 --- a/riocli/network/delete.py +++ b/riocli/network/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -48,8 +48,34 @@ def delete_network( workers: int = 10, spinner: Yaspin = None ) -> None: - """ - Deletes a network + """Delete one or more networks with a name or a regex pattern. + + You can specify a name or a regex pattern to delete one + or more networks. + + If you want to delete all the networks, then + simply use the ``--all`` flag. + + If you want to delete networks without confirmation, then use the + ``--force`` or ``--silent`` or ``-f``. + + Usage Examples: + + Delete a network by name + + $ rio network delete NETWORK_NAME + + Delete a network without confirmation + + $ rio network delete NETWORK_NAME --force + + Delete all networks in the project + + $ rio network delete --all + + Delete networks using regex pattern + + $ rio network delete "NETWORK.*" """ client = new_v2_client() diff --git a/riocli/network/inspect.py b/riocli/network/inspect.py index 95692c84..9209d626 100644 --- a/riocli/network/inspect.py +++ b/riocli/network/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -12,12 +12,11 @@ # 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.utils import inspect_with_format -from riocli.config import new_v2_client -from munch import unmunchify @click.command('inspect') @@ -25,8 +24,10 @@ type=click.Choice(['json', 'yaml'], case_sensitive=False)) @click.argument('network-name') def inspect_network(format_type: str, network_name: str) -> None: - """ - Inspect the network resource + """Print the details of a network. + + You can specify the format of the output using the ``--format`` flag. + The supported formats are ``json`` and ``yaml``. Default is ``yaml``. """ try: client = new_v2_client() diff --git a/riocli/network/list.py b/riocli/network/list.py index 4a312e8f..1ea760ca 100644 --- a/riocli/network/list.py +++ b/riocli/network/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -33,8 +33,16 @@ @click.option('--label', '-l', 'labels', multiple=True, type=click.STRING, default=(), help='Filter the deployment list by labels') def list_networks(network: str, labels: typing.List[str]) -> None: - """ - List the networks in the selected project + """List the networks in the current project. + + You can also filter the list by specifying labels using + the ``--label`` or the ``-l`` flag. + + Usage Examples: + + List all networks with label "app=nginx" + + $ rio network list --label app=nginx """ try: client = new_v2_client(with_project=True) diff --git a/riocli/network/util.py b/riocli/network/util.py index 6d64bf93..1a4bfdcf 100644 --- a/riocli/network/util.py +++ b/riocli/network/util.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/organization/__init__.py b/riocli/organization/__init__.py index 398c5338..a85a0b9c 100644 --- a/riocli/organization/__init__.py +++ b/riocli/organization/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -30,8 +30,15 @@ help_options_color=Colors.GREEN, ) def organization() -> None: - """ - Organizations in rapyuta.io + """Interact with organizations. + + In rapyuta.io, an organization is the top-level entity that + contains all the projects and resources. Using the CLI, you + can view and select organizations, it's users, invite users, + and remove users. + + Note that in order to invite or remove users, you need to login + as the organization admin. """ pass diff --git a/riocli/organization/inspect.py b/riocli/organization/inspect.py index 9ad297ff..b072e19d 100644 --- a/riocli/organization/inspect.py +++ b/riocli/organization/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -38,8 +38,11 @@ def inspect_organization( organization_guid: str, organization_short_id: str, ) -> None: - """ - Inspect an organization + """Inspect an organization. + + Provides an overview of the organization. The output + is not the exact ouptut of the API, but a more human-readable + version of the organization details. """ try: organization = get_organization_details(organization_guid) diff --git a/riocli/organization/invite_user.py b/riocli/organization/invite_user.py index 44925982..23192c66 100644 --- a/riocli/organization/invite_user.py +++ b/riocli/organization/invite_user.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -30,8 +30,18 @@ @click.argument('user-email', type=str) @click.pass_context def invite_user(ctx: click.Context, user_email: str) -> None: - """ - Invite a new user to the current organization + """Invite a new user to the current organization. + + If the user does not have a rapyuta.io account, they will + receive an email with an invitation to join the organization. + If the user already has an account, they will be added to + the organization. + + Usage Examples: + + Add a new user to the organization + + $ rio organization invite-user user@email.com """ ctx = get_root_context(ctx) diff --git a/riocli/organization/list.py b/riocli/organization/list.py index dae57f7a..9a5b4f9d 100644 --- a/riocli/organization/list.py +++ b/riocli/organization/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -28,12 +28,10 @@ ) @click.pass_context def list_organizations(ctx: click.Context) -> None: - """ - List all the organizations that you are a part of - - Example: + """List all the organizations for the current user. - rio organization list + You will only see the organizations that you are a + part of. The current organization is highlighted in green. """ try: client = new_client(with_project=False) diff --git a/riocli/organization/remove_user.py b/riocli/organization/remove_user.py index 0160569f..15e81748 100644 --- a/riocli/organization/remove_user.py +++ b/riocli/organization/remove_user.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -30,8 +30,7 @@ @click.argument('user-email', type=str) @click.pass_context def remove_user(ctx: click.Context, user_email: str) -> None: - """ - Remove a user from the current organization + """Remove a user from the current organization """ ctx = get_root_context(ctx) diff --git a/riocli/organization/select.py b/riocli/organization/select.py index f6cb2139..de5b9fd2 100644 --- a/riocli/organization/select.py +++ b/riocli/organization/select.py @@ -42,14 +42,27 @@ def select_organization( organization_short_id: str, interactive: bool, ) -> None: - """ - Sets the current organization to the one provided - in the argument and prompts you to select a new project - in the changed organization + """Set the current organization. + + You can set the current organization using the name + or the guid of the organization. You will be prompted + to select a project if you are running the command in + an interactive mode. + + To simply set the organization without selecting a project, + use the `--no-interactive` or `--silent` flag. + + If your organization name has spaces, use quotes around the name. + + Usage Examples: + + Set the current organization to 'Platform JP Staging' + + $ rio organization select 'Platform JP Staging' - Example: + Set the current organization to 'Platform JP Staging' without selecting a project - rio organization select other-org + $ rio organization select 'Platform JP Staging' --silent """ ctx = get_root_context(ctx) diff --git a/riocli/organization/users.py b/riocli/organization/users.py index 3e7b9ec9..0e4fa006 100644 --- a/riocli/organization/users.py +++ b/riocli/organization/users.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -29,9 +29,7 @@ ) @click.pass_context def list_users(ctx: click.Context) -> None: - """ - Lists all users in the organization. - """ + """Lists all users in the organization.""" ctx = get_root_context(ctx) current_user_email = ctx.obj.data.get('email_id') diff --git a/riocli/organization/utils.py b/riocli/organization/utils.py index 83b81f62..eee98ff3 100644 --- a/riocli/organization/utils.py +++ b/riocli/organization/utils.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/package/__init__.py b/riocli/package/__init__.py index 3ba2f409..5520b8c6 100644 --- a/riocli/package/__init__.py +++ b/riocli/package/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/package/deployment.py b/riocli/package/deployment.py index 79fa69fd..46790f26 100644 --- a/riocli/package/deployment.py +++ b/riocli/package/deployment.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/package/inspect.py b/riocli/package/inspect.py index ed329240..5fd7f91e 100644 --- a/riocli/package/inspect.py +++ b/riocli/package/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/package/list.py b/riocli/package/list.py index 6ad8fb0f..1d6b556c 100644 --- a/riocli/package/list.py +++ b/riocli/package/list.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/package/model.py b/riocli/package/model.py index becf3bc3..8c7cb57f 100644 --- a/riocli/package/model.py +++ b/riocli/package/model.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. diff --git a/riocli/parameter/__init__.py b/riocli/parameter/__init__.py index b6f3f780..8674d0e1 100644 --- a/riocli/parameter/__init__.py +++ b/riocli/parameter/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -31,8 +31,15 @@ help_options_color=Colors.GREEN, ) def parameter() -> None: - """ - Manage configuration parameters for your devices and deployments + """Configuration parameters for your devices and deployments. + + The configuration parameters are file based configs that are + stored in a directory-like structure. You can upload, download, + and apply these configurations to your devices and deployments. + + The platform ensures the availability of the configurations at + predefined paths on the devices and deployments as well as the + deployments in the cloud. """ pass diff --git a/riocli/parameter/apply.py b/riocli/parameter/apply.py index 452da9b1..292ad308 100644 --- a/riocli/parameter/apply.py +++ b/riocli/parameter/apply.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -54,8 +54,27 @@ def apply_configurations( device_name_pattern: str = None, silent: bool = False, ) -> None: - """ - Apply a set of configurations to a list of devices + """Apply a set of configuration parameter trees to a list of devices. + + You can either specify the device names using the ``--devices`` flag or + use the ``--device-name-pattern`` flag to apply configurations to devices. + + Note that the ``--devices`` flag will be ignored if the ``--device-name-pattern`` + flag is provided. + + You can specify the trees to apply using the ``--tree-names`` flag. + + Skip the confirmation prompt by using the ``--force`` or ``--silent`` or the ``-f`` flag. + + Usage Examples: + + Apply configurations to a list of devices + + $ rio parameter apply --devices device1 --devices device2 --tree-names tree1 + + Apply configurations to devices using a regex pattern + + $ rio parameter apply --device-name-pattern 'amr.*' --tree-names params """ client = new_client() diff --git a/riocli/parameter/delete.py b/riocli/parameter/delete.py index e9bb64bc..2d84ac91 100644 --- a/riocli/parameter/delete.py +++ b/riocli/parameter/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -41,8 +41,10 @@ def delete_configurations( tree: str, silent: bool = False ) -> None: - """ - Deletes the configuration parameter tree. + """Delete a configuration parameter tree. + + You can skip the confirmation prompt by using the ``--force`` or + ``--silent`` or ``-f`` flag. """ click.secho('Configuration Parameter {} will be deleted'.format(tree)) diff --git a/riocli/parameter/diff.py b/riocli/parameter/diff.py index a3b38a4f..9873aa86 100644 --- a/riocli/parameter/diff.py +++ b/riocli/parameter/diff.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -42,8 +42,9 @@ 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. + + You can specify the tree names to diff using the ``--tree-names`` flag. """ trees = filter_trees(path, tree_names) diff --git a/riocli/parameter/download.py b/riocli/parameter/download.py index 3e4845e7..5a9612c7 100644 --- a/riocli/parameter/download.py +++ b/riocli/parameter/download.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -19,7 +19,7 @@ from click_help_colors import HelpColorsCommand from riocli.config import new_client -from riocli.constants import Symbols, Colors +from riocli.constants import Colors, Symbols from riocli.utils.spinner import with_spinner @@ -50,8 +50,14 @@ def download_configurations( delete_existing: bool = False, spinner=None ) -> None: - """ - Download configuration parameter trees from rapyuta.io + """Download configuration parameter trees from rapyuta.io. + + You can specify the tree names to download using the ``--tree-names`` flag. + + If you do not specify any tree names, all the trees will be downloaded. + + You can also specify the ``--overwrite`` or ``--delete-existing`` flag to + overwrite the existing parameter tree on the local machine. """ if path is None: # Not using the Context Manager because diff --git a/riocli/parameter/list.py b/riocli/parameter/list.py index 9acb8f9d..8fde8655 100644 --- a/riocli/parameter/list.py +++ b/riocli/parameter/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -26,9 +26,7 @@ help_options_color=Colors.GREEN, ) def list_configuration_trees() -> None: - """ - List the Configuration Parameter Trees. - """ + """List the configuration parameter trees in current project.""" try: data = list_trees() trees = [[tree] for tree in data] diff --git a/riocli/parameter/upload.py b/riocli/parameter/upload.py index f92cc656..4af7a3eb 100644 --- a/riocli/parameter/upload.py +++ b/riocli/parameter/upload.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -47,8 +47,34 @@ def upload_configurations( delete_existing: bool = False, silent: bool = False ) -> None: - """ - Upload a directories as configuration parameters. + """Upload directories as configuration parameter trees. + + You can upload one or more directories as configuration + parameter trees on rapyuta.io. If you do not wish to + upload all the directories as a tree you can specify + the directory names using the ``--tree-names`` flag. + Directories that match the tree names will be parsed and + uploaded. + + You can also specify the ``--recreate`` or ``--delete-existing`` + flag to overwrite the existing parameter tree on rapyuta.io. + + You can skip the confirmation prompt by using the ``--force`` or + ``--silent`` or the ``-f`` flag. + + Usage Examples: + + Upload all directories as configuration parameter trees + + $ rio parameter upload . + + Upload only the directories "config" and "secrets" + + $ rio parameter upload . --tree-names config --tree-names secrets + + Recreate the existing parameter tree + + $ rio parameter upload . --recreate """ try: trees = filter_trees(path, tree_names) diff --git a/riocli/parameter/utils.py b/riocli/parameter/utils.py index dca2a22a..dd454f31 100644 --- a/riocli/parameter/utils.py +++ b/riocli/parameter/utils.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/project/create.py b/riocli/project/create.py index d5cdbbc5..a52a8e62 100644 --- a/riocli/project/create.py +++ b/riocli/project/create.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -40,8 +40,10 @@ def create_project( organization_short_id: str, spinner=None, ) -> None: - """ - Creates a new project + """Create a new project. + + If you do not specify the organization, the project will + be created in the current organization. """ if not organization_guid: organization_guid = ctx.obj.data.get('organization_id') diff --git a/riocli/project/delete.py b/riocli/project/delete.py index 73800679..f4a182d1 100644 --- a/riocli/project/delete.py +++ b/riocli/project/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -15,7 +15,7 @@ from click_help_colors import HelpColorsCommand from riocli.config import new_v2_client -from riocli.constants import Symbols, Colors +from riocli.constants import Colors, Symbols from riocli.project.util import name_to_guid from riocli.utils.spinner import with_spinner @@ -37,8 +37,10 @@ def delete_project( project_guid: str, spinner=None, ) -> None: - """ - Deletes a project + """Delete a project. + + You can skip the confirmation prompt by using the ``--force`` + or ``-f`` or the ``--silent`` flag. """ if not force: with spinner.hidden(): diff --git a/riocli/project/features/__init__.py b/riocli/project/features/__init__.py index 95e011ba..ffbdb8dc 100644 --- a/riocli/project/features/__init__.py +++ b/riocli/project/features/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/project/inspect.py b/riocli/project/inspect.py index 6c6426fd..341c8e1d 100644 --- a/riocli/project/inspect.py +++ b/riocli/project/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. @@ -33,8 +33,10 @@ @name_to_guid def inspect_project(format_type: str, project_name: str, project_guid: str) -> None: - """ - Inspect the project resource + """Print the project details. + + You can specify the format of the output using the ``--format`` flag. + The supported formats are ``json`` and ``yaml``. Default is ``yaml``. """ try: client = new_v2_client(with_project=False) diff --git a/riocli/project/list.py b/riocli/project/list.py index cd0b16cb..e258f4fd 100644 --- a/riocli/project/list.py +++ b/riocli/project/list.py @@ -46,8 +46,22 @@ def list_projects( labels: typing.List[str] = (), wide: bool = False, ) -> None: - """ - List all the projects you are part of + """List all the projects you are a part of in current organization. + + You can also filter the list by specifying labels using the ``--label`` + or the ``-l`` flag. + + For more details, you can use the ``--wide`` or the ``-w`` flag. + + Usage Examples: + + List all projects with label "release=3.0" + + $ rio project list --label release=3.0 + + List projects with the wide option + + $ rio project list --wide """ # If organization is not passed in the options, use organization_guid = organization_guid or ctx.obj.data.get('organization_id') diff --git a/riocli/project/select.py b/riocli/project/select.py index 376c256f..82de2ab5 100644 --- a/riocli/project/select.py +++ b/riocli/project/select.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -34,8 +34,10 @@ def select_project( project_name: str, project_guid: str, ) -> None: - """ - Sets the given project in the CLI context. All other resources use this project to act upon. + """Switch to a different project in the current organization. + + The project will be set in the CLI's context and will be used + for all the subsequent commands. """ ctx = get_root_context(ctx) diff --git a/riocli/project/update_owner.py b/riocli/project/update_owner.py index 2d48a128..c32af786 100644 --- a/riocli/project/update_owner.py +++ b/riocli/project/update_owner.py @@ -42,7 +42,13 @@ def update_owner( Update the owner of the project. The command will show an interactive list of users in the project if - you do not specify --user-email. You can select the new owner from the list. + you do not specify ``--user-email.`` You can select the new owner from the list. + + Usage Examples: + + Update the owner of the project to a specific user + + $ rio project update-owner PROJECT --user-email user@email.com """ config = get_config_from_context(ctx) client = config.new_v2_client(with_project=False) diff --git a/riocli/project/whoami.py b/riocli/project/whoami.py index 034da931..6fea259a 100644 --- a/riocli/project/whoami.py +++ b/riocli/project/whoami.py @@ -32,8 +32,10 @@ @name_to_guid @click.pass_context def whoami(ctx: click.Context, project_name: str, project_guid: str) -> None: - """ - Find the role of the current user in a project. + """Find your role in a project. + + If you do not specify the project name, the command will use the project + set in the CLI context. """ if not ctx.obj.data.get('email_id'): raise LoggedOut diff --git a/riocli/rosbag/__init__.py b/riocli/rosbag/__init__.py index 3437ac70..d9e4dabe 100644 --- a/riocli/rosbag/__init__.py +++ b/riocli/rosbag/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/secret/__init__.py b/riocli/secret/__init__.py index 22b16d4c..5985f6fb 100644 --- a/riocli/secret/__init__.py +++ b/riocli/secret/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/secret/delete.py b/riocli/secret/delete.py index 0fbc1b4b..69930ded 100644 --- a/riocli/secret/delete.py +++ b/riocli/secret/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/secret/inspect.py b/riocli/secret/inspect.py index 80c76ce6..a6149aab 100644 --- a/riocli/secret/inspect.py +++ b/riocli/secret/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/secret/list.py b/riocli/secret/list.py index b08e177a..e8d063a3 100644 --- a/riocli/secret/list.py +++ b/riocli/secret/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/shell/__init__.py b/riocli/shell/__init__.py index 7284ce18..de867f8e 100644 --- a/riocli/shell/__init__.py +++ b/riocli/shell/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. @@ -19,18 +19,21 @@ from prompt_toolkit.history import FileHistory, ThreadedHistory from riocli.config import Configuration +from riocli.constants import Colors from riocli.shell.prompt import prompt_callback @click.command( cls=HelpColorsCommand, - help_headers_color='yellow', - help_options_color='green', + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, ) @click.pass_context def shell(ctx: click.Context): - """ - Interactive Shell for Rapyuta.io + """Start an interactive shell + + The shell provides an interactive environment to run commands + and is useful for running multiple commands in a single session. """ start_shell(ctx) @@ -38,8 +41,8 @@ def shell(ctx: click.Context): @click.command( 'repl', cls=HelpColorsCommand, - help_headers_color='yellow', - help_options_color='green', + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, hidden=True ) @click.pass_context diff --git a/riocli/shell/prompt.py b/riocli/shell/prompt.py index 14281169..8deafbef 100644 --- a/riocli/shell/prompt.py +++ b/riocli/shell/prompt.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. diff --git a/riocli/static_route/__init__.py b/riocli/static_route/__init__.py index d14b22f3..3cb805e0 100644 --- a/riocli/static_route/__init__.py +++ b/riocli/static_route/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/static_route/create.py b/riocli/static_route/create.py index d66fc266..45dc61ad 100644 --- a/riocli/static_route/create.py +++ b/riocli/static_route/create.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -18,6 +18,7 @@ from riocli.constants import Colors, Symbols from riocli.utils.spinner import with_spinner + @click.command( 'create', cls=HelpColorsCommand, @@ -27,8 +28,12 @@ @click.argument('name', type=str) @with_spinner(text="Creating static route...") def create_static_route(name: str, spinner=None) -> None: - """ - Creates a new static route + """Create a new static route + + Please note that the name you provide while creating the + static route will be suffixed with the organization's + short guid in the backend. Please run the list command + to view the name of the static route and inspect it later. """ try: client = new_v2_client(with_project=True) diff --git a/riocli/static_route/delete.py b/riocli/static_route/delete.py index 6c549a01..3186804e 100644 --- a/riocli/static_route/delete.py +++ b/riocli/static_route/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -18,6 +18,7 @@ from riocli.constants import Colors, Symbols from riocli.utils.spinner import with_spinner + @click.command( 'delete', cls=HelpColorsCommand, @@ -32,8 +33,10 @@ def delete_static_route( force: bool, spinner=None, ) -> None: - """ - Deletes a static route + """Delete a static route. + + To skip confirmation, use the ``--force`` or ``-f`` or + the ``--silent`` flag. """ with spinner.hidden(): if not force: diff --git a/riocli/static_route/inspect.py b/riocli/static_route/inspect.py index 3f8a4bb5..eb0d6cc4 100644 --- a/riocli/static_route/inspect.py +++ b/riocli/static_route/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -34,8 +34,10 @@ def inspect_static_route( format_type: str, static_route: str, ) -> None: - """ - Inspect a static route + """Print the details of a static route. + + You can choose the format of the output using the ``--format`` flag. + The supported formats are ``json`` and ``yaml``. Default is ``yaml``. """ try: client = new_v2_client() diff --git a/riocli/static_route/list.py b/riocli/static_route/list.py index b4097177..8af5d249 100644 --- a/riocli/static_route/list.py +++ b/riocli/static_route/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -32,8 +32,16 @@ @click.option('--label', '-l', 'labels', multiple=True, type=click.STRING, default=(), help='Filter the deployment list by labels') def list_static_routes(labels: typing.List[str]) -> None: - """ - List the static routes in the selected project + """List the static routes in the current project. + + You can filter the list by providing labels using + the ``--label`` or ``-l`` flag. + + Usage Examples: + + List static routes with label 'app=web' + + $ rio static-route list --label app=web """ try: client = new_v2_client(with_project=True) diff --git a/riocli/static_route/open.py b/riocli/static_route/open.py index 9f1fa082..7d6d7bb4 100644 --- a/riocli/static_route/open.py +++ b/riocli/static_route/open.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -26,9 +26,7 @@ ) @click.argument('static-route', type=str) def open_static_route(static_route) -> None: - """ - Opens the static route in the default browser - """ + """Open a static route in the default browser.""" try: client = new_v2_client() route = client.get_static_route(static_route) diff --git a/riocli/static_route/util.py b/riocli/static_route/util.py index ab7cc6b9..19f22a1d 100644 --- a/riocli/static_route/util.py +++ b/riocli/static_route/util.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/usergroup/__init__.py b/riocli/usergroup/__init__.py index 69839067..02e9513d 100644 --- a/riocli/usergroup/__init__.py +++ b/riocli/usergroup/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -28,8 +28,17 @@ help_options_color=Colors.GREEN, ) def usergroup() -> None: - """ - Manage usergroups on rapyuta.io + """Manage usergroups in current organization. + + Usergroups are a way to organize users and projects + in your organization. You can create usergroups and + add users and projects to them. This helps in managing + access control and permissions in your organization. + + Users can be part of multiple usergroups and projects + can be part of multiple usergroups. You can further + make some users admins of a usergroup and they will + have the permissions to manage the usergroup. """ pass diff --git a/riocli/usergroup/delete.py b/riocli/usergroup/delete.py index ad7eeccb..0f9b87ca 100644 --- a/riocli/usergroup/delete.py +++ b/riocli/usergroup/delete.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -41,8 +41,10 @@ def delete_usergroup( force: bool, spinner: Yaspin = None, ) -> None: - """ - Delete usergroup from organization + """Delete a usergroup from current organization. + + To skip confirmation, use the ``--force`` or ``-f`` or + the ``--silent`` flag. """ if not force: with spinner.hidden(): diff --git a/riocli/usergroup/inspect.py b/riocli/usergroup/inspect.py index ea1e81bf..71586979 100644 --- a/riocli/usergroup/inspect.py +++ b/riocli/usergroup/inspect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -35,8 +35,10 @@ @click.pass_context @name_to_guid def inspect_usergroup(ctx: click.Context, format_type: str, group_name: str, group_guid: str, spinner=None) -> None: - """ - Inspect the usergroup resource + """Print the details of a usergroup + + You choose the format of the output using the ``--format`` flag. + The supported formats are ``json`` and ``yaml``. Default is ``yaml``. """ try: client = new_client() diff --git a/riocli/usergroup/list.py b/riocli/usergroup/list.py index 551c237b..458050f6 100644 --- a/riocli/usergroup/list.py +++ b/riocli/usergroup/list.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -16,6 +16,7 @@ import click from click_help_colors import HelpColorsCommand + from riocli.config import new_client from riocli.constants import Colors from riocli.utils import tabulate_data @@ -29,10 +30,7 @@ ) @click.pass_context def list_usergroup(ctx: click.Context) -> None: - """ - List all user groups in selected organization - """ - + """List all user groups in current organization.""" try: client = new_client() org_guid = ctx.obj.data.get('organization_id') diff --git a/riocli/usergroup/util.py b/riocli/usergroup/util.py index 861eb66f..9120df9e 100644 --- a/riocli/usergroup/util.py +++ b/riocli/usergroup/util.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/utils/__init__.py b/riocli/utils/__init__.py index bda73ed6..64040bab 100644 --- a/riocli/utils/__init__.py +++ b/riocli/utils/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/utils/context.py b/riocli/utils/context.py index 3e7787ca..bc4063aa 100644 --- a/riocli/utils/context.py +++ b/riocli/utils/context.py @@ -1,4 +1,4 @@ -# Copyright 2022 Rapyuta Robotics +# 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. diff --git a/riocli/utils/execute.py b/riocli/utils/execute.py index 83f58eef..2ab9afc1 100644 --- a/riocli/utils/execute.py +++ b/riocli/utils/execute.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/utils/spinner.py b/riocli/utils/spinner.py index 822a97e1..ee753d96 100644 --- a/riocli/utils/spinner.py +++ b/riocli/utils/spinner.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. diff --git a/riocli/utils/ssh_tunnel.py b/riocli/utils/ssh_tunnel.py index e8f9f39b..64be9358 100644 --- a/riocli/utils/ssh_tunnel.py +++ b/riocli/utils/ssh_tunnel.py @@ -1,4 +1,4 @@ -# Copyright 2021 Rapyuta Robotics +# 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. diff --git a/riocli/vpn/__init__.py b/riocli/vpn/__init__.py index c2eec2cc..ab63af2a 100644 --- a/riocli/vpn/__init__.py +++ b/riocli/vpn/__init__.py @@ -28,8 +28,13 @@ help_options_color='green', ) def vpn() -> None: - """ - Connect your machine to the current project's VPN network + """Connect to the rapyuta.io VPN + + You can connect to the rapyuta.io VPN from your system + and access the machines in the VPN. You can view other + machines in the VPN, ping them, and check the status of + the VPN connection. You can also register a new machine + that may not be able to run the CLI. """ pass diff --git a/riocli/vpn/connect.py b/riocli/vpn/connect.py index 9e178efe..63c5473d 100644 --- a/riocli/vpn/connect.py +++ b/riocli/vpn/connect.py @@ -51,8 +51,20 @@ @click.pass_context @with_spinner(text="Connecting...") def connect(ctx: click.Context, update_hosts: bool, spinner: Yaspin): - """ - Connect to the current project's VPN network + """Connect to the current project's VPN network. + + Simpy run the command to connect to the VPN network + of the current project. If ``tailscale`` isn't found + on the system then the command will prompt to install + the required tools. + + If the VPN is not enabled in the + project, the command will inform the user to enable + it on the project. + + If you are already connected to the VPN, the command + will prompt to stop the current connection and connect + to the project's VPN. """ config = get_config_from_context(ctx) diff --git a/riocli/vpn/disconnect.py b/riocli/vpn/disconnect.py index 8f389306..187e9a7e 100644 --- a/riocli/vpn/disconnect.py +++ b/riocli/vpn/disconnect.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -32,8 +32,14 @@ ) @click.pass_context def disconnect(ctx: click.Context): - """ - Disconnect from the project's VPN network + """Disconnect from the project's VPN network. + + Simply run the command to disconnect from the VPN network. + + If ``tailscale`` isn't found on the system then the command will + prompt to install the required tools. While it may seem unnecessary + to install the tools to disconnect, it is works as a safety measure + to ensure that the user has the required tools to connect to the VPN. """ try: install_vpn_tools() diff --git a/riocli/vpn/machines.py b/riocli/vpn/machines.py index 370e489c..c04d8d2c 100644 --- a/riocli/vpn/machines.py +++ b/riocli/vpn/machines.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from typing import Iterable + import click from click_help_colors import HelpColorsCommand, HelpColorsGroup from yaspin.core import Yaspin @@ -44,8 +45,10 @@ def machines() -> None: help_options_color=Colors.GREEN, ) def list_machines() -> None: - """ - List all the registered Machines on the VPN. + """List all the registered machines on the VPN. + + This command lists all the machines that are registered + on the VPN using the CLI. """ labels = 'machine-key=true' @@ -67,10 +70,14 @@ def list_machines() -> None: @click.argument('name', type=str) @click.argument('node_key', type=str) @click.pass_context -@with_spinner(text="Registering Machine...") +@with_spinner(text="Registering machine...") def register_machine(ctx: click.Context, name: str, node_key: str, spinner: Yaspin) -> None: - """ - Register an Android or iOS Tailscale Client in the Project VPN. + """Register an Android or iOS Tailscale Client in the project's VPN. + + Provide a name and the node key of the machine to register it + in the project's VPN. The node key can be obtained from the + Tailscale client running on the machine. The name can be any + name that you want to give to the machine. """ labels = get_binding_labels() labels['machine-key'] = 'true' @@ -95,12 +102,9 @@ def register_machine(ctx: click.Context, name: str, node_key: str, spinner: Yasp help_options_color=Colors.GREEN, ) @click.argument('name', type=str) -@with_spinner(text="De-registering Machine...") +@with_spinner(text="De-registering machine...") def deregister_machine(name: str, spinner: Yaspin) -> None: - """ - Register an Android or iOS Tailscale Client in the Project VPN. - """ - + """Deregister an Android or iOS Tailscale Client in the Project VPN.""" try: client = new_v2_client() client.delete_instance_binding("rio-internal-headscale", name) diff --git a/riocli/vpn/ping.py b/riocli/vpn/ping.py index 59e393c4..147d4411 100644 --- a/riocli/vpn/ping.py +++ b/riocli/vpn/ping.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -18,12 +18,7 @@ from riocli.constants import Colors, Symbols from riocli.utils.spinner import with_spinner -from riocli.vpn.util import ( - install_vpn_tools, - is_tailscale_up, - get_tailscale_status, - tailscale_ping -) +from riocli.vpn.util import (get_tailscale_status, install_vpn_tools, is_tailscale_up, tailscale_ping) @click.command( @@ -35,8 +30,12 @@ @click.pass_context @with_spinner(text="Pinging all peers...") def ping_all(ctx: click.Context, spinner: Yaspin = None): - """ - Ping all the peers in the network + """Ping all the peers in the network. + + This command will ping all the peers in the network. It is + convenient to check the connectivity of all the peers in the + network. Also, it helps establish a direct connection with + the peers. """ try: with spinner.hidden(): diff --git a/riocli/vpn/status.py b/riocli/vpn/status.py index ccea7b36..392a7850 100644 --- a/riocli/vpn/status.py +++ b/riocli/vpn/status.py @@ -1,4 +1,4 @@ -# Copyright 2023 Rapyuta Robotics +# 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. @@ -18,12 +18,7 @@ from riocli.config import new_v2_client from riocli.constants import Colors, Symbols from riocli.utils import tabulate_data -from riocli.vpn.util import ( - install_vpn_tools, - is_tailscale_up, - get_tailscale_status, - is_vpn_enabled_in_project, -) +from riocli.vpn.util import (get_tailscale_status, install_vpn_tools, is_tailscale_up, is_vpn_enabled_in_project) @click.command( @@ -36,8 +31,11 @@ help='Print more details', type=bool) @click.pass_context def status(ctx: click.Context, wide: bool = False): - """ - Check VPN status + """Check VPN network status. + + You can view all the connected peers in the VPN network. + + User the ``--wide`` flag to view more details about the peers. """ try: install_vpn_tools()