Skip to content

Commit 331d8ff

Browse files
committed
add publishing of agent to github releases
1 parent f3904d7 commit 331d8ff

File tree

8 files changed

+243
-37
lines changed

8 files changed

+243
-37
lines changed

.github/workflows/_release.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
on:
2+
workflow_call:
3+
4+
jobs:
5+
agent:
6+
runs-on: ubuntu-latest
7+
strategy:
8+
matrix:
9+
goarch: [amd64, arm64]
10+
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
15+
- name: Set up Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Build agent
21+
run: CGO_ENABLED=0 GOARCH=${{ matrix.goarch }} go build -o agent-linux-${{ matrix.goarch }} ./cmd/agent/
22+
23+
- name: Upload artifact
24+
uses: actions/upload-artifact@v4
25+
with:
26+
name: agent-linux-${{ matrix.goarch }}
27+
path: agent-linux-${{ matrix.goarch }}
28+
29+
release:
30+
needs: agent
31+
runs-on: ubuntu-latest
32+
33+
steps:
34+
- name: Checkout
35+
uses: actions/checkout@v4
36+
37+
- name: Download artifacts
38+
uses: actions/download-artifact@v4
39+
with:
40+
merge-multiple: true
41+
42+
- name: Create GitHub Release
43+
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
44+
with:
45+
prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
46+
files: |
47+
agent-linux-amd64
48+
agent-linux-arm64
49+
scripts/install-agent.sh
50+
generate_release_notes: true
51+
env:
52+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ jobs:
3131
contents: read
3232
packages: write
3333

34+
release:
35+
needs: test
36+
if: github.ref_type == 'tag'
37+
uses: ./.github/workflows/_release.yml
38+
permissions:
39+
contents: write
40+
3441
docs:
3542
uses: ./.github/workflows/_docs.yml
3643
permissions:

