Findings are written and read in the seat mesh-conditions' layout: gitea, distribution, mesh-config, artifact-store-tools (B5b Left 5 part; ADR 0634 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -23,11 +23,12 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
)
|
||||
@@ -39,8 +40,8 @@ const (
|
||||
HavesRead = "node-engine.have"
|
||||
// ManifestsRead is the indexer's manifests: the images a manifest pins by itself.
|
||||
ManifestsRead = delivery.IndexerModule + ".manifests"
|
||||
// FindingsState is the holder's own findings (health.FindingsState): image-missing.
|
||||
FindingsState = health.FindingsState
|
||||
// FindingsState is the holder's own findings (meshconditions.StateFindings): image-missing.
|
||||
FindingsState = meshconditions.StateFindings
|
||||
// Module is this module, the observer its findings name.
|
||||
Module = "artifact-store-tools"
|
||||
// GoneSubject is where the seat says artifacts-gone.
|
||||
@@ -865,7 +866,7 @@ func (h *Holder) Observe(ctx context.Context) error {
|
||||
for _, b := range j.built {
|
||||
builds[b.Module+" "+b.FP] = b
|
||||
}
|
||||
now := map[string]health.Finding{}
|
||||
now := map[string]meshconditions.FindingsByKeyValue{}
|
||||
for _, w := range j.wants {
|
||||
b, ok := builds[w.Module+" "+w.FP]
|
||||
if !ok {
|
||||
@@ -905,7 +906,7 @@ func (h *Holder) Observe(ctx context.Context) error {
|
||||
if _, still := now[k]; !still {
|
||||
// A finding of a first view unanswered is the reader's (views.Reader), cleared by its answer, not by a sweep.
|
||||
if raw, found, err := h.Bus.Get(FindingsState, k); err == nil && found {
|
||||
if f, err := health.DecodeFinding(raw); err == nil && f.Kind == views.UnansweredKind {
|
||||
if f, err := meshconditions.DecodeFindingsByKeyValue(raw); err == nil && f.Kind == views.UnansweredKind {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -920,11 +921,11 @@ func (h *Holder) Observe(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
if found {
|
||||
if was, err := health.DecodeFinding(raw); err == nil && was.Summary == f.Summary {
|
||||
if was, err := meshconditions.DecodeFindingsByKeyValue(raw); err == nil && was.Summary == f.Summary {
|
||||
continue // written only when what it says changes
|
||||
}
|
||||
}
|
||||
if _, err := health.EncodeFinding(f); err != nil {
|
||||
if err := meshconditionsclient.CheckFinding(f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.Bus.Put(FindingsState, k, f); err != nil {
|
||||
@@ -935,11 +936,11 @@ func (h *Holder) Observe(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// imageMissing is S25's finding, in the controller's words (cmd/mesh-controller/image_missing.go watchMissingImages).
|
||||
func imageMissing(node, module, image string, at time.Time) health.Finding {
|
||||
func imageMissing(node, module, image string, at time.Time) meshconditions.FindingsByKeyValue {
|
||||
id := module + "." + node
|
||||
return health.Finding{V: health.FindingVersion, Key: health.FindingKey(health.ScopeModule, id, ImageMissing), Kind: ImageMissing,
|
||||
Subject: health.Subject{Scope: health.ScopeModule, ID: id, Machine: node},
|
||||
Severity: health.Warning, Resolver: health.ResolverOperator,
|
||||
return meshconditions.FindingsByKeyValue{V: meshconditionsclient.FindingVersion, Key: meshconditionsclient.Key(meshconditionsclient.ScopeModule, id, ImageMissing), Kind: ImageMissing,
|
||||
Subject: meshconditions.Subject{Scope: meshconditionsclient.ScopeModule, ID: id, Machine: node},
|
||||
Severity: meshconditionsclient.Warning, Resolver: meshconditionsclient.ResolverOperator,
|
||||
Summary: fmt.Sprintf("%s is left out of every send to %s: its declaration names an image that the artifact store does "+
|
||||
"not hold (the evidence names it); the running container is untouched", module, node),
|
||||
Headline: capital(module) + " is not updated on " + node,
|
||||
@@ -947,8 +948,8 @@ func imageMissing(node, module, image string, at time.Time) health.Finding {
|
||||
"was not sent to %s. What runs there is untouched, and the rest of %s is sent as usual.", module, node, node),
|
||||
Needs: fmt.Sprintf("build %s again; the details name the image.", module),
|
||||
Resolved: "Resolved: the store holds the image of " + module + " again",
|
||||
Evidence: []health.Evidence{{At: at.UTC(), Said: "image " + image + " is not in the store"}},
|
||||
Source: "S25", Observer: Module, At: at.UTC()}
|
||||
Evidence: []meshconditions.Evidence{{At: at.UTC().Format(time.RFC3339Nano), Said: "image " + image + " is not in the store"}},
|
||||
Source: "S25", Observer: Module, At: at.UTC().Format(time.RFC3339Nano)}
|
||||
}
|
||||
|
||||
func capital(s string) string {
|
||||
|
||||
@@ -12,10 +12,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
@@ -403,9 +404,9 @@ func TestAWantedImageTheStoreLacksIsAFindingAndImagesNamesWantsAndHaves(t *testi
|
||||
if err := h.Observe(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
key := health.FindingKey(health.ScopeModule, "letta.ace", ImageMissing)
|
||||
key := meshconditionsclient.Key(meshconditionsclient.ScopeModule, "letta.ace", ImageMissing)
|
||||
raw, found, _ := b.Get(FindingsState, key)
|
||||
f, err := health.DecodeFinding(raw)
|
||||
f, err := meshconditions.DecodeFindingsByKeyValue(raw)
|
||||
if !found || err != nil || f.Subject.Machine != "ace" || f.Source != "S25" || !strings.Contains(f.Evidence[0].Said, imageRef("letta", 1)) {
|
||||
t.Fatalf("the finding is %+v (%v, %v)", f, found, err)
|
||||
}
|
||||
|
||||
@@ -13,10 +13,12 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
ociseat "git.novox.be/novox/mesh-delivery/contracts/go/seats/ociartifactregistry"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
|
||||
reg "git.novox.be/novox/mesh-delivery/contracts/go/seats/containerimageregistry"
|
||||
)
|
||||
@@ -25,7 +27,7 @@ import (
|
||||
const SweepRefused = "sweep-refused"
|
||||
|
||||
// sweepFindingKey is the one key of the sweep's finding in the module's findings.
|
||||
var sweepFindingKey = health.FindingKey(health.ScopeModule, Module, SweepRefused)
|
||||
var sweepFindingKey = meshconditionsclient.Key(meshconditionsclient.ScopeModule, Module, SweepRefused)
|
||||
|
||||
// canonical is a kept reference in the older form, `artifact-store://<path>`, whichever form it came in; another is as
|
||||
// it was.
|
||||
@@ -113,17 +115,17 @@ func (h *Holder) removeOnSeat(reference, why string) error {
|
||||
// sweepFinding writes the sweep's finding: what the seat refused, and why.
|
||||
func (h *Holder) sweepFinding(what string, err error) {
|
||||
at := h.now().UTC()
|
||||
f := health.Finding{V: health.FindingVersion, Key: sweepFindingKey, Kind: SweepRefused,
|
||||
Subject: health.Subject{Scope: health.ScopeModule, ID: Module},
|
||||
Severity: health.Warning, Resolver: health.ResolverOperator,
|
||||
f := meshconditions.FindingsByKeyValue{V: meshconditionsclient.FindingVersion, Key: sweepFindingKey, Kind: SweepRefused,
|
||||
Subject: meshconditions.Subject{Scope: meshconditionsclient.ScopeModule, ID: Module},
|
||||
Severity: meshconditionsclient.Warning, Resolver: meshconditionsclient.ResolverOperator,
|
||||
Summary: fmt.Sprintf("the artifact sweep stopped: a registry seat refused %s (the evidence names why)", what),
|
||||
Headline: "The artifact sweep stopped",
|
||||
Explanation: "The sweep keeps what the mesh still needs and removes the rest through the registry seats. A seat " +
|
||||
"refused one of its asks, so it stopped before anything more was removed; what it kept stays kept.",
|
||||
Needs: "read the seat holder's journal for the refusal; the next sweep asks again.",
|
||||
Resolved: "Resolved: the artifact sweep ran through without a refusal",
|
||||
Evidence: []health.Evidence{{At: at, Said: fmt.Sprintf("%s: %v", what, err)}},
|
||||
Source: "CAT-AS1", Observer: Module, At: at}
|
||||
Evidence: []meshconditions.Evidence{{At: at.UTC().Format(time.RFC3339Nano), Said: fmt.Sprintf("%s: %v", what, err)}},
|
||||
Source: "CAT-AS1", Observer: Module, At: at.Format(time.RFC3339Nano)}
|
||||
if werr := h.Bus.Put(FindingsState, sweepFindingKey, f); werr != nil {
|
||||
h.logf("the sweep's finding (%s: %v) could not be written: %v", what, err, werr)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ module artifactstoretools
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts v0.0.0-00010101000000-000000000000
|
||||
|
||||
@@ -18,12 +18,13 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
reg "git.novox.be/novox/mesh-delivery/contracts/go/seats/containerimageregistry"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/parts"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
|
||||
"distribution/internal/holder"
|
||||
)
|
||||
@@ -68,16 +69,16 @@ func say(seat, event string, body holder.Event) error {
|
||||
}
|
||||
|
||||
func finding(kind, subject, words string, raised bool) {
|
||||
key := health.FindingKey(health.ScopeSeat, "distribution", kind+"."+strings.NewReplacer(".", "_", "@", "_", "/", "_").Replace(subject))
|
||||
key := meshconditionsclient.Key(meshconditionsclient.ScopeSeat, "distribution", kind+"."+strings.NewReplacer(".", "_", "@", "_", "/", "_").Replace(subject))
|
||||
if !raised {
|
||||
_ = stdio.State(health.FindingsState).Delete(key)
|
||||
_ = stdio.State(meshconditions.StateFindings).Delete(key)
|
||||
return
|
||||
}
|
||||
f := health.Finding{V: health.FindingVersion, Key: key, Kind: kind, Ref: key[strings.LastIndex(key, ".")+1:],
|
||||
Subject: health.Subject{Scope: health.ScopeSeat, ID: "distribution"}, Severity: health.Warning,
|
||||
f := meshconditions.FindingsByKeyValue{V: meshconditionsclient.FindingVersion, Key: key, Kind: kind, Ref: key[strings.LastIndex(key, ".")+1:],
|
||||
Subject: meshconditions.Subject{Scope: meshconditionsclient.ScopeSeat, ID: "distribution"}, Severity: meshconditionsclient.Warning,
|
||||
Summary: words, Headline: words, Explanation: words, Resolved: "cleared once it no longer holds",
|
||||
Source: kind, Observer: "distribution", At: time.Now().UTC()}
|
||||
if _, err := stdio.State(health.FindingsState).Put(key, f); err != nil {
|
||||
Source: kind, Observer: "distribution", At: time.Now().UTC().Format(time.RFC3339Nano)}
|
||||
if _, err := stdio.State(meshconditions.StateFindings).Put(key, f); err != nil {
|
||||
logf("the finding %s could not be written: %v", key, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
|
||||
"distribution/internal/holder"
|
||||
@@ -178,17 +179,17 @@ func findingsKV(kv jetstream.KeyValue, logf func(string, ...any)) func(kind, sub
|
||||
if kv == nil {
|
||||
return
|
||||
}
|
||||
key := health.FindingKey(health.ScopeSeat, holder.Self, kind+"."+strings.NewReplacer(".", "_", "@", "_", "/", "_").Replace(subject))
|
||||
key := meshconditionsclient.Key(meshconditionsclient.ScopeSeat, holder.Self, kind+"."+strings.NewReplacer(".", "_", "@", "_", "/", "_").Replace(subject))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if !raised {
|
||||
_ = kv.Delete(ctx, key)
|
||||
return
|
||||
}
|
||||
f := health.Finding{V: health.FindingVersion, Key: key, Kind: kind, Ref: key[strings.LastIndex(key, ".")+1:],
|
||||
Subject: health.Subject{Scope: health.ScopeSeat, ID: holder.Self}, Severity: health.Warning,
|
||||
f := meshconditions.FindingsByKeyValue{V: meshconditionsclient.FindingVersion, Key: key, Kind: kind, Ref: key[strings.LastIndex(key, ".")+1:],
|
||||
Subject: meshconditions.Subject{Scope: meshconditionsclient.ScopeSeat, ID: holder.Self}, Severity: meshconditionsclient.Warning,
|
||||
Summary: words, Headline: words, Explanation: words + "; registry_old_name or registry_direct_writes drops a retired node by hand",
|
||||
Resolved: "cleared when the window closes", Source: kind, Observer: holder.Self, At: time.Now().UTC()}
|
||||
Resolved: "cleared when the window closes", Source: kind, Observer: holder.Self, At: time.Now().UTC().Format(time.RFC3339Nano)}
|
||||
b, _ := json.Marshal(f)
|
||||
if _, err := kv.Put(ctx, key, b); err != nil {
|
||||
logf("the finding %s could not be written: %v", key, err)
|
||||
|
||||
@@ -4,6 +4,8 @@ go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-delivery/sdk v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-delivery/contracts/go/seats/containerimageregistry v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f
|
||||
|
||||
@@ -27,13 +27,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
goreg "git.novox.be/novox/mesh-delivery/contracts/go/seats/gopackageregistry"
|
||||
npmreg "git.novox.be/novox/mesh-delivery/contracts/go/seats/npmpackageregistry"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/parts"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
|
||||
"gitea/internal/packageseats"
|
||||
)
|
||||
@@ -250,16 +251,16 @@ func sayOn(seat, event string, o packageseats.Outcome) error {
|
||||
}
|
||||
|
||||
func finding(kind, subject, words string, raised bool) {
|
||||
key := health.FindingKey(health.ScopeSeat, packageseats.Self, kind+"."+strings.NewReplacer(".", "_", "@", "_", "/", "_").Replace(subject))
|
||||
key := meshconditionsclient.Key(meshconditionsclient.ScopeSeat, packageseats.Self, kind+"."+strings.NewReplacer(".", "_", "@", "_", "/", "_").Replace(subject))
|
||||
if !raised {
|
||||
_ = stdio.State(health.FindingsState).Delete(key)
|
||||
_ = stdio.State(meshconditions.StateFindings).Delete(key)
|
||||
return
|
||||
}
|
||||
f := health.Finding{V: health.FindingVersion, Key: key, Kind: kind, Ref: key[strings.LastIndex(key, ".")+1:],
|
||||
Subject: health.Subject{Scope: health.ScopeSeat, ID: packageseats.Self}, Severity: health.Warning,
|
||||
f := meshconditions.FindingsByKeyValue{V: meshconditionsclient.FindingVersion, Key: key, Kind: kind, Ref: key[strings.LastIndex(key, ".")+1:],
|
||||
Subject: meshconditions.Subject{Scope: meshconditionsclient.ScopeSeat, ID: packageseats.Self}, Severity: meshconditionsclient.Warning,
|
||||
Summary: words, Headline: words, Explanation: words, Resolved: "cleared once it no longer holds",
|
||||
Source: kind, Observer: packageseats.Self, At: time.Now().UTC()}
|
||||
if _, err := stdio.State(health.FindingsState).Put(key, f); err != nil {
|
||||
Source: kind, Observer: packageseats.Self, At: time.Now().UTC().Format(time.RFC3339Nano)}
|
||||
if _, err := stdio.State(meshconditions.StateFindings).Put(key, f); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "the finding %s could not be written: %v\n", key, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ go 1.26.0
|
||||
require (
|
||||
git.novox.be/novox/mesh-delivery/sdk v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-delivery/contracts/go/seats/gopackageregistry v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-delivery/contracts/go/seats/npmpackageregistry v0.0.0-00010101000000-000000000000
|
||||
|
||||
@@ -10,11 +10,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
)
|
||||
|
||||
// FindingsState is the state, health.FindingsState.
|
||||
const FindingsState = health.FindingsState
|
||||
// FindingsState is the state, meshconditions.StateFindings.
|
||||
const FindingsState = meshconditions.StateFindings
|
||||
|
||||
// The kinds of finding mesh-config writes.
|
||||
const (
|
||||
@@ -36,23 +37,23 @@ func findingKey(kind, module, node, ref string) string {
|
||||
if node != "" {
|
||||
id += "." + node
|
||||
}
|
||||
return health.Key(health.ScopeModule, id, kind+"-"+ref)
|
||||
return meshconditionsclient.Key(meshconditionsclient.ScopeModule, id, kind+"-"+ref)
|
||||
}
|
||||
|
||||
func finding(kind, module, node, ref, summary, headline, explanation, needs, resolved, said string, at time.Time) health.Finding {
|
||||
func finding(kind, module, node, ref, summary, headline, explanation, needs, resolved, said string, at time.Time) meshconditions.FindingsByKeyValue {
|
||||
id := module
|
||||
if node != "" {
|
||||
id += "." + node
|
||||
}
|
||||
return health.Finding{V: health.FindingVersion, Key: findingKey(kind, module, node, ref), Kind: kind, Ref: kind + "-" + ref,
|
||||
Subject: health.Subject{Scope: health.ScopeModule, ID: id, Machine: node},
|
||||
Severity: health.Warning, Resolver: health.ResolverOperator, Summary: summary, Headline: headline,
|
||||
return meshconditions.FindingsByKeyValue{V: meshconditionsclient.FindingVersion, Key: findingKey(kind, module, node, ref), Kind: kind, Ref: kind + "-" + ref,
|
||||
Subject: meshconditions.Subject{Scope: meshconditionsclient.ScopeModule, ID: id, Machine: node},
|
||||
Severity: meshconditionsclient.Warning, Resolver: meshconditionsclient.ResolverOperator, Summary: summary, Headline: headline,
|
||||
Explanation: explanation, Needs: needs, Resolved: resolved,
|
||||
Evidence: []health.Evidence{{At: at.UTC(), Said: said}}, Source: "config", Observer: Module, At: at.UTC()}
|
||||
Evidence: []meshconditions.Evidence{{At: at.UTC().Format(time.RFC3339Nano), Said: said}}, Source: "config", Observer: Module, At: at.UTC().Format(time.RFC3339Nano)}
|
||||
}
|
||||
|
||||
// renameRefused is the finding of a move mesh-config refused.
|
||||
func renameRefused(module, to, from, why string, at time.Time) health.Finding {
|
||||
func renameRefused(module, to, from, why string, at time.Time) meshconditions.FindingsByKeyValue {
|
||||
return finding(FindingRenameRefused, module, "", to,
|
||||
fmt.Sprintf("the rename of %s's config value %s to %s is refused: %s", module, from, to, why),
|
||||
fmt.Sprintf("%s's value %s is not moved to %s", module, from, to),
|
||||
@@ -62,7 +63,7 @@ func renameRefused(module, to, from, why string, at time.Time) health.Finding {
|
||||
}
|
||||
|
||||
// windowHeld is the finding of a rename window held open past HeldFinding by a node.
|
||||
func windowHeld(r Rename, node string, at time.Time) health.Finding {
|
||||
func windowHeld(r Rename, node string, at time.Time) meshconditions.FindingsByKeyValue {
|
||||
return finding(FindingWindowHeld, r.Module, node, r.To,
|
||||
fmt.Sprintf("%s on %s has held the old config name %s open for %d days", r.Module, node, r.From, int(HeldFinding.Hours()/24)),
|
||||
fmt.Sprintf("%s on %s still runs the old config name", r.Module, node),
|
||||
@@ -73,13 +74,13 @@ func windowHeld(r Rename, node string, at time.Time) health.Finding {
|
||||
}
|
||||
|
||||
// setFinding writes a finding when it differs from the one kept.
|
||||
func (c *Config) setFinding(f health.Finding) {
|
||||
if _, err := health.EncodeFinding(f); err != nil {
|
||||
func (c *Config) setFinding(f meshconditions.FindingsByKeyValue) {
|
||||
if err := meshconditionsclient.CheckFinding(f); err != nil {
|
||||
c.logf("[mesh-config] a finding is not valid: %v", err)
|
||||
return
|
||||
}
|
||||
if e, err := c.Store.Get(FindingsState, f.Key); err == nil && e != nil {
|
||||
if old, derr := health.DecodeFinding(e.Value); derr == nil && old.Summary == f.Summary {
|
||||
if old, derr := meshconditions.DecodeFindingsByKeyValue(e.Value); derr == nil && old.Summary == f.Summary {
|
||||
return // what it says has not changed
|
||||
}
|
||||
}
|
||||
@@ -100,7 +101,7 @@ func (c *Config) clearFinding(kind, module, ref string, keep ...string) {
|
||||
if err != nil || e == nil {
|
||||
continue
|
||||
}
|
||||
f, err := health.DecodeFinding(e.Value)
|
||||
f, err := meshconditions.DecodeFindingsByKeyValue(e.Value)
|
||||
if err != nil || f.Ref != want || !(f.Subject.ID == module || strings.HasPrefix(f.Subject.ID, module+".")) ||
|
||||
(f.Subject.Machine != "" && slices.Contains(keep, f.Subject.Machine)) {
|
||||
continue
|
||||
@@ -112,7 +113,7 @@ func (c *Config) clearFinding(kind, module, ref string, keep ...string) {
|
||||
}
|
||||
|
||||
// retirementHeld is the finding of a retirement that waits seven days for nodes that still run a build reading the value.
|
||||
func retirementHeld(e Retiring, at time.Time) health.Finding {
|
||||
func retirementHeld(e Retiring, at time.Time) meshconditions.FindingsByKeyValue {
|
||||
node := ""
|
||||
if len(e.Nodes) > 0 {
|
||||
node = e.Nodes[0]
|
||||
@@ -127,7 +128,7 @@ func retirementHeld(e Retiring, at time.Time) health.Finding {
|
||||
}
|
||||
|
||||
// retireUnanswered is the finding of a retirement asked twice and not answered.
|
||||
func retireUnanswered(e Retiring, at time.Time) health.Finding {
|
||||
func retireUnanswered(e Retiring, at time.Time) meshconditions.FindingsByKeyValue {
|
||||
return finding(FindingRetireUnanswered, e.Module, "", e.Key,
|
||||
fmt.Sprintf("the operator did not answer the ask to remove %s's %s, asked twice", e.Module, e.Key),
|
||||
fmt.Sprintf("%s's %s waits for an answer", e.Module, e.Key),
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
)
|
||||
|
||||
// fakeDelivery is the delivery parts as mesh-config asks them: each node's have, whether a node-engine states what it
|
||||
@@ -85,12 +85,12 @@ func aRenamingMesh(t *testing.T) (*Config, *memStore, *fakeDelivery, *time.Time)
|
||||
return c, m, d, &clock
|
||||
}
|
||||
|
||||
func findingsOf(t *testing.T, m *memStore, kind string) []health.Finding {
|
||||
func findingsOf(t *testing.T, m *memStore, kind string) []meshconditions.FindingsByKeyValue {
|
||||
t.Helper()
|
||||
var out []health.Finding
|
||||
var out []meshconditions.FindingsByKeyValue
|
||||
for _, k := range m.keysOf(FindingsState) {
|
||||
e, _ := m.Get(FindingsState, k)
|
||||
f, err := health.DecodeFinding(e.Value)
|
||||
f, err := meshconditions.DecodeFindingsByKeyValue(e.Value)
|
||||
if err != nil {
|
||||
t.Fatalf("finding %s: %v", k, err)
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@ import (
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/meshconfig"
|
||||
meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
"git.novox.be/novox/mesh-sdk/go/testbus"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
@@ -718,7 +718,7 @@ func TestConfigWholeRenamesAndRetiresAgainstTheBus(t *testing.T) {
|
||||
keys, _ := (func() ([]string, error) { kv, _ := p.kv(FindingsState); return kv.Keys(p.ctx) })()
|
||||
for _, k := range keys {
|
||||
raw, _ := p.get(FindingsState, k)
|
||||
if f, err := health.DecodeFinding(raw); err == nil && f.Kind == FindingRenameRefused && strings.Contains(f.Summary, "dock") {
|
||||
if f, err := meshconditions.DecodeFindingsByKeyValue(raw); err == nil && f.Kind == FindingRenameRefused && strings.Contains(f.Summary, "dock") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ module mesh-config
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient v0.0.0-00010101000000-000000000000
|
||||
|
||||
Reference in New Issue
Block a user