100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
// Command noplacement refuses what the repository path of placement left behind (novox/hq ADR 0567 §10, §12).
|
|
//
|
|
// Placement, which module runs on which node, is bus state held by the seat mesh-placement; no file of the
|
|
// catalogue says it, and no manifest reads it from the delivery indexer, which no longer keeps it. It refuses:
|
|
//
|
|
// 1. a `placement` directory (or file) at the root of the catalogue;
|
|
//
|
|
// 2. a `particulars` file at the root (the mesh's node names come from the checker's run, §16);
|
|
//
|
|
// 3. a manifest naming a state, stream, event or bucket of the indexer's placement (`mesh-delivery-indexer.placement…`
|
|
// or `mesh-delivery-indexer_placement…`) in any string value, such as `reads`.
|
|
//
|
|
// go run . <catalogue root>
|
|
//
|
|
// Exits 1 on a finding.
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// Prefixes are the names of the indexer's placement parts; a manifest string starting with one names them.
|
|
var Prefixes = []string{"mesh-delivery-indexer.placement", "mesh-delivery-indexer_placement"}
|
|
|
|
// Findings is every refusal in the catalogue at root, sorted.
|
|
func Findings(root string) ([]string, error) {
|
|
var out []string
|
|
if _, err := os.Lstat(filepath.Join(root, "placement")); err == nil {
|
|
out = append(out, "placement: the repository holds no placement; it is bus state of the seat mesh-placement (novox/hq ADR 0567 §10)")
|
|
}
|
|
if _, err := os.Lstat(filepath.Join(root, "particulars")); err == nil {
|
|
out = append(out, "particulars: the repository lists no node names; the checker hands them to the check (novox/hq ADR 0567 §16)")
|
|
}
|
|
manifests, err := filepath.Glob(filepath.Join(root, "modules", "*", "module.json"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sort.Strings(manifests)
|
|
for _, file := range manifests {
|
|
raw, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var doc any
|
|
if err := json.Unmarshal(raw, &doc); err != nil {
|
|
return nil, fmt.Errorf("%s: %w", file, err)
|
|
}
|
|
module := filepath.Base(filepath.Dir(file))
|
|
for _, s := range named(doc, nil) {
|
|
out = append(out, fmt.Sprintf("%s: names %q, which the indexer no longer keeps; placement is the seat mesh-placement's (novox/hq ADR 0567 §12)", module, s))
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// named collects the strings of a decoded manifest that start with one of the Prefixes.
|
|
func named(v any, into []string) []string {
|
|
switch v := v.(type) {
|
|
case string:
|
|
for _, p := range Prefixes {
|
|
if strings.HasPrefix(v, p) {
|
|
return append(into, v)
|
|
}
|
|
}
|
|
case []any:
|
|
for _, e := range v {
|
|
into = named(e, into)
|
|
}
|
|
case map[string]any:
|
|
for _, e := range v {
|
|
into = named(e, into)
|
|
}
|
|
}
|
|
return into
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) != 2 {
|
|
fmt.Fprintln(os.Stderr, "usage: noplacement <catalogue root>")
|
|
os.Exit(2)
|
|
}
|
|
found, err := Findings(os.Args[1])
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
for _, f := range found {
|
|
fmt.Println(f)
|
|
}
|
|
if len(found) > 0 {
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println("no placement directory, and no manifest reads the indexer's placement")
|
|
}
|