Skip to content

Commit 26213df

Browse files
authored
feat: add SFTP file transfer with upload/download commands (#3)
* feat: implement SFTP upload/download with rename from copy to upload command * update: cargo fmt * feat: add glob pattern support for upload and download commands - Add glob dependency for pattern matching - Implement local glob expansion for upload command - Support uploading multiple files with wildcards (*.txt, logs/*.log) - Implement remote glob expansion for download via SSH ls command - Support downloading multiple files with wildcards - Add automatic directory detection for multi-file uploads - Add human-readable file size formatting - Update manpage with glob pattern examples - Add test_glob.sh script for testing glob functionality This allows users to: - Upload multiple files: bssh upload "*.log" /remote/dir/ - Download with patterns: bssh download "/var/log/*.log" ./downloads/ * test: add comprehensive tests for upload/download functionality - Add unit tests for CLI command parsing (upload/download) - Add unit tests for executor file transfer results - Add glob pattern matching tests - Add error handling tests for various failure scenarios - Add integration tests for localhost SSH operations - Test coverage for: * Upload/download result structures * Parallel executor with file transfers * Glob pattern resolution * Error cases (invalid hosts, ports, files) * Multiple file operations All unit tests pass (47 tests total). Integration tests require SSH server on localhost to run successfully. * fix: make integration tests more robust for CI environments - Add SSH key detection for integration tests - Only use SSH key if it exists, otherwise fall back to agent - Update CI workflow to skip integration tests - Fix formatting in all test files - Ensure tests work both locally and in GitHub Actions Integration tests now gracefully handle environments without: - SSH keys - SSH agent identities - localhost SSH access * fix: resolve clippy warnings and improve test robustness * chore: update GitHub action * update: packages
1 parent a2e4180 commit 26213df

File tree

15 files changed

+1775
-69
lines changed

15 files changed

+1775
-69
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ jobs:
2828
restore-keys: |
2929
${{ runner.os }}-cargo-
3030
31-
- name: Run tests
32-
run: cargo test --verbose
31+
- name: Run unit tests
32+
run: |
33+
cargo test --lib --verbose
34+
cargo test --tests --verbose -- --skip integration_test
3335
3436
- name: Check formatting
3537
run: cargo fmt --check
@@ -57,4 +59,4 @@ jobs:
5759
${{ runner.os }}-cargo-
5860
5961
- name: Build binary
60-
run: cargo build --release --bin all-smi
62+
run: cargo build --release

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ futures = "0.3"
2020
async-trait = "0.1"
2121
indicatif = "0.18"
2222
rpassword = "7"
23-
directories = "5"
23+
directories = "6"
2424
dirs = "6.0"
2525
chrono = "0.4"
26+
glob = "0.3"
2627

2728
[dev-dependencies]
2829
tempfile = "3"

docs/man/bssh.1

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.\" Manpage for bssh
22
.\" Contact the maintainers to correct errors or typos.
3-
.TH BSSH 1 "August 21, 2025" "v0.3.0" "bssh Manual"
3+
.TH BSSH 1 "August 21, 2025" "v0.3.1" "bssh Manual"
44

55
.SH NAME
66
bssh \- Backend.AI SSH - Parallel command execution across cluster nodes
@@ -13,7 +13,9 @@ bssh \- Backend.AI SSH - Parallel command execution across cluster nodes
1313
.B bssh
1414
is a high-performance parallel SSH command execution tool for cluster management, built with Rust.
1515
It enables efficient execution of commands across multiple nodes simultaneously with real-time output streaming.
16-
The tool automatically detects Backend.AI multi-node session environments and supports various configuration methods.
16+
The tool provides secure file transfer capabilities using SFTP protocol for both uploading and downloading files
17+
to/from multiple remote hosts in parallel. It automatically detects Backend.AI multi-node session environments
18+
and supports various configuration methods.
1719

1820
.SH OPTIONS
1921
.TP
@@ -83,10 +85,27 @@ List available clusters from configuration
8385
Test connectivity to hosts
8486

8587
.TP
86-
.B copy
87-
Copy files to remote hosts
88+
.B upload
89+
Upload files to remote hosts using SFTP (supports glob patterns)
8890
.RS
89-
Usage: bssh copy \fISOURCE\fR \fIDESTINATION\fR
91+
Usage: bssh upload \fISOURCE\fR \fIDESTINATION\fR
92+
.br
93+
Uploads the local file(s) matching SOURCE pattern to DESTINATION path on all specified remote hosts.
94+
SOURCE can be a single file path or a glob pattern (e.g., *.txt, logs/*.log).
95+
When uploading multiple files, DESTINATION should be a directory (end with /).
96+
Uses SFTP protocol for secure file transfer with progress indicators.
97+
.RE
98+
99+
.TP
100+
.B download
101+
Download files from remote hosts using SFTP (supports glob patterns)
102+
.RS
103+
Usage: bssh download \fISOURCE\fR \fIDESTINATION\fR
104+
.br
105+
Downloads the remote file(s) matching SOURCE pattern from all specified hosts to the local DESTINATION directory.
106+
SOURCE can be a single file path or a glob pattern (e.g., /var/log/*.log, /etc/*.conf).
107+
Each downloaded file is saved with a unique name prefixed by the hostname.
108+
Uses SFTP protocol for secure file transfer with progress indicators.
90109
.RE
91110

92111
.SH CONFIGURATION
@@ -159,8 +178,16 @@ Test connectivity:
159178
.B bssh -c production ping
160179

161180
.TP
162-
Copy file to remote hosts:
163-
.B bssh -c production copy local_file.txt /tmp/remote_file.txt
181+
Upload file to remote hosts (SFTP):
182+
.B bssh -c production upload local_file.txt /tmp/remote_file.txt
183+
184+
.TP
185+
Download file from remote hosts (SFTP):
186+
.B bssh -c production download /etc/passwd ./downloads/
187+
.RS
188+
Downloads /etc/passwd from each host to ./downloads/ directory.
189+
Files are saved as hostname_passwd (e.g., web1_passwd, web2_passwd)
190+
.RE
164191

165192
.TP
166193
Backend.AI multi-node session (automatic):
@@ -193,6 +220,35 @@ Creates timestamped files per node:
193220
- summary_TIMESTAMP.txt (execution summary)
194221
.RE
195222

223+
.TP
224+
Upload configuration file to all nodes:
225+
.B bssh -H "node1,node2,node3" upload /etc/myapp.conf /etc/myapp.conf
226+
227+
.TP
228+
Download logs from all web servers:
229+
.B bssh -c webservers download /var/log/nginx/access.log ./logs/
230+
.RS
231+
Each file is saved as hostname_access.log in the ./logs/ directory
232+
.RE
233+
234+
.TP
235+
Upload with custom SSH key and increased parallelism:
236+
.B bssh -i ~/.ssh/deploy_key -p 20 -c production upload deploy.tar.gz /tmp/
237+
238+
.TP
239+
Upload multiple files with glob pattern:
240+
.B bssh -c production upload "*.log" /var/backups/logs/
241+
.RS
242+
Uploads all .log files from current directory to /var/backups/logs/ on all nodes
243+
.RE
244+
245+
.TP
246+
Download logs with wildcard pattern:
247+
.B bssh -c production download "/var/log/app*.log" ./collected_logs/
248+
.RS
249+
Downloads all files matching app*.log from /var/log/ on each node
250+
.RE
251+
196252
.SH EXIT STATUS
197253
.TP
198254
.B 0
@@ -290,10 +346,26 @@ Licensed under the Apache License, Version 2.0
290346
.SH SEE ALSO
291347
.BR ssh (1),
292348
.BR scp (1),
349+
.BR sftp (1),
293350
.BR ssh-agent (1),
294351
.BR ssh-keygen (1)
295352

296353
.SH NOTES
354+
.SS SFTP Requirements
355+
The upload and download commands require SFTP subsystem to be enabled on the remote SSH servers.
356+
Most SSH servers have SFTP enabled by default with a configuration line like:
357+
.br
358+
.I Subsystem sftp /usr/lib/openssh/sftp-server
359+
.br
360+
or
361+
.br
362+
.I Subsystem sftp internal-sftp
363+
364+
.SS Performance
365+
File transfers use SFTP protocol which provides secure and reliable transfers.
366+
The parallel transfer capability allows simultaneous uploads/downloads to multiple nodes,
367+
significantly reducing total transfer time for cluster-wide file distribution or collection.
368+
297369
For more information and documentation, visit:
298370
.br
299371
https://github.com/lablup/bssh

src/cli.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,23 @@ pub enum Commands {
101101
#[command(about = "Test connectivity to hosts")]
102102
Ping,
103103

104-
#[command(about = "Copy files to remote hosts")]
105-
Copy {
106-
#[arg(help = "Source file path")]
104+
#[command(about = "Upload files to remote hosts")]
105+
Upload {
106+
#[arg(help = "Local file path")]
107107
source: PathBuf,
108108

109-
#[arg(help = "Destination path on remote hosts")]
109+
#[arg(help = "Remote destination path")]
110110
destination: String,
111111
},
112+
113+
#[command(about = "Download files from remote hosts")]
114+
Download {
115+
#[arg(help = "Remote file path")]
116+
source: String,
117+
118+
#[arg(help = "Local destination directory")]
119+
destination: PathBuf,
120+
},
112121
}
113122

114123
impl Cli {

0 commit comments

Comments
 (0)