Documentation
¶
Overview ¶
Package connection defines the transport abstraction the typed Hyper-V client (internal/hyperv) uses to ship PowerShell scripts to a Windows host and read their results back. Three backends are planned: local (exec pwsh.exe directly), ssh (golang.org/x/crypto/ssh), and winrm (github.com/masterzen/winrm). local and ssh are implemented; winrm ships in M3.
Design notes are in docs/PLAN.md §4. Spike findings shaped the contract: docs/spikes/02-json-contract.md (script body via -EncodedCommand, stdin for data, stderr stripped of CLIXML), and docs/spikes/04-ps-startup-latency.md (per-call cost dominated by PS startup, not transport).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnreachable means the transport could not reach the host (DNS, // TCP, TLS handshake, auth failure). Resource code typically retries. ErrUnreachable = errors.New("transport unreachable") // ErrTimeout means the call exceeded its context deadline. Distinct // from ErrUnreachable so callers can decide whether to retry vs. // surface as `timeouts.Diagnostics`. ErrTimeout = errors.New("transport timeout") // ErrUnsupportedBackend is returned by the backend selector when the // requested backend identifier is not yet implemented. Removed once // SSH/WinRM backends ship. ErrUnsupportedBackend = errors.New("backend not implemented") )
Functions ¶
This section is empty.
Types ¶
type Connection ¶
type Connection interface {
Runner
// Open establishes any persistent state the backend needs (an SSH
// client, a pooled HTTP transport, etc.). Local is stateless and
// returns nil.
Open(ctx context.Context) error
// Close releases the backend's persistent state. Idempotent. Local
// is a no-op.
Close() error
// Healthcheck returns nil if the backend can reach the host and run
// a trivial command. Used at provider Configure time to fail fast on
// misconfiguration.
Healthcheck(ctx context.Context) error
// Backend returns the lowercase identifier of the implementation —
// "local" | "ssh" | "winrm". Used for tflog field decoration; the
// schema's `backend` attribute is the user-facing form.
Backend() string
}
Connection is the abstract transport. Each provider instance holds a single Connection per (backend, host, user) tuple. Resources never reach for a new one; they share the configured Connection via the typed client in internal/hyperv.
func NewLocal ¶
func NewLocal(opts LocalOptions) (Connection, error)
NewLocal returns a Connection backed by a local pwsh / powershell.exe process per call. Opens nothing — the local backend is stateless.
func NewSSH ¶
func NewSSH(opts SSHOptions) (Connection, error)
NewSSH builds a Connection backed by ssh.Client. It resolves authentication methods and the known_hosts callback up-front so misconfiguration surfaces before Open dials. The client itself is established lazily by Open.
type LocalOptions ¶
type LocalOptions struct {
// PwshPath, if non-empty, is used as-is. Set via the provider's
// `local.pwsh_path` attribute or the HYPERV_PWSH_PATH env var.
PwshPath string
}
LocalOptions configures the local backend. Empty values mean "discover from PATH": prefer pwsh (faster cold start), fall back to powershell.exe.
type Result ¶
Result is what every script invocation returns. The transport layer captures four pieces of information; the typed Hyper-V client maps them into typed Go errors per docs/PLAN.md §5.
`Stderr` has CLIXML progress noise stripped (see docs/spikes/02-json-contract.md finding 6) before reaching this struct. Real PS errors arrive as a JSON envelope on stderr per the Write-HypervError contract.
`error` from RunScript is reserved for transport failures (connection refused, auth failed, ctx canceled). PS-level failures come back via `ExitCode != 0` plus the structured envelope on `Stderr`.
type Runner ¶
type Runner interface {
RunScript(ctx context.Context, script string, stdinJSON []byte) (Result, error)
}
Runner is the narrowest useful interface — just "run a script, get a result." Connection composes Runner with lifecycle methods (Open/Close/ Healthcheck) that backends with persistent state need.
The split exists so unit tests can implement just Runner via the fake in internal/testutil, without faking lifecycle calls that don't matter for the typed-client tests.
Calling convention (verified by spike #2):
`script` is the full PowerShell body. The caller has already concatenated common/preamble.ps1 to the top. Backends transmit it as UTF-16LE base64 via -EncodedCommand. **Never** via stdin or as a command-line argument — multi-line scripts get mis-parsed otherwise.
`stdinJSON` is structured input. Empty for scripts that don't need input. Backends pipe these bytes to the PS process's stdin. Scripts read with `$input_json = $Input | ConvertFrom-Json -Compress`.
The returned `Result` carries the four useful streams. The error return is reserved for transport-level failures (connection refused, ctx canceled). Non-zero `ExitCode` is the application-level signal.
type SSHOptions ¶
type SSHOptions struct {
Host string // required
Port int // default 22
Username string // required
// Auth methods, in priority order:
//
// 1. PrivateKey (raw key contents -- wins if both PrivateKey and PrivateKeyPath are set)
// 2. PrivateKeyPath (path read at Open time)
// 3. Password (fallback only -- key auth is preferred)
//
// Passphrase decrypts the key when set.
PrivateKey []byte
PrivateKeyPath string
Passphrase []byte
Password string
// KnownHostsPath is the file used for host key verification. Default:
// ~/.ssh/known_hosts. Empty path falls back to the default. A missing
// file is a hard error -- silently disabling host-key checking would be
// a security regression.
KnownHostsPath string
// Timeout is the dial timeout. Default 30s.
Timeout time.Duration
// CommandTimeout bounds an individual RunScript call. Default
// 5m. A wedged remote cmdlet surfaces as ErrTimeout instead of
// blocking the whole apply. Set to 0 to disable.
CommandTimeout time.Duration
// KeepaliveInterval is how often the backend sends an SSH
// keepalive request while the persistent client is open.
// Default 30s. Prevents NAT/firewall mid-apply drops. Set to
// 0 to disable.
KeepaliveInterval time.Duration
// PwshPath is the binary the remote shell invokes per call. Default:
// "powershell.exe" -- universally available on Windows. Set to "pwsh"
// or "pwsh.exe" to prefer PS 7+ if installed.
PwshPath string
}
SSHOptions configures the SSH backend. The provider's Configure pass resolves env vars + provider attributes into this struct (see internal/provider/backend_select.go).