app_network.go RawHistoryFolder

1package domain
2
3import (
4	"crypto/sha256"
5	"fmt"
6	"strings"
7)
8
9// DefaultNetworkPrefix applies when no installation prefix is configured.
10const DefaultNetworkPrefix = "gordon"
11
12// Network roles identifying what a Gordon-managed network is for.
13const (
14	// AppNetworkRolePrivate marks the incarnation-owned network of one app.
15	// Containers of different apps never share it.
16	AppNetworkRolePrivate = "private"
17	// AppNetworkRoleShared marks a declared cross-app shared network.
18	AppNetworkRoleShared = "shared"
19)
20
21// Network ownership label keys. Management follows the same fail-closed
22// rule as volumes: an existing network is reused only when its labels
23// prove Gordon ownership; anything else is refused, never adopted.
24const (
25	// LabelAppNetworkRole carries AppNetworkRolePrivate/AppNetworkRoleShared.
26	LabelAppNetworkRole = "gordon.app.network.role"
27	// LabelAppNetworkName carries the declared shared-network name, so a
28	// derived runtime name can be tied back to exactly one declaration.
29	LabelAppNetworkName = "gordon.app.network.name"
30)
31
32// NormalizeNetworkPrefix returns the configured prefix or the default.
33func NormalizeNetworkPrefix(prefix string) string {
34	if strings.TrimSpace(prefix) == "" {
35		return DefaultNetworkPrefix
36	}
37	return prefix
38}
39
40// AppPrivateNetworkName derives the incarnation-owned network name from
41// the app's stable internal UUID. The name is deterministic so recovery
42// reattaches the same network, and it never derives from the public name:
43// removing and re-adding an app under the same name yields a different
44// incarnation UUID and therefore a different network.
45func AppPrivateNetworkName(prefix, appID string) string {
46	sum := sha256.Sum256([]byte(appID))
47	return fmt.Sprintf("%s-app-%x", NormalizeNetworkPrefix(prefix), sum[:6])
48}
49
50// AppSharedNetworkName derives the Gordon-managed name of a declared
51// shared network. Deriving from the declaration means two apps that
52// declare the same name join the same network, while a foreign network
53// that happens to use the name is never mistaken for it.
54func AppSharedNetworkName(prefix, declared string) string {
55	sum := sha256.Sum256([]byte(declared))
56	return fmt.Sprintf("%s-shared-%x", NormalizeNetworkPrefix(prefix), sum[:6])
57}
58
59// AppPrivateNetworkLabels is the ownership label set stamped on an
60// incarnation-owned network.
61func AppPrivateNetworkLabels(app, appID string) map[string]string {
62	labels := map[string]string{
63		LabelManaged:        "true",
64		LabelApp:            app,
65		LabelAppNetworkRole: AppNetworkRolePrivate,
66	}
67	if appID != "" {
68		labels[LabelAppID] = appID
69	}
70	return labels
71}
72
73// AppSharedNetworkLabels is the ownership label set stamped on a declared
74// shared network. A shared network belongs to the installation, not to a
75// single app, so it carries no app identity.
76func AppSharedNetworkLabels(declared string) map[string]string {
77	return map[string]string{
78		LabelManaged:        "true",
79		LabelAppNetworkRole: AppNetworkRoleShared,
80		LabelAppNetworkName: declared,
81	}
82}
83
84// NetworkOwnedBy reports whether an observed network's labels prove the
85// exact expected Gordon ownership. Extra labels are tolerated; every
86// expected key must be present and equal, so a network created with
87// different ownership (or none) is never adopted.
88func NetworkOwnedBy(observed, expected map[string]string) bool {
89	if len(expected) == 0 {
90		return false
91	}
92	for key, want := range expected {
93		if observed[key] != want {
94			return false
95		}
96	}
97	return true
98}
99
100// AppServiceSharedNetworks returns the declared shared-network memberships
101// that the named service joins, preserving declaration order and
102// de-duplicating by network name.
103func AppServiceSharedNetworks(spec AppSpec, service string) []AppSharedNetwork {
104	var memberships []AppSharedNetwork
105	seen := map[string]struct{}{}
106	for _, network := range spec.Networks {
107		if _, ok := seen[network.Network]; ok {
108			continue
109		}
110		for _, member := range network.Services {
111			if member != service {
112				continue
113			}
114			seen[network.Network] = struct{}{}
115			memberships = append(memberships, network)
116			break
117		}
118	}
119	return memberships
120}

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