105 lines
5.2 KiB
Markdown
105 lines
5.2 KiB
Markdown
|
J
|
# `ria-app` Hub-Side Handoff
|
||
|
|
|
||
|
|
**Repo:** `ria-hub`
|
||
|
|
**Goal:** Make containerized apps built by Application Composer self-describing so the new `ria-app` CLI in `ria-toolkit-oss` can auto-configure GPU/USB/network flags at `docker run` time. No user copy-paste of flags.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Context — what exists today
|
||
|
|
|
||
|
|
In `ria-toolkit-oss` (branch `screens-connection`) there is now a `ria-app` CLI:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ria-app configure --registry registry.riahub.ai --namespace qoherent
|
||
|
|
ria-app pull <app>[:tag]
|
||
|
|
ria-app run <app>[:tag] [--config config.yaml]
|
||
|
|
ria-app list
|
||
|
|
ria-app logs <app> [-f]
|
||
|
|
ria-app stop <app>
|
||
|
|
```
|
||
|
|
|
||
|
|
`ria-app run` inspects OCI image labels and auto-adds runtime flags:
|
||
|
|
|
||
|
|
| Label | Value (example) | Effect |
|
||
|
|
|---|---|---|
|
||
|
|
| `ria.profile` | `native-x86`, `nvidia-x86`, `holoscan` | `nvidia`/`holoscan`/`cuda` → adds `--gpus all` |
|
||
|
|
| `ria.hardware` | comma list: `pluto,usrp,rtlsdr,hackrf,bladerf,thinkrf` | USB-attached SDRs → `--device /dev/bus/usb`; networked SDRs → `--net host` |
|
||
|
|
| `ria.app` | `<app-name>` | Used by `ria-app list` to filter images |
|
||
|
|
| `ria.version` | `<git sha or semver>` | Informational |
|
||
|
|
|
||
|
|
If the labels are missing, `ria-app run` still works but can't auto-configure — the user has to pass `--docker-args ...` themselves. So the value here is entirely in getting CI to stamp the labels.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## What to change in `ria-hub`
|
||
|
|
|
||
|
|
### 1. Stamp OCI labels on every built image
|
||
|
|
|
||
|
|
In the Application Composer build flow (follow the path from `application_composer.go:172` `ComposerBuildTrigger` → generated `.riahub/workflows/*.yml` → `sample-build-tools` `full_generator.py` → `Dockerfile` emission), add `LABEL` instructions to the generated Dockerfile. The values should be computed from the app JSON the user submitted, not hard-coded:
|
||
|
|
|
||
|
|
```dockerfile
|
||
|
|
LABEL ria.app="${APP_NAME}"
|
||
|
|
LABEL ria.profile="${PROFILE}" # native-x86 | nvidia-x86 | holoscan | ...
|
||
|
|
LABEL ria.hardware="${HARDWARE_CSV}" # e.g. "pluto,usrp" (empty string if none)
|
||
|
|
LABEL ria.version="${GIT_SHA}"
|
||
|
|
LABEL ria.operators="${OPERATORS_CSV}" # optional, nice for debugging
|
||
|
|
```
|
||
|
|
|
||
|
|
`HARDWARE_CSV` derivation: walk the operator graph in the submitted app JSON and collect the set of hardware backends that any operator requires. The mapping from operator → hardware tag should live next to the existing `operator_generator.py` apt-dep resolution (that code already knows, per operator, whether it needs `libuhd-dev`, `libad9361-dev`, `libhackrf-dev`, `librtlsdr-dev`, etc.). Reuse that table — just emit the short tag (`usrp`, `pluto`, `hackrf`, `rtlsdr`) alongside the apt package name.
|
||
|
|
|
||
|
|
Allowed hardware tags (must match what `ria-app` recognizes):
|
||
|
|
|
||
|
|
- `pluto`, `rtlsdr`, `hackrf`, `bladerf` → USB
|
||
|
|
- `usrp`, `thinkrf` → network
|
||
|
|
- (extend here when new SDR backends are added)
|
||
|
|
|
||
|
|
If an operator needs both (e.g. Pluto over USB *and* its iio network endpoint), list it once — `ria-app` already applies both USB and host-net when `pluto` appears.
|
||
|
|
|
||
|
|
### 2. Prefer `LABEL` over `ARG`-only
|
||
|
|
|
||
|
|
The CI job likely already passes things like `APP_NAME` and `GIT_SHA` as build args. Those args disappear after build unless promoted to `LABEL`. Make sure each of the five labels above ends up in the final image layer (verify with `docker image inspect --format '{{json .Config.Labels}}' <ref>`).
|
||
|
|
|
||
|
|
### 3. Push with both `:<sha>` and `:latest` tags
|
||
|
|
|
||
|
|
`ria-app` defaults to `:latest` when the user omits a tag. If CI only pushes immutable SHA tags today, also push `:latest` on main-branch builds so `ria-app run my-classifier` Just Works.
|
||
|
|
|
||
|
|
### 4. (Optional but recommended) App index endpoint
|
||
|
|
|
||
|
|
Add `GET /apps` to the hub API returning something like:
|
||
|
|
|
||
|
|
```json
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"name": "my-classifier",
|
||
|
|
"image": "registry.riahub.ai/qoherent/my-classifier:latest",
|
||
|
|
"profile": "nvidia-x86",
|
||
|
|
"hardware": ["pluto"],
|
||
|
|
"updated_at": "2026-04-14T10:00:00Z"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
```
|
||
|
|
|
||
|
|
This lets `ria-app list --remote` show available apps without the user knowing image names. Not required for MVP — skip if it adds scope.
|
||
|
|
|
||
|
|
### 5. (Optional) Ship a default `config.yaml` inside the image at a known path
|
||
|
|
|
||
|
|
`ria-app run --config <path>` mounts the user's config to `/config/config.yaml` and sets `RIA_CONFIG=/config/config.yaml`. The runtime already falls back to an embedded config per your handoff notes, so this just needs to keep working — no change unless you want to standardize the embedded path.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Acceptance checklist
|
||
|
|
|
||
|
|
- [ ] A Composer-built image for a native-x86 app with a Pluto operator has labels: `ria.profile=native-x86`, `ria.hardware=pluto`, `ria.app=<name>`, `ria.version=<sha>`.
|
||
|
|
- [ ] A Composer-built image for an nvidia-x86 app has `ria.profile=nvidia-x86`.
|
||
|
|
- [ ] `docker image inspect --format '{{json .Config.Labels}}' <ref>` shows all five labels.
|
||
|
|
- [ ] `:latest` tag is pushed for main-branch builds.
|
||
|
|
- [ ] Running `ria-app run <app>` on a user's machine starts the container with the right `--gpus` / `--device` / `--net` flags without the user passing anything beyond the app name.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Out of scope
|
||
|
|
|
||
|
|
- Anything on the `ria-toolkit-oss` side — the CLI is already implemented on branch `screens-connection`.
|
||
|
|
- Changes to the generated C++ code, CMakeLists, or runtime config lookup.
|
||
|
|
- Artifact downloads — we're distributing via the container registry only.
|