The sandbox composes a node from the input its engine took in, through one shape
mesh/delivery merged: source.main moved to novox/mesh-host@798d73eb11e9
mesh/check checking df13a83a9117 on 798d73eb11e9
mesh/delivery merged: source.main moved to novox/mesh-host@798d73eb11e9
mesh/check checking df13a83a9117 on 798d73eb11e9
The second sandbox fault of the same kind on mesh-host #200 (postgres's secret reader handed, the module not): the engine stripped the whole catalogue from the input it answers, so the sandbox composed the node's own modules from the indexer's source manifests while the bus reader composes them taken in from their builds (artifacts, templates archive texts, what is handed). Both sides now go through composer.SentInput: the node's own taken-in manifests and kept builds stay in the input, and the sandbox composes them over the cases'. An input past what one bus answer carries is refused in words. A conformance row composes one node through the bus reader and through the sandbox and requires the same declaration. Issue 1126. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -144,10 +144,18 @@ func runCase(r Request, c Case, depth string) (CaseVerdict, error) {
|
||||
}
|
||||
shelf[name] = m
|
||||
}
|
||||
// A module the input carries as its node-engine took it in from its build (SentInput) is composed so: the bus
|
||||
// reader composes it from its build, never from the indexer's manifest a case gives.
|
||||
for name, m := range base.Catalogue {
|
||||
shelf[name] = m
|
||||
}
|
||||
in.Catalogue = shelf
|
||||
in.Nodes = slices.Clone(in.Nodes)
|
||||
in.Holdings = slices.Clone(in.Holdings)
|
||||
for i := range in.Nodes {
|
||||
if len(c.Kept[in.Nodes[i].Name]) == 0 {
|
||||
continue // what the input keeps of this node, as its engine took it in, stands
|
||||
}
|
||||
in.Nodes[i].Kept = nil
|
||||
if kept := c.Kept[in.Nodes[i].Name]; len(kept) > 0 {
|
||||
k, err := parse(kept, nil, nil)
|
||||
@@ -244,3 +252,38 @@ const Package = "github.com/novox/mesh-host/cmd/mesh-compose"
|
||||
|
||||
// Decode reads a request (sdk.Decode); it refuses one that is not JSON or of another version.
|
||||
func Decode(data []byte) (Request, error) { return sdk.Decode(data) }
|
||||
|
||||
// SentInput is the composition input a node-engine answers for the sandbox (delivery.ComposeCandidateAsk.Input), from the
|
||||
// input it composed node from: the one shape both read (issue 1126, checks of mesh-host #200). Every other node's modules
|
||||
// are left to the cases (the indexer's manifests, as the bus reader reads them too); node's own placed modules stay as the
|
||||
// bus reader took them in from their builds (their artifacts, the texts of their templates archive, what is handed to the
|
||||
// provisioner), with what node keeps at another build, which no case can give: the sandbox has no build or archive to
|
||||
// read. Without them the sandbox composed another node than the engine (restic's templates and artifacts unread, postgres's
|
||||
// secret reader handed and the module not).
|
||||
func SentInput(in compose.Input, node string) compose.Input {
|
||||
own := map[string]bool{}
|
||||
for _, n := range in.Nodes {
|
||||
if n.Name == node {
|
||||
for _, m := range n.Assigned {
|
||||
own[m] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
taken := in.Catalogue
|
||||
in.Catalogue = nil
|
||||
for name, m := range taken {
|
||||
if own[name] {
|
||||
if in.Catalogue == nil {
|
||||
in.Catalogue = map[string]catalogue.Manifest{}
|
||||
}
|
||||
in.Catalogue[name] = m
|
||||
}
|
||||
}
|
||||
in.Nodes = slices.Clone(in.Nodes)
|
||||
for i := range in.Nodes {
|
||||
if in.Nodes[i].Name != node {
|
||||
in.Nodes[i].Kept = nil
|
||||
}
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package composer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"github.com/novox/mesh-host/internal/compose"
|
||||
"github.com/novox/mesh-host/internal/compose/frombus"
|
||||
"github.com/novox/mesh-host/internal/compose/frombus/frombustest"
|
||||
)
|
||||
|
||||
const demo = `{"module": "demo", "version": "1", "claims": [{"name": "node-files"}]}`
|
||||
@@ -70,6 +74,40 @@ func TestARequestItCannotRunIsRefused(t *testing.T) {
|
||||
if v, err := Run(provided); err != nil || !v.Cases[0].Machines["a"].Composes {
|
||||
t.Errorf("a node assigned the mesh's own module: %+v, %v", v, err)
|
||||
}
|
||||
// Issue 1126 (checks of mesh-host #200, fix-a-bug-met-twice): the sandbox composes one node from the same inputs as
|
||||
// the bus reader, through one path. A mesh whose restic is built (its files from an archive) and handed to the
|
||||
// provisioner composes n1 through frombus, and the request a node-engine answers for it (the input as the engine
|
||||
// sends it, the indexer's manifests in the case) declares the same paths for n1.
|
||||
t.Run("the sandbox composes a node as the bus reader does", func(t *testing.T) {
|
||||
b, err := frombustest.Provisioned()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, scope := context.Background(), frombus.Scope{Node: frombustest.Node}
|
||||
read, err := frombus.Input(ctx, b, frombus.Mesh{}, scope)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d, problems, err := compose.Compose(read, frombustest.Node)
|
||||
if err != nil || len(problems) > 0 {
|
||||
t.Fatalf("the bus reader's input composes n1: %v %v", err, problems)
|
||||
}
|
||||
want := pathsOf(d)
|
||||
sent := SentInput(read, frombustest.Node)
|
||||
cases := Case{Name: "change", Manifests: map[string]Manifest{}}
|
||||
for name, m := range b.Module {
|
||||
cases.Manifests[name] = Manifest{Raw: b.Manifests[m.Manifest]}
|
||||
}
|
||||
r := withInput(t, Request{V: Version, Machines: []string{frombustest.Node}, Declarations: true, Cases: []Case{cases}}, sent)
|
||||
v, err := Run(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := v.Cases[0].Machines[frombustest.Node]
|
||||
if !got.Composes || !reflect.DeepEqual(got.Declared, want) {
|
||||
t.Errorf("the sandbox composed n1 %+v; the bus reader declared %+v", got, want)
|
||||
}
|
||||
})
|
||||
v, err := Run(Request{V: Version, Cases: []Case{{Name: "only-read", Manifests: map[string]Manifest{"demo": {Raw: json.RawMessage(demo)}}}}})
|
||||
if err != nil || len(v.Cases) != 1 || !v.Cases[0].Manifests["demo"].Accepted || v.Cases[0].Machines != nil || v.SDK == "" {
|
||||
t.Fatalf("a request with no machines: %+v, %v", v, err)
|
||||
|
||||
Reference in New Issue
Block a user