mesh-provisioner: the provision's plan entry typed in the definition, and fixtures for its two states (ADR 0634 §6; issue 1966)
This commit is contained in:
@@ -184,6 +184,25 @@ type ProvisionsByNodeConsumerProvisionValueConsumer struct {
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValuePlan is the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126).
|
||||
type ProvisionsByNodeConsumerProvisionValuePlan struct {
|
||||
As string `json:"as,omitempty"`
|
||||
At string `json:"at,omitempty"`
|
||||
// the provider's own contract's bytes, carried unread
|
||||
Contributed map[string]any `json:"contributed,omitempty"`
|
||||
Contributes map[string]any `json:"contributes,omitempty"`
|
||||
CredentialForm any `json:"credential-form,omitempty"`
|
||||
CredentialTool string `json:"credential-tool,omitempty"`
|
||||
From string `json:"from,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Names map[string]string `json:"names,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderModule string `json:"provider-module"`
|
||||
Provision string `json:"provision"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValueProvider is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionValueProvider struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
@@ -211,8 +230,8 @@ type ProvisionsByNodeConsumerProvisionValue struct {
|
||||
Consumer ProvisionsByNodeConsumerProvisionValueConsumer `json:"consumer"`
|
||||
DependsOn []string `json:"depends-on,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
// the plan's provision
|
||||
Plan map[string]any `json:"plan,omitempty"`
|
||||
// the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126)
|
||||
Plan *ProvisionsByNodeConsumerProvisionValuePlan `json:"plan,omitempty"`
|
||||
Provider ProvisionsByNodeConsumerProvisionValueProvider `json:"provider"`
|
||||
Provision string `json:"provision"`
|
||||
Reference *ProvisionsByNodeConsumerProvisionValueReference `json:"reference,omitempty"`
|
||||
@@ -237,6 +256,25 @@ type ProvisionsByNodeConsumerProvisionLocalValueConsumer struct {
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValuePlan is the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126).
|
||||
type ProvisionsByNodeConsumerProvisionLocalValuePlan struct {
|
||||
As string `json:"as,omitempty"`
|
||||
At string `json:"at,omitempty"`
|
||||
// the provider's own contract's bytes, carried unread
|
||||
Contributed map[string]any `json:"contributed,omitempty"`
|
||||
Contributes map[string]any `json:"contributes,omitempty"`
|
||||
CredentialForm any `json:"credential-form,omitempty"`
|
||||
CredentialTool string `json:"credential-tool,omitempty"`
|
||||
From string `json:"from,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Names map[string]string `json:"names,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderModule string `json:"provider-module"`
|
||||
Provision string `json:"provision"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValueProvider is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionLocalValueProvider struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
@@ -264,8 +302,8 @@ type ProvisionsByNodeConsumerProvisionLocalValue struct {
|
||||
Consumer ProvisionsByNodeConsumerProvisionLocalValueConsumer `json:"consumer"`
|
||||
DependsOn []string `json:"depends-on,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
// the plan's provision
|
||||
Plan map[string]any `json:"plan,omitempty"`
|
||||
// the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126)
|
||||
Plan *ProvisionsByNodeConsumerProvisionLocalValuePlan `json:"plan,omitempty"`
|
||||
Provider ProvisionsByNodeConsumerProvisionLocalValueProvider `json:"provider"`
|
||||
Provision string `json:"provision"`
|
||||
Reference *ProvisionsByNodeConsumerProvisionLocalValueReference `json:"reference,omitempty"`
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package meshprovisioner
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/mesh-provisioner/fixtures: each decodes into its type, a field the type does not
|
||||
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
|
||||
func TestFixtures(t *testing.T) {
|
||||
cases := []struct {
|
||||
name, subject, given, wire string
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a database provision provided to a consumer under a local name", subject: "", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"consumer\":{\"module\":\"keycloak\",\"node\":\"ace\"},\"depends-on\":[\"novox.postgres.secret-postgres-database\"],\"local\":\"main\",\"plan\":{\"credential-form\":\"pair\",\"local\":\"main\",\"names\":{\"name-main\":\"keycloak.example.internal\"},\"provider\":\"novox\",\"provider-module\":\"postgres\",\"provision\":\"postgres-database\"},\"provider\":{\"module\":\"postgres\",\"node\":\"novox\"},\"provision\":\"postgres-database\",\"reference\":{\"generation\":2,\"id\":\"pair/novox/postgres-database/ace/keycloak/main\"},\"state\":\"provided\",\"v\":1}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"consumer\":{\"module\":\"keycloak\",\"node\":\"ace\"},\"depends-on\":[\"novox.postgres.secret-postgres-database\"],\"local\":\"main\",\"plan\":{\"credential-form\":\"pair\",\"local\":\"main\",\"names\":{\"name-main\":\"keycloak.example.internal\"},\"provider\":\"novox\",\"provider-module\":\"postgres\",\"provision\":\"postgres-database\"},\"provider\":{\"module\":\"postgres\",\"node\":\"novox\"},\"provision\":\"postgres-database\",\"reference\":{\"generation\":2,\"id\":\"pair/novox/postgres-database/ace/keycloak/main\"},\"state\":\"provided\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v ProvisionsByNodeConsumerProvisionLocalValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a provision that waits for the operator", subject: "", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"consumer\":{\"module\":\"bazarr\",\"node\":\"ace\"},\"provider\":{\"module\":\"mesh-vault\",\"node\":\"novox\"},\"provision\":\"api-token\",\"state\":\"waits\",\"v\":1,\"why\":\"the token is the operator's to give\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"consumer\":{\"module\":\"bazarr\",\"node\":\"ace\"},\"provider\":{\"module\":\"mesh-vault\",\"node\":\"novox\"},\"provision\":\"api-token\",\"state\":\"waits\",\"v\":1,\"why\":\"the token is the operator's to give\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v ProvisionsByNodeConsumerProvisionValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a retiring provision with the operator's warrant", subject: "", given: "{\"ask\":\"a7\",\"at\":\"2026-11-04T12:00:00Z\",\"consumer\":{\"module\":\"old-app\",\"node\":\"ace\"},\"provider\":{\"module\":\"postgres\",\"node\":\"novox\"},\"provision\":\"postgres-database\",\"state\":\"retiring\",\"v\":1,\"warrant\":{\"ask\":\"a7\",\"at\":\"2026-11-04T13:00:00Z\",\"by\":\"operator\",\"option\":\"retire\"},\"why\":\"no want needs it\"}", wire: "{\"ask\":\"a7\",\"at\":\"2026-11-04T12:00:00Z\",\"consumer\":{\"module\":\"old-app\",\"node\":\"ace\"},\"provider\":{\"module\":\"postgres\",\"node\":\"novox\"},\"provision\":\"postgres-database\",\"state\":\"retiring\",\"v\":1,\"warrant\":{\"ask\":\"a7\",\"at\":\"2026-11-04T13:00:00Z\",\"by\":\"operator\",\"option\":\"retire\"},\"why\":\"no want needs it\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v ProvisionsByNodeConsumerProvisionValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a module's plan on a node", subject: "", given: "{\"module\":\"keycloak\",\"node\":\"ace\",\"plan\":{\"provisions\":[{\"credential-form\":\"pair\",\"provider\":\"novox\",\"provider-module\":\"postgres\",\"provision\":\"postgres-database\"}]},\"v\":1}", wire: "{\"module\":\"keycloak\",\"node\":\"ace\",\"plan\":{\"provisions\":[{\"credential-form\":\"pair\",\"provider\":\"novox\",\"provider-module\":\"postgres\",\"provision\":\"postgres-database\"}]},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v PlansByNodeModuleValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not decode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
back, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not encode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
var got, want any
|
||||
if err := json.Unmarshal(back, &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
|
||||
}
|
||||
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
|
||||
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"name": "a database provision provided to a consumer under a local name",
|
||||
"of": "state:provisions/<node>.<consumer>.<provision>.<local>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"provision": "postgres-database",
|
||||
"local": "main",
|
||||
"consumer": {"module": "keycloak", "node": "ace"},
|
||||
"provider": {"module": "postgres", "node": "novox"},
|
||||
"depends-on": ["novox.postgres.secret-postgres-database"],
|
||||
"state": "provided",
|
||||
"reference": {"id": "pair/novox/postgres-database/ace/keycloak/main", "generation": 2},
|
||||
"plan": {"provision": "postgres-database", "local": "main", "provider": "novox", "provider-module": "postgres", "credential-form": "pair", "names": {"name-main": "keycloak.example.internal"}},
|
||||
"at": "2026-11-04T12:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a provision that waits for the operator",
|
||||
"of": "state:provisions/<node>.<consumer>.<provision>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"provision": "api-token",
|
||||
"consumer": {"module": "bazarr", "node": "ace"},
|
||||
"provider": {"module": "mesh-vault", "node": "novox"},
|
||||
"state": "waits",
|
||||
"why": "the token is the operator's to give",
|
||||
"at": "2026-11-04T12:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a retiring provision with the operator's warrant",
|
||||
"of": "state:provisions/<node>.<consumer>.<provision>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"provision": "postgres-database",
|
||||
"consumer": {"module": "old-app", "node": "ace"},
|
||||
"provider": {"module": "postgres", "node": "novox"},
|
||||
"state": "retiring",
|
||||
"why": "no want needs it",
|
||||
"ask": "a7",
|
||||
"warrant": {"ask": "a7", "option": "retire", "by": "operator", "at": "2026-11-04T13:00:00Z"},
|
||||
"at": "2026-11-04T12:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a module's plan on a node",
|
||||
"of": "state:plans/<node>.<module>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"node": "ace",
|
||||
"module": "keycloak",
|
||||
"plan": {"provisions": [{"provision": "postgres-database", "provider": "novox", "provider-module": "postgres", "credential-form": "pair"}]}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -168,7 +168,67 @@
|
||||
},
|
||||
"plan": {
|
||||
"type": "object",
|
||||
"description": "the plan's provision"
|
||||
"description": "the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126)",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provision": {
|
||||
"type": "string"
|
||||
},
|
||||
"local": {
|
||||
"type": "string"
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"provider-module": {
|
||||
"type": "string"
|
||||
},
|
||||
"credential-form": {
|
||||
"enum": [
|
||||
"pair",
|
||||
"shared",
|
||||
"issued",
|
||||
"given",
|
||||
"none"
|
||||
]
|
||||
},
|
||||
"credential-tool": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"contributes": {
|
||||
"type": "object"
|
||||
},
|
||||
"at": {
|
||||
"type": "string"
|
||||
},
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"as": {
|
||||
"type": "string"
|
||||
},
|
||||
"names": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"contributed": {
|
||||
"type": "object",
|
||||
"description": "the provider's own contract's bytes, carried unread"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"provision",
|
||||
"provider",
|
||||
"provider-module"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
@@ -275,7 +335,67 @@
|
||||
},
|
||||
"plan": {
|
||||
"type": "object",
|
||||
"description": "the plan's provision"
|
||||
"description": "the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126)",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provision": {
|
||||
"type": "string"
|
||||
},
|
||||
"local": {
|
||||
"type": "string"
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"provider-module": {
|
||||
"type": "string"
|
||||
},
|
||||
"credential-form": {
|
||||
"enum": [
|
||||
"pair",
|
||||
"shared",
|
||||
"issued",
|
||||
"given",
|
||||
"none"
|
||||
]
|
||||
},
|
||||
"credential-tool": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"contributes": {
|
||||
"type": "object"
|
||||
},
|
||||
"at": {
|
||||
"type": "string"
|
||||
},
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"as": {
|
||||
"type": "string"
|
||||
},
|
||||
"names": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"contributed": {
|
||||
"type": "object",
|
||||
"description": "the provider's own contract's bytes, carried unread"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"provision",
|
||||
"provider",
|
||||
"provider-module"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
|
||||
@@ -111,6 +111,25 @@ export interface ProvisionsByNodeConsumerProvisionValueConsumer {
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
/** the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126) */
|
||||
export interface ProvisionsByNodeConsumerProvisionValuePlan {
|
||||
"as"?: string;
|
||||
"at"?: string;
|
||||
/** the provider's own contract's bytes, carried unread */
|
||||
"contributed"?: Record<string, unknown>;
|
||||
"contributes"?: Record<string, unknown>;
|
||||
"credential-form"?: unknown;
|
||||
"credential-tool"?: string;
|
||||
"from"?: string;
|
||||
"local"?: string;
|
||||
"name"?: string;
|
||||
"names"?: Record<string, string>;
|
||||
"path"?: string;
|
||||
"provider": string;
|
||||
"provider-module": string;
|
||||
"provision": string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionValueProvider {
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
@@ -135,8 +154,8 @@ export interface ProvisionsByNodeConsumerProvisionValue {
|
||||
"consumer": ProvisionsByNodeConsumerProvisionValueConsumer;
|
||||
"depends-on"?: string[];
|
||||
"local"?: string;
|
||||
/** the plan's provision */
|
||||
"plan"?: Record<string, unknown>;
|
||||
/** the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126) */
|
||||
"plan"?: ProvisionsByNodeConsumerProvisionValuePlan;
|
||||
"provider": ProvisionsByNodeConsumerProvisionValueProvider;
|
||||
"provision": string;
|
||||
"reference"?: ProvisionsByNodeConsumerProvisionValueReference;
|
||||
@@ -151,6 +170,25 @@ export interface ProvisionsByNodeConsumerProvisionLocalValueConsumer {
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
/** the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126) */
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValuePlan {
|
||||
"as"?: string;
|
||||
"at"?: string;
|
||||
/** the provider's own contract's bytes, carried unread */
|
||||
"contributed"?: Record<string, unknown>;
|
||||
"contributes"?: Record<string, unknown>;
|
||||
"credential-form"?: unknown;
|
||||
"credential-tool"?: string;
|
||||
"from"?: string;
|
||||
"local"?: string;
|
||||
"name"?: string;
|
||||
"names"?: Record<string, string>;
|
||||
"path"?: string;
|
||||
"provider": string;
|
||||
"provider-module": string;
|
||||
"provision": string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValueProvider {
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
@@ -175,8 +213,8 @@ export interface ProvisionsByNodeConsumerProvisionLocalValue {
|
||||
"consumer": ProvisionsByNodeConsumerProvisionLocalValueConsumer;
|
||||
"depends-on"?: string[];
|
||||
"local"?: string;
|
||||
/** the plan's provision */
|
||||
"plan"?: Record<string, unknown>;
|
||||
/** the plan's provision: the entry the key was composed from, at the consumer's wanted build or its newest (issue 1126) */
|
||||
"plan"?: ProvisionsByNodeConsumerProvisionLocalValuePlan;
|
||||
"provider": ProvisionsByNodeConsumerProvisionLocalValueProvider;
|
||||
"provision": string;
|
||||
"reference"?: ProvisionsByNodeConsumerProvisionLocalValueReference;
|
||||
|
||||
Reference in New Issue
Block a user