Documentation
¶
Index ¶
- func ParseSpeed(raw string) (float64, error)
- type OpenOptions
- type OverlayScope
- type ReplayClock
- func (c *ReplayClock) AddEvents(n int64)
- func (c *ReplayClock) EventsEmitted() int64
- func (c *ReplayClock) Loop() bool
- func (c *ReplayClock) Now() time.Time
- func (c *ReplayClock) ParkAtWindowEnd()
- func (c *ReplayClock) Pause()
- func (c *ReplayClock) Paused() bool
- func (c *ReplayClock) Resume()
- func (c *ReplayClock) Sample() (pos time.Time, epoch int, ended bool)
- func (c *ReplayClock) Seek(t time.Time)
- func (c *ReplayClock) SeekGen() int
- func (c *ReplayClock) SetSpeed(s float64)
- func (c *ReplayClock) Speed() float64
- func (c *ReplayClock) Window() (time.Time, time.Time)
- type ReplayOptions
- type Server
- func (s *Server) Address() string
- func (s *Server) CertPEM() []byte
- func (s *Server) Clock() *ReplayClock
- func (s *Server) HasWatchEvents() bool
- func (s *Server) KubeconfigPath() string
- func (s *Server) KubernetesVersion() string
- func (s *Server) MergeOverlayList(group, version, resource, namespace string, base []json.RawMessage) []json.RawMessage
- func (s *Server) OverlayDeletedNamespaces() map[string]struct{}
- func (s *Server) OverlayObject(group, version, resource, namespace, name string) (obj json.RawMessage, deleted, found bool)
- func (s *Server) OverlayScopes() []OverlayScope
- func (s *Server) Shutdown()
- func (s *Server) Store() *kstore.CaptureStore
- func (s *Server) Wait() error
- func (s *Server) WaitForSignal()
- func (s *Server) Writable() bool
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseSpeed ¶
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.
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 ¶
Address returns the HTTPS listen address (e.g. "https://127.0.0.1:54321").
func (*Server) CertPEM ¶
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 ¶
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 ¶
KubeconfigPath returns the path to the generated kubeconfig.
func (*Server) KubernetesVersion ¶
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 ¶
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 ¶
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.