feat: save short cut image to remote by ssh
- add settings for ssh config - implement save remote function by ssh
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
// uploader.go — small adapter that satisfies application.SSHUploader by
|
||||
// dialing a one-shot connection per upload. This keeps the application
|
||||
// layer free of any direct dependency on golang.org/x/crypto/ssh while
|
||||
// still exposing a clean, unit-testable contract.
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/mmmy/snapgo/internal/domain"
|
||||
)
|
||||
|
||||
// Uploader is the production implementation of application.SSHUploader.
|
||||
//
|
||||
// We dial fresh per-upload because:
|
||||
// - Captures happen sparsely (a few per minute at peak), so the cost of
|
||||
// a TCP+SSH handshake is dwarfed by user think-time.
|
||||
// - Holding a long-lived connection would force us to add keepalives,
|
||||
// reconnection logic, and config-change invalidation — not worth it
|
||||
// for the current usage profile.
|
||||
type Uploader struct {
|
||||
cfg domain.SSHConfig
|
||||
}
|
||||
|
||||
// NewUploader returns a ready-to-use uploader. The configuration is
|
||||
// captured by value so a simultaneous in-flight upload cannot be re-
|
||||
// targeted by a settings save.
|
||||
func NewUploader(cfg domain.SSHConfig) *Uploader {
|
||||
return &Uploader{cfg: cfg}
|
||||
}
|
||||
|
||||
// Upload satisfies application.SSHUploader. We log entry/exit at INFO so
|
||||
// the operator sees a single line per upload in the normal happy path,
|
||||
// and ERROR with elapsed time when something fails.
|
||||
func (u *Uploader) Upload(ctx context.Context, remoteRelPath string, data []byte, mode os.FileMode) error {
|
||||
start := time.Now()
|
||||
sshLog().Info("uploader.Upload start",
|
||||
"host", u.cfg.Host, "user", u.cfg.User, "port", u.cfg.Port,
|
||||
"remote_path", remoteRelPath, "size", len(data))
|
||||
|
||||
client, err := Dial(ctx, u.cfg)
|
||||
if err != nil {
|
||||
sshLog().Error("uploader.Upload dial failed",
|
||||
"host", u.cfg.Host, "elapsed", time.Since(start), "err", err)
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
if err := client.CopyFile(ctx, remoteRelPath, data, mode); err != nil {
|
||||
sshLog().Error("uploader.Upload copy failed",
|
||||
"remote_path", remoteRelPath, "elapsed", time.Since(start), "err", err)
|
||||
return err
|
||||
}
|
||||
sshLog().Info("uploader.Upload done",
|
||||
"remote_path", remoteRelPath, "size", len(data),
|
||||
"total_elapsed", time.Since(start))
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user