105 lines
5.3 KiB
Go
105 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"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"}]}}`
|
|
_, 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" {
|
|
t.Fatalf("the credential forms are read as %v", forms)
|
|
}
|
|
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")
|
|
}
|
|
}
|