Skip to content

Commit ded8a2c

Browse files
committed
feat: add file module for bidirectional file transfers
Implements a new file module that supports both upload (client → dutagent) and download (dutagent → client) operations with flexible path resolution. Signed-off-by: Fabian Wienand <fabian.wienand@9elements.com>
1 parent 13a4ace commit ded8a2c

File tree

8 files changed

+1223
-0
lines changed

8 files changed

+1223
-0
lines changed

cmds/dutagent/modules.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package main
1414
import (
1515
_ "github.com/BlindspotSoftware/dutctl/pkg/module/agent"
1616
_ "github.com/BlindspotSoftware/dutctl/pkg/module/dummy"
17+
_ "github.com/BlindspotSoftware/dutctl/pkg/module/file"
1718
_ "github.com/BlindspotSoftware/dutctl/pkg/module/flash"
1819
_ "github.com/BlindspotSoftware/dutctl/pkg/module/gpio"
1920
_ "github.com/BlindspotSoftware/dutctl/pkg/module/ipmi"

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
connectrpc.com/connect v1.19.1
77
github.com/bougou/go-ipmi v0.7.8
88
github.com/go-playground/validator/v10 v10.29.0
9+
github.com/google/go-cmp v0.7.0
910
github.com/stianeikeland/go-rpio/v4 v4.6.0
1011
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
1112
golang.org/x/crypto v0.46.0

pkg/module/file/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
The _file_ package provides a single module:
2+
3+
# File
4+
5+
This module transfers files between client and dutagent, supporting both upload and download operations.
6+
7+
```
8+
ARGUMENTS:
9+
<path> Single path argument. Interpretation depends on configuration.
10+
<source>:<dest> Explicitly specify both paths (incompatible with source/destination config)
11+
12+
The operation type (upload or download) must be configured in the device YAML.
13+
14+
Path Restrictions:
15+
- Destination paths (sanitized): must be relative, no absolute paths, no leading '..'
16+
- Source paths (not sanitized): any path allowed, including absolute paths
17+
18+
Configuration Behavior:
19+
- source configured: arg becomes destination (sanitized - must be relative)
20+
- destination configured: arg becomes source (not sanitized - absolute allowed)
21+
- neither configured: arg becomes both source and destination (dest is sanitized)
22+
- both configured: no arg allowed
23+
- Colon syntax: both parts are destinations and sanitized (must be relative)
24+
25+
Path Processing:
26+
- Relative paths preserve directory structure: ./dir/file.bin → dir/file.bin
27+
- Internal '..' references are resolved: dir/../other/file.bin → other/file.bin
28+
```
29+
30+
See [file-example-cfg.yml](./file-example-cfg.yml) for examples.
31+
32+
## Configuration Options
33+
34+
| Option | Value | Required | Description |
35+
|-------------|--------|----------|----------------------------------------------------------------------------------------------------|
36+
| operation | string | yes | Operation type: "upload" or "download" |
37+
| source | string | no | Source path. If set, argument path becomes the destination. Cannot be used with colon syntax |
38+
| destination | string | no | Destination path. If set, argument path becomes the source. Cannot be used with colon syntax |
39+
| permission | string | no | File permissions in octal format (e.g., "0644", "0755"). Upload only. Default: "0644" |
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Example configuration for the file module
2+
# This file demonstrates various use cases for file transfers between client and dutagent
3+
# $WD is a placeholder of the working directory on both the client and dutagent
4+
5+
devices:
6+
example-device:
7+
cmds:
8+
# Upload any file - preserves directory structure
9+
upload:
10+
desc: "Upload file to device"
11+
modules:
12+
- module: file
13+
main: true
14+
options:
15+
operation: "upload"
16+
# Usage:
17+
# dutctl example-device upload ./build/firmware.bin
18+
# → uploads to $WD/firmware.bin (preserves structure)
19+
#
20+
# dutctl example-device upload ./firmware.bin:custom/firmware.bin
21+
# → uploads to $WD/custom/firmware.bin (custom destination via colon syntax)
22+
23+
# Upload with destination configured - arg becomes source
24+
upload-script:
25+
desc: "Upload and install a script"
26+
modules:
27+
- module: file
28+
main: true
29+
options:
30+
operation: "upload"
31+
destination: "/opt/scripts/install.sh"
32+
permission: "0755" # Make it executable
33+
# Usage:
34+
# dutctl example-device upload-script ./scripts/init.sh
35+
# → uploads to: /opt/scripts/install.sh on device
36+
37+
# Download with source configured - arg becomes destination
38+
fetch-logs:
39+
desc: "Download logs from device"
40+
modules:
41+
- module: file
42+
main: true
43+
options:
44+
operation: "download"
45+
source: "/var/log.txt"
46+
# Usage:
47+
# dutctl example-device fetch-logs ./local-log.txt
48+
# → downloads /var/log.txt to ./local-log.txt on client
49+
50+
# Upload with both paths configured - no arg allowed
51+
upload-config:
52+
desc: "Upload configuration file with fixed paths"
53+
modules:
54+
- module: file
55+
main: true
56+
options:
57+
operation: "upload"
58+
source: "./configs/device.conf"
59+
destination: "/etc/device/device.conf"
60+
permission: "0644"
61+
# Usage:
62+
# dutctl example-device upload-config
63+
# → uploads ./configs/device.conf to /etc/device/device.conf

0 commit comments

Comments
 (0)