| index 83dc32d8e..6fc85e926 100644 |
| --- a/internal/status/dryrun.go |
| +++ b/internal/status/dryrun.go |
| @@ -92,6 +92,28 @@ const ( |
| // the identical private home: Box.Metrics. |
| var dryRunRouteVersionNeedles = []string{dryRunRouteVersionHost, dryRunRouteVersionVersion} |
| |
| +// dryRunRouteServingHost and dryRunRouteServingServing are Task 13's needle |
| +// pair (plan 5's ServingVersion): a THIRD un-opted route, distinct from |
| +// all others, whose only purpose is carrying a ServingVersion — the one |
| +// thing that makes CollectBox populate Box.Metrics.RouteServing. Neither |
| +// string reuses any existing needle: route_serving gets its own |
| +// dedicated positive/negative check, scope-split exactly like |
| +// dryRunRouteVersionNeedles, rather than riding along on an assertion |
| +// built for something else. |
| +const ( |
| + dryRunRouteServingHost = "serving-secret.internal" |
| + dryRunRouteServingServing = "servingver5678" |
| +) |
| + |
| +// dryRunRouteServingNeedles is the scope-split pair for the fixture above: |
| +// REQUIRED inside status/boxes/*.json (proof that RouteServing actually |
| +// attached — an unexercised field is a field this self-check can't vouch |
| +// for) and BANNED everywhere else DryRun publishes (proof that |
| +// route_serving hostnames never reach fleet.json or the rendered page). |
| +// Same reasoning and the same scan-loop shape as dryRunRouteVersionNeedles, |
| +// because RouteServing lives in the identical private home: Box.Metrics. |
| +var dryRunRouteServingNeedles = []string{dryRunRouteServingHost, dryRunRouteServingServing} |
| + |
| // dryRunUpstreamHost and dryRunUpstreamAddr are the multi-upstream plan's own |
| // needle pair (Task 6) for Box.Metrics.Upstreams — the probe table, which is |
| // the most identifying thing this block carries: a route hostname as the KEY |
| @@ -186,6 +208,14 @@ func dryRunFixtures() ([]registry.Route, Probes) { |
| Host: dryRunRouteVersionHost, Kind: "instance", App: "stagedapp", |
| Status: "ready", Version: dryRunRouteVersionVersion, |
| }, |
| + { |
| + // Un-opted, so its host must not surface via the apps feed either |
| + // — the ONLY reason this route exists is to give CollectBox a |
| + // ServingVersion to fold into Box.Metrics.RouteServing (see the |
| + // needle pair's own doc comment above). |
| + Host: dryRunRouteServingHost, Kind: "sidecar", App: "servingapp", |
| + Status: "ready", ServingVersion: dryRunRouteServingServing, |
| + }, |
| } |
| |
| memFrac, diskFrac := dryRunMemFrac, dryRunDiskFrac |
| @@ -395,6 +425,10 @@ func DryRun(dir string, out io.Writer) error { |
| // status/boxes/ object carrying the route_versions fixture, so this |
| // self-check can't pass by simply never exercising RouteVersions. |
| routeVersionKeySeen := false |
| + // routeServingKeySeen is the same positive half for the serving version |
| + // map (dryRunRouteServingNeedles) — Box.Metrics.RouteServing, plan 5 |
| + // Task 2. |
| + routeServingKeySeen := false |
| // upstreamKeySeen is the same positive half for the probe table |
| // (dryRunUpstreamNeedles) — Box.Metrics.Upstreams, Task 6. |
| upstreamKeySeen := false |
| @@ -455,6 +489,19 @@ func DryRun(dir string, out io.Writer) error { |
| return fmt.Errorf("dry run: %s leaked a route_versions fixture %v — RouteVersions must never reach the public feed", key, leaks) |
| } |
| |
| + // dryRunRouteServingNeedles: same scope split as RouteVersions. |
| + // RouteServing (plan 5's ServingVersion) is also a Box.Metrics field |
| + // with hostnames, so status/boxes/*.json is its one privileged home |
| + // and every other published key must never carry it. |
| + if strings.HasPrefix(key, "status/boxes/") { |
| + if leaks := ScanForLeaks(body, dryRunRouteServingNeedles); len(leaks) == 0 { |
| + return fmt.Errorf("dry run: %s: expected route_serving fixtures %v, found none — RouteServing not attached?", key, dryRunRouteServingNeedles) |
| + } |
| + routeServingKeySeen = true |
| + } else if leaks := ScanForLeaks(body, dryRunRouteServingNeedles); len(leaks) > 0 { |
| + return fmt.Errorf("dry run: %s leaked a route_serving fixture %v — RouteServing must never reach the public feed", key, leaks) |
| + } |
| + |
| // dryRunUpstreamNeedles: the third scope split, on the same pattern. |
| // Upstreams is Box.Metrics's other hostname-keyed field and the only |
| // one carrying backend ADDRESSES, so status/boxes/*.json is its one |
| @@ -534,6 +581,9 @@ func DryRun(dir string, out io.Writer) error { |
| if !routeVersionKeySeen { |
| return fmt.Errorf("dry run: no status/boxes/*.json object was scanned — route_versions scope check never ran") |
| } |
| + if !routeServingKeySeen { |
| + return fmt.Errorf("dry run: no status/boxes/*.json object was scanned — route_serving scope check never ran") |
| + } |
| if !upstreamKeySeen { |
| return fmt.Errorf("dry run: no status/boxes/*.json object was scanned — upstreams scope check never ran") |
| } |