carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1{{/* /fleet/architecture (archpage.go): the deployment's map — how a request
2 reaches a process, drawn over the estate the account is carrying.
3
4 Everything here is server-rendered: the diagram is inline SVG built in
5 Go (archlayout.go's RenderArchSVG) so the picture is deterministic and
6 testable as a whole, and the page works with JS off because there is no
7 JS. Every block below is independently guarded — the inventory, the
8 boxes, the resource tables and the failed-reads footer each appear only
9 when their own read produced something, so one bad read costs its own
10 section and never the page. */}}
11{{define "architecture"}}{{template "top" .}}
12<h1>Architecture</h1>
13{{if .Flash}}<p class="banner">{{.Flash}}</p>{{end}}
14{{if .FlashErr}}<p class="banner error">{{.FlashErr}}</p>{{end}}
15{{/* The page's only control, at the top with the inventory timestamp it acts
16 on. It used to sit below every resource table, several thousand pixels
17 from the line telling you the inventory was stale (discussion #9).
18 Outside the {{with .Arch}} below on purpose: a page that could not read
19 an inventory is exactly the page whose refresh button has to still be
20 there. */}}
21<form method="post" action="/fleet/architecture/refresh">
22 <input type="hidden" name="csrf" value="{{.CSRF}}">
23 <button type="submit">Refresh inventory</button>
24</form>
25{{/* A firing alarm, said where the reader already is. The marks ride the
26 nodes they watch, which is right, but that put them off to the right of
27 a drawing wider than the window and left the Alarms table thousands of
28 pixels below — so the page could know something was on fire and show
29 nothing above the fold. Spans both estates: the reader wants to know
30 something is firing, not which half of the page to look in. */}}
31{{with .Arch}}{{if .Firing}}
32<p class="banner error">{{icon "triangle-alert"}}
33 {{len .Firing}} alarm{{if ne (len .Firing) 1}}s{{end}} firing:
34 {{range $i, $a := .Firing}}{{if $i}}, {{end}}{{$a}}{{end}}
35</p>
36{{end}}{{end}}
37{{with .Arch}}
38{{/* The three missing states are named apart, never collapsed into one
39 "nothing here": never-taken, ungranted and unreadable are three
40 different facts about the deployment and only one of them is normal. */}}
41{{if .Missing}}
42<p class="banner">{{icon "triangle-alert"}}
43 {{if eq .Missing "never"}}No inventory has been taken yet — the first pass runs within the hour. The boxes below are what CARLOS itself reports.
44 {{else if eq .Missing "ungranted"}}This deployment has no infrastructure read grant, so the cloud half of this page is unavailable. The boxes below are what CARLOS itself reports.
45 {{else}}The inventory snapshot could not be read. The boxes below are what CARLOS itself reports.{{end}}
46</p>
47{{else}}
48<p class="small">Estate {{.Account}} &middot; inventoried {{fmtTime .TakenAt}}</p>
49{{end}}
50
51{{/* Two estates, one above the other, never one picture with a line
52 through it. The account holds a CARLOS deployment and, very often,
53 whatever was already there — Tito's own account carries a Kubernetes
54 estate CARLOS deliberately sits beside so it can reach the legacy
55 database. Drawn together that is one unreadable graph; drawn apart it
56 is two readable ones.
57
58 NOTHING IS FILTERED. Every node and every resource on the old single
59 page is still here, under one of the two headings — the split groups,
60 it does not hide (archestate.go). */}}
61<h2>CARLOS</h2>
62{{/* One picture per region, stacked down the page. Region is the
63 STRUCTURE here, not a word on a card: a box is the only thing on this
64 diagram that is really in a region, and everything else is drawn in the
65 band of the box it reaches (archregion.go). That is also what keeps
66 each picture inside the 64rem column — a band is at most four nodes
67 wide — so this page scrolls down and never across. */}}
68{{range .CARLOS.Bands}}
69<h4 class="archband">{{.Label}}</h4>
70<div class="archwrap">{{.SVG}}</div>
71{{end}}
72
73<h3>Boxes</h3>
74{{range .Boxes}}
75<section class="archbox">
76 <h4>{{.Label}}{{if .Region}} <span class="small">{{.Region}}</span>{{end}}</h4>
77 {{/* Each fact is its own span and the separators are drawn by CSS
78 (.fact + .fact::before), because every one of these is independently
79 absent — a deployment with no rate card entry has no size and no
80 price, and a hand-written separator would leave a dangling middot on
81 the commonest page of all. */}}
82 <p class="small">
83 {{if .InstanceType}}<span class="fact">{{.InstanceType}}</span>{{end}}
84 {{if .State}}<span class="fact">{{.State}}</span>{{end}}
85 {{if .Cores}}<span class="fact">{{printf "%.0f" .Cores}} cores</span>{{end}}
86 {{if .MemGB}}<span class="fact">{{printf "%.0f" .MemGB}} GB</span>{{end}}
87 {{if .DiscoveredDiskGB}}<span class="fact">{{printf "%.0f" .DiscoveredDiskGB}} GB disk</span>{{end}}
88 {{if .USDMonth}}<span class="fact">${{printf "%.0f" .USDMonth}}/mo</span>{{end}}
89 {{if not .CloudID}}<span class="fact">no cloud machine (bring-your-own box)</span>{{end}}
90 </p>
91 <p class="small">Apps: {{if .Apps}}{{range .Apps}}<code>{{.}}</code> {{end}}{{else}}none reported{{end}}</p>
92 {{/* The counts come from the fleet aggregate and nowhere else, so a box
93 that read never described has NO counts — printing three zeroes here
94 would state a read that never happened, beside an awake/asleep that
95 correctly says it does not know. */}}
96 <p class="small">
97 {{if .CountsKnown}}static {{.Static}} &middot; resident {{.Resident}} &middot; hibernating {{.Hibernating}} &middot;
98 awake {{intOrDash .Awake}} &middot; asleep {{intOrDash .Asleep}}
99 {{else}}counts unknown{{end}}
100 {{with .Release}}&middot; <code>{{.}}</code>{{end}}
101 </p>
102 {{if .Stale}}<p><span class="chip chip-stale">dark{{if .Dark}} {{.Dark}}{{end}}</span></p>{{end}}
103 {{/* Drift is where the rate card and the estate disagree — a fact to
104 watch, not an outage, so it wears chip-stale's bordered warn tone
105 rather than a filled marker. */}}
106 {{range .Drift}}<p><span class="chip chip-stale">{{.}}</span></p>{{end}}
107</section>
108{{else}}
109{{/* An empty box list has two causes and they are not the same fact: no box
110 has reported, or the read that would have listed them failed. Saying the
111 first when the second happened is the confident negative claim this page
112 exists to avoid — so the handler carries which one it is. */}}
113{{if $.ArchBoxesUnread}}<p>The box list could not be read — this is not a claim that the deployment has no boxes.</p>
114{{else}}<p>No box has reported to this deployment yet.</p>{{end}}
115{{end}}
116
117{{range .CARLOS.Groups}}
118<h3>{{.Title}}</h3>
119{{template "archtable" .}}
120{{end}}
121
122{{/* The second bank is named for what is TRUE of it in every deployment,
123 not for what it happens to be here. This console serves every CARLOS
124 estate; "legacy" describes Tito's Kubernetes cluster and would be
125 wrong, and unexplained, on the next account. */}}
126<h2>Also in this account</h2>
127<p class="small">Everything else the account is carrying. The console has no
128first-hand knowledge of these — it can see them, and it cannot trace a path
129to any of them from a box it runs or the bucket it deploys from.</p>
130{{/* One picture per region, stacked down the page. Region is the
131 STRUCTURE here, not a word on a card: a box is the only thing on this
132 diagram that is really in a region, and everything else is drawn in the
133 band of the box it reaches (archregion.go). That is also what keeps
134 each picture inside the 64rem column — a band is at most four nodes
135 wide — so this page scrolls down and never across. */}}
136{{range .Rest.Bands}}
137<h4 class="archband">{{.Label}}</h4>
138<div class="archwrap">{{.SVG}}</div>
139{{end}}
140{{range .Rest.Groups}}
141<h3>{{.Title}}</h3>
142{{template "archtable" .}}
143{{end}}
144
145{{/* The inventory's own partial-read list: which service or region the
146 estate read could not see. A page that quietly dropped these would be
147 claiming the estate is smaller than it is. */}}
148{{if .Partial}}
149<h2>Reads that failed</h2>
150<ul class="small">{{range .Partial}}<li>{{.}}</li>{{end}}</ul>
151{{end}}
152{{end}}
153
154{{template "bottom" .}}{{end}}
155
156{{/* One resource table, rendered identically in both banks — the two halves
157 of this page differ in what they contain and in nothing else. */}}
158{{define "archtable"}}<div class="tablewrap"><table>
159 <tr><th>Name</th><th>Type</th><th>Region</th><th>Detail</th></tr>
160 {{range .Rows}}<tr><td>{{.Name}}</td><td><code>{{.NativeType}}</code></td><td>{{.Region}}</td><td class="small">{{.Detail}}</td></tr>{{end}}
161</table></div>{{end}}
162