Skip to content

Commit

Permalink
Merge pull request #395 from rapyuta-robotics/devel
Browse files Browse the repository at this point in the history
release: v9.5.0
  • Loading branch information
pallabpain authored Dec 11, 2024
2 parents 838f928 + 2a68b2d commit e64a625
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 85 deletions.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ dependencies = [
"python-magic>=0.4.27",
"pytz",
"pyyaml>=5.4.1",
"rapyuta-io>=2.1.1",
"rapyuta-io>=2.2.2",
"requests>=2.20.0",
"semver>=3.0.0",
"setuptools",
Expand All @@ -55,6 +55,7 @@ dependencies = [
"urllib3>=1.23",
"waiting>=1.4.1",
"yaspin==2.5.0",
"ansible-core>=2.13.13",
]

[tool.uv]
Expand Down
24 changes: 16 additions & 8 deletions riocli/apply/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,15 @@ def apply(
) -> None:
"""Apply resource manifests.
The apply command provides the mechanism to create or update
resources on rapyuta.io. The resources are defined in YAML manifests allowing for
a declarative and repeatable process. 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.
The apply command provides the mechanism to create or update resources on
rapyuta.io. The resources are defined in YAML manifests allowing for a
declarative and repeatable process. The command can take multiple files,
paths or globs as arguments and parse the manifests to create or update
resources.
The manifest files can optionally be templated using Jinja2 syntax. All the
Ansible filters are supported. The secret management with sops is also
supported.
You can provide value files with the ``--values`` option and
sops encrypted secret files with ``--secret`` option.
Expand Down Expand Up @@ -146,6 +149,7 @@ def apply(
Apply manifests with multiple value files.
$ rio apply -v values1.yaml -v values2.yaml templates/**
"""
glob_files, abs_values, abs_secrets = process_files_values_secrets(
files, values, secrets
Expand Down Expand Up @@ -257,8 +261,11 @@ def delete(
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.
as arguments and parse the manifests to remove resources.
The manifest files can optionally be templated using Jinja2 syntax. All the
Ansible filters are supported. The secret management with sops is also
supported.
You can provide value files with the ``--values`` option and
sops encrypted secret files with ``--secret`` option.
Expand Down Expand Up @@ -291,6 +298,7 @@ def delete(
Delete manifests with multiple value files.
$ rio delete -v values1.yaml -v values2.yaml templates/**
"""
glob_files, abs_values, abs_secrets = process_files_values_secrets(
files, values, secrets
Expand Down
1 change: 1 addition & 0 deletions riocli/apply/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""
Filters to use in the manifests.
"""

import os

from riocli.config import new_client
Expand Down
7 changes: 7 additions & 0 deletions riocli/apply/manifests/deployment-nonros-device.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ spec:
kind: device
nameOrGUID: device-docker
restart: always # Options: [always, onfailure, never]
features:
params:
enabled: true
trees:
- config01
- config02
blockUntilSynced: true # Optional [true, false]. Default is false.
envArgs:
- name: TEST_KEY
value: test_value
Expand Down
7 changes: 7 additions & 0 deletions riocli/apply/manifests/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,13 @@ spec:
kind: device
nameOrGUID: device-docker
restart: always # Options: [always, onfailure, never]
features:
params:
enabled: true
trees:
- config01
- config02
blockUntilSynced: true # Optional [true, false]. Default is false.
envArgs:
- name: TEST_KEY
value: test_value
Expand Down
4 changes: 2 additions & 2 deletions riocli/apply/manifests/device.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ spec:
rosDistro: "melodic" # Options: ["kinetic", "melodic" (default), "noetic"]
virtual:
enabled: True # Required
product: "sootballs" # Required Options: ["sootballs", "flaptter", "oks", "platform"]
product: "sootballs" # Optional: ["sootballs", "flaptter", "oks"]
arch: "amd64" # Options: ["amd64" (default), "arm64" ]
os: "ubuntu" # Options: ["ubuntu" (default), "debian" ]
codename: "focal" # Options: ["bionic", "focal" (default), "jammy", "bullseye"]
codename: "focal" # Options: ["bionic", "focal" (default), "jammy", "noble", "bullseye"]
highperf: False # Optional [True, False (default)]
wait: True # Optional [True, False (default)] Wait until the device is ready.
expireAfter: '12h' # Optional ["s", "m", "h", "d"] Expire after set duration.
Expand Down
20 changes: 20 additions & 0 deletions riocli/apply/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
import click
import jinja2
from yaspin.api import Yaspin
from ansible.plugins.filter.core import FilterModule as CoreFilterModule
from ansible.plugins.filter.urls import FilterModule as URLFilterModule
from ansible.plugins.filter.urlsplit import FilterModule as URLSplitFilterModule
from ansible.plugins.filter.mathstuff import FilterModule as MathFilterModule
from ansible.plugins.filter.encryption import FilterModule as EncryptionFilterModule

from riocli.apply.filters import FILTERS
from riocli.constants import Colors
Expand Down Expand Up @@ -149,4 +154,19 @@ def init_jinja_environment():
for name, func in FILTERS.items():
environment.filters[name] = func

for name, func in CoreFilterModule().filters().items():
environment.filters[name] = func

for name, func in URLFilterModule().filters().items():
environment.filters[name] = func

for name, func in URLSplitFilterModule().filters().items():
environment.filters[name] = func

for name, func in MathFilterModule().filters().items():
environment.filters[name] = func

for name, func in EncryptionFilterModule().filters().items():
environment.filters[name] = func

return environment
19 changes: 18 additions & 1 deletion riocli/deployment/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
)
@click.option("--user", default="root")
@click.option("--shell", default="/bin/bash")
@click.option("--timeout", default=300)
@click.option(
"--async",
"run_async",
is_flag=True,
default=False,
help="Run the command asynchronously.",
)
@click.option(
"--exec", "exec_name", default=None, help="Name of a executable in the component"
)
Expand All @@ -44,7 +52,9 @@
def execute_command(
user: str,
shell: str,
timeout: int,
exec_name: str,
run_async: bool,
deployment_name: str,
command: typing.List[str],
) -> None:
Expand All @@ -61,6 +71,12 @@ def execute_command(
shell is ``/bin/bash``. You can also specify the user using the ``--user``
option. The default user is ``root``.
To run the command asynchronously, set the --async flag to true.
The default value is false.
To specify the timeout, use the --timeout
flag, providing the duration in seconds. The default value is 300.
Please ensure that you enclose the command in quotes to avoid
any issues with the command parsing.
Expand Down Expand Up @@ -112,10 +128,11 @@ def execute_command(
user=user,
shell=shell,
command=command,
background=False,
background=run_async,
deployment=deployment,
exec_name=exec_name,
device_name=deployment.spec.device.depends.nameOrGUID,
timeout=timeout,
)
click.echo(response)
except Exception as e:
Expand Down
30 changes: 24 additions & 6 deletions riocli/device/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,36 @@
help_options_color=Colors.GREEN,
)
@click.option("--user", default="root")
@click.option("--timeout", default=300)
@click.option("--shell", default="/bin/bash")
@click.option(
"--async",
"run_async",
is_flag=True,
default=False,
help="Run the command asynchronously.",
)
@click.argument("device-name", type=str)
@click.argument("command", nargs=-1)
@name_to_guid
def execute_command(
device_name: str, device_guid: str, user: str, shell: str, command: typing.List[str]
device_name: str,
device_guid: str,
user: str,
timeout: int,
shell: str,
run_async: bool,
command: typing.List[str],
) -> None:
"""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.
You can specify the user, shell, run-async, and timeout options to customize
the command execution. 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'. To run the command asynchronously,
set the --async flag to true. The default value is false. To
specify the timeout, use the --timeout flag, providing the duration
in seconds. The default value is 300.
Make sure you put your command in quotes to avoid any issues.
Expand All @@ -54,7 +71,8 @@ def execute_command(
user=user,
shell=shell,
command=command,
background=False,
background=run_async,
timeout=timeout,
)

click.secho(response)
Expand Down
9 changes: 7 additions & 2 deletions riocli/device/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def apply(self, *args, **kwargs) -> ApplyResult:

# Create the HWIL (virtual) device and then generate the labels
# to store HWIL metadata in rapyuta.io device.
hwil_response = create_hwil_device(self.spec, self.metadata)
hwil_response = create_hwil_device(virtual, self.metadata)
labels = make_device_labels_from_hwil_device(hwil_response)

# Create the rapyuta.io device with labels if the
Expand Down Expand Up @@ -100,10 +100,15 @@ def delete(self, *args, **kwargs) -> None:
try:
device = find_device_by_name(client, self.metadata.name)
except DeviceNotFound:
# If it was a virtual device, try deleting the HWIL
# resource if it is present and raise ResourceNotFound.
if self.spec.get("virtual", {}).get("enabled", False):
delete_hwil_device(self.spec.virtual, self.metadata)

raise ResourceNotFound

if self.spec.get("virtual", {}).get("enabled", False):
delete_hwil_device(device)
delete_hwil_device(self.spec.virtual, self.metadata)

device.delete()

Expand Down
Loading

0 comments on commit e64a625

Please sign in to comment.