101 lines
3.6 KiB
Go
101 lines
3.6 KiB
Go
package frombus
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"maps"
|
|
"slices"
|
|
"sort"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/declaration"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
"github.com/novox/mesh-host/internal/compose"
|
|
"github.com/novox/mesh-host/internal/compose/resolution"
|
|
)
|
|
|
|
// **What runs is kept while a manifest does not yet say what shared code no longer infers** (novox/hq ADR 0601 §4). mesh-sdk
|
|
// knows the tool runner and the modules whose own secrets are the core's credentials only by what their manifests say
|
|
// (`tool-runner`, `core-credentials`), no longer by their names. A module placed on the composing node whose manifest (an
|
|
// older build's) does not say so yet, while what the node runs of it shows it (the tool runner's process, `<module>.runtime`;
|
|
// an own secret carried as the vault's box, the file's `vault-sealed`), is composed as what runs shows: its tool runner
|
|
// process and its sealed secrets alike are kept, never composed away, and the node says so until the manifest says it.
|
|
// Known by what runs, never by a module's name.
|
|
|
|
// keepWhatRuns marks, in in, each module placed on node that what runs shows is the tool runner or carries the core's
|
|
// credentials, where its manifest does not say so; it returns, sorted, what it marked, in words. The tool runner is marked
|
|
// only where no placed module's manifest says it is one.
|
|
func keepWhatRuns(in *compose.Input, node string, running []delivery.Composed) []string {
|
|
placed := assignedOn(*in, node)
|
|
if len(placed) == 0 || len(running) == 0 {
|
|
return nil
|
|
}
|
|
runner, sealed := "", map[string]bool{}
|
|
for _, run := range running {
|
|
for _, raw := range run.Resources {
|
|
var r struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"`
|
|
}
|
|
if json.Unmarshal(raw, &r) != nil || r.ID == "" {
|
|
continue
|
|
}
|
|
owner := run.Module
|
|
if owner == "" {
|
|
owner, _ = declaration.ModuleGuess(r.ID)
|
|
}
|
|
if owner == "" || !slices.Contains(placed, owner) {
|
|
continue
|
|
}
|
|
if r.Type == "process" && r.ID == owner+"."+resolution.RuntimeProcessID() {
|
|
runner = owner
|
|
}
|
|
if r.Type == "file" {
|
|
var fields map[string]json.RawMessage
|
|
if json.Unmarshal(raw, &fields) == nil {
|
|
if _, ok := fields[catalogue.VaultSealedField]; ok {
|
|
sealed[owner] = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var said []string
|
|
saysRunner := false
|
|
for _, m := range placed {
|
|
if man, ok := manifestOn(*in, node, m); ok && catalogue.IsToolRunner(man) {
|
|
saysRunner = true
|
|
}
|
|
}
|
|
mark := func(module string, set func(*catalogue.Manifest), words string) {
|
|
for i := range in.Nodes {
|
|
if in.Nodes[i].Name != node {
|
|
continue
|
|
}
|
|
if man, ok := in.Nodes[i].Kept[module]; ok {
|
|
set(&man)
|
|
in.Nodes[i].Kept[module] = man
|
|
said = append(said, words)
|
|
return
|
|
}
|
|
}
|
|
if man, ok := in.Catalogue[module]; ok {
|
|
set(&man)
|
|
in.Catalogue[module] = man
|
|
said = append(said, words)
|
|
}
|
|
}
|
|
if runner != "" && !saysRunner {
|
|
mark(runner, func(m *catalogue.Manifest) { m.ToolRunner = true }, fmt.Sprintf("%s runs the tool runner's process here and its "+
|
|
"manifest does not say it is the tool runner (tool-runner): it is composed as the tool runner it runs as, until its manifest says so", runner))
|
|
}
|
|
for _, m := range slices.Sorted(maps.Keys(sealed)) {
|
|
if man, ok := manifestOn(*in, node, m); ok && !catalogue.CarriesCoreCredentials(man) {
|
|
mark(m, func(m *catalogue.Manifest) { m.CoreCredentials = true }, fmt.Sprintf("%s carries its own secrets sealed by the vault here "+
|
|
"and its manifest does not say they are the core's credentials (core-credentials): they stay sealed, until its manifest says so", m))
|
|
}
|
|
}
|
|
sort.Strings(said)
|
|
return said
|
|
}
|