main bac21c6

apps.go RawHistoryFolder

1package in
2
3import (
4	"context"
5	"time"
6
7	"github.com/bnema/gordon/internal/domain"
8)
9
10// AppService is the driving port for the v3 app lifecycle:
11// apply + reads (list/show/diff), lifecycle verbs
12// (deploy/stop/start/restart/remove), op recovery by idempotency key,
13// and service-scoped secret value writes.
14//
15// The port owns its view structs and speaks domain types only — never
16// adapter DTOs. Secret VALUES cross SetSecrets by necessity (that is the
17// write path); every other method carries names, digests, and ids only.
18//
19// This is preparation: the interface is frozen here, unreachable.
20// The admin handler and the service implementation wire in at cutover;
21// until then no caller exists.
22type AppService interface {
23	// Apply validates a manifest spec and persists it as desired state,
24	// or validates without persistence when dryRun is set. source is the
25	// raw manifest bytes (hashed for audit, never re-read).
26	Apply(ctx context.Context, spec domain.AppSpec, source []byte, dryRun bool) (*AppApplyResult, *AppDryRunResult, error)
27
28	// List returns one summary per known app.
29	List(ctx context.Context) ([]AppSummary, error)
30
31	// Show inspects desired + active + intent + last op for one app.
32	Show(ctx context.Context, app string) (*AppDetail, error)
33
34	// Diff returns the normalized desired-vs-active diff for one app.
35	Diff(ctx context.Context, app string) (domain.AppDiff, error)
36
37	// Deploy activates a captured revision (empty revision means the
38	// desired head). An empty service targets every service, which a
39	// multi-service app accepts only with all set (domain.ErrAppServiceScope).
40	Deploy(ctx context.Context, app, revision, service string, all bool, idempotencyKey string) (*domain.AppOperation, error)
41
42	// Stop persists the durable stopped intent and stops exact containers.
43	Stop(ctx context.Context, app, idempotencyKey string) (*domain.AppOperation, error)
44
45	// Start clears the stopped intent and ensures running from active.
46	Start(ctx context.Context, app, idempotencyKey string) (*domain.AppOperation, error)
47
48	// Restart restarts from pinned digests without re-resolution.
49	// An empty service targets every service, which a multi-service app
50	// accepts only with all set (domain.ErrAppServiceScope).
51	Restart(ctx context.Context, app, service string, all bool, idempotencyKey string) (*domain.AppOperation, error)
52
53	// Remove withdraws workloads; volumes and secrets are retained as
54	// owned orphans and the name stays reserved.
55	Remove(ctx context.Context, app, idempotencyKey string) (*domain.AppOperation, error)
56
57	// OperationByKey recovers an ambiguous mutation outcome by the
58	// client-supplied idempotency key.
59	OperationByKey(ctx context.Context, app, key string) (*domain.AppOperation, error)
60
61	// ListSecrets returns metadata-only desired and active registrations.
62	ListSecrets(ctx context.Context, app, service string) ([]AppSecretMetadata, error)
63
64	// SetSecrets writes secret values for pre-registered names in one
65	// service. service is required; every key must already exist in
66	// desired or active state.
67	SetSecrets(ctx context.Context, app, service string, values map[string]string) error
68
69	// DeleteSecret removes one secret value. Refused when referenced.
70	DeleteSecret(ctx context.Context, app, service, key string) error
71}
72
73// AppApplyResult describes one accepted (or no-op) apply.
74// AppSecretMetadata is a secret registration without its value.
75type AppSecretMetadata struct {
76	Service  string
77	Key      string
78	Name     string
79	Source   string
80	Presence string
81}
82
83type AppApplyResult struct {
84	App               string
85	FormerRevision    string
86	ResultingRevision string
87	Noop              bool
88	Pending           bool
89	Diff              domain.AppDiff
90	IntentID          string
91}
92
93// AppDryRunResult describes validation without persistence.
94// The resulting revision is a preview only and is never stored.
95type AppDryRunResult struct {
96	App   string
97	Valid bool
98	Diff  domain.AppDiff
99}
100
101// AppSummary is one row of the app list: revisions, acceptance status,
102// and the latest recorded outcome.
103type AppSummary struct {
104	App           string
105	Desired       string
106	DesiredStatus string
107	Active        string
108	Converged     bool
109	// Pending reports desired state that the active revision has not
110	// reached yet. It is derived from desired vs ACTIVE, never from a
111	// journal.
112	Pending     bool
113	Stopped     bool
114	LastOutcome string
115}
116
117// AppServiceView is one service's effective state for inspection.
118// Digest and container are ids, never secret values.
119type AppServiceView struct {
120	EffectiveRevision string
121	Digest            string
122	Container         string
123	RestartUnsafe     bool
124}
125
126// AppRetainedView lists the resources the app owns and would retain on
127// removal: runtime volume names, secret paths, and pinned image
128// references. It never carries secret values.
129type AppRetainedView struct {
130	Volumes []string
131	Secrets []string
132	Images  []string
133}
134
135// AppDetail inspects desired + active + intent + ownership + last op for
136// one app.
137type AppDetail struct {
138	App               string
139	DesiredRevision   string
140	DesiredStatus     string
141	Pending           bool
142	Converged         bool
143	ConvergedRevision string
144	Services          map[string]AppServiceView
145	Stopped           bool
146	Retained          AppRetainedView
147	LastOp            string
148	LastOpKind        string
149	LastOutcome       string
150	LastOpStartedAt   time.Time
151}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close