server

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: Apache-2.0 Imports: 55 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseSpeed

func ParseSpeed(raw string) (float64, error)

ParseSpeed parses a speed factor such as "2x", "0.5x", "3", or "1.5x" for callers outside this package (e.g. the UI transport control endpoint). An empty string means real time (1x).

Types

type OpenOptions

type OpenOptions struct {
	ArchivePath   string
	Port          string
	KubeconfigOut string
	At            string
	Verbose       bool
	// Identities decrypts an encrypted archive; ignored for plaintext archives.
	Identities []age.Identity
}

OpenOptions holds parameters for opening a capture archive.

type OverlayScope

type OverlayScope struct {
	Group, Version, Resource, Namespace string
	Count                               int
	Sample                              json.RawMessage
}

OverlayScope identifies a group/version/resource/namespace combination with at least one live object in the writable overlay, plus a representative object body — used to discover kinds/namespaces that exist only because of overlay writes (e.g. a CRD's custom resources, or a namespace created by `helm install --create-namespace`) and so have no entry in the capture's static index at all. Namespace is "" for cluster-scoped resources.

type ReplayClock

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

ReplayClock maps wall-clock time onto capture time at a configurable speed, advancing a position within a [from, to] window. It is the heart of replay mode: LIST/GET reconstruct state as-of the clock's current position, and the watch stream emits captured events as the clock crosses their timestamps.

A single global clock backs a replay server (phase 1). It supports pause, resume, seek, and speed changes so later phases can expose transport controls; the streaming path polls the clock and adapts automatically.

func NewReplayClock

func NewReplayClock(from, to time.Time, speed float64, loop, paused bool) *ReplayClock

NewReplayClock creates a clock over [from, to] advancing at speed (a factor: 1 = real time, 2 = twice as fast, 0.5 = half). When loop is true the position wraps back to from on reaching to; otherwise it stops at to. When paused the clock does not advance until Resume is called. The initial position is always from. Callers that want a paused clock parked elsewhere for preview (e.g. the Web UI defaulting to the window end) should call ParkAtWindowEnd right after construction, not Seek — a plain Seek(to) would report ended=true while parked and wouldn't get Resume's rewind-and-play behavior.

func (*ReplayClock) AddEvents

func (c *ReplayClock) AddEvents(n int64)

AddEvents increments the emitted-event counter (surfaced on the status line).

func (*ReplayClock) EventsEmitted

func (c *ReplayClock) EventsEmitted() int64

EventsEmitted returns how many watch events have been streamed so far.

func (*ReplayClock) Loop

func (c *ReplayClock) Loop() bool

Loop reports whether the clock wraps at the end of the window.

func (*ReplayClock) Now

func (c *ReplayClock) Now() time.Time

Now returns the clock's current capture-time position.

func (*ReplayClock) ParkAtWindowEnd

func (c *ReplayClock) ParkAtWindowEnd()

ParkAtWindowEnd positions a paused clock at the window end for preview — the Web UI's default, so a client reading through the clock sees the most complete captured state rather than a capture's typically-sparse opening moments. It does not count as the replay having ended: Sample reports ended=false, and the next Resume rewinds to the window start and plays forward normally, rather than immediately re-reporting the end it was parked at. A no-op if the clock isn't paused.

func (*ReplayClock) Pause

func (c *ReplayClock) Pause()

Pause stops the clock at its current position.

func (*ReplayClock) Paused

func (c *ReplayClock) Paused() bool

Paused reports whether the clock is currently paused.

func (*ReplayClock) Resume

func (c *ReplayClock) Resume()

Resume restarts a paused clock from where it stopped — unless it was merely parked at the window end for preview (ParkAtWindowEnd), in which case it rewinds to from first, so Play actually plays the window rather than re-reporting the end it was already sitting at.

func (*ReplayClock) Sample

func (c *ReplayClock) Sample() (pos time.Time, epoch int, ended bool)

Sample returns the current position, the loop epoch (which increments each time the window wraps under loop), and whether the clock has reached the end (only possible when loop is disabled).

func (*ReplayClock) Seek

func (c *ReplayClock) Seek(t time.Time)

Seek jumps the position to t, clamped to [from, to]. The loop epoch is unchanged. Clears any pending ParkAtWindowEnd preview state — an explicit seek is the user choosing a position, not a request to preview the end.

func (*ReplayClock) SeekGen

func (c *ReplayClock) SeekGen() int

SeekGen returns a counter that increments on every Seek. A watch stream polls it to detect a seek (which, unlike a loop wrap, doesn't change the epoch) and restart from the new position.

func (*ReplayClock) SetSpeed

func (c *ReplayClock) SetSpeed(s float64)

SetSpeed changes the speed factor, preserving the current position.

func (*ReplayClock) Speed

func (c *ReplayClock) Speed() float64

Speed returns the current speed factor.

func (*ReplayClock) Window

func (c *ReplayClock) Window() (time.Time, time.Time)

Window returns the immutable [from, to] replay window.

type ReplayOptions

type ReplayOptions struct {
	ArchivePath   string
	Port          string
	KubeconfigOut string
	Speed         string // speed factor, e.g. "2x", "0.5x" (empty = real time)
	From          string // window start: RFC3339 or relative like -10m (empty = capture start)
	To            string // window end: RFC3339 or relative like -1m (empty = capture end)
	Loop          bool
	StartPaused   bool
	// Identities decrypts an encrypted archive; ignored for plaintext archives.
	Identities []age.Identity
	// PauseAtWindowEnd, when StartPaused is set, parks the clock at the window
	// end (the most complete captured state) instead of the window start. The
	// Web UI sets this: a capture's opening moments are typically sparse
	// (informers are still completing their initial LIST), so a dashboard
	// paused at the window start until the user presses Play would otherwise
	// show a near-empty cluster by default. Headless `kshrk replay
	// --start-paused` leaves this unset — its documented behavior is "press
	// Enter to begin playback" from the window start.
	PauseAtWindowEnd bool
	Writable         bool // accept client writes into an in-memory overlay
	// DisableScheduling turns off the pod-scheduling shim (which otherwise binds
	// an unscheduled Pod to a node on create). Zero value keeps the shim on under
	// --writable; set it to opt out (--schedule-pods=false).
	DisableScheduling bool
	Verbose           bool
}

ReplayOptions holds parameters for replaying a capture forward through time.

type Server

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

Server represents a running mock API server.

func Open

func Open(opts OpenOptions) (*Server, error)

Open opens a capture archive, starts the mock HTTPS server, and writes a kubeconfig pointing at it.

func Replay

func Replay(opts ReplayOptions) (*Server, error)

Replay opens a capture and starts the mock HTTPS server in replay mode: a clock advances through the [from, to] window at the given speed, streaming captured watch events over time. LIST/GET return state as-of the clock.

func (*Server) Address

func (s *Server) Address() string

Address returns the HTTPS listen address (e.g. "https://127.0.0.1:54321").

func (*Server) CertPEM

func (s *Server) CertPEM() []byte

CertPEM returns a copy of this run's self-signed TLS certificate in PEM form, so an in-process client (one that isn't going through the generated kubeconfig's insecure-skip-tls-verify) can pin it instead of disabling verification. A copy is returned so a caller can't mutate the server's stored cert bytes.

func (*Server) Clock

func (s *Server) Clock() *ReplayClock

Clock returns the replay clock, or nil when the server is not in replay mode.

func (*Server) HasWatchEvents

func (s *Server) HasWatchEvents() bool

HasWatchEvents reports whether the capture contains watch events to stream. Poll-only captures return false; replay still serves LIST/GET as-of the clock but emits no watch events (inferring events for poll-only captures is a later phase).

func (*Server) KubeconfigPath

func (s *Server) KubeconfigPath() string

KubeconfigPath returns the path to the generated kubeconfig.

func (*Server) KubernetesVersion

func (s *Server) KubernetesVersion() string

KubernetesVersion returns the capture's Kubernetes gitVersion (e.g. "v1.36.1"), as reported by the captured cluster's /version endpoint.

func (*Server) MergeOverlayList

func (s *Server) MergeOverlayList(group, version, resource, namespace string, base []json.RawMessage) []json.RawMessage

MergeOverlayList merges overlay writes for (group, version, resource, namespace — "" for cluster-wide/all-namespaces) over base, "overlay wins" (see overlay.applyToList), and drops any items left in a namespace the overlay deleted. Returns base unchanged when the server has no writable overlay.

func (*Server) OverlayDeletedNamespaces

func (s *Server) OverlayDeletedNamespaces() map[string]struct{}

OverlayDeletedNamespaces returns the set of namespaces deleted via the overlay, so a reader can filter their (possibly still-captured) contents out. Returns nil when the server has no writable overlay.

func (*Server) OverlayObject

func (s *Server) OverlayObject(group, version, resource, namespace, name string) (obj json.RawMessage, deleted, found bool)

OverlayObject returns the overlay's copy of a single object identity, if any overlay write touched it. found is false when the server has no writable overlay or no write ever touched this identity; deleted is true for a tombstone (the object was created then deleted in the overlay).

func (*Server) OverlayScopes

func (s *Server) OverlayScopes() []OverlayScope

OverlayScopes returns every distinct scope with at least one live overlay entry. Returns nil when the server has no writable overlay.

func (*Server) Shutdown

func (s *Server) Shutdown()

Shutdown immediately stops the server and closes the archive. Useful in tests and programmatic usage; Wait() is preferred for CLI use.

func (*Server) Store

func (s *Server) Store() *kstore.CaptureStore

Store returns the kstore.CaptureStore backing this server, so a second in-process reader (the web UI) can share it instead of loading the archive again. Returns nil on a nil *Server, matching every other accessor in this file.

func (*Server) Wait

func (s *Server) Wait() error

Wait blocks until Ctrl+C / SIGTERM (or the server stops on its own), then tears it down and closes the archive. Prefer WaitForSignal + Shutdown when the caller has other resources that must be torn down in a specific order relative to this server (see cmd/ui.go, cmd/replay.go).

func (*Server) WaitForSignal

func (s *Server) WaitForSignal()

WaitForSignal blocks until Ctrl+C / SIGTERM (or the server stops on its own) but does NOT shut the server down or close the archive — it returns control to the caller, who may own other resources (a companion UI server, kwok, kube-controller-manager) that must be torn down in a specific order relative to this one. Call Shutdown afterward. Callers that don't own any such resources can use Wait instead.

func (*Server) Writable

func (s *Server) Writable() bool

Writable reports whether the server accepts client writes into the overlay.

Jump to

Keyboard shortcuts

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