Delete go/provisions: no importer is left in any tree; the list of packages and notInSDK follow (S-7, ADR 0634 §5; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -25,7 +25,7 @@ import (
|
||||
var meshSDKPackages = []string{
|
||||
".", "announce", "announcetest", "buildstep", "buscalls", "buscompose", "busstate", "busretry", "calladdress", "catalogue",
|
||||
"declaration", "delivery", "forgekey", "health", "internal/beside", "keys", "kvlimit", "membership", "motion",
|
||||
"objectlink", "outward", "overlay", "pernode", "process", "provisions",
|
||||
"objectlink", "outward", "overlay", "pernode", "process",
|
||||
"sdkversion", "seal", "seatdef", "seatlist", "seatlist/seatlisttest", "testbus", "views", "views/viewstest",
|
||||
}
|
||||
|
||||
@@ -39,14 +39,13 @@ var clientSeats = []string{"operator-channel", "mesh-vault", "node-engine", "npm
|
||||
var moduleWord = regexp.MustCompile(`\bmesh-(?:delivery|grants|vault|host|config|provisioner|broker|knowledge|enrolment)\b[-a-z]*|\b(?:indexer|assigner|teller|watchman|checker|builder)(?:-views|_read_)`)
|
||||
|
||||
// notInSDK are the packages that moved to a seat's client or contract (ADR 0627 §1, §4) and may not come back.
|
||||
var notInSDK = []string{"asks", "asker", "publish", "composer", "parts", "provider", "handacts", "channel"}
|
||||
var notInSDK = []string{"asks", "asker", "publish", "composer", "parts", "provider", "handacts", "channel", "provisions"}
|
||||
|
||||
// untilTheJoin is what ADR 0627 still moves at the group's join, each `<file>: <what>`, naming what the checks below
|
||||
// would refuse; it only shrinks. The vault module's name in delivery and provisions stays past this milestone's pin
|
||||
// would refuse; it only shrinks. The vault module's name in delivery stays past this milestone's pin
|
||||
// (issue 1966 note 28) and goes in the next milestone, when the vault's answers are its contract's.
|
||||
var untilTheJoin = []string{
|
||||
"delivery/signers.go: mesh-vault",
|
||||
"provisions/provisions.go: mesh-vault",
|
||||
// Names of whole seats in packages that leave in S-7 (delivery, buscompose's grants-part names), with their packages.
|
||||
"delivery/builder.go: container-image-registry",
|
||||
"delivery/builder.go: oci-artifact-registry",
|
||||
|
||||
@@ -1,310 +0,0 @@
|
||||
// Package provisions is the contract of the seat mesh-provisioner's records (novox/hq ADR 0570 clauses 1, 2 and 5; issue
|
||||
// 1954): every provision one key of the state `provisions`, holding a reference and never a value, and every handed
|
||||
// module's provisioning plan one key of the state `plans`. The module mesh-provisioner alone writes both; the vault,
|
||||
// each node's provisioner client and every provider read them through `reads`.
|
||||
package provisions
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
|
||||
// The seat, its holder and its two states, and the names a reader declares in its `reads`.
|
||||
const (
|
||||
Seat = "mesh-provisioner"
|
||||
Module = "mesh-provisioner"
|
||||
ProvisionsState = "provisions"
|
||||
PlansState = "plans"
|
||||
ProvisionsRead = Module + "." + ProvisionsState
|
||||
PlansRead = Module + "." + PlansState
|
||||
// ProvisionsBucket and PlansBucket are the states' buckets.
|
||||
ProvisionsBucket = Module + "_" + ProvisionsState
|
||||
PlansBucket = Module + "_" + PlansState
|
||||
)
|
||||
|
||||
// The states of a provision (clause 1).
|
||||
const (
|
||||
// Asked is a provision its consumer needs that its provider has not answered yet, or whose dependencies are not
|
||||
// all provided (clause 3).
|
||||
Asked = "asked"
|
||||
// Provided is a provision the provider said it made: set only from the provider's outcome (clause 3).
|
||||
Provided = "provided"
|
||||
// Waits is a provision only a person can give, naming what is awaited (clause 7).
|
||||
Waits = "waits"
|
||||
// Failed is a provision the provider could not make, with why.
|
||||
Failed = "failed"
|
||||
// Retiring is a provision no want needs, asked of the operator before its credential goes (clause 5).
|
||||
Retiring = "retiring"
|
||||
)
|
||||
|
||||
// States is every state a provision may be in.
|
||||
var States = []string{Asked, Provided, Waits, Failed, Retiring}
|
||||
|
||||
// Version is the version of the records' layout.
|
||||
const Version = 1
|
||||
|
||||
// token is one part of a key: what a bucket's key takes, no dot.
|
||||
var token = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
|
||||
|
||||
// Key is a provision's key: `<node>.<consumer>.<provision>`, and `.<local>` where the consumer keeps several values of
|
||||
// one provision (ADR 0094). The same key the provider's own entry for that consumer has (provider.Entry.Key).
|
||||
func Key(node, consumer, provision, local string) (string, error) {
|
||||
parts := []string{node, consumer, provision}
|
||||
if local != "" {
|
||||
parts = append(parts, local)
|
||||
}
|
||||
for _, p := range parts {
|
||||
if !token.MatchString(p) {
|
||||
return "", fmt.Errorf("provisions: %q cannot be part of a provision's key", p)
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, "."), nil
|
||||
}
|
||||
|
||||
// ParseKey is the inverse of Key.
|
||||
func ParseKey(key string) (node, consumer, provision, local string, err error) {
|
||||
parts := strings.Split(key, ".")
|
||||
if len(parts) < 3 || len(parts) > 4 {
|
||||
return "", "", "", "", fmt.Errorf("provisions: %q is not <node>.<consumer>.<provision>[.<local>]", key)
|
||||
}
|
||||
for _, p := range parts {
|
||||
if !token.MatchString(p) {
|
||||
return "", "", "", "", fmt.Errorf("provisions: %q is not <node>.<consumer>.<provision>[.<local>]", key)
|
||||
}
|
||||
}
|
||||
if len(parts) == 4 {
|
||||
local = parts[3]
|
||||
}
|
||||
return parts[0], parts[1], parts[2], local, nil
|
||||
}
|
||||
|
||||
// PlanKey is a plan's key in `plans`: `<node>.<module>` (clause 2).
|
||||
func PlanKey(node, module string) (string, error) {
|
||||
if !token.MatchString(node) || !token.MatchString(module) {
|
||||
return "", fmt.Errorf("provisions: %s.%s is not a plan's key, <node>.<module>", node, module)
|
||||
}
|
||||
return node + "." + module, nil
|
||||
}
|
||||
|
||||
// The forms of a provision's credential, as a plan's entry names them (catalogue.PlanProvision.CredentialForm): the
|
||||
// catalogue's one list (catalogue.CredentialForms, issue 774), under the names this package has used.
|
||||
const (
|
||||
FormPair = catalogue.CredentialFormPair
|
||||
FormShared = catalogue.CredentialFormShared
|
||||
FormIssued = catalogue.CredentialFormIssued
|
||||
FormGiven = catalogue.CredentialFormGiven
|
||||
// FormNone is an offer whose consumers present no credential (catalogue.CredentialFormNone): the vault mints nothing,
|
||||
// and the provision depends on no credential.
|
||||
FormNone = catalogue.CredentialFormNone
|
||||
)
|
||||
|
||||
// VaultName is the vault's name of a provision's credential in form, as its verb `own` names it and the provider asks
|
||||
// it: `pair/<provider node>/<provision>/<consumer node>/<module>[/<local>]` for a login of the consumer's own (ADR 0158
|
||||
// §11), `provision/<provider node>/<provision>` for the provider's one shared value, and `provision/<provider
|
||||
// node>/<provision>/<consumer node>/<module>` for a holder's own issued or given value. Empty for a form with no
|
||||
// credential.
|
||||
func VaultName(form string, p Provision) string {
|
||||
switch form {
|
||||
case FormPair:
|
||||
n := "pair/" + p.Provider.Node + "/" + p.Provision + "/" + p.Consumer.Node + "/" + p.Consumer.Module
|
||||
if p.Local != "" {
|
||||
n += "/" + p.Local
|
||||
}
|
||||
return n
|
||||
case FormShared:
|
||||
return "provision/" + p.Provider.Node + "/" + p.Provision
|
||||
case FormIssued, FormGiven:
|
||||
return "provision/" + p.Provider.Node + "/" + p.Provision + "/" + p.Consumer.Node + "/" + p.Consumer.Module
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// VaultModule is the provider of every provision's credential (novox/hq ADR 0570 clauses 1, 6).
|
||||
const VaultModule = "mesh-vault"
|
||||
|
||||
// CredentialKey is the key of a provision's credential, itself a provision whose provider is the vault (clause 6; the
|
||||
// key form the lead settled on 2026-10-29): `<consumer node>.<consumer>.secret-<provision>[.<local>]` for a value of the
|
||||
// consumer's own (pair, issued, given), and `<provider node>.<provider>.secret-<provision>` for the provider's one
|
||||
// shared value. False for a form with no vault value, and for a provision the vault itself provides.
|
||||
func CredentialKey(form string, consumer, provider End, provision, local string) (string, bool) {
|
||||
if provider.Module == VaultModule {
|
||||
return "", false // the vault's own offer is the value: it has no credential beside it (the lead, 2026-10-29)
|
||||
}
|
||||
name := catalogue.CredentialProvisionPrefix + provision
|
||||
switch form {
|
||||
case FormPair, FormIssued, FormGiven:
|
||||
k, err := Key(consumer.Node, consumer.Module, name, local)
|
||||
return k, err == nil
|
||||
case FormShared:
|
||||
k, err := Key(provider.Node, provider.Module, name, "")
|
||||
return k, err == nil
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// DependsOn is what a provision waits for before its provider makes it (clause 3): its credential's key, where its form
|
||||
// has a vault value, and the key of every provision its provider module itself requires on its own node, read from
|
||||
// the provider's plan there (nil when the provider is not handed and has none). Sorted, none twice.
|
||||
func DependsOn(consumer End, entry catalogue.PlanProvision, providerPlan *catalogue.Plan) []string {
|
||||
seen := map[string]bool{}
|
||||
var out []string
|
||||
add := func(k string) {
|
||||
if k != "" && !seen[k] {
|
||||
seen[k] = true
|
||||
out = append(out, k)
|
||||
}
|
||||
}
|
||||
provider := End{Module: entry.ProviderModule, Node: entry.Provider}
|
||||
if k, ok := CredentialKey(entry.CredentialForm, consumer, provider, entry.Provision, entry.Local); ok {
|
||||
add(k)
|
||||
}
|
||||
if providerPlan != nil {
|
||||
for _, own := range providerPlan.Provisions {
|
||||
if k, err := Key(provider.Node, provider.Module, own.Provision, own.Local); err == nil {
|
||||
add(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// End is one end of a provision: a module on a node.
|
||||
type End struct {
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
}
|
||||
|
||||
// Reference is a value the vault keeps, by its id and the generation of the value: never the value, sealed or not
|
||||
// (ADR 0349 §7). The holder writes the generation the vault says in its own entry (clause 6). ID is the vault's name of
|
||||
// the credential exactly as its verb `own` names it (VaultName): the consuming node's engine checks both the name and
|
||||
// the generation of what it is handed.
|
||||
type Reference struct {
|
||||
ID string `json:"id"`
|
||||
Generation int `json:"generation"`
|
||||
}
|
||||
|
||||
// Warrant is the operator's answer to a retiring provision's ask, as the holder writes it into the key (clause 5).
|
||||
type Warrant struct {
|
||||
Ask string `json:"ask"`
|
||||
Option string `json:"option"`
|
||||
By string `json:"by"`
|
||||
At time.Time `json:"at"`
|
||||
}
|
||||
|
||||
// Provision is one key of `provisions`.
|
||||
type Provision struct {
|
||||
V int `json:"v"`
|
||||
Provision string `json:"provision"`
|
||||
Local string `json:"local,omitempty"`
|
||||
Consumer End `json:"consumer"`
|
||||
Provider End `json:"provider"`
|
||||
// DependsOn are the keys of the provisions this one waits for (clause 3): a database user whose password is the
|
||||
// vault's.
|
||||
DependsOn []string `json:"depends-on,omitempty"`
|
||||
State string `json:"state"`
|
||||
// Why is the reason for waits, failed and retiring, and for asked when a dependency holds it.
|
||||
Why string `json:"why,omitempty"`
|
||||
Reference *Reference `json:"reference,omitempty"`
|
||||
// Ask is a retiring provision's ask of the operator; Warrant the answer, once given.
|
||||
Ask string `json:"ask,omitempty"`
|
||||
Warrant *Warrant `json:"warrant,omitempty"`
|
||||
// Plan is the plan entry the key was composed from, at the consumer's wanted build or its newest (issue 1126): the
|
||||
// provider binds the consumer from it, so a requirement the newest build adds is provided before the want that
|
||||
// waits for it moves, though the plan the seat keeps at the wanted build names it not yet.
|
||||
Plan *catalogue.PlanProvision `json:"plan,omitempty"`
|
||||
At time.Time `json:"at"`
|
||||
}
|
||||
|
||||
// Key is the provision's key.
|
||||
func (p Provision) Key() (string, error) {
|
||||
return Key(p.Consumer.Node, p.Consumer.Module, p.Provision, p.Local)
|
||||
}
|
||||
|
||||
func (p Provision) check() error {
|
||||
if _, err := p.Key(); err != nil {
|
||||
return err
|
||||
}
|
||||
if p.Provider.Module == "" || p.Provider.Node == "" {
|
||||
return fmt.Errorf("provisions: %s names no provider", p.Provision)
|
||||
}
|
||||
known := false
|
||||
for _, s := range States {
|
||||
known = known || s == p.State
|
||||
}
|
||||
switch {
|
||||
case !known:
|
||||
return fmt.Errorf("provisions: a provision's state is one of %s, not %q", strings.Join(States, ", "), p.State)
|
||||
case (p.State == Waits || p.State == Failed || p.State == Retiring) && strings.TrimSpace(p.Why) == "":
|
||||
return fmt.Errorf("provisions: a %s provision says why", p.State)
|
||||
case p.Warrant != nil && p.State != Retiring:
|
||||
return fmt.Errorf("provisions: only a retiring provision carries the operator's warrant")
|
||||
}
|
||||
for _, d := range p.DependsOn {
|
||||
if _, _, _, _, err := ParseKey(d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode is p as JSON at Version; it refuses what a holder may not write.
|
||||
func Encode(p Provision) ([]byte, error) {
|
||||
p.V = Version
|
||||
if err := p.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// Decode reads a key's value. **A field the layout does not name is read past and dropped** (issue 1126 review 1): a
|
||||
// reader on an older mesh-sdk must not refuse a key a newer writer adds a field to. No value rides in a provision all
|
||||
// the same (clause 1, ADR 0201 §13): Encode writes the layout alone, so what a reader does not know is never kept.
|
||||
func Decode(data []byte) (Provision, error) {
|
||||
var p Provision
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
if err := dec.Decode(&p); err != nil {
|
||||
return Provision{}, fmt.Errorf("provisions: a provision is not readable: %w", err)
|
||||
}
|
||||
if p.V != Version {
|
||||
return Provision{}, fmt.Errorf("provisions: a provision of version %d, and this reads %d", p.V, Version)
|
||||
}
|
||||
return p, p.check()
|
||||
}
|
||||
|
||||
// Plan is one key of `plans`: a module's provisioning plan on a node, never a value (clause 2).
|
||||
type Plan struct {
|
||||
V int `json:"v"`
|
||||
Node string `json:"node"`
|
||||
Module string `json:"module"`
|
||||
Plan catalogue.Plan `json:"plan"`
|
||||
}
|
||||
|
||||
// EncodePlan is p as JSON at Version.
|
||||
func EncodePlan(p Plan) ([]byte, error) {
|
||||
p.V = Version
|
||||
if _, err := PlanKey(p.Node, p.Module); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// DecodePlan reads a plan's key.
|
||||
func DecodePlan(data []byte) (Plan, error) {
|
||||
var p Plan
|
||||
if err := json.Unmarshal(data, &p); err != nil {
|
||||
return Plan{}, fmt.Errorf("provisions: a plan is not readable: %w", err)
|
||||
}
|
||||
if p.V != Version {
|
||||
return Plan{}, fmt.Errorf("provisions: a plan of version %d, and this reads %d", p.V, Version)
|
||||
}
|
||||
_, err := PlanKey(p.Node, p.Module)
|
||||
return p, err
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package provisions
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
|
||||
// ADR 0570 clauses 1, 2 and 5 (issue 1954 L6-P2): a provision's key is its consumer's node and module, the provision and
|
||||
// its local name, the provider's entry's key; its value round-trips, names its state and why, and refuses any field the
|
||||
// layout does not name, so no value rides in it; a plan's key is its node and module.
|
||||
func TestAProvisionIsAReferenceUnderItsConsumersKey(t *testing.T) {
|
||||
at := time.Date(2026, 10, 29, 22, 0, 0, 0, time.UTC)
|
||||
db := Provision{Provision: "postgres-database", Consumer: End{Module: "keycloak", Node: "novox"},
|
||||
Provider: End{Module: "postgres", Node: "novox"}, DependsOn: []string{"novox.keycloak.secret.db"}, State: Asked,
|
||||
Reference: &Reference{ID: "provision/postgres/postgres-database", Generation: 2}, At: at}
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
edit func(*Provision)
|
||||
key string
|
||||
refused string
|
||||
}{
|
||||
{name: "asked, depending on the vault's", key: "novox.keycloak.postgres-database"},
|
||||
{name: "under a local name", edit: func(p *Provision) { p.Local = "replica" }, key: "novox.keycloak.postgres-database.replica"},
|
||||
{name: "retiring with the operator's warrant", edit: func(p *Provision) {
|
||||
p.State, p.Why, p.Ask = Retiring, "keycloak left novox", "a-1"
|
||||
p.Warrant = &Warrant{Ask: "a-1", Option: "yes", By: "the operator", At: at}
|
||||
}, key: "novox.keycloak.postgres-database"},
|
||||
{name: "an unknown state", edit: func(p *Provision) { p.State = "done" }, refused: "one of"},
|
||||
{name: "failed without why", edit: func(p *Provision) { p.State = Failed }, refused: "says why"},
|
||||
{name: "a warrant on a provided one", edit: func(p *Provision) { p.State, p.Warrant = Provided, &Warrant{Ask: "a"} }, refused: "only a retiring"},
|
||||
{name: "no provider", edit: func(p *Provision) { p.Provider = End{} }, refused: "no provider"},
|
||||
{name: "a dotted consumer", edit: func(p *Provision) { p.Consumer.Module = "a.b" }, refused: "cannot be part"},
|
||||
{name: "a dependency that is no key", edit: func(p *Provision) { p.DependsOn = []string{"x"} }, refused: "is not"},
|
||||
} {
|
||||
p := db
|
||||
if c.edit != nil {
|
||||
c.edit(&p)
|
||||
}
|
||||
raw, err := Encode(p)
|
||||
if c.refused != "" {
|
||||
if err == nil || !strings.Contains(err.Error(), c.refused) {
|
||||
t.Errorf("%s: %v, want refused saying %q", c.name, err, c.refused)
|
||||
}
|
||||
continue
|
||||
}
|
||||
back, err := Decode(raw)
|
||||
key, kerr := back.Key()
|
||||
if err != nil || kerr != nil || key != c.key || back.V != Version || back.Reference.Generation != 2 {
|
||||
t.Errorf("%s: read back as %+v under %q, %v %v", c.name, back, key, err, kerr)
|
||||
}
|
||||
if node, consumer, provision, local, err := ParseKey(key); err != nil || node != "novox" || consumer != "keycloak" ||
|
||||
provision != "postgres-database" || local != p.Local {
|
||||
t.Errorf("%s: %s parses as %s %s %s %s, %v", c.name, key, node, consumer, provision, local, err)
|
||||
}
|
||||
}
|
||||
// A field a later layout adds is read past, never kept (issue 1126 review 1: a reader on an older mesh-sdk must not
|
||||
// refuse a key a newer writer adds a field to). A value still never rides in a provision: Encode writes the layout
|
||||
// alone, so what a reader does not know is dropped, and encoding it again carries none of it.
|
||||
later, err := Decode([]byte(`{"v":1,"provision":"p","consumer":{"module":"c","node":"n"},"provider":{"module":"p","node":"n"},` +
|
||||
`"state":"provided","at":"2026-10-29T22:00:00Z","a-later-field":{"x":1},"password":"hunter2"}`))
|
||||
if err != nil || later.Provision != "p" || later.State != Provided {
|
||||
t.Errorf("a provision with a field of a later layout: %+v, %v", later, err)
|
||||
}
|
||||
if again, _ := Encode(later); strings.Contains(string(again), "hunter2") || strings.Contains(string(again), "a-later-field") {
|
||||
t.Errorf("a field the layout does not name was kept: %s", again)
|
||||
}
|
||||
plan := Plan{Node: "novox", Module: "restic", Plan: catalogue.Plan{}}
|
||||
raw, err := EncodePlan(plan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if back, err := DecodePlan(raw); err != nil || back.Node != "novox" || back.Module != "restic" {
|
||||
t.Errorf("a plan read back as %+v, %v", back, err)
|
||||
}
|
||||
if k, err := PlanKey("novox", "restic"); k != "novox.restic" || err != nil {
|
||||
t.Errorf("a plan's key is %q, %v", k, err)
|
||||
}
|
||||
// A reference's id is the vault's name as its verb own names it, in each form (the host agent, 2026-10-29).
|
||||
for form, want := range map[string]string{FormPair: "pair/novox/postgres-database/novox/keycloak", FormShared: "provision/novox/postgres-database",
|
||||
FormIssued: "provision/novox/postgres-database/novox/keycloak", FormNone: ""} {
|
||||
if got := VaultName(form, db); got != want {
|
||||
t.Errorf("the %s name is %q", form, got)
|
||||
}
|
||||
}
|
||||
if got := VaultName(FormPair, Provision{Provision: "p", Local: "r", Provider: End{Node: "a"}, Consumer: End{Node: "b", Module: "m"}}); got != "pair/a/p/b/m/r" {
|
||||
t.Errorf("a local name's pair is %q", got)
|
||||
}
|
||||
// A provision waits for its credential, the vault's provision `secret-<provision>`, and for what its provider itself
|
||||
// requires on its node (clause 3; the key form the lead settled on 2026-10-29).
|
||||
keycloak, postgres := End{Module: "keycloak", Node: "novox"}, End{Module: "postgres", Node: "ace"}
|
||||
providerPlan := &catalogue.Plan{Provisions: []catalogue.PlanProvision{{Provision: "backup-target", Provider: "ace", ProviderModule: "restic"}}}
|
||||
for _, c := range []struct {
|
||||
form string
|
||||
plan *catalogue.Plan
|
||||
want string
|
||||
}{
|
||||
{FormPair, nil, "novox.keycloak.secret-postgres-database"},
|
||||
{FormShared, nil, "ace.postgres.secret-postgres-database"},
|
||||
{FormPair, providerPlan, "ace.postgres.backup-target,novox.keycloak.secret-postgres-database"},
|
||||
{"", nil, ""},
|
||||
// An offer with no credential (the lead, 2026-10-29): nothing minted, nothing to wait for.
|
||||
{FormNone, nil, ""},
|
||||
} {
|
||||
entry := catalogue.PlanProvision{Provision: "postgres-database", Provider: postgres.Node, ProviderModule: postgres.Module,
|
||||
CredentialForm: c.form}
|
||||
if got := strings.Join(DependsOn(keycloak, entry, c.plan), ","); got != c.want {
|
||||
t.Errorf("%q depends on %q, want %q", c.form, got, c.want)
|
||||
}
|
||||
}
|
||||
// The vault's own offer is the value: no secret-secret beside it.
|
||||
vaultEntry := catalogue.PlanProvision{Provision: "secret", Provider: "novox", ProviderModule: VaultModule, CredentialForm: FormPair}
|
||||
if got := DependsOn(keycloak, vaultEntry, nil); len(got) != 0 {
|
||||
t.Errorf("the vault's secret depends on %v", got)
|
||||
}
|
||||
if ProvisionsBucket != "mesh-provisioner_provisions" || PlansRead != "mesh-provisioner.plans" {
|
||||
t.Errorf("the states are %s and %s", ProvisionsBucket, PlansRead)
|
||||
}
|
||||
}
|
||||
Vendored
-2
@@ -42,6 +42,4 @@ health/findings.go: mesh-healers
|
||||
health/findings.go: mesh-self-check
|
||||
internal/beside/beside.go: mesh-catalog
|
||||
overlay/overlay.go: the-private-network
|
||||
provisions/provisions.go: mesh-provisioner
|
||||
provisions/provisions.go: mesh-vault
|
||||
seatlist/seatlist.go: mesh-catalog
|
||||
|
||||
Reference in New Issue
Block a user