Documentation
¶
Overview ¶
Package backend obtains a reachable local CDP/VNC endpoint for a browser that runs in one of four places: a local docker container, a Kubernetes Deployment, docker on an ssh host, or a pre-exposed direct URL. Every CDP/VNC-facing operation runs against the Endpoint a backend yields, so the rest of cuttle is transport-agnostic.
Index ¶
- Constants
- func SuperviseTunnel(name string, args []string)
- type Backend
- type Direct
- type Endpoint
- type ExecRunner
- type K8s
- func (k *K8s) EnsureTunnel(ctx context.Context, cdpPort, vncPort int) (Endpoint, error)
- func (k *K8s) LogsCommand(follow bool) (string, []string)
- func (k *K8s) PurgeProfileVolume(ctx context.Context) error
- func (k *K8s) Reach(ctx context.Context, cdpPort, vncPort int) (Endpoint, func(), error)
- func (k *K8s) Start(ctx context.Context, opts StartOpts) error
- func (k *K8s) State(ctx context.Context) (State, error)
- func (k *K8s) Stop(ctx context.Context, purge bool) error
- func (k *K8s) StopTunnel() error
- type Local
- func (l *Local) Diagnostics(ctx context.Context) []string
- func (l *Local) DiscoverPorts(ctx context.Context) (int, int, bool)
- func (l *Local) Image(ctx context.Context) string
- func (l *Local) LogsCommand(follow bool) (string, []string)
- func (l *Local) PurgeProfileVolume(ctx context.Context) error
- func (l *Local) Reach(_ context.Context, _, _ int) (Endpoint, func(), error)
- func (l *Local) Start(ctx context.Context, opts StartOpts) error
- func (l *Local) State(ctx context.Context) (State, error)
- func (l *Local) Stop(ctx context.Context, purge bool) error
- type LogSource
- type PortDiscoverer
- type Process
- type ProfilePurger
- type Result
- type Runner
- type SSH
- func (s *SSH) DiscoverPorts(ctx context.Context) (int, int, bool)
- func (s *SSH) EnsureTunnel(ctx context.Context, cdpPort, vncPort int) (Endpoint, error)
- func (s *SSH) LogsCommand(follow bool) (string, []string)
- func (s *SSH) PurgeProfileVolume(ctx context.Context) error
- func (s *SSH) Reach(ctx context.Context, cdpPort, vncPort int) (Endpoint, func(), error)
- func (s *SSH) Start(ctx context.Context, opts StartOpts) error
- func (s *SSH) State(ctx context.Context) (State, error)
- func (s *SSH) Stop(ctx context.Context, purge bool) error
- func (s *SSH) StopTunnel() error
- type StartOpts
- type State
- type Tunneler
Constants ¶
const DefaultContainerName = "cuttle"
DefaultContainerName is the docker container name used when --name is not set. The CLI's default flows through here so a caller can distinguish the default from an explicit --name (which keys a per-instance tunnel identity below).
const SuperviseTunnelSubcmd = "__supervise-tunnel"
SuperviseTunnelSubcmd is the hidden CLI subcommand spawnTunnel re-execs cuttle into: `cuttle __supervise-tunnel <forward-cmd> <args...>`. Keeping auto-reconnect in the cuttle binary itself avoids an external dependency like autossh.
Variables ¶
This section is empty.
Functions ¶
func SuperviseTunnel ¶ added in v0.10.3
SuperviseTunnel runs the forward (name + args) in a restart loop until SIGTERM/ SIGINT, with capped exponential backoff that resets after a healthy run, so a dropped forward re-establishes on its own instead of staying down until the next `cuttle status`. It is the body of the hidden SuperviseTunnelSubcmd that spawnTunnel re-execs. exec.CommandContext ties each forward to ctx, so the signal that cancels ctx also kills the in-flight child; the child shares this supervisor's process group, so `cuttle down`'s killTunnel(-pid) stops both.
Types ¶
type Backend ¶
type Backend interface {
State(ctx context.Context) (State, error)
Start(ctx context.Context, opts StartOpts) error
Stop(ctx context.Context, purge bool) error
// Reach yields a local endpoint plus a release func that tears down any
// tunnel opened to reach it. release is always safe to call (no-op for
// direct/local). cdpPort/vncPort request specific local ports for a tunneled
// backend (k8s/ssh) so a held forward is deterministic and a driver can attach
// to it; 0 auto-picks a free port. The forward Reach opens is ephemeral by
// design - it lives only until release is called (the CLI exit) - and is the
// internal fallback for the short-lived open/login flows. A backend that also
// implements Tunneler (k8s/ssh) additionally offers a detached, standing
// forward that outlives the CLI (see tunnel.go); that is what up/status
// advertise so the briefing endpoint is stable across invocations.
Reach(ctx context.Context, cdpPort, vncPort int) (Endpoint, func(), error)
}
Backend manages one browser's lifecycle and reachability.
func New ¶
func New(name, ctxName string, ctx config.Context, r Runner, cdpPort, vncPort int, image string) (Backend, error)
New builds the backend for a resolved context. Ports are the host-side CDP/VNC ports for the local backend (and the remote container ports for ssh). ctxName is the resolved context name; tunneled backends use it as the standing-tunnel pidfile identity - a non-default container name (--name) is folded in so two named instances sharing one ssh context get distinct tunnels.
type Direct ¶
type Direct struct {
// contains filtered or unexported fields
}
Direct targets a pre-exposed CDP/VNC endpoint from config as-is. It is the escape hatch for any browser cuttle does not itself manage (e.g. reached over a tailnet), so Start/Stop are errors.
type Endpoint ¶
Endpoint is a reachable CDP (and optional VNC) address. For tunneled backends the host is loopback and the ports are auto-picked local forwards; for direct it is the configured host/port as-is.
type ExecRunner ¶
type ExecRunner struct{}
ExecRunner is the production Runner backed by os/exec.
type K8s ¶
type K8s struct {
// contains filtered or unexported fields
}
K8s runs the browser as a Helm-managed Deployment in a cluster, reached via kubectl port-forward. It shells out to kubectl/helm and inherits the user's kube context (and thus their routing) with zero cuttle-specific setup.
func (*K8s) EnsureTunnel ¶ added in v0.7.0
EnsureTunnel establishes (or reuses) a detached `kubectl port-forward` on the fixed cdp/vnc ports that outlives the CLI. A forward dropped by a pod restart is reconnected by the supervisor (see spawnTunnel); status re-establishes it too on the next health-check if the supervisor itself is gone.
func (*K8s) LogsCommand ¶ added in v0.10.2
LogsCommand targets pods by the release's instance label (matching State), so it works whatever the chart names the Deployment. A selector query defaults to 10 trailing lines; --tail=-1 (one token - a separate "-1" could parse as a flag) restores docker's show-everything.
func (*K8s) PurgeProfileVolume ¶ added in v0.9.0
PurgeProfileVolume deletes the durable profile PVC, the k8s analogue of removing the named Docker volume. `cuttle purge-profile` uninstalls the release first (releasing the RWO claim), so this deletes a now-unbound PVC; a lingering PVC from a prior install is removed too.
func (*K8s) Reach ¶
Reach opens a kubectl port-forward. cdpPort/vncPort pin the local ports (so a held `cuttle connect` forward is deterministic and a driver can attach to it); 0 auto-picks free ports for the ephemeral status/login forwards, which then never collide with a local container already on 9222.
func (*K8s) StopTunnel ¶ added in v0.7.0
type Local ¶
type Local struct {
// contains filtered or unexported fields
}
Local runs the browser in a docker container on this host. It is a faithful port of the Python cuttle CLI's docker lifecycle, so existing behavior does not regress when no config file is present.
func (*Local) Diagnostics ¶
Diagnostics returns human-readable triage lines for an unhealthy container: the real host<-container port bindings and a log tail, so triage never needs a raw docker command. It is used by `status` via an optional interface.
func (*Local) DiscoverPorts ¶ added in v0.10.2
DiscoverPorts reads the running container's published CDP/VNC host ports.
func (*Local) LogsCommand ¶ added in v0.10.2
LogsCommand returns the docker argv that prints the container's logs.
func (*Local) PurgeProfileVolume ¶ added in v0.9.0
PurgeProfileVolume removes the persistent profile's named volume. The caller (`cuttle purge-profile`) removes the container first so the volume is detached.
func (*Local) Reach ¶
Reach for local is a direct loopback endpoint on the host-mapped ports; no tunnel, so release is a no-op.
type LogSource ¶ added in v0.10.2
LogSource is implemented by backends whose browser logs cuttle can surface (local/ssh via docker logs, k8s via kubectl logs). LogsCommand returns the argv that prints them; the CLI execs it with the terminal attached so follow streams and Ctrl-C behave exactly like the underlying tool. The direct backend does not implement it - cuttle does not manage where that browser runs.
type PortDiscoverer ¶ added in v0.10.2
type PortDiscoverer interface {
DiscoverPorts(ctx context.Context) (cdpPort, vncPort int, ok bool)
}
PortDiscoverer reports the host-published CDP/VNC ports of the running instance, so a caller targeting an existing instance need not restate the ports chosen at `up`. Implemented by the docker backends (local/ssh) via `docker port`; k8s (caller-chosen forward ports) and direct (URL-fixed) do not. Returns ok=false when the ports cannot be read - nothing running, or an unparseable mapping - and the caller then keeps its configured/default ports.
type Process ¶
type Process interface {
Stop() error
}
Process is a running command that can be stopped.
type ProfilePurger ¶ added in v0.9.0
ProfilePurger removes the persistent profile's backing store - the named Docker volume on local/ssh, the PVC on k8s - so the next start begins from a clean profile. Implemented by local, ssh, and k8s; the direct backend has no store cuttle manages.
type Runner ¶
type Runner interface {
// Output runs a command to completion and captures its output. A non-zero
// exit is reported in Result.Code with a nil error (mirroring the Python
// check=False); a nil error means only that the command ran.
Output(ctx context.Context, name string, args ...string) (Result, error)
// Start launches a long-running command (a tunnel) and returns a handle to
// stop it.
Start(ctx context.Context, name string, args ...string) (Process, error)
// LookPath reports the resolved path of an executable, or an error if absent.
LookPath(name string) (string, error)
}
Runner is the exec seam every backend goes through, so command construction is unit-testable without docker/kubectl/ssh installed.
type SSH ¶
type SSH struct {
// contains filtered or unexported fields
}
SSH runs the browser in docker on a remote host reached over ssh, tunneled to this machine with ssh -L. It inherits ~/.ssh/config (keys, jump hosts, and any routing the user provides), so cuttle needs no ssh setup of its own.
func (*SSH) DiscoverPorts ¶ added in v0.10.2
DiscoverPorts reads the remote container's published CDP/VNC host ports (the ports ssh -L then forwards), so a caller need only pass --context/--name.
func (*SSH) EnsureTunnel ¶ added in v0.7.0
EnsureTunnel establishes (or reuses) a detached `ssh -N -L` forward on the fixed cdp/vnc ports that outlives the CLI.
func (*SSH) LogsCommand ¶ added in v0.10.2
LogsCommand returns the ssh argv that streams the remote container's docker logs, reusing the ControlMaster socket like every other remote call.
func (*SSH) PurgeProfileVolume ¶ added in v0.9.0
PurgeProfileVolume removes the persistent profile's named volume on the ssh host. The caller (`cuttle purge-profile`) removes the container first so the volume is detached.
func (*SSH) Reach ¶
Reach opens an ssh -L tunnel from local ports to the remote container's published ports, establishing the ControlMaster the other calls reuse. cdpPort/vncPort pin the local ports (so a held `cuttle connect` forward is deterministic and a driver can attach to it); 0 auto-picks free ports for the ephemeral status/login forwards.
func (*SSH) StopTunnel ¶ added in v0.7.0
type StartOpts ¶
type StartOpts struct {
Image string
Recreate bool
// KeepProfile is the legacy override for the durable-profile behavior:
// nil = backend default (persist), false = ephemeral. --ephemeral is the
// preferred opt-out and sets Ephemeral instead. See persistProfile.
KeepProfile *bool
// Ephemeral opts out of the persistent default profile: no named volume, a
// fresh scratch profile that is discarded on recreate/down --purge.
Ephemeral bool
// PurgeProfile resets the persistent profile before (re)creating the
// container/pod: it drops the named volume (docker local/ssh) or the PVC (k8s)
// so the next start begins from a clean profile.
PurgeProfile bool
Proxy string
IdleTimeout string // seconds of idle before a per-seed browser is reaped; "" = off
Screen string // "WxH" the browser claims and is sized to (CUTTLE_SCREEN); "" = daemon default
// Humanize overrides behavioral input humanization: nil = daemon default (on),
// &false = disable (CUTTLE_HUMANIZE=0), &true = force on. Only the disable case
// is passed through, since the daemon defaults humanize on.
Humanize *bool
// AllowContextCreation lets drivers call Target.createBrowserContext instead of
// having it rejected. Only the enable case is passed through, since the daemon
// defaults it off.
AllowContextCreation bool
}
StartOpts carries the per-invocation choices for Start. Not every field applies to every backend (e.g. Recreate is docker-only); a backend ignores what it does not use.
func (StartOpts) Persistent ¶ added in v0.9.0
Persistent reports whether the default profile is durable (a named volume / PVC mounted at the container's data dir, plus CUTTLE_KEEP_PROFILE=1 so the daemon treats it as the source of truth). Persist-by-default: --ephemeral (or the legacy --keep-profile=false) opts out. It is the single source of truth for the persist decision - the CLI and every backend derive from it.
type Tunneler ¶ added in v0.7.0
type Tunneler interface {
// EnsureTunnel returns a stable local endpoint, (re)spawning the detached
// forward on the given ports when none is healthy.
EnsureTunnel(ctx context.Context, cdpPort, vncPort int) (Endpoint, error)
// StopTunnel tears down the standing forward, if any.
StopTunnel() error
}
Tunneler is implemented by backends that reach the browser through a local forward (ssh, k8s). Unlike Reach's ephemeral forward, EnsureTunnel establishes a detached, long-lived forward on fixed ports that outlives the CLI process, so the briefing can advertise a stable 127.0.0.1 endpoint across invocations. local/direct do not implement it (their endpoint is already stable and needs no process).