docs/how-to.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
```{toctree}
44
:maxdepth: 1
55
6+
how-to/setup-agent
67
how-to/deploy
78
how-to/run-ci-locally
89
how-to/run-sphinx

docs/how-to/deploy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Deploy to Kubernetes
1+
# Install the manager and plugin on Kubernetes
22

33
This guide covers deploying the manager and plugin to a Kubernetes cluster
44
using Helm.

docs/how-to/run-sphinx.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Run Sphinx
1+
# Build the docs locally
22

33
This guide explains how to build and preview the project documentation locally
44
using Sphinx. Makefile targets are provided so you don't need to remember the

docs/how-to/setup-agent.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Install the agent on a USB/IP host
2+
3+
The agent runs on a machine with USB devices (typically a Raspberry Pi) and
4+
exposes them over the network via USB/IP. The Kubernetes manager polls agents
5+
to discover available devices.
6+
7+
## Prerequisites
8+
9+
- A Linux machine (Raspberry Pi OS, Debian, Ubuntu, etc.) with USB devices
10+
attached
11+
- The `usbip` kernel module and userspace tools installed
12+
- `curl` available for the install script
13+
- Root access (the installer creates a systemd service)
14+
15+
### Install USB/IP tools
16+
17+
On Debian/Ubuntu/Raspberry Pi OS:
18+
19+
```bash
20+
$ sudo apt-get update && sudo apt-get install -y linux-tools-generic
21+
```
22+
23+
On Raspberry Pi OS the package may be `usbip` instead:
24+
25+
```bash
26+
$ sudo apt-get update && sudo apt-get install -y usbip
27+
```
28+
29+
### Load the kernel module
30+
31+
```bash
32+
$ sudo modprobe usbip_host
33+
```
34+
35+
To load the module automatically on boot:
36+
37+
```bash
38+
$ echo usbip_host | sudo tee /etc/modules-load.d/usbip_host.conf
39+
```
40+
41+
## Install the agent
42+
43+
The install script downloads the correct binary for your architecture,
44+
installs it to `/usr/local/bin/agent`, and creates a systemd service:
45+
46+
```bash
47+
$ curl -fsSL https://raw.githubusercontent.com/DiamondLightSource/dra-usbip-driver/main/scripts/install-agent.sh | sudo sh
48+
```
49+
50+
To install a specific version:
51+
52+
```bash
53+
$ curl -fsSL https://raw.githubusercontent.com/DiamondLightSource/dra-usbip-driver/main/scripts/install-agent.sh | sudo sh -s -- 0.1.0
54+
```
55+
56+
## Verify
57+
58+
Check that the service is running:
59+
60+
```bash
61+
$ sudo systemctl status dra-usbip-agent
62+
```
63+
64+
The agent serves a device list on port 13240. Test it with:
65+
66+
```bash
67+
$ curl http://localhost:13240/devices
68+
```
69+
70+
## Uninstall
71+
72+
```bash
73+
$ sudo systemctl stop dra-usbip-agent
74+
$ sudo systemctl disable dra-usbip-agent
75+
$ sudo rm /etc/systemd/system/dra-usbip-agent.service
76+
$ sudo systemctl daemon-reload
77+
$ sudo rm /usr/local/bin/agent
78+
```

docs/tutorials/quick-start.md

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,44 @@ USB device available to a pod in your Kubernetes cluster.
66
## Prerequisites
77

88
- A Kubernetes cluster (v1.34+) with DRA enabled
9-
- `kubectl` configured to access the cluster
10-
- A machine with USB devices to share (the Agent host)
11-
- The `usbip` tools installed on both the Agent host and cluster nodes
9+
- `kubectl` and [Helm](https://helm.sh/docs/intro/install/) 3.x configured
10+
to access the cluster
11+
- A machine with USB devices to share (the agent host, typically a
12+
Raspberry Pi or similar)
13+
- The `usbip` tools installed on both the agent host and cluster nodes
1214
- The `vhci-hcd` and `usbip-host` kernel modules loaded
1315

14-
## 1. Run the Agent
16+
## 1. Install the agent
1517

16-
On the machine with USB devices attached, build and run the Agent binary:
18+
On the machine with USB devices attached, run the install script:
1719

1820
```bash
19-
make agent
20-
./agent --bind-all-devices
21+
curl -fsSL https://raw.githubusercontent.com/DiamondLightSource/dra-usbip-driver/main/scripts/install-agent.sh | sudo sh -s -- 0.1.0
2122
```
2223

23-
The Agent serves device metadata on port 13240. Verify it is working:
24+
This downloads the correct binary for your architecture, installs it as a
25+
systemd service, and starts it. The agent serves device metadata on port
26+
13240.
27+
28+
Verify it is working:
2429

2530
```bash
2631
curl http://<agent-host>:13240/devices
2732
```
2833

2934
You should see a JSON array describing the connected USB devices.
3035

31-
## 2. Deploy the Manager
32-
33-
The Manager runs inside the cluster and polls Agents for device information.
36+
For more detail see {doc}`/how-to/setup-agent`.
3437

35-
```bash
36-
kubectl apply -f examples/manager.yaml
37-
```
38+
## 2. Deploy the manager and plugin
3839

39-
Or run the container image directly:
40+
Install the Helm chart, passing the address of your agent host:
4041

4142
```bash
42-
kubectl run usbip-manager \
43-
--image=ghcr.io/diamondlightsource/dra-usbip-driver-manager:latest \
44-
-- --agent=<agent-host>
43+
helm -n kube-system upgrade --install dra-usbip-driver \
44+
oci://ghcr.io/diamondlightsource/charts/dra-usbip-driver \
45+
--version 0.1.0 \
46+
--set 'manager.agents={<agent-host>}'
4547
```
4648

4749
Check that ResourceSlices have been created:
@@ -50,29 +52,32 @@ Check that ResourceSlices have been created:
5052
kubectl get resourceslices
5153
```
5254

53-
## 3. Deploy the Plugin DaemonSet
54-
55-
The Plugin runs on each node and handles attaching USB/IP devices when pods
56-
request them:
57-
58-
```bash
59-
kubectl apply -f examples/plugin-daemonset.yaml
60-
```
55+
For more detail see {doc}`/how-to/deploy`.
6156

