Documentation
¶
Overview ¶
Package api serves the controller's HTTP interface.
Per D1 it is designed UI-first: the API comes first, a TUI view second and a web UI third, and it has to already be the shape those need. That is a constraint on the endpoint set rather than a slogan — every screen a UI has is one request, and every action a user can take is one endpoint:
GET /healthz unauthenticated liveness
GET /api/v1/status the controller's own state
GET /api/v1/applications the list view
GET /api/v1/applications/{app} the detail view
GET /api/v1/applications/{app}/diff the diff view
GET /api/v1/applications/{app}/history the history view
POST /api/v1/applications/{app}/sync the sync button
GET /api/v1/events live updates, so nothing polls
Applications are read-only: they are declared in the app set, which is either mounted at deploy time or committed to git, and changing them means changing that file rather than posting to this API. The paths are nouns so that CRUD can be added later without any of them moving.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Controller ¶
type Controller interface {
Status() application.ControllerStatus
}
Controller reports the controller's own state, as distinct from the applications'. *appset.Loop implements it.
type Options ¶
type Options struct {
Authorizer authz.Authorizer
Log *slog.Logger
// Controller reports where the app set came from and whether it is loading.
// Absent, the status endpoint still answers — with the application count and
// an empty app-set mode, which is what "no app-set source is wired" looks
// like. A status endpoint that 404s is a status endpoint a monitor cannot
// tell from a dead controller.
Controller Controller
}
Options tune a Server. Every field has a working default.
type Reconciler ¶
type Reconciler interface {
Views() []application.View
View(app string) (application.View, bool)
Diffs(app string) ([]application.ReleaseDiff, error)
History(ctx context.Context, app string) (application.History, error)
SyncNow(ctx context.Context, app string) error
}
Reconciler is what the API serves. *reconcile.Reconciler implements it.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the HTTP interface. It is also a notify.Notifier: the event stream is fed by the same seam that feeds the log, which is why notify appends rather than replaces — a companion adding Slack must not silently kill the UI's live updates.
func New ¶
func New(rec Reconciler, o Options) *Server
New returns a Server over rec.
It does not register itself as a notifier. The caller does that, so that the notifier list is not appended to as a side effect of constructing a server — which in a test suite means one stream per test, all still subscribed.