mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group feat/setting-defaults failed: a member failed
A key dropped silently ran a module without what its manifest says, and a key inside a block still failed the whole catalogue. Judge a key by what it is about, and narrow the listing to one machine.
65 lines
2.5 KiB
Go
65 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/conditions"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// A stored manifest with a key this controller does not know (novox/hq ADR 0262). The module is left out
|
|
// of every machine's declaration by name; this is the loud half: a condition per module until the
|
|
// controller is updated, or the module is registered again in a shape this controller reads.
|
|
|
|
const (
|
|
sourceUnknownFields = "the catalogue"
|
|
kindUnknownField = "unknown-field"
|
|
)
|
|
|
|
// unknownFieldObservations is one condition for each module of the catalogue whose stored manifest has
|
|
// a key this controller does not know.
|
|
func unknownFieldObservations(known map[string]catalogue.Manifest) []conditions.Observation {
|
|
names := make([]string, 0, len(known))
|
|
for name, m := range known {
|
|
if m.UnknownField() != "" {
|
|
names = append(names, name)
|
|
}
|
|
}
|
|
sort.Strings(names)
|
|
var out []conditions.Observation
|
|
for _, name := range names {
|
|
m := known[name]
|
|
out = append(out, conditions.Observation{
|
|
Scope: conditions.ScopeMesh, ID: name, Kind: kindUnknownField, Severity: conditions.Warning,
|
|
Resolver: conditions.ResolverOperator, Source: sourceUnknownFields,
|
|
Summary: catalogue.UnknownFieldReason(m),
|
|
Said: m.UnknownField(),
|
|
Headline: name + " is left out until the controller is updated",
|
|
Explanation: name + " uses a field this controller does not know, so it is left out of every machine it is on, and nothing of it changes there until the controller is updated.",
|
|
Needs: "update the controller, or register " + name + " again at a version this controller knows.",
|
|
Resolved: "the controller reads " + name + " again",
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// raiseUnknownFields raises those conditions and clears the ones no longer true, on the controller's
|
|
// tick. A catalogue that could not be read raises and clears nothing: "none" is not said for "could not
|
|
// tell" (ADR 0227 rule 4).
|
|
func raiseUnknownFields(ctx context.Context, inv *inventory.Inventory) []string {
|
|
if conditionsFrom == nil {
|
|
return nil
|
|
}
|
|
known, err := inv.Catalogue(ctx)
|
|
if err != nil {
|
|
return []string{fmt.Sprintf("the catalogue could not be read to say which modules it cannot read: %v", err)}
|
|
}
|
|
if err := conditionsFrom.Reconcile(ctx, sourceUnknownFields, unknownFieldObservations(known)); err != nil {
|
|
return []string{fmt.Sprintf("the modules with a field this controller does not know could not be kept as conditions: %v", err)}
|
|
}
|
|
return nil
|
|
}
|