62-
## 4. Create a ResourceClaim and Pod
57+
## 3. Request a USB device in a pod
6358

64-
Create a ResourceClaim to request a USB device, then a Pod that references it:
59+
Create a `ResourceClaimTemplate` to match a specific USB device, then
60+
reference it from a pod:
6561

6662
```yaml
6763
apiVersion: resource.k8s.io/v1
68-
kind: ResourceClaim
64+
kind: ResourceClaimTemplate
6965
metadata:
70-
name: my-usb-device
66+
name: serial-adapter
7167
spec:
72-
devices:
73-
requests:
74-
- name: usb
75-
deviceClassName: usbip
68+
spec:
69+
devices:
70+
requests:
71+
- name: req-0
72+
firstAvailable:
73+
- name: adapter
74+
deviceClassName: usbip
75+
selectors:
76+
- cel:
77+
expression: |-
78+
device.attributes["usbip.diamond.ac.uk"].vendor == "0403" &&
79+
device.attributes["usbip.diamond.ac.uk"].product == "6015" &&
80+
device.attributes["usbip.diamond.ac.uk"].serial == "FTA954OZ"
7681
---
7782
apiVersion: v1
7883
kind: Pod
@@ -85,7 +90,7 @@ spec:
8590
command: ["sleep", "infinity"]
8691
resourceClaims:
8792
- name: usb-claim
88-
resourceClaimName: my-usb-device
93+
resourceClaimTemplateName: serial-adapter
8994
```
9095
9196
```bash

scripts/install-agent.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
REPO="DiamondLightSource/dra-usbip-driver"
5+
INSTALL_DIR="/usr/local/bin"
6+
SERVICE_NAME="dra-usbip-agent"
7+
BINARY_NAME="agent"
8+
9+
# Detect architecture
10+
ARCH=$(uname -m)
11+
case "$ARCH" in
12+
x86_64) GOARCH="amd64" ;;
13+
aarch64) GOARCH="arm64" ;;
14+
*)
15+
echo "Error: unsupported architecture: $ARCH" >&2
16+
exit 1
17+
;;
18+
esac
19+
20+
# Determine version — use first argument, VERSION env var, or fetch latest release
21+
if [ -n "${1:-}" ]; then
22+
TAG="$1"
23+
elif [ -n "${VERSION:-}" ]; then
24+
TAG="$VERSION"
25+
else
26+
TAG=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | cut -d'"' -f4)
27+
if [ -z "$TAG" ]; then
28+
echo "Error: could not determine latest release" >&2
29+
exit 1
30+
fi
31+
fi
32+
33+
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${TAG}/agent-linux-${GOARCH}"
34+
35+
echo "Installing ${SERVICE_NAME} ${TAG} (linux/${GOARCH})..."
36+
37+
# Download binary
38+
curl -fsSL -o /tmp/${BINARY_NAME} "$DOWNLOAD_URL"
39+
chmod +x /tmp/${BINARY_NAME}
40+
mv /tmp/${BINARY_NAME} "${INSTALL_DIR}/${BINARY_NAME}"
41+
42+
echo "Installed ${INSTALL_DIR}/${BINARY_NAME}"
43+
44+
# Create systemd service
45+
cat > /etc/systemd/system/${SERVICE_NAME}.service <<EOF
46+
[Unit]
47+
Description=DRA USB/IP Agent
48+
After=network.target
49+
50+
[Service]
51+
ExecStart=${INSTALL_DIR}/${BINARY_NAME}
52+
Restart=on-failure
53+
RestartSec=5
54+
55+
[Install]
56+
WantedBy=multi-user.target
57+
EOF
58+
59+
systemctl daemon-reload
60+
systemctl enable "${SERVICE_NAME}"
61+
systemctl start "${SERVICE_NAME}"
62+
63+
echo "Service ${SERVICE_NAME} enabled and started."

0 commit comments

Comments
 (0)