carlos / platform Public

console: RouteView carries Unit/Backing/Provisioned

RouteView now mirrors registry.Route's process-ownership fields
(Unit, Backing, Provisioned), copied through in Assemble's RouteView
literal. Later tasks (2, 3, 6, 9) need these to tell "no readings
because nothing samples this route's process" apart from "not
responding".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell f9e8c259a7f7670817d67ed8e796f4e0c126d588 parent f5cf49c
2 files changed, +48 −0
  • internal/console/view.go +12 −0
  • internal/console/view_test.go +36 −0
diff --git a/internal/console/view.go b/internal/console/view.go
index 6b57bddcb..8a208a6a8 100644
--- a/internal/console/view.go
+++ b/internal/console/view.go
@@ -137,6 +137,17 @@ type RouteView struct {
// can hold another tenant's rows, and a grant is the one field here that
// names privileged ports and box authority.
Caps string
+ // Unit is the bespoke systemd unit bound to this route
+ // (registry.Route.Unit, #110): set when an operator-run service owns the
+ // route's process. The sweep samples stamped units (Task 5), so a stamped
+ // route's silence is meaningful — see expectsReadings.
+ Unit string
+ // Backing mirrors registry.Route.Backing: "" = an exec child the
+ // activator spawns, registry.BackingUnit = a carlos-app@<host> unit.
+ Backing string
+ // Provisioned mirrors registry.Route.Provisioned: minted from a bucket
+ // instance record, so the activator runs its process by construction.
+ Provisioned bool
}
// humanizeCaps renders a registry.Route.Caps column for a person: the
@@ -380,6 +391,7 @@ func Assemble(regPath string, s release.Store, pub ed25519.PublicKey, acct strin
Account: rtAcct,
Environment: rt.Environment,
Caps: capsFor,
+ Unit: rt.Unit, Backing: rt.Backing, Provisioned: rt.Provisioned,
})
domainsByApp[rt.App] = append(domainsByApp[rt.App], domainView(rt, edgeIPs))
}
diff --git a/internal/console/view_test.go b/internal/console/view_test.go
index 2d4f94e25..46d87091b 100644
--- a/internal/console/view_test.go
+++ b/internal/console/view_test.go
@@ -268,6 +268,42 @@ func TestAssembleDegradesBadChannel(t *testing.T) {
}
}
+// TestAssembleCarriesProcessOwnership guards the copy in Assemble's
+// RouteView literal: Unit/Backing/Provisioned are what later tasks (2, 3, 6,
+// 9) use to tell "no readings because nothing samples this route's process"
+// apart from "not responding" — a silent drop here would make every
+// unit-backed route look unowned.
+func TestAssembleCarriesProcessOwnership(t *testing.T) {
+ regPath, store, _, pub := buildFixtures(t)
+ reg, err := registry.Open(regPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := reg.Upsert(registry.Route{Host: "unit-stamped.example.test", Kind: "instance",
+ Status: "ready", App: "kass", Channel: "stable",
+ Unit: "titogo@demo.service", Backing: registry.BackingUnit, Provisioned: true}); err != nil {
+ t.Fatal(err)
+ }
+ views, err := Assemble(regPath, store, pub, release.OpsAccount, []string{"kass"}, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var rt RouteView
+ found := false
+ for _, r := range views[0].Routes {
+ if r.Host == "unit-stamped.example.test" {
+ rt = r
+ found = true
+ }
+ }
+ if !found {
+ t.Fatalf("route unit-stamped.example.test not in %+v", views[0].Routes)
+ }
+ if rt.Unit != "titogo@demo.service" || rt.Backing != registry.BackingUnit || !rt.Provisioned {
+ t.Fatalf("RouteView lost process ownership: %+v", rt)
+ }
+}
+
func TestVersionsNewestFirst(t *testing.T) {
_, store, _, _ := buildFixtures(t)
vs, err := Versions(store, release.OpsAccount, "kass")