conn.go

v0.3.0
Doc Versions Source
1
package legatus
2
3
import (
4
	"context"
5
	"io"
6
	"io/fs"
7
)
8
9
// FileMode is the permission mode used when writing remote files.
10
type FileMode = fs.FileMode
11
12
// Cmd is a remote command. Args are passed structurally: a transport must
13
// quote each element so the remote shell can never re-split or re-evaluate it.
14
type Cmd struct {
15
	Path  string
16
	Args  []string
17
	Env   map[string]string
18
	Sudo  bool
19
	Stdin io.Reader
20
}
21
22
// ExecResult is the outcome of a remote command.
23
type ExecResult struct {
24
	Stdout   []byte
25
	Stderr   []byte
26
	ExitCode int
27
}
28
29
// Combined returns stdout followed by stderr.
30
func (r ExecResult) Combined() []byte {
31
	out := make([]byte, 0, len(r.Stdout)+len(r.Stderr))
32
	out = append(out, r.Stdout...)
33
	out = append(out, r.Stderr...)
34
	return out
35
}
36
37
// PutOptions configures a file upload.
38
type PutOptions struct {
39
	Sudo  bool
40
	Owner string
41
}
42
43
// PutOption mutates PutOptions.
44
type PutOption func(*PutOptions)
45
46
// WithPutSudo stages the upload and moves it into place with sudo.
47
func WithPutSudo() PutOption { return func(o *PutOptions) { o.Sudo = true } }
48
49
// WithPutOwner chowns the uploaded file to owner.
50
func WithPutOwner(owner string) PutOption { return func(o *PutOptions) { o.Owner = owner } }
51
52
// Conn is a live connection to one host. Transports implement it; the core
53
// engine depends only on this interface and never imports SSH (IV1, PC1).
54
type Conn interface {
55
	// Exec runs cmd to completion. A command that runs is not an error even on a
56
	// non-zero exit: the status is reported via ExecResult.ExitCode and err is
57
	// nil. err is reserved for failures to run the command at all (no session,
58
	// IO error, context cancellation). Callers decide whether a non-zero exit is
59
	// a failure (a step's Apply) or a signal (a probe like `test -e`).
60
	Exec(ctx context.Context, cmd Cmd) (ExecResult, error)
61
	// ExecStream runs cmd like Exec but streams output: a non-nil stdout/stderr
62
	// writer receives that stream live and the matching ExecResult field is left
63
	// nil; a nil writer buffers that stream into ExecResult exactly as Exec does,
64
	// so a caller can stream one stream while capturing the other. The exit-code
65
	// contract is identical to Exec — a clean run with a non-zero exit returns
66
	// err==nil with ExecResult.ExitCode set; ctx cancellation tears down the
67
	// process and returns ctx.Err() with bytes-so-far already written to the sink.
68
	ExecStream(ctx context.Context, cmd Cmd, stdout, stderr io.Writer) (ExecResult, error)
69
	Put(ctx context.Context, content io.Reader, remote string, mode FileMode, opts ...PutOption) error
70
	Get(ctx context.Context, remote string, w io.Writer) error
71
	Close() error
72
}
73
74
// Dialer opens a Conn to a host. transport provides the SSH implementation.
75
type Dialer interface {
76
	Dial(ctx context.Context, h *Host) (Conn, error)
77
}
78

Source Files