The sandbox refuses no module the node holds composing without the change, a module blamed for a refusal among them (issue 774, review round 1)

This commit is contained in:
2026-11-03 13:28:44 +01:00
parent 23cbf9294a
commit 649ed21d55
4 changed files with 22 additions and 3 deletions
+5 -3
View File
@@ -607,11 +607,13 @@ func ComposeSent(in compose.Input, node string) (map[string]delivery.Composed, b
if err != nil {
return nil, true, err
}
// A module the sandbox held that the node-engine did not is the change refusing it: the node does not compose, said
// in that module's words, never passed with the rest composed (issue 774, review of the sandbox input).
// A module the sandbox held that the node-engine held neither in the read nor composing without the change is the change
// refusing it: the node does not compose, said in that module's words, never passed with the rest composed (issue 774,
// review of the sandbox input).
var refused []string
for _, m := range sortedKeys(held) {
if _, was := c.Held[m]; !was {
_, was := c.Held[m]
if _, before := c.HeldBefore[m]; !was && !before {
refused = append(refused, m+": "+held[m])
}
}
+3
View File
@@ -249,6 +249,9 @@ type ComposedHow struct {
Held map[string]string
// Running is what runs of each held module, its own composition, by which it is carried as it runs.
Running []delivery.Composed
// HeldBefore is each module the node holds composing without the change (the candidate's base), held by the read or
// blamed later for a refusal: the change refuses none of them (issue 774, review round 1).
HeldBefore map[string]string
}
// Place is where a node is, as its placement says (inv.Overlay).
+11
View File
@@ -159,6 +159,17 @@ func TestARequestItCannotRunIsRefused(t *testing.T) {
if m := refused.Cases[0].Machines["a"]; m.Composes || !strings.Contains(m.Reason, "app: ") || !strings.Contains(m.Reason, "repository") {
t.Errorf("a module the change refuses on a node composed as its node-engine does: %+v", m)
}
// Held composing without the change, blamed for a refusal beyond the read (issue 1960's unset names): no refusal of
// the change either (review round 1).
in.ComposedHow.HeldBefore = map[string]string{"app": "its route names are unset"}
before, err := Run(request(in))
if err != nil {
t.Fatal(err)
}
if m := before.Cases[0].Machines["a"]; !m.Composes {
t.Errorf("a module the node holds composing without the change: %+v", m)
}
in.ComposedHow.HeldBefore = nil
in.ComposedHow.Held = map[string]string{"app": "held on the node"}
held, err := Run(request(in))
if err != nil {
+3
View File
@@ -191,6 +191,9 @@ func (s *Shadow) composeCandidate(ctx context.Context, c *Composer, ask delivery
if err != nil {
return
}
// What the node holds composing without the candidate, a module blamed for a refusal among them, is no refusal of
// the change (review round 1).
in.ComposedHow.HeldBefore = maps.Clone(baseHeld)
// As the sandbox reads it (composer.SentInput, the one shape): this node's own modules as taken in from their
// builds, every other module's manifest left to the cases.
if body, err := json.Marshal(composer.SentInput(in, laid.env.Node)); err == nil {