ssh

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package ssh implements the Storager interface on top of SSH/SFTP. The implementation is inspired by wal-g's pkg/storages/sh.

Index

Constants

This section is empty.

Variables

View Source
var ErrStorageClosed = errors.New("ssh storage is closed")

ErrStorageClosed is returned by any operation on a storage whose Close has already been called. Callers can test for it with errors.Is to tell a closed-storage misuse apart from a transport failure.

Functions

func New added in v0.2.0

func New(cfg Config, opts ...Option) (storages.Storager, error)

New builds an SSH/SFTP backend from cfg, after running Config.Validate. The connection is established lazily on first use (or via Ping). Pass WithLogger to enable diagnostic output; without it the backend does not log at all. Call Close on the returned storage when done to release the connection.

The returned storage is guarded: keys cannot escape cfg.Prefix. See WithUnsafe to opt out.

Types

type Config

type Config struct {
	Host                 string        // required
	Port                 int           // default 22
	User                 string        // required
	Password             string        // auth: password
	PrivateKeyPath       string        // auth: private key
	PrivateKeyPassphrase string        // decrypts an encrypted private key
	Prefix               string        // remote root path
	ConnectTimeout       time.Duration // bounds the TCP dial and the SSH handshake, default 30s
}

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config populated with sensible defaults. Set the required fields (Host, User) and the credentials on the result before passing it to New.

func (*Config) Validate

func (c *Config) Validate() error

type Option

type Option func(*Storage)

Option configures a Storage.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger sets the logger for the backend's diagnostic output. Without this option the backend does not log at all.

func WithUnsafe added in v0.2.0

func WithUnsafe() Option

WithUnsafe turns the key guard off. By default the storage returned by New is guarded: a key that reaches outside the configured prefix or that names the prefix itself is refused with storages.ErrUnsafeKey before it reaches the remote host. Pass this only when every key is known to be trusted and a path with legitimate ".." segments has to get through.

type SFTPClient

type SFTPClient interface {
	ReadDir(path string) ([]os.FileInfo, error)
	Join(elem ...string) string
	Remove(path string) error
	RemoveDirectory(path string) error
	Stat(p string) (os.FileInfo, error)
	Open(path string) (*sftp.File, error)
	Create(path string) (*sftp.File, error)
	MkdirAll(path string) error
	Rename(oldname, newname string) error
	PosixRename(oldname, newname string) error
}

SFTPClient is the subset of *sftp.Client used by the storage. It is kept as an interface so the dependency surface stays small and explicit.

type Storage

type Storage struct {
	// contains filtered or unexported fields
}

func (*Storage) Close

func (s *Storage) Close() error

Close releases the shared SSH/SFTP connection. It must be called once by the lifecycle owner when the storage and all of its sub-storages are no longer needed; otherwise the connection, its receive goroutine and its socket leak until the process exits. SubStorage clones share the same connection, so only the connection is closed (not the clone) — Close is idempotent and safe to call more than once and before the connection has been established.

func (*Storage) Copy added in v0.3.3

func (s *Storage) Copy(ctx context.Context, srcPath, dstPath string, _ ...storages.CopyOption) (storages.CopyStat, error)

Copy streams srcPath through the client into a temporary sibling and renames it over dstPath, as SFTP has no reliable copy. Options are ignored.

func (*Storage) CopyAll added in v0.3.3

func (s *Storage) CopyAll(
	ctx context.Context, srcPrefix, dstPrefix string, opts ...storages.CopyAllOption,
) (storages.CopyStat, error)

CopyAll copies every object under srcPrefix to dstPrefix with storages.CopyEach.

func (*Storage) Delete

func (s *Storage) Delete(ctx context.Context, filePaths ...string) error

func (*Storage) DeleteAll

func (s *Storage) DeleteAll(ctx context.Context, pathPrefix string) error

func (*Storage) Dirname

func (s *Storage) Dirname() string

func (*Storage) Exists

func (s *Storage) Exists(ctx context.Context, fileName string) (bool, error)

func (*Storage) GetCwd

func (s *Storage) GetCwd() string

func (*Storage) GetObject

func (s *Storage) GetObject(ctx context.Context, filePath string) (reader io.ReadCloser, err error)

func (*Storage) GetObjectRange added in v0.2.0

func (s *Storage) GetObjectRange(
	ctx context.Context, filePath string, offset, length int64,
) (io.ReadCloser, error)

GetObjectRange reads a byte range without transferring the rest of the file: SFTP reads carry an explicit offset (SSH_FXP_READ), so seeking is a protocol operation rather than a client-side skip.

func (*Storage) List added in v0.2.0

func (s *Storage) List(ctx context.Context, prefix string) ([]storages.ObjectStat, error)

func (*Storage) ListDir

func (s *Storage) ListDir(ctx context.Context) (files []string, dirs []storages.Storager, err error)

func (*Storage) Ping

func (s *Storage) Ping(ctx context.Context) error

Ping forces the lazy SSH/SFTP connection to be established, which serves as a real reachability check for the remote host.

func (*Storage) PutObject

func (s *Storage) PutObject(ctx context.Context, filePath string, body io.Reader) error

PutObject streams body into a temporary sibling and renames it over filePath.

func (*Storage) Stat

func (s *Storage) Stat(fileName string) (*storages.ObjectStat, error)

func (*Storage) SubStorage

func (s *Storage) SubStorage(subPath string, relative bool) (storages.Storager, error)

SubStorage re-roots the backend, which opens no connection, so the error is always nil here: it exists for the storages that gate the path, such as the key guard.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址