Swaps three import paths for mesh-sdk's go/catalogue, go/overlay and go/validate (the same packages, copied from this repository at 6c2a8d62) and lets gofmt order the groups. The six swap commits compile together once the pin commit (go.mod, modules.txt) is on the branch; each alone does not, because a file on the SDK's types cannot call one still on the old package.
136 lines
5.0 KiB
Go
136 lines
5.0 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// What an assignment says about the machines it was not about.
|
|
|
|
// **An assignment that blocks another machine says so.**
|
|
//
|
|
// The shape found on a four-node raise: a module offering a mesh-scoped provision stops offering it
|
|
// the moment its own node stops resolving, so an assignment to the provider's machine silently took
|
|
// a provision away from every consumer elsewhere. Those consumers were then told *nothing in this
|
|
// mesh provides it*, naming as the remedy a module that was already assigned — which read, on the
|
|
// way back, as a version bump breaking provider recognition. It was neither the version nor the
|
|
// provider: it was one machine's set of assignments, and nothing said so.
|
|
//
|
|
// novox/hq 04-ISSUES/017 names the general shape — an action succeeding into a state its own verify
|
|
// rejects, because the action's test is not the test the verify uses. `assign` tested one node; the
|
|
// verify is resolution over all of them.
|
|
func TestAnAssignmentThatBlocksAnotherMachineSaysWhichAndWhy(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
|
|
// A provider on the hub and a consumer on the other machine, both resolving.
|
|
register(t, open, catalogue.Manifest{Module: "step-ca", Version: "1",
|
|
Provides: []catalogue.Offer{{Name: "acme-ca", Scope: catalogue.ScopeMesh}},
|
|
Serves: map[string]map[string]any{"acme-ca": {"path": "/acme/directory"}}})
|
|
register(t, open, catalogue.Manifest{Module: "route-proxy", Version: "1",
|
|
Requires: []string{"acme-ca"}})
|
|
if _, err := assign(ctx, open, "anchor", "step-ca"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
said, err := assign(ctx, open, "laptop", "route-proxy")
|
|
if err != nil {
|
|
t.Fatalf("a mesh that should resolve did not: %v\n%s", err, said)
|
|
}
|
|
if strings.Contains(said, "cannot be worked out") {
|
|
t.Fatalf("a well mesh was reported as blocked:\n%s", said)
|
|
}
|
|
|
|
// Now break the hub's own set, with nothing but the command a person has.
|
|
one, two := rivals()
|
|
register(t, open, one)
|
|
register(t, open, two)
|
|
if _, err := assign(ctx, open, "anchor", "rival-one"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
said, err = assign(ctx, open, "anchor", "rival-two")
|
|
if err == nil {
|
|
t.Fatal("an assignment that makes its own node incoherent was not reported at all")
|
|
}
|
|
|
|
// The node's own refusal is the error, as it always was. What is new is that the machines this
|
|
// just took a provision away from are named in the same breath.
|
|
if !strings.Contains(said, "laptop") {
|
|
t.Fatalf("the machine this blocked is not named:\n%s\n\n%v", said, err)
|
|
}
|
|
if !strings.Contains(said, "acme-ca") {
|
|
t.Fatalf("what laptop is now missing is not said:\n%s", said)
|
|
}
|
|
if !strings.Contains(said, "cannot be worked out as things stand") {
|
|
t.Fatalf("the report does not say what state the mesh is in:\n%s", said)
|
|
}
|
|
// And the assignment is kept: it is what a person meant, and assignment is not an ordering.
|
|
assigned, err := open.inventory.Assigned(ctx, "anchor")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !contains(assigned, "rival-two") {
|
|
t.Fatalf("the assignment was not kept: %v", assigned)
|
|
}
|
|
}
|
|
|
|
// A consumer assigned before its provider is refused for itself and kept, because assignment is not
|
|
// an ordering — refusing the first half of a pair would make the order somebody types two commands
|
|
// in part of the mesh's rules.
|
|
func TestAConsumerAssignedBeforeItsProviderIsStillAssigned(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
register(t, open, catalogue.Manifest{Module: "route-proxy", Version: "1",
|
|
Requires: []string{"acme-ca"}})
|
|
|
|
said, err := assign(ctx, open, "laptop", "route-proxy")
|
|
if err == nil {
|
|
t.Fatalf("a consumer with nothing to consume resolved:\n%s", said)
|
|
}
|
|
assigned, err := open.inventory.Assigned(ctx, "laptop")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !contains(assigned, "route-proxy") {
|
|
t.Fatalf("assignment became an ordering: %v", assigned)
|
|
}
|
|
}
|
|
|
|
// Unassigning is the ordinary way to stop providing something to another machine, and it reports
|
|
// the same way for the same reason.
|
|
func TestUnassigningAProviderNamesWhoIsNowBlocked(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
register(t, open, catalogue.Manifest{Module: "step-ca", Version: "1",
|
|
Provides: []catalogue.Offer{{Name: "acme-ca", Scope: catalogue.ScopeMesh}},
|
|
Serves: map[string]map[string]any{"acme-ca": {"path": "/acme/directory"}}})
|
|
register(t, open, catalogue.Manifest{Module: "route-proxy", Version: "1",
|
|
Requires: []string{"acme-ca"}})
|
|
if _, err := assign(ctx, open, "anchor", "step-ca"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := assign(ctx, open, "laptop", "route-proxy"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
said, err := unassign(ctx, open, "anchor", "step-ca")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(said, "laptop") || !strings.Contains(said, "acme-ca") {
|
|
t.Fatalf("taking the provider away said nothing about who was consuming it:\n%s", said)
|
|
}
|
|
}
|
|
|
|
func contains(all []string, one string) bool {
|
|
for _, s := range all {
|
|
if s == one {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|