buildrun leaves mesh-sdk for the builder's own Go module (ADR 0593 §1); the checker, assigner, indexer and watchman require it by a replace to the sibling directory. Issue 1930's bound was already on mesh-sdk's main and moves with it. The builder copies the imports a build module answers to the done key and the log's end entry, where the indexer keeps them (§2; D7). Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
74 lines
2.9 KiB
Go
74 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"log"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/process"
|
|
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// 1945 (a part exits at start for a bucket it works without): a bus that refuses every toolchains bucket leaves the
|
|
// watch unstarted and the part running, said; a refused bucket it cannot work without is an error naming the bucket and
|
|
// its grant. The gate over the seat's placement, and its refusal, are mesh-sdk's (buildrun.ToolchainGate,
|
|
// issue 774).
|
|
func TestARefusedBucketIsSaidAndThePartGoesOn(t *testing.T) {
|
|
set := &buildrun.ToolchainSet{}
|
|
var logs bytes.Buffer
|
|
logger := log.New(&logs, "", 0)
|
|
refused := refusingBus{err: errors.New("nats: permissions violation for publish to $JS.API.CONSUMER.CREATE.KV_mesh-build-node_toolchains")}
|
|
if err := newToolchainWatch(context.Background(), refusingBus{refuseOpen: true, err: refused.err}, set, func(context.Context) {}, logger).start(); err != nil {
|
|
t.Errorf("a refused toolchains bucket stopped the start: %v", err)
|
|
}
|
|
if !strings.Contains(logs.String(), "cannot be read") {
|
|
t.Errorf("the refusals were not said: %q", logs.String())
|
|
}
|
|
if _, err := process.EssentialBucket(context.Background(), refusingBus{refuseOpen: true, err: refused.err}, "builder", "mesh-delivery-indexer_modules", "work"); err == nil ||
|
|
!strings.Contains(err.Error(), "grant of mesh-delivery-indexer_modules") {
|
|
t.Errorf("a refused bucket the part needs: %v, want an error naming its grant", err)
|
|
}
|
|
// The gate's source (the previews' trunk heads): refused at start, the builder goes on, and a candidate asking a trunk
|
|
// head is told why and opens it again then.
|
|
src := &trunkSource{ctx: context.Background(), js: refusingBus{refuseOpen: true, err: refused.err}, heads: &sourceHeads{}, errs: make(chan error, 1), logf: logger.Printf}
|
|
src.start()
|
|
if _, err := src.head(context.Background(), 7, "novox/mesh-catalog"); err == nil || !strings.Contains(err.Error(), delivery.SourceBucket) {
|
|
t.Errorf("a trunk head with the source refused: %v, want why", err)
|
|
}
|
|
if src.opened {
|
|
t.Error("a refused source counts as opened, so it is never opened again")
|
|
}
|
|
}
|
|
|
|
// refusingBus is a bus that refuses: every open (refuseOpen), or every watch of a bucket it opens, with err.
|
|
type refusingBus struct {
|
|
refuseOpen bool
|
|
err error
|
|
}
|
|
|
|
func (r refusingBus) KeyValue(context.Context, string) (jetstream.KeyValue, error) {
|
|
if r.refuseOpen {
|
|
return nil, r.err
|
|
}
|
|
return refusedWatch{err: r.err}, nil
|
|
}
|
|
|
|
type refusedWatch struct {
|
|
jetstream.KeyValue
|
|
err error
|
|
}
|
|
|
|
func (r refusedWatch) WatchAll(context.Context, ...jetstream.WatchOpt) (jetstream.KeyWatcher, error) {
|
|
return nil, r.err
|
|
}
|
|
func (r refusedWatch) Watch(context.Context, string, ...jetstream.WatchOpt) (jetstream.KeyWatcher, error) {
|
|
return nil, r.err
|
|
}
|