connection

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: May 2, 2026 License: MPL-2.0 Imports: 20 Imported by: 0

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

View Source
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

type Result struct {
	Stdout   []byte
	Stderr   []byte
	ExitCode int
	Duration time.Duration
}

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).

Jump to

Keyboard shortcuts

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