Files
mesh-catalog/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/providers_test.go
T
jschoubben 67dcf252ec
mesh/delivery merged: source.main moved to novox/mesh-catalog@72cee59acc32
mesh/delivery-group group fix/credential-forms-one-list merged: every member is merged
mesh/check checking 67dcf252ecfa on 82ac613b4ed0 | novox/mesh-catalog#564 in group fix/credential-forms-one-list
Check a plan's credential form against mesh-sdk's one list, so the client takes plans naming none again (issue 774)
Since 13:55 the client refused every plan with credential-form none
(gitea's forge-account, the artifact store), and g14 and shanks placed no
files for mesh-build-go, mesh-build-node, mesh-build-image or ssh-client.
Second meeting of the credential-form list kind: the controller's copy was
fixed alone before. Thorough: one list in mesh-sdk; this client drops its
copy and pins mesh-sdk 9379e9a. A none entry is never a holder's issued
value: its bound values come from the provider's entry, and a secret named
for it fails loudly instead of waiting on a vault that mints nothing.
2026-10-30 16:06:46 +01:00

128 lines
6.7 KiB
Go

package main
import (
"context"
"reflect"
"strings"
"testing"
)
// A plan names, for each provision its module requires, the provider serving it (design 57 V5a, issue 760): the
// client reads that strictly, before the controller writes it, and fills nothing from an entry with no credential;
// the vault acts on it.
func TestAPlanNamingItsProvidersIsRead(t *testing.T) {
value := `{"node":"g14","module":"app","provisioning":{` +
`"templates":{"source":"x","digest":"sha256:` + strings.Repeat("0", 64) + `"},` +
`"files":[{"id":"conf","path":"/etc/app.conf","template":"app.conf","owner-at-runtime":"owned"}],` +
`"provisions":[{"provision":"postgres-database","provider":"novox","provider-module":"postgres"},` +
`{"provision":"s3-bucket","local":"hot","provider":"ace","provider-module":"minio"},` +
`{"name":"forge-read","provision":"forge-read","provider":"novox","provider-module":"forge",` +
`"path":"/var/lib/app/forge.secret"}]}}`
_, p, err := planOf("g14", "g14.app", []byte(value))
if err != nil {
t.Fatal(err)
}
want := []PlannedProvision{{Provision: "postgres-database", Provider: "novox", ProviderModule: "postgres"},
{Provision: "s3-bucket", Local: "hot", Provider: "ace", ProviderModule: "minio"},
{Name: "forge-read", Provision: "forge-read", Provider: "novox", ProviderModule: "forge",
Path: "/var/lib/app/forge.secret"}}
if len(p.Provisions) != len(want) {
t.Fatalf("the plan's provisions are read as %+v, want %+v", p.Provisions, want)
}
for i := range want {
if !reflect.DeepEqual(p.Provisions[i], want[i]) {
t.Fatalf("the plan's provisions are read as %+v, want %+v", p.Provisions, want)
}
}
// Only the credential is a file to fill: an entry naming a provider alone fills nothing.
targets, why := fillTargets(p, map[string]string{"app.conf": "x"})
if why != "" || len(targets) != 2 || targets[1].Path != "/var/lib/app/forge.secret" {
t.Fatalf("the files filled are %+v (%s)", targets, why)
}
for why, provisions := range map[string][]PlannedProvision{
"a file and no credential's name": {{Provision: "p", Provider: "a", ProviderModule: "m", Path: "/var/lib/p"}},
"one provision and local twice": {{Provision: "p", Local: "l", Provider: "a", ProviderModule: "m"},
{Provision: "p", Local: "l", Provider: "b", ProviderModule: "m"}},
"no provider": {{Provision: "p", ProviderModule: "m"}},
} {
bad := p
bad.Provisions = provisions
if len(bad.problems()) == 0 {
t.Errorf("a plan with %s was taken", why)
}
}
}
// Each entry names the credential form of its provider's offer (issue 768), which the vault acts on: the client
// reads it strictly, before the controller writes it, and refuses a form it does not know.
func TestAPlanNamingEachProvidersCredentialFormIsRead(t *testing.T) {
value := `{"node":"g14","module":"app","provisioning":{` +
`"templates":{"source":"x","digest":"sha256:` + strings.Repeat("0", 64) + `"},` +
`"files":[{"id":"conf","path":"/etc/app.conf","template":"app.conf","owner-at-runtime":"owned"}],` +
`"provisions":[{"provision":"postgres-database","provider":"novox","provider-module":"postgres",` +
`"credential-form":"pair"},` +
`{"provision":"sonarr-api","provider":"ace","provider-module":"sonarr","credential-form":"shared"},` +
`{"name":"forge-read","provision":"forge-read","provider":"novox","provider-module":"forge",` +
`"credential-form":"issued","path":"/var/lib/app/forge.secret"},` +
`{"provision":"smtp-relay","provider":"ace","provider-module":"relay","credential-form":"given"},` +
// An offer with no credential (issue 774), as design 47's catalogue declares gitea's forge-account.
`{"provision":"forge-account","provider":"novox","provider-module":"gitea","credential-form":"none"}]}}`
_, p, err := planOf("g14", "g14.app", []byte(value))
if err != nil {
t.Fatal(err)
}
var forms []string
for _, pr := range p.Provisions {
forms = append(forms, pr.CredentialForm)
}
if strings.Join(forms, ",") != "pair,shared,issued,given,none" {
t.Fatalf("the credential forms are read as %v", forms)
}
// A none entry places no file of its own and is never a holder's issued value: its bound values are read from
// its provider's entry, and the plan's files are placed as they are.
targets, fail := fillTargets(p, map[string]string{"app.conf": "x"})
var paths []string
for _, f := range targets {
paths = append(paths, f.Path)
}
if fail != "" || strings.Join(paths, ",") != "/etc/app.conf,/var/lib/app/forge.secret" {
t.Fatalf("the plan places %v (%s)", paths, fail)
}
if none := (PlannedProvision{Name: "forge-account", CredentialForm: "none"}); none.issuedForHolder() {
t.Fatal("a credential of an offer with none is read as a holder's issued value")
}
// A template naming such a credential fails loudly, and the vault, which mints nothing for it, is never asked.
named := Plan{Provisions: []PlannedProvision{{Name: "forge-account", Provision: "forge-account", Provider: "novox",
CredentialForm: "none"}}}
if _, wait, fail := (&Client{Node: "g14"}).secretOf(context.Background(), nil, "app", named,
Need{Kind: "secret", Name: "forge-account"}); wait != "" || !strings.Contains(fail, "no credential (form none)") {
t.Fatalf("a secret of an offer with none: wait %q, fail %q", wait, fail)
}
bad := strings.Replace(value, `"credential-form":"pair"`, `"credential-form":"one-for-all"`, 1)
if _, _, err := planOf("g14", "g14.app", []byte(bad)); err == nil || !strings.Contains(err.Error(), "one-for-all") {
t.Fatalf("a credential form the client does not know was taken: %v", err)
}
}
// A consumer's plan entry may carry what its module contributes to the provider (issue 776): the client reads it
// strictly, keeps it on the entry, and still refuses any other field it does not know.
func TestAPlanEntryCarryingItsContributionIsRead(t *testing.T) {
value := `{"node":"g14","module":"app","provisioning":{` +
`"templates":{"source":"x","digest":"sha256:` + strings.Repeat("0", 64) + `"},` +
`"files":[{"id":"conf","path":"/etc/app.conf","template":"app.conf","owner-at-runtime":"owned"}],` +
`"provisions":[{"provision":"postgres-database","provider":"novox","provider-module":"postgres",` +
`"contributes":{"name":"nextcloud","extensions":["pg_trgm"]}}]}}`
_, p, err := planOf("g14", "g14.app", []byte(value))
if err != nil {
t.Fatal(err)
}
want := map[string]any{"name": "nextcloud", "extensions": []any{"pg_trgm"}}
if len(p.Provisions) != 1 || !reflect.DeepEqual(p.Provisions[0].Contributes, want) {
t.Fatalf("the plan's provisions are read as %+v, want the contribution %v kept", p.Provisions, want)
}
bad := strings.Replace(value, `"contributes":`, `"contribution":`, 1)
if _, _, err := planOf("g14", "g14.app", []byte(bad)); err == nil {
t.Error("a plan entry with a field the client does not know was taken")
}
}