ops

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package ops implements the App Ops Interface contract v1 (plan §4): discovery, the versioned descriptor, Terminus-style health normalization, queues, the pluggable adapter seam, and the per-app prober. All app responses are treated as hostile input: size-capped (by opsclient), schema-checked, and on ANY parse failure the app degrades to BASIC — never a crash (plan §4.3).

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrBadQueueAction = errors.New("ops: invalid queue action")
	ErrBadQueueName   = errors.New("ops: invalid queue name")
	ErrOpsNotEnabled  = errors.New("ops: not enabled for this app")
	ErrQueueFailed    = errors.New("ops: queue action failed")
)

ErrBadQueueAction / ErrBadQueueName guard the server-side queue proxy.

Functions

func Register

func Register(a Adapter)

Register adds an adapter (called from init()).

func ValidateBaseURL

func ValidateBaseURL(raw string) error

ValidateBaseURL enforces the pinned-origin rules (plan §4.1): http(s) scheme, a host, NO path/query/fragment, and not a loopback literal (loopback can't be distinguished from the control plane, which is loopback-bound).

Types

type Adapter

type Adapter interface {
	Name() string
	// Discover classifies the app (RICH/BASIC) and returns its capabilities.
	Discover(ctx context.Context, c Doer, t Target) Discovery
	// Probe fetches and normalizes the live record for a RICH app.
	Probe(ctx context.Context, c Doer, t Target, d Discovery) Result
}

Adapter is the §4.4 plugin seam: ops.v1 is built in; others (Prometheus, plain /healthz) can register so non-Terminus apps light up RICH panels too.

func Lookup

func Lookup(name string) Adapter

Lookup returns a registered adapter, defaulting to ops.v1.

type Config

type Config struct {
	Project      string
	Enabled      bool
	BaseURL      string
	SecretHeader string
	Secret       secret.Redacted
	HasSecret    bool
	OpsMode      string // auto | rich | basic
	BasePath     string
	Adapter      string
}

Config is one app's ops coordinates. The decrypted Secret lives only in memory (Redacted); it is never sent to the browser and never logged (plan §4.1/§5.5).

type ConfigStore

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

ConfigStore persists per-app ops config, encrypting the shared secret.

func NewConfigStore

func NewConfigStore(db *store.DB, cipher *secret.Cipher) *ConfigStore

NewConfigStore builds a store. cipher must be the master AES-256-GCM cipher.

func (*ConfigStore) DeleteApp

func (s *ConfigStore) DeleteApp(project string) error

DeleteApp removes an app's ops config (incl. the encrypted shared secret) and its recorded health-score history. Used by the app-delete teardown.

func (*ConfigStore) EnabledProjects

func (s *ConfigStore) EnabledProjects() ([]string, error)

EnabledProjects returns the projects with ops probing enabled.

func (*ConfigStore) Get

func (s *ConfigStore) Get(project string) (Config, bool, error)

Get returns an app's ops config, decrypting the secret. ok=false if none.

func (*ConfigStore) Set

func (s *ConfigStore) Set(project string, in SetInput) error

Set upserts an app's ops config, encrypting a provided secret.

func (*ConfigStore) Status

func (s *ConfigStore) Status(project string) (Status, bool)

Status returns the last recorded probe outcome. ok=false if never probed.

type Descriptor

type Descriptor struct {
	OpsInterfaceVersion string   `json:"opsInterfaceVersion"`
	Capabilities        []string `json:"capabilities"`
	BasePath            string   `json:"basePath"`
}

Descriptor is the public GET /.well-known/ops document (plan §4.1).

type Discovery

type Discovery struct {
	Mode         Mode
	Version      string
	Capabilities []string
	BasePath     string
	Note         string
}

Discovery is the outcome of the discovery phase (plan §4.1).

type Doer

type Doer interface {
	Get(ctx context.Context, base, relPath, secretHeader string, sec secret.Redacted) (*opsclient.Response, error)
	Post(ctx context.Context, base, relPath, secretHeader string, sec secret.Redacted, body []byte) (*opsclient.Response, error)
}

Doer is the minimal SSRF-safe client surface adapters use. *opsclient.Client satisfies it; tests inject a fake. (All host-pinning/rebind defense lives in the concrete client — this interface only decouples for testing.)

type Indicator

type Indicator struct {
	Name    string
	Status  string // up | down | degraded | unknown
	Message string
	Source  string // adapter name, e.g. "ops.v1"
}

Indicator is one normalized per-dependency health tile (plan §4.3).

type MetricGroup

type MetricGroup struct {
	Title string
	Items []MetricItem
}

MetricGroup is a titled card of metric items — the open-ended "monitor" unit. The app names the groups it wants (Database, Cache, Routes, System, Memory, …); Mooring renders each as a panel, so the set is NOT limited to a fixed schema.

type MetricItem

type MetricItem struct {
	Label  string
	Value  string
	Unit   string
	Status string // "" | up | down | degraded | unknown
}

MetricItem is one labeled value within a metric group (e.g. "Hit rate" = "94.2" "%"). Status is optional and only used to color the row (up/down/degraded).

type Mode

type Mode string

Mode distinguishes a RICH (contract-implementing) app from a BASIC one.

const (
	RICH  Mode = "rich"
	BASIC Mode = "basic"
)

type Prober

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

Prober runs discovery + probe for one app per call (the monitor drives the cadence: sequential + jittered, plan §4). It also persists the snapshot ring and performs server-side-proxied queue actions.

func NewProber

func NewProber(cs *ConfigStore, client Doer, db *store.DB, resolve ServiceResolver) *Prober

NewProber builds a Prober. client is the SSRF-safe outbound client; resolve rewrites a service-name base_url to the backing container's bridge IP (nil = literal-IP only).

func (*Prober) Probe

func (p *Prober) Probe(ctx context.Context, project string) (*Result, bool)

Probe returns the canonical ops Result for a project. ok=false means ops is not enabled for this app (it stays BASIC from Docker-derived data).

func (*Prober) ProbeTarget

func (p *Prober) ProbeTarget(ctx context.Context, project string, target Target, adapterName, mode string) *Result

ProbeTarget probes ONE ops Target directly (no DB-backed config, no snapshot ring), for per-service ops driven from the canonical mooring.yaml. mode is auto|rich|basic. Returns nil when mode is "basic" (ops disabled for the service).

func (*Prober) QueueAction

func (p *Prober) QueueAction(ctx context.Context, project, queue, action string) error

QueueAction performs a server-side, secret-bearing POST to an app's queue control endpoint (plan §4.2). The secret never reaches the browser.

func (*Prober) QueueActionTarget added in v0.4.1

func (p *Prober) QueueActionTarget(ctx context.Context, project string, target Target, queue, action string) error

QueueActionTarget runs a queue action against an EXPLICIT ops target — a single service's own ops endpoint — instead of the project-level ops config QueueAction uses. The per-service page renders queues discovered from the service's own ops interface (probeServiceOps → ProbeTarget), so its action buttons MUST POST to that same endpoint; routing them through the project target would hit the wrong process (or none, when an app has only per-service ops). The caller resolves the Target from the service's OpsInterface. Same action/queue validation and SSRF-safe client as QueueAction.

type Queue

type Queue struct {
	Name     string
	IsPaused bool
	Counts   []QueueCount
}

Queue is a normalized queue row (plan §4.2).

type QueueCount

type QueueCount struct {
	Name  string
	Value int64
}

QueueCount is one named counter within a queue.

type Result

type Result struct {
	Mode            Mode
	Version         string
	Capabilities    []string
	Indicators      []Indicator
	Queues          []Queue
	Metrics         []MetricGroup
	Snapshot        []SnapshotPoint
	AlertingCapable bool
	Err             string
}

Result is the canonical ops record attached to a service (plan §4.3: one record, distinguished by Mode + per-indicator Source).

func (Result) HealthScore

func (r Result) HealthScore() float64

HealthScore returns the fraction of indicators that are up (1.0 if none).

func (Result) IsRich

func (r Result) IsRich() bool

IsRich reports whether this is a RICH ops record (for template use).

type ServiceResolver

type ServiceResolver func(ctx context.Context, project, service string) (ip string, ok bool)

ServiceResolver maps (project, service) → a routable container bridge IP, via the read-only socket-proxy. ok=false when no running replica is found. It exists because the control plane is a host process that cannot resolve a compose service name (those live only on Docker's internal DNS) — so a base_url like http://api:3000 must be rewritten to the container's IP before the prober dials it. nil disables the rewrite (only literal-IP base_urls work then).

type SetInput

type SetInput struct {
	Enabled      bool
	BaseURL      string
	SecretHeader string
	NewSecret    *string
	OpsMode      string
	BasePath     string
	Adapter      string
}

SetInput is an operator's ops-config edit. NewSecret is tri-state: nil keeps the stored secret, "" clears it, any other value replaces it.

type SnapshotPoint

type SnapshotPoint struct {
	At    int64
	Value float64 // 0..1 fraction of dependencies up
}

SnapshotPoint is one health-score ring sample for the sparkline.

type Status

type Status struct {
	Mode        string
	Version     string
	LastProbeAt int64
	LastError   string
}

Status is the cached discovery/probe state for an app (review #10: surfaces the disc_* columns the prober records so the operator can see last outcome).

type Target

type Target struct {
	BaseURL      string
	SecretHeader string
	Secret       secret.Redacted
	BasePath     string // operator-configured fallback prefix; descriptor may override
}

Target is everything an adapter needs to reach an app's ops endpoints. The host is pinned by BaseURL; the secret travels server-side only (plan §4.1).

Jump to

Keyboard shortcuts

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