mesh/merge-gate head 181b579ac6ea merged into trunk 22c9815f6522 — pass: builds mesh-controller → novox; no bus step; every machine composes with the chang…
mesh/repo-check head 181b579ac6ea merged into trunk 22c9815f6522 — pass: its merge-check.sh passed
mesh/delivery delivered
136 lines
5.1 KiB
Go
136 lines
5.1 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/compose"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
"github.com/novox/mesh-controller/internal/testbus"
|
|
)
|
|
|
|
func gainedAndPlain(t *testing.T) (plain, gained catalogue.Manifest) {
|
|
t.Helper()
|
|
plain, err := catalogue.ParseManifest([]byte(`{"module":"mesh-mail","version":"1",
|
|
"own-secrets":{"broker-send":{"path":"/var/lib/mesh-mail/broker-send","owner":"mesh-mail-send"}},
|
|
"resources":[{"id":"account","type":"user","name":"mesh-mail-send"}]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return plain, mailSenderWithProcess()
|
|
}
|
|
|
|
// 1226/AC2: given an assigned module whose new definition adds a bus process, when the delivery records it
|
|
// (takeIn, the function that records a build result), the process's account is minted; and 1226/AC3: the same
|
|
// build heard again replaces nothing.
|
|
func TestAGainedProcessIsIssuedWhenTheDeliveryRecordsIt(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
inv := open.inventory
|
|
|
|
dir := t.TempDir()
|
|
if err := busCertificate([]string{"--into", dir}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv(broker.AddressVar, strings.TrimPrefix(testbus.URL(t), "nats://"))
|
|
t.Setenv(broker.CertificateVar, filepath.Join(dir, "tls.crt"))
|
|
|
|
plain, gained := gainedAndPlain(t)
|
|
register(t, open, plain)
|
|
if _, err := assign(ctx, open, "laptop", "mesh-mail"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, minted, _ := inv.BusUserHash(ctx, "laptop.mesh-mail.send"); minted {
|
|
t.Fatal("the account was minted before the module gained the process")
|
|
}
|
|
|
|
manifest, _ := json.Marshal(gained)
|
|
build := func(id, commit string) {
|
|
t.Helper()
|
|
if _, _, err := takeIn(ctx, inv, asTheOperator(t, inv, link.BuildResult{
|
|
ID: id, Repository: "http://forge.internal:20000/novox/mesh-mail.git", Path: "modules/mesh-mail",
|
|
Ref: "main", On: "anchor", Commit: commit, Manifest: manifest,
|
|
Source: &link.SourceOnSeat{Seat: "git", Repository: "novox/mesh-mail"},
|
|
})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
build("b-1", "aaaaaaa1111")
|
|
hash, held, err := inv.BusUserHash(ctx, "laptop.mesh-mail.send")
|
|
if err != nil || !held {
|
|
t.Fatalf("1226/AC2: recording the gained definition did not mint the process's account: held %v, %v", held, err)
|
|
}
|
|
// And the next compose carries the account, with no warning (1226/AC2).
|
|
var said bytes.Buffer
|
|
if _, err := prepareSend(leftOutSaidBy(ctx, &said), open, "laptop"); err != nil {
|
|
t.Fatalf("1226/AC2: the next compose failed: %v", err)
|
|
}
|
|
if strings.Contains(said.String(), "bus account is not issued") {
|
|
t.Fatalf("1226/AC2: the next compose warns of an account just minted: %q", said.String())
|
|
}
|
|
// The row the compose reads is the account issueProcess accepted (origin accepted), never a value the mesh
|
|
// made for it (a stand-in).
|
|
in, err := inputFor(ctx, open)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var row *compose.OwnSecretRow
|
|
for i, r := range in.OwnSecrets {
|
|
if r.Node == "laptop" && r.Module == "mesh-mail" && r.Name == "broker-send" {
|
|
row = &in.OwnSecrets[i]
|
|
}
|
|
}
|
|
if row == nil {
|
|
t.Fatal("1226/AC2: the next compose carries no row for the process's account")
|
|
}
|
|
if row.Origin != inventory.OriginAccepted {
|
|
t.Fatalf("1226/AC2: the process's account is a stand-in the mesh made (origin %q), not the issued account", row.Origin)
|
|
}
|
|
build("b-2", "bbbbbbb2222")
|
|
again, _, err := inv.BusUserHash(ctx, "laptop.mesh-mail.send")
|
|
if err != nil || again != hash {
|
|
t.Fatalf("1226/AC3: recording again replaced the issued account (%v)", err)
|
|
}
|
|
}
|
|
|
|
// 1226/AC1 and AC4 against the store: given two modules on a machine, one with an unissued process account, when
|
|
// the machine is composed, the rest of it is composed and sent, and only the warning in the push's answer names
|
|
// the first, with `mesh-controller.issue <node> <module>`.
|
|
func TestAnUnissuedProcessAccountIsWarnedOfAndTheRestIsComposed(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
_, gained := gainedAndPlain(t)
|
|
register(t, open, gained)
|
|
other := catalogue.Manifest{Module: "other", Version: "1",
|
|
OwnSecrets: catalogue.OwnSecrets{"token": {Path: "/var/lib/other/token"}}}
|
|
register(t, open, other)
|
|
for _, m := range []string{"mesh-mail", "other"} {
|
|
if _, err := assign(ctx, open, "laptop", m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
var said bytes.Buffer
|
|
if _, err := prepareSend(leftOutSaidBy(ctx, &said), open, "laptop"); err != nil {
|
|
t.Fatalf("1226/AC4: an unissued process account held the machine: %v", err)
|
|
}
|
|
want := "laptop/mesh-mail process send: its bus account is not issued — mesh-controller.issue laptop mesh-mail"
|
|
if !strings.Contains(said.String(), want) {
|
|
t.Fatalf("1226/AC1: the push says %q, want %q", said.String(), want)
|
|
}
|
|
if strings.Contains(said.String(), "other") {
|
|
t.Fatalf("1226/AC4: the other module is warned of: %q", said.String())
|
|
}
|
|
if _, held, err := open.inventory.ModuleSecretIfIssued(ctx, "laptop", "other", "token"); err != nil || !held {
|
|
t.Fatalf("1226/AC4: the other module's secret was not composed: held %v, %v", held, err)
|
|
}
|
|
}
|