Help us shape the future of Go! Take the 2026 Go Developer Survey

exec

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package exec provides WebSocket-based remote command execution in workspace pods. It bridges WebSocket connections from clients to Kubernetes exec streams, enabling interactive terminal sessions within running workspace containers.

Package exec provides a WebSocket-to-Kubernetes-exec bridge for terminal sessions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AgentOwnerMiddleware added in v0.10.0

func AgentOwnerMiddleware(instance string, keys func(context.Context) ([][]byte, error), hop *OwnerHop, next http.Handler) http.Handler

AgentOwnerMiddleware routes lifecycle calls only to a cryptographically authenticated issuer. Forward resolves pod identity through Kubernetes, preserves credentials for reauthorization, and bounds forwarding to one hop.

func ClaimTier1Session added in v0.5.0

func ClaimTier1Session(namespace, name string, cancel func()) (func(), bool)

ClaimTier1Session registers a new Tier 1 transport session for the workspace. It returns a release function and true on success, or nil and false if the slot is already taken.

func ContextWithPod added in v0.10.0

func ContextWithPod(ctx context.Context, name string) context.Context

ContextWithPod sets the server-resolved target for Deployment-backed scratch workspaces. A client query parameter must never select a different pod.

func DisplayOwnerMiddleware added in v0.6.0

func DisplayOwnerMiddleware(store *display.Store, instance string, hop *OwnerHop, next http.Handler) http.Handler

DisplayOwnerMiddleware forwards Goa display membership/control requests (everything under /v1/workspaces/{name}/display except the /display/ws stream, which forwards itself) to the replica owning the workspace's display, whenever an owner is known. The membership registry is in-memory per replica, so a join on one pod and a stream attach on another would otherwise diverge into 404s; routing every call to the owner keeps the one registry coherent. With no owner known yet, any replica may answer — the stream attach that follows creates the generation on the same pod.

func Handler

func Handler(opts *Options) http.HandlerFunc

Handler creates an HTTP handler that upgrades to WebSocket and bridges to pod exec. The handler expects path parameters: namespace, name (workspace name). Query parameters: shell (optional, auto-detected if not provided), cols, rows.

func ParseTCPPort added in v0.6.0

func ParseTCPPort(raw string) (int, error)

ParseTCPPort validates the ?port= query: 1-65535, no names, no ranges. The editor/admin gate on the route is the authorization; this is the syntax.

func SSHConsoleInUse added in v0.4.0

func SSHConsoleInUse(namespace, name string) bool

SSHConsoleInUse reports whether an SSH bridge is currently active for the workspace.

func SSHHandler added in v0.4.0

func SSHHandler(opts *SSHOptions) http.HandlerFunc

SSHHandler creates an HTTP handler that upgrades to WebSocket and bridges to the guest's sshd over the workspace's masqueraded port. The client authentic with the private key matching one of the public keys the controller seeded into the guest's cloud-init (SshKey CRs).

The target is the workspace Service's endpoints address:port — the virt-launcher pod IP where KubeVirt's masquerade DNATs to the guest — which bypasses the Service ClusterIP (VM Services do not DNAT correctly under the launcher's iptables; the pod IP path works cross-node). Guest sshd host keys are self-generated and rotate per image rebuild, so no host key verification is possible; the session is carried over the authenticated WS + TLS to the API instead.

func ScreenshotHandler added in v0.6.0

func ScreenshotHandler(opts *Options) http.HandlerFunc

ScreenshotHandler returns an HTTP handler serving a one-shot PNG of the VM display: GET /v1/workspaces/{name}/vnc/screenshot?namespace=...

It dials the same KubeVirt VMI VNC subresource as the interactive bridge but holds only the capture lease (display.AcquireCapture), so a thumbnail never evicts the viewer or the seat holder — and a held console answers 409 instead of stealing the session. The RFB handshake advertises Raw only, so no pseudo-encoding acks or payloads are involved.

func SerialConsoleInUse added in v0.4.0

func SerialConsoleInUse(namespace, name string) bool

SerialConsoleInUse reports whether a serial console bridge is currently active for the workspace.

func TCPHandler added in v0.6.0

func TCPHandler(opts *TCPOptions) http.HandlerFunc

TCPHandler upgrades to WebSocket and bridges raw binary frames to guest TCP port ?port=N on the workspace's VM. VM workspaces only.

The target is the launcher pod IP (from the workspace Service Endpoints) dialled at the requested port — the same masquerade path the SSH bridge uses, minus the SSH protocol: every client binary frame is written to TCP and every TCP byte is returned as a binary frame. Text frames are rejected. Requires editor/admin (enforced by the route's requireEditorAccess).

func TCPInUse added in v0.6.0

func TCPInUse(namespace, name string, port int) bool

TCPInUse reports whether a TCP bridge holds (namespace, name, port).

func TakeOverSSHConsole added in v0.4.0

func TakeOverSSHConsole(namespace, name string) bool

TakeOverSSHConsole force-ends the active SSH bridge for the workspace, if any.

func TakeOverSerialConsole added in v0.4.0

func TakeOverSerialConsole(namespace, name string) bool

TakeOverSerialConsole force-ends the active serial console bridge for the workspace, if any, so the caller can open a fresh session. It returns whether a session was active.

func TakeOverTCP added in v0.6.0

func TakeOverTCP(namespace, name string, port int) bool

TakeOverTCP force-ends the TCP bridge for (namespace, name, port), if any.

func TakeOverTier1 added in v0.5.0

func TakeOverTier1(namespace, name string) bool

TakeOverTier1 force-ends the active Tier 1 transport session for the workspace, if any, so the caller can open a fresh session. It returns whether a session was active.

func TakeOverVNC added in v0.5.0

func TakeOverVNC(namespace, name string) bool

TakeOverVNC force-ends the active VNC bridge for the workspace, if any, so the caller can open a fresh session. It returns whether a session was active.

func Tier1InUse added in v0.5.0

func Tier1InUse(namespace, name string) bool

Tier1InUse reports whether either interactive display transport is in use.

func VMConsoleHandler added in v0.4.0

func VMConsoleHandler(opts *Options) http.HandlerFunc

VMConsoleHandler creates an HTTP handler that upgrades the client connection to a WebSocket and bridges it to the KubeVirt VMI serial console subresource. The VMI name equals the workspace name. The console is a raw serial stream: no shell is spawned — the guest image must run a getty on the console for a login prompt to appear.

func VMVNCHandler added in v0.4.0

func VMVNCHandler(opts *Options) http.HandlerFunc

VMVNCHandler returns an HTTP handler that upgrades the client connection to a WebSocket and bridges it to the KubeVirt VMI VNC subresource. The VMI name equals the workspace name. The socket carries the raw RFB (VNC) byte stream; the client side is expected to run a noVNC RFB client on top. KubeVirt's VNC console is single-session: while another session is active the dial fails with "Active VNC connection. Request denied."

func VNCInUse added in v0.5.0

func VNCInUse(namespace, name string) bool

VNCInUse reports whether either interactive display transport is in use.

Types

type Options

type Options struct {
	// RESTConfig is the Kubernetes REST config for SPDY exec connections.
	RESTConfig *rest.Config
	// Clientset is the Kubernetes clientset for pod exec requests.
	Clientset kubernetes.Interface
	Display   *display.Store
	// Sessions is the shared-display membership registry. When set, the shared
	// display route registers/unregisters participants here; it must be the same
	// instance backing the Goa display service.
	Sessions *display.Sessions
	// SharedDisplayDisabled is the pilot gate for the shared-display stream
	// route (plan E: opt-in until acceptance passes). When set, the route
	// answers 404 like an unknown capability.
	SharedDisplayDisabled bool
	// Revalidate re-checks the credential that authorised an open stream. When
	// it reports a revoked credential the stream is ended with a
	// closeCodeCredentialRevoked close frame.
	Revalidate RevalidateFunc
	// RevalidateInterval is how often Revalidate runs for an open stream.
	RevalidateInterval time.Duration
}

Options configures the exec handler.

type OwnerHop added in v0.6.0

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

OwnerHop forwards a shared-display request to the replica that owns the workspace's display generation, so any API pod can answer while exactly one pod dials the VM's VNC console. The owner identity never comes from the caller: it is read from the lease annotation the owning replica wrote, and resolved to a pod IP through the Kubernetes API. The forwarded request keeps the client's credentials, so the owning pod re-authorizes it like any direct request.

func NewOwnerHop added in v0.6.0

func NewOwnerHop(clientset kubernetes.Interface) *OwnerHop

NewOwnerHop returns an OwnerHop resolving owner pod names against the API's own namespace (from the service account, defaulting to the deployment's namespace when running off-cluster).

func (*OwnerHop) Forward added in v0.6.0

func (h *OwnerHop) Forward(w http.ResponseWriter, r *http.Request, owner string)

Forward proxies r to the owning replica. When the request already made a hop, or the owner cannot be resolved, it answers the 409/owner body itself: the client's next attempt re-reads a fresher lease and either succeeds or learns the new owner.

type RevalidateFunc added in v0.11.0

type RevalidateFunc func(context.Context) error

RevalidateFunc re-checks the credential that authorised a stream. It returns auth.ErrCredentialRevoked once the credential is no longer usable.

type SSHOptions added in v0.4.0

type SSHOptions struct {
	// Clientset is used to resolve the workspace Service endpoints (the
	// launcher pod IP:port that masquerade forwards to the guest sshd).
	Clientset kubernetes.Interface
	// Revalidate re-checks the credential that authorised an open stream. When
	// it reports a revoked credential the stream is ended with a
	// closeCodeCredentialRevoked close frame.
	Revalidate RevalidateFunc
	// RevalidateInterval is how often Revalidate runs for an open stream.
	RevalidateInterval time.Duration
}

SSHOptions configures the SSH bridge handler.

type SharedDisplay added in v0.6.0

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

SharedDisplay serves the shared-display WebSocket route GET /v1/workspaces/{name}/display/ws. The route must have been authorized (editor/admin + namespace access) and confirmed VM-only before Handle runs. role=controller (query) joins as the controlling participant, whose input is gated by the display control lease; anything else joins as a view-only observer. No viewer accepts role=controller while another controller exists.

func NewSharedDisplay added in v0.6.0

func NewSharedDisplay(opts *Options) *SharedDisplay

NewSharedDisplay creates the shared-display route runtime.

func (*SharedDisplay) Handle added in v0.6.0

func (s *SharedDisplay) Handle(w http.ResponseWriter, r *http.Request)

Handle upgrades the client to a WebSocket and serves it an RFB shared-display stream. It blocks until disconnect, broker shutdown or cancellation.

type TCPOptions added in v0.6.0

type TCPOptions struct {
	// Clientset resolves the workspace Service endpoints to the launcher pod
	// IP where masquerade forwards guest ports.
	Clientset kubernetes.Interface
	// Revalidate re-checks the credential that authorised an open stream. When
	// it reports a revoked credential the stream is ended with a
	// closeCodeCredentialRevoked close frame.
	Revalidate RevalidateFunc
	// RevalidateInterval is how often Revalidate runs for an open stream.
	RevalidateInterval time.Duration
}

TCPOptions configures the generic TCP bridge.

Jump to

Keyboard shortcuts

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