Read the rest of the mesh and the network over mesh-sdk, and fail when a caller reaches for the old composition (issue 1388)
The seats, holdings, source, build-source, delivery group check, check request, backup plan, adoption (take and converge) and the network graph now read the rest of the mesh through restOfTheMesh and compose.Graph. compose_callers_test.go scans the package and names any function other than the old composition's own that still calls planFor, declarationWith, composedAndValidated, generators, renderingFor, theRestOfTheMesh or whoResolves; issue 1389 deletes those.
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/compose"
|
||||
"git.novox.be/novox/mesh-sdk/go/overlay"
|
||||
"github.com/novox/mesh-controller/internal/inventory"
|
||||
)
|
||||
@@ -243,7 +244,7 @@ func take(ctx context.Context, open *stores, node, module string, opts takeOptio
|
||||
return "", err
|
||||
}
|
||||
if !slices.Contains(assigned, module) {
|
||||
if plan, _, err := planFor(ctx, open, node); err == nil {
|
||||
if plan, _, err := resolveNode(ctx, open, node); err == nil {
|
||||
if why, runs := plan.Because[module]; runs {
|
||||
return "", fmt.Errorf("%w: %s runs on %s because %s — assign it to %s to take it",
|
||||
inventory.ErrNotAssigned, module, node, why, node)
|
||||
@@ -649,7 +650,7 @@ func converge(ctx context.Context, open *stores, node string, yes bool, digest s
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
plan, settings, err := planFor(ctx, open, node)
|
||||
plan, _, err := resolveNode(ctx, open, node)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -706,14 +707,19 @@ func converge(ctx context.Context, open *stores, node string, yes bool, digest s
|
||||
filter)
|
||||
}
|
||||
|
||||
gens, err := generators(ctx, open)
|
||||
// What the filter is derived from: the rendering of this machine as a question reads it, with the private network.
|
||||
input, err := inputFor(ctx, open)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
with, _, err := renderingFor(ctx, open, node, plan, settings, gens, Reading)
|
||||
rendered, err := compose.Render(input.Input, node, compose.Reading)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
with := rendered.Rendering
|
||||
if with.Generators, err = compose.Generators(input.Input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
rules, err := plan.Rules(with)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -776,7 +782,7 @@ func converge(ctx context.Context, open *stores, node string, yes bool, digest s
|
||||
if _, err := inv.Assign(ctx, node, filter); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, _, err := planFor(ctx, open, node); err != nil {
|
||||
if _, _, err := resolveNode(ctx, open, node); err != nil {
|
||||
_ = inv.Unassign(ctx, node, filter)
|
||||
return "", fmt.Errorf("%s cannot run %s, so it was not converged: %w", node, filter, err)
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func newSourceForms(ctx context.Context, inv *inventory.Inventory) *sourceForms
|
||||
if world == nil {
|
||||
w := catalogue.World{}
|
||||
if shelf, err := inv.Catalogue(ctx); err == nil {
|
||||
if read, err := theRestOfTheMesh(ctx, inv, shelf, ""); err == nil {
|
||||
if read, err := restOfTheMeshOf(ctx, inv, shelf, ""); err == nil {
|
||||
w = read
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ func checkRequestFor(ctx context.Context, open *stores, p link.PullUpdated, scop
|
||||
for _, e := range entries {
|
||||
shelf[e.Manifest.Module] = e.Manifest
|
||||
}
|
||||
world, err := theRestOfTheMesh(ctx, open.inventory, shelf, "")
|
||||
world, err := restOfTheMesh(ctx, open, shelf, "")
|
||||
if err != nil {
|
||||
return link.BuildRequest{}, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// 1388: no caller composes through the controller's own composition any more. The only functions left that call it are the
|
||||
// composition's own, which issue 1389 deletes with it; this fails the moment any other function reaches for it again.
|
||||
func TestNoCallerComposesThroughTheControllersOwnComposition(t *testing.T) {
|
||||
legacy := map[string]bool{"planFor": true, "declarationWith": true, "composedAndValidated": true, "generators": true,
|
||||
"renderingFor": true, "theRestOfTheMesh": true, "whoResolves": true}
|
||||
// The composition's own pairs, until 1389: "file: caller calls callee".
|
||||
allowed := map[string]bool{
|
||||
"facts.go: composedAndValidated calls declarationWith": true,
|
||||
"facts.go: composedAndValidated calls planFor": true,
|
||||
"network.go: generators calls whoResolves": true,
|
||||
"network.go: whoResolves calls planFor": true,
|
||||
"plan.go: declarationWith calls renderingFor": true,
|
||||
"plan.go: grantsFor calls planFor": true,
|
||||
"plan.go: planFor calls theRestOfTheMesh": true,
|
||||
}
|
||||
files, err := filepath.Glob("*.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fset := token.NewFileSet()
|
||||
var found []string
|
||||
for _, f := range files {
|
||||
if strings.HasSuffix(f, "_test.go") {
|
||||
continue
|
||||
}
|
||||
file, err := parser.ParseFile(fset, f, nil, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, d := range file.Decls {
|
||||
fn, ok := d.(*ast.FuncDecl)
|
||||
if !ok || fn.Body == nil {
|
||||
continue
|
||||
}
|
||||
ast.Inspect(fn.Body, func(n ast.Node) bool {
|
||||
if c, ok := n.(*ast.CallExpr); ok {
|
||||
if id, ok := c.Fun.(*ast.Ident); ok && legacy[id.Name] {
|
||||
found = append(found, f+": "+fn.Name.Name+" calls "+id.Name)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
sort.Strings(found)
|
||||
for _, pair := range found {
|
||||
if !allowed[pair] {
|
||||
t.Errorf("%s: it composes through the controller's own composition, not mesh-sdk's", pair)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1179,7 +1179,7 @@ func askGroupCheck(ctx context.Context, open *stores, group string, members []or
|
||||
request.Check.Group = group
|
||||
// A group's check is queued as ready when any member's pull request is marked ready.
|
||||
request.Check.Ready = slices.ContainsFunc(members, func(m orderMember) bool { return m.Ready })
|
||||
world, err := theRestOfTheMesh(ctx, open.inventory, shelfOf(entries), "")
|
||||
world, err := restOfTheMesh(ctx, open, shelfOf(entries), "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func recordDerivedHolders(ctx context.Context, open *stores) ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
// exclude nobody: every node's claims, resolved with the holdings on record.
|
||||
world, err := theRestOfTheMesh(ctx, inv, shelf, "")
|
||||
world, err := restOfTheMesh(ctx, open, shelf, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/compose"
|
||||
"git.novox.be/novox/mesh-sdk/go/overlay"
|
||||
"github.com/novox/mesh-controller/internal/inventory"
|
||||
)
|
||||
@@ -308,16 +309,11 @@ func network(ctx context.Context, inv *inventory.Inventory, on map[string]bool,
|
||||
|
||||
// graph is the whole mesh's network, for showing it.
|
||||
func graph(ctx context.Context, open *stores) ([]overlay.Node, overlay.Graph, error) {
|
||||
inv := open.inventory
|
||||
on, refused, err := whoResolves(ctx, open, overlay.Requirement)
|
||||
in, err := inputFor(ctx, open)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
g, err := network(ctx, inv, on, refused)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return g.Nodes(), g.Graph(), nil
|
||||
return compose.Graph(in.Input)
|
||||
}
|
||||
|
||||
// whoResolves is the machines whose resolution answers a requirement, and why the others did not.
|
||||
|
||||
@@ -124,7 +124,7 @@ func loadBackupFacts(ctx context.Context, inv *inventory.Inventory) (backupFacts
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
world, err := theRestOfTheMesh(ctx, inv, shelf, "")
|
||||
world, err := restOfTheMeshOf(ctx, inv, shelf, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ func seatsCommand(ctx context.Context, args []string) error {
|
||||
return err
|
||||
}
|
||||
// Every node, none excluded: the same view of what each machine holds that planning uses.
|
||||
world, err := theRestOfTheMesh(ctx, inv, shelf, "")
|
||||
world, err := restOfTheMesh(ctx, open, shelf, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func cloneFrom(ctx context.Context, source buildSource) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
world, err := theRestOfTheMesh(ctx, open.inventory, shelf, "")
|
||||
world, err := restOfTheMesh(ctx, open, shelf, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -154,7 +154,7 @@ func seatBases(ctx context.Context) map[string]string {
|
||||
if err != nil {
|
||||
return unread("the catalogue", err)
|
||||
}
|
||||
world, err := theRestOfTheMesh(ctx, open.inventory, shelf, "")
|
||||
world, err := restOfTheMesh(ctx, open, shelf, "")
|
||||
if err != nil {
|
||||
return unread("who holds which seat", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user