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

httpapi

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: AGPL-3.0 Imports: 72 Imported by: 0

Documentation

Overview

Package httpapi is the REST surface: chi handlers and nothing else.

The API is the product (R-261). Handlers contain no business logic — it lives in a service layer under internal/core that both httpapi and mcp call. A capability that exists in one surface and not the other means someone put logic in a handler.

Index

Constants

View Source
const ACMEChallengePrefix = "/.well-known/acme-challenge/"

ACMEChallengePrefix is where a certificate authority asks for an HTTP-01 answer (RFC 8555 §8.3).

View Source
const IdempotencyHeader = "Idempotency-Key"

IdempotencyHeader is the canonical place to put a key.

View Source
const LoginPath = ReservedPrefix + "/login"

LoginPath is where the proxy sends someone who needs to sign in.

View Source
const MinPasscodeLength = 4

MinPasscodeLength is the shortest passcode accepted. Short on purpose — a passcode is typed by people it was read out to — and made safe by the attempt limit below rather than by length.

View Source
const RequestIDHeader = "X-Request-Id"

RequestIDHeader is returned on every response, including errors.

View Source
const ReservedPrefix = "/.pando"

ReservedPrefix is the one path that is Pando's on every hostname.

Its users are the sign-in page and the assets that page needs, reached from an app's hostname where every other path is the app's. Leading dot so it cannot collide with an app slug, which may not start with one.

View Source
const SSOBindCookie = "pando_sso_bind"

SSOBindCookie binds a redirect sign-in to the browser that started it (design 06 §3.2). In Pando's namespace, so the proxy strips it from every request an app receives (R-173).

View Source
const SessionCookie = "pando_session"

SessionCookie carries only the session ID (design 02 §2.7).

View Source
const VersionHeader = "Pando-Version"

VersionHeader carries the server's version to a signed-in caller (R-353).

Variables

This section is empty.

Functions

func AuditFunc

func AuditFunc(w interface {
	Write(ctx context.Context, e audit.Event) error
}) func(ctx context.Context, e audit.Event)

AuditFunc is how a core service that audits on its own records an event with the request ID the HTTP layer assigned, and logs rather than fails when the write does not land — the same rule as Server.audit.

func Authenticate

func Authenticate(a *Authenticator) func(http.Handler) http.Handler

Authenticate is middleware that attaches a principal to every request.

It never rejects: an unauthenticated request proceeds as anonymous and is rejected, or not, by the authorization check the handler performs. Rejecting here would create a second place where access is decided.

func Error

func Error(w http.ResponseWriter, r *http.Request, err error)

Error writes the error envelope (design 00 §3.2).

An error arriving without an envelope becomes INTERNAL and its detail is logged rather than returned: an unenveloped error is by definition one nobody wrote a user-facing message for, and guessing one would leak implementation detail into a response body.

func JSON

func JSON(w http.ResponseWriter, status int, body any)

JSON writes a successful response.

func Logger

func Logger(base *zap.Logger) func(http.Handler) http.Handler

Logger threads the request's logger through context, carrying request_id (design 00 §3.3). principal_id is added by the authentication middleware in phase 1, and app_id by handlers that resolve one.

func PrincipalFrom

func PrincipalFrom(ctx context.Context) authz.Principal

PrincipalFrom returns the request's principal, or anonymous.

func Reference

func Reference() reference.Document

Reference returns the assembled document, for the generator that writes `docs/` from it.

func RequestID

func RequestID(next http.Handler) http.Handler

RequestID stamps every request with an identifier and puts it in the context and the response. The error envelope carries it too, so a user reporting a failure hands over one string that finds the log line.

func RequestIDFrom

func RequestIDFrom(ctx context.Context) string

RequestIDFrom returns the request ID in ctx, or "".

func ReservedOrApp

func ReservedOrApp(pando, app http.Handler) http.Handler

ReservedOrApp serves Pando's reserved path, and everything else from app.

For the listeners that are not the front door: a port-mode app has a socket of its own whose every path belongs to that app (design 03 §4.2), so the router — and with it the sign-in page — is not in front of it. Without this the R-172 redirect lands back on the proxy and loops, which is the bug R-172 exists to fix, reintroduced one listener over.

Types

type ACMEChallenges

type ACMEChallenges interface {
	KeyAuthorization(ctx context.Context, token string) (string, bool, error)
}

ACMEChallenges answers HTTP-01 challenges for certificates Pando issues for the edge (R-169; notes-kubernetes-runtime-issue-72.md).

type AnonymousPolicy

type AnonymousPolicy interface {
	AllowsAnonymousGrant(ctx context.Context, withPasscode bool) error
	PublicSharing(ctx context.Context) (corepolicy.PublicSharing, error)
}

AnonymousPolicy gates sharing an app with everyone (R-076).

type AppHosts

type AppHosts interface {
	IsAppHostname(ctx context.Context, host string) (bool, error)
}

AppHosts answers whether a hostname belongs to an app.

Used only to decide whether the console or the proxy should handle a request (see consoleOrApp). It is not an authorization decision — the proxy still makes that — and a failure here falls back to the console, which is the safe direction: someone sees Pando instead of their app, rather than reaching an app without passing through the proxy.

type AuditArchives

type AuditArchives interface {
	List(ctx context.Context) ([]audit.ArchiveRecord, error)
	Open(ctx context.Context, archiveID string) (audit.ArchiveRecord, io.ReadCloser, error)
}

AuditArchives lists and opens audit archives.

type AuditReader

type AuditReader interface {
	List(ctx context.Context, q audit.Query) ([]audit.Record, error)
}

AuditReader queries the audit log.

type AuditSinks

type AuditSinks interface {
	Statuses(ctx context.Context) ([]auditstream.Status, error)
}

AuditSinks reports where each audit sink has got to (R-383).

type AuditStream

type AuditStream interface {
	ResolveCursor(ctx context.Context, s string) (audit.Cursor, error)
	Wait(ctx context.Context, q audit.StreamQuery, wait time.Duration, c clock.Clock) (audit.StreamPage, error)
	Export(ctx context.Context, q audit.StreamQuery, enc audit.Encoder, write func([]byte) error) (int, error)
	Oldest(ctx context.Context) (time.Time, bool, error)
}

AuditStream reads the audit log in commit order (R-381, R-387).

type Authenticator

type Authenticator struct {
	Sessions *state.Sessions
	Tokens   *state.Tokens
	Users    *state.Users
	Groups   interface {
		GroupsForUser(ctx context.Context, userID string) ([]string, error)
	}
}

Authenticator resolves credentials to a principal. Steps 1–3 of the evaluation order; steps 4–7 belong to the authorizer.

func (*Authenticator) Authenticate

func (a *Authenticator) Authenticate(r *http.Request) (authz.Principal, error)

Authenticate resolves a request to a principal, or to anonymous.

Anonymous is a principal, not an absence: R-075's anonymous grant is checked on the same path as any other, and there is no branch that skips the check.

func (*Authenticator) SessionPrincipal

func (a *Authenticator) SessionPrincipal(ctx context.Context, sessionID string) (authz.Principal, time.Time, error)

SessionPrincipal resolves a session cookie to its principal, and says when the session expires so a caller that keeps the answer keeps it no longer (the proxy's cache, issue #93). The session, its account and the account's groups are one query (Sessions.ActiveWithUser); groups are still read live on every call (R-079).

type DeployLogOwner

type DeployLogOwner func(ctx context.Context, deploymentID string) (string, error)

DeployLogOwner says where a deploy's live log is: the base URL of the replica running it, or "" when that is this replica or no live replica holds it (issue #72). Nil with one replica.

type DetectionQueue

type DetectionQueue interface {
	Enqueue(ctx context.Context, appID string) (state.Detection, error)
}

DetectionQueue queues a detection to run on whichever replica has room (detection.Queue). Enqueue returns the detection as queued, read before any replica can claim it: a detection that fails at once would otherwise finish between queueing it and reading it back, and a 202 would report the outcome of work it says has only begun.

type Detector

type Detector interface {
	Detect(ctx context.Context, appID string) (state.Detection, error)

	// Check refuses what Detect would refuse before it starts, without
	// writing anything.
	Check(ctx context.Context, appID string) error

	// Revise changes a finished proposal as a person asked, through the AI
	// adapter, and records the exchange on it (R-336).
	Revise(ctx context.Context, appID, message string) (state.Detection, error)

	// Rebuild builds the proposal's image again, in the background, when
	// what it would build has changed — an answer the build waited on — so
	// the plan shows the score of what will run (R-311). True when it
	// started.
	Rebuild(ctx context.Context, appID string) (bool, error)
}

Detector runs detection for an app.

An interface rather than the concrete job, so the HTTP layer does not have to know how source is fetched or which adapters are involved — and so a test can assert what the endpoints do without a network, a builder or a daemon.

type FailedAttempts

type FailedAttempts interface {
	Recent(ctx context.Context, key string, window time.Duration) (int, error)
	// Wait is how long until the oldest failure within window leaves it.
	Wait(ctx context.Context, key string, window time.Duration) (time.Duration, error)
	Record(ctx context.Context, key string, window time.Duration) error
	Clear(ctx context.Context, key string) error
}

FailedAttempts counts wrong guesses at a passcode (R-075a) or a password (R-404), by a key that says which and whose.

Shared by every replica in production (state.FailedAttempts): a count kept in one process's memory gave an attacker one allowance per replica behind the load balancer, and a fresh one whenever a replica restarted (issue #72).

type Health

type Health interface {
	Ping(ctx context.Context) error
}

Health reports whether a dependency is reachable.

type InstallVerbs

type InstallVerbs interface {
	InstallVerbsFor(ctx context.Context, p authz.Principal) ([]string, error)
}

InstallVerbs reports the installation-wide verbs a principal holds.

Read by GET /me so the console can decide what to offer (R-265) from the server's answer rather than by inferring administration from some other response. Inference is what it did before install verbs existed — it treated a non-empty GET /apps as "this person is an administrator" — and that is a second opinion about authorization living in a client (R-261).

type PolicyDocument

type PolicyDocument interface {
	Load(ctx context.Context) (corepolicy.Document, error)
	Save(ctx context.Context, doc corepolicy.Document, updatedBy string) error
}

PolicyDocument reads and writes host policy.

type RegistryCredentials

type RegistryCredentials interface {
	SaveCredential(ctx context.Context, appID string, c oci.Credential) error
	RemoveCredential(ctx context.Context, appID string) error
	DescribeCredential(ctx context.Context, appID string) (oci.CredentialSummary, bool, error)
}

RegistryCredentials keeps the credential an image app's image is pulled with (oci.Images).

type Security

type Security interface {
	Report(ctx context.Context, appID, specID string) (security.Report, error)
	Scan(ctx context.Context, req api.ScanRequest, principal audit.Event) (state.Scan, error)
	Place(ctx context.Context, scores map[string]security.Scores) (map[string]security.Placed, error)
}

Security is what the API needs from the security service. Three calls, so a handler cannot reach past them into policy or the scan store.

type Server

type Server struct {
	Logger *zap.Logger
	DB     Health

	Identity api.IdentityAdapter
	Users    *state.Users

	// IDP is external identity: providers, redirect sign-in, linking and
	// SCIM (issue #51). Nil leaves password sign-in the only way in.
	IDP      *idp.Service
	Sessions *state.Sessions
	Tokens   *state.Tokens
	Apps     *state.Apps
	Volumes  *state.Volumes
	Authz    *authz.Authorizer
	Auditor  *audit.Writer
	Authent  *Authenticator

	Registry *api.Registry
	Adapters *state.Adapters

	// Observations shares the runtime's answers for /status and /usage between
	// requests asking at the same moment (issue #72). Authorization is checked
	// before it is consulted, every request. Nil asks the runtime every time.
	Observations *observe.Cache

	// Address resolves changes to where an app is reached (R-162, R-163).
	// Nil means the address cannot be changed after configuration.
	Address *address.Service

	// Edges reports whether each routing adapter's edge is running (R-174).
	// Nil means no adapter's edge is reported.
	Edges *edge.Service

	// AIFunctions is which AI adapter handles each AI function (R-259). Nil
	// means the endpoints say assignment is not set up.
	AIFunctions *assist.Assignments

	// Assist runs the administrative AI functions. Nil means the endpoints
	// say AI assistance is not set up.
	Assist *assist.Service

	// TeardownNow asks for a deleted app's bundle to be torn down now rather
	// than at the collector's next pass. Nil leaves it to the pass.
	TeardownNow func()

	// AdapterKinds are the kinds of adapter this build can run, with the
	// settings each takes (api.KindInfo), for GET /adapters/kinds.
	AdapterKinds []api.KindInfo

	// AdapterCredentials holds adapters' credentials encrypted (O-20). Written
	// by POST /adapters, never read back by any handler.
	AdapterCredentials *state.AdapterCredentials

	// Reconciles is the loop's bookkeeping. The lifecycle handlers touch it
	// for one reason: a person starting an app Pando gave up on is the human
	// intervention R-151 requires, and the failure count has to be cleared for
	// the loop to look at the app again.
	Reconciles  *state.Reconciles
	Planner     *planner.Planner
	Allocations *state.Allocations
	Deployments *state.Deployments

	// Capacity is GET /capacity's runtime readings, refreshed in the
	// background (issue #72).
	Capacity *capacity.Snapshots

	// Security scores apps and answers where one stands (R-310). Nil on an
	// installation with no scanner, where the endpoints say so rather than
	// returning a zero.
	Security Security
	Deployer *deploy.Runner

	// Approvals starts every deploy, and asks for, records and acts on the
	// approval of those that need one (R-154 – R-159).
	Approvals *approval.Service

	// AutoDeploy reads and changes automatic deploy settings and takes the
	// webhooks git hosts send (R-141, R-142).
	AutoDeploy *autodeploy.Service

	// Subscriptions manages event subscriptions and notification
	// preferences (issue #50). Nil answers that they are unavailable.
	Subscriptions *subscription.Service

	// Inbox is the console notifications a person reads (R-377).
	Inbox *subscription.Inbox

	// Notifier sends Pando's own notifications to the people they name, as
	// their preferences allow. Optional.
	Notifier interface {
		Notify(ctx context.Context, n api.Notification) error
	}

	Logs *deploy.LogStore

	// LogStreams shares one live runtime log stream per app part between
	// everyone on this replica watching it (O-51). Nil makes the following
	// endpoints answer that live logs are not available.
	LogStreams *logstream.Hub
	// DeployLogReauthEvery is how often a connected deploy-log stream checks
	// the viewer's access again (R-048). logstream.DefaultReauthEvery when
	// zero; tests shorten it.
	DeployLogReauthEvery time.Duration

	// QueuePollEvery is how often a queued deploy's log stream reads its
	// place in the queue (issue #93). A second when zero.
	QueuePollEvery time.Duration

	// RelayTransport carries a deploy-log request to the replica holding the
	// log. http.DefaultTransport when nil.
	RelayTransport http.RoundTripper
	// LogOwner finds the replica running a deploy, so its live log can be
	// read from any replica (issue #72). Nil with one replica.
	LogOwner DeployLogOwner
	// FailedAttempts is the shared count behind the limits on guessing a
	// passcode (R-075a) and a password (R-404). In memory, for one process,
	// when nil.
	FailedAttempts FailedAttempts

	Secrets    *state.Secrets
	Detections *state.Detections

	// Clock times a detection wait and how long one has been running. Nil is
	// the system clock.
	Clock clock.Clock

	// Detector runs detection for an app. Nil on an install with no builder or
	// runtime configured, in which case the detection endpoints say so rather
	// than returning an empty proposal — R-106's shape: with nothing
	// configured, each step degrades to a question, not a dead end.
	Detector Detector

	// DetectionQueue is where a detection the API starts is queued (issue
	// #72, O-32). Nil, with a Detector, means detection is not started on
	// create and a re-run is refused as not configured.
	DetectionQueue DetectionQueue

	// Sources keeps an uploaded source (R-262) and fetches an app's source for
	// a scan on request.
	Sources source.Sources

	// SourceConnections is the install's source connections (R-091, issue
	// #127): which one a new app's repository is read with, and the
	// repositories each can list. Nil reads every repository anonymously and
	// answers the /sources routes with an error.
	SourceConnections *sourceconn.Service

	// Images keeps the credential an image app's image is pulled with (issue
	// #41). Nil on an install that cannot store one, where setting one says so.
	Images RegistryCredentials

	// ImageRegistries builds the install's image registry adapters (R-252,
	// issue #153), which are configured with POST /adapters like any adapter
	// but built from their rows each time they are used, so saving one needs
	// no restart. Nil checks nothing before saving one.
	ImageRegistries *imageregistry.Service

	// Defaults fills in what an author left out of a spec — the install's
	// adapters, its routing shape, and the retention caps R-211 and R-223 set.
	// Nil means a hand-written spec is taken exactly as written, which is how
	// it behaved before and is wrong: an app with no log cap is an app that can
	// fill the host.
	Defaults SpecDefaults

	// Policy is host policy. Nil until phase 3 configures it, in which case the
	// source allowlist check (R-092) is skipped rather than assumed to pass —
	// the call site says so explicitly.
	Policy SourcePolicy

	// ExternalURL is how a browser reaches this installation, when something
	// other than Pando terminates TLS. It decides one thing: whether the
	// session cookie is marked Secure (O-19). Nil falls back to the request,
	// which is right when Pando serves TLS itself and on a localhost install.
	ExternalURL *url.URL

	// Minter publishes the assertion signing keys at /.well-known/jwks.json.
	Minter     *assertion.Minter
	Grants     *state.Grants
	HostPolicy AnonymousPolicy

	// Verbs answers "what may this principal do install-wide" for GET /me.
	// Nil leaves the list empty, which denies nothing — every install-level
	// endpoint checks the verb itself — but it does hide the admin entry.
	Verbs InstallVerbs

	// PolicyStore reads and writes the host policy document (R-274). Distinct
	// from HostPolicy above, which *evaluates* it: one is the document, the
	// other is the decision, and an endpoint that edits the document has no
	// business asking the evaluator anything.
	PolicyStore PolicyDocument

	// PolicyOverlay is the host policy fields set in the startup config
	// (R-271). PolicyStore already reads through it; this is for refusing a
	// change to one of them and for saying where each was set. Nil means none.
	PolicyOverlay *corepolicy.Overlay

	// StartedAt is when this process started. An adapter configured after it
	// is saved but not running, since adapters are loaded at startup (R-253).
	StartedAt time.Time

	// Restart asks the server to shut down cleanly and start again, loading
	// the adapters and the configuration file afresh. It returns at once; the
	// restart follows the response. Nil means this process cannot restart
	// itself, and POST /restart says so.
	Restart func()

	// Startup is the configuration Pando started with, for GET /config: every
	// non-secret setting and where it came from. Nil in tests that do not set it.
	Startup *config.Config

	// AuditLog reads the append-only log (R-227). Nil on an install where the
	// endpoint should 500 rather than quietly return nothing — an empty audit
	// log and an unreadable one are very different answers.
	AuditLog AuditReader

	// AuditArchives lists and serves the months retention has archived
	// (R-347). Nil answers an empty list: an install with nothing archived
	// and one that cannot archive look the same from here, and both are true.
	AuditArchives AuditArchives

	// AuditStream reads the log in commit order, for the stream and exports
	// (R-381, R-387). AuditEncoders turn native lines into other formats, by
	// name — "ocsf" (R-384). AuditSinks reports each audit sink's delivery
	// (R-383). AuditReads decides when a stream read is itself audited
	// (R-388).
	AuditStream   AuditStream
	AuditEncoders map[string]audit.Encoder
	AuditSinks    AuditSinks
	AuditReads    *audit.ReadThrottle

	// AuditSinkCheck configures an audit sink as it would be saved, so one
	// its adapter refuses is refused by POST /adapters (R-382).
	AuditSinkCheck interface {
		Validate(ctx context.Context, id, kind string, config json.RawMessage, given map[string]secret.Value) error
	}

	// Updates is whether a newer Pando is released (R-351). Nil answers that
	// the check is not running, which is true.
	Updates Updates

	// Upgrades is the in-place upgrade (R-355 – R-362). Nil answers that it
	// is not set up.
	Upgrades Upgrades

	// Version is this binary's version, sent to signed-in callers as
	// Pando-Version so a CLI can tell it is out of step (R-353). Never to an
	// anonymous one: a version is a map of which advisories apply.
	Version string

	// Backups records what has been backed up; Backup does the backing up
	// (R-212). Two fields because they are two concerns: the record has to
	// survive the thing it records, which is R-204's whole point.
	Backups *state.Backups
	Backup  *backup.Service

	// Groups and Roles back the identity endpoints (R-078, R-082).
	Groups *state.Groups
	Roles  *state.Roles

	// AppLimits decides how many apps a person may own, and AppLimitStore
	// holds the values set on users and groups (R-244). Nil AppLimits is no
	// limit.
	AppLimits     *applimit.Service
	AppLimitStore *state.AppLimits

	// IdleSettings reads and changes an app's idle settings (R-397).
	IdleSettings *idle.Settings

	// BundleSource supplies what goes into a backup. Held separately from
	// Backups because one records what was taken and the other reads what is
	// being taken — and the record has to outlive the thing (R-204).
	BundleSource *state.BundleSource

	// Idempotency deduplicates retried infrastructure-creating requests. Nil
	// disables replay rather than failing: the cost is a possible duplicate,
	// and refusing to deploy because a deduplication table is missing would be
	// a worse outcome than deploying twice.
	Idempotency *state.Idempotency

	// Console serves the embedded UI on Pando's own paths. Nil when the binary
	// was built without it, in which case those paths 404 like any other and
	// the API is unaffected — the API is the product (R-261), and the console
	// is one of its clients.
	Console http.Handler

	// AppHosts tells the console handler when a request belongs to an app
	// instead. Nil means the console answers on every hostname, which is
	// correct for a path-addressed install and wrong for a subdomain one.
	AppHosts AppHosts

	// ACMEChallenges answers HTTP-01 challenges for the certificates Pando
	// issues for the edge, on every hostname. Nil answers none.
	ACMEChallenges ACMEChallenges

	// AppProxy serves every request to every app (R-023). Mounted last, as the
	// catch-all, so Pando's own routes are reachable and everything else goes
	// through enforcement. There is no path that reaches an app without it.
	AppProxy http.Handler

	// ClientAddr decides which address each request came from for the audit
	// log (R-380). The zero value records the connecting peer.
	ClientAddr clientaddr.Trusted
	// contains filtered or unexported fields
}

Server holds what the HTTP surface needs.

Handlers contain no business logic (R-261). Everything lives in a service layer under internal/core that both this package and internal/mcp call — a capability in one surface and not the other means logic leaked into a handler.

func (*Server) Routes

func (s *Server) Routes() http.Handler

Routes builds the router.

type SourcePolicy

type SourcePolicy interface {
	AllowsSource(ctx context.Context, src spec.Source) error
}

SourcePolicy gates where apps may be created from (R-092).

Evaluated before anything touches disk. There is nothing to clone yet in this phase, but the check belongs at creation and putting it here now means the ordering is already right when cloning arrives in phase 6.

type SpecDefaults

type SpecDefaults interface {
	Defaults(ctx context.Context) spec.Defaults
}

SpecDefaults supplies the install's defaults for a spec.

type Updates

type Updates interface {
	Status(ctx context.Context) (update.Status, error)
	// CheckNow asks GitHub now rather than at the next tick (R-349).
	CheckNow(ctx context.Context) (update.Status, error)
}

Updates reports what the update check knows.

type Upgrades

type Upgrades interface {
	PlanFor(ctx context.Context, version string) (upgrade.Plan, error)
	Start(ctx context.Context, p authz.Principal, req upgrade.Request) (upgrade.Attempt, error)
	Last(ctx context.Context) (*upgrade.Attempt, error)
}

Upgrades plans, starts and reports in-place upgrades.

type VolumeUsage

type VolumeUsage struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Path  string `json:"path"`
	Bytes int64  `json:"bytes"`
}

VolumeUsage is one volume a part mounts and how much it holds; -1 when unknown.

type WorkloadStatus

type WorkloadStatus struct {
	Name    string `json:"name"`
	Primary bool   `json:"primary"`

	Present bool `json:"present"`
	Running bool `json:"running"`

	// Restarting is the crash loop, which is the thing somebody looking at a
	// degraded app most needs to see. A container that exits and is restarted
	// by the runtime is "running" at almost every instant Pando looks at it.
	Restarting   bool `json:"restarting"`
	RestartCount int  `json:"restart_count"`

	// Healthy is null when the workload declares no health check: no signal is
	// not the same as unhealthy (R-221).
	Healthy  *bool  `json:"healthy"`
	ExitCode *int   `json:"exit_code,omitempty"`
	Image    string `json:"image,omitempty"`

	StartedAt *time.Time `json:"started_at,omitempty"`
}

WorkloadStatus is one part of an app, as it is right now.

The adapter's own struct used to be serialized straight out, which put Go field names on the wire — `Running`, `RestartCount` — in an API that is snake_case everywhere else, and left the console reading a shape nothing documented. It is the product (R-261), so it gets a type.

type WorkloadUsage

type WorkloadUsage struct {
	Name    string `json:"name"`
	Primary bool   `json:"primary"`
	Running bool   `json:"running"`

	CPUMillis      int   `json:"cpu_millis"`
	CPULimitMillis int   `json:"cpu_limit_millis"`
	MemoryBytes    int64 `json:"memory_bytes"`
	MemoryLimit    int64 `json:"memory_limit_bytes"`

	// DiskBytes is written outside the part's volumes; -1 when unknown.
	DiskBytes int64         `json:"disk_bytes"`
	Volumes   []VolumeUsage `json:"volumes"`
}

WorkloadUsage is one part of an app and what it is using now (R-245). Limits of 0 mean none: the part may use what the host has, and HostCPUMillis and HostMemoryBytes on the reading say how much that is.

Jump to

Keyboard shortcuts

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