package main import ( "crypto/ecdh" "crypto/rand" "encoding/base64" "encoding/json" "fmt" "testing" "github.com/novox/mesh-control/internal/catalogue" "github.com/novox/mesh-control/internal/inventory" "github.com/novox/mesh-control/internal/licences" "github.com/novox/mesh-control/internal/overlay" ) // A mesh a command can be run against. // // The commands here were tested through the pieces they call and never through themselves, so // three faults that only exist where the pieces meet — an assignment reported as fine while it // blocked other machines, a read-shaped invocation that wrote, a JSON interface that stopped // emitting JSON — were invisible to every test in this package. This raises the real stores and // calls the real functions. // aMesh is two placed, capable machines on a private network, with nothing assigned but the // network itself. // // `anchor` is the hub. That is not decoration: a mesh whose hub cannot be resolved has no private // network at all, which is how one machine's problem reaches every other. func aMesh(t *testing.T) *stores { t.Helper() inventory.ForTest(t) // raises the store, migrates it, and points the environment at it licences.ForTest(t) // planning reaches this one too, by name and never by connection open, err := openStores(t.Context()) if err != nil { t.Fatal(err) } t.Cleanup(open.Close) for _, m := range provided { if err := open.inventory.Provide(t.Context(), m); err != nil { t.Fatal(err) } } for i, name := range []string{"anchor", "laptop"} { record, err := open.inventory.AddNode(t.Context(), name) if err != nil { t.Fatal(err) } if err := open.inventory.SetPlace(t.Context(), name, name+".example:51820", "here", name == "anchor", fmt.Sprintf("10.77.0.%d", i+1)); err != nil { t.Fatal(err) } reported, err := json.Marshal(map[string]any{"capabilities": []map[string]any{ {"name": "container-runtime", "present": true}, {"name": "wireguard", "present": true}, {"name": "systemd", "present": true}, }}) if err != nil { t.Fatal(err) } var profile map[string]any if err := json.Unmarshal(reported, &profile); err != nil { t.Fatal(err) } if err := open.inventory.RecordProfile(t.Context(), record.ID, profile); err != nil { t.Fatal(err) } if err := open.inventory.RecordSealingKey(t.Context(), record.ID, aPublicKey(t)); err != nil { t.Fatal(err) } if err := open.inventory.RecordOverlayKey(t.Context(), record.ID, aPublicKey(t)); err != nil { t.Fatal(err) } if err := open.inventory.Assign(t.Context(), name, overlay.Name); err != nil { t.Fatal(err) } } return open } // aPublicKey is a key a machine could have reported. Its private half is thrown away: nothing here // opens anything, it only needs the mesh to believe a machine has a key. func aPublicKey(t *testing.T) string { t.Helper() k, err := ecdh.X25519().GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } return base64.StdEncoding.EncodeToString(k.PublicKey().Bytes()) } // register puts a manifest in the catalogue. func register(t *testing.T, open *stores, m catalogue.Manifest) { t.Helper() if err := open.inventory.RegisterModule(t.Context(), m, inventory.Source{}); err != nil { t.Fatal(err) } } // rivals are two modules that cannot share a machine, which is the shortest way to make a node's // own set of assignments incoherent using nothing but commands a person has. func rivals() (catalogue.Manifest, catalogue.Manifest) { claim := []catalogue.Claim{{Name: "the-seat", Scope: catalogue.ScopeNode}} return catalogue.Manifest{Module: "rival-one", Version: "1", Claims: claim}, catalogue.Manifest{Module: "rival-two", Version: "1", Claims: claim} }