diff --git a/modules/gitea/cmd/forge-account-provider/builder_test.go b/modules/gitea/cmd/forge-account-provider/builder_test.go index 8897013fa..64e4231ab 100644 --- a/modules/gitea/cmd/forge-account-provider/builder_test.go +++ b/modules/gitea/cmd/forge-account-provider/builder_test.go @@ -14,7 +14,7 @@ import ( "sync" "testing" - "git.novox.be/novox/mesh-sdk/go/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" "gitea/internal/forgehttp" ) diff --git a/modules/gitea/cmd/forge-account-provider/bus_test.go b/modules/gitea/cmd/forge-account-provider/bus_test.go index 7cacfe5be..22babf898 100644 --- a/modules/gitea/cmd/forge-account-provider/bus_test.go +++ b/modules/gitea/cmd/forge-account-provider/bus_test.go @@ -29,8 +29,8 @@ import ( "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" ) const bundleVar = "MESH_FORGE_ACCOUNT_TEST_BUNDLE" @@ -301,7 +301,7 @@ func TestTheProviderWholeAnswersAMachineThatReportedItsKey(t *testing.T) { "plan": map[string]any{"provisions": []map[string]any{{"provision": "forge-account", "provider": "novox", "provider-module": "gitea", "as": "mesh_g14_ssh_client"}}}}) rt.put("mesh-provisioner.provisions", "g14.ssh-client.forge-account", - json.RawMessage(provisionKey("g14", "ssh-client", provisions.Asked, nil))) + json.RawMessage(provisionKey("g14", "ssh-client", meshprovisionerclient.Asked, nil))) rt.put("ssh-client.keys", "g14.nox", map[string]string{"node": "g14", "account": "nox", "kind": "machine", "public": pubA + " nox@g14 (mesh)", "fingerprint": "SHA256:x", "at": "2026-10-16T10:00:00Z"}) rt.start([]string{"MESH_NODE=novox", "MESH_MODULE=gitea", "MESH_SERVED_MODULE=gitea", diff --git a/modules/gitea/cmd/forge-account-provider/main.go b/modules/gitea/cmd/forge-account-provider/main.go index ddd2b624a..298a6ed75 100644 --- a/modules/gitea/cmd/forge-account-provider/main.go +++ b/modules/gitea/cmd/forge-account-provider/main.go @@ -22,8 +22,8 @@ import ( "sync" "time" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" stdio "git.novox.be/novox/mesh-sdk/go" - "git.novox.be/novox/mesh-sdk/go/provider" "gitea/internal/forgeaccount" "gitea/internal/forgehttp" diff --git a/modules/gitea/cmd/forge-account-provider/service.go b/modules/gitea/cmd/forge-account-provider/service.go index 0b2ad1131..3ab458d53 100644 --- a/modules/gitea/cmd/forge-account-provider/service.go +++ b/modules/gitea/cmd/forge-account-provider/service.go @@ -12,7 +12,7 @@ import ( "sync" "time" - "git.novox.be/novox/mesh-sdk/go/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" "gitea/internal/forgeaccount" "gitea/internal/forgehttp" diff --git a/modules/gitea/cmd/forge-account-provider/service_test.go b/modules/gitea/cmd/forge-account-provider/service_test.go index f91aa2afc..4fa5f7070 100644 --- a/modules/gitea/cmd/forge-account-provider/service_test.go +++ b/modules/gitea/cmd/forge-account-provider/service_test.go @@ -16,8 +16,8 @@ import ( "testing" "time" - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" "gitea/internal/forgehttp" ) @@ -84,7 +84,7 @@ func (b *fakeBus) entry(t *testing.T, key string) provider.Entry { // values (ADR 0570 clause 3: an entry the provider could not make is kept, failed, serving nothing; one it is not // ready to make waits and keeps serving). func (b *fakeBus) serves(key string, state ...string) bool { - want := provisions.Provided + want := meshprovisionerclient.Provided if len(state) > 0 { want = state[0] } @@ -110,29 +110,29 @@ func (b *fakeBus) bindClient(node string) { // bindPlan makes module on node bind gitea's forge-account as the seat mesh-provisioner keeps it: its plan, and the // provision key asked of gitea on novox (novox/hq ADR 0570 clauses 1 to 3). func (b *fakeBus) bindPlan(node, module, as string) { - b.set(provisions.PlansBucket, node+"."+module, []byte(fmt.Sprintf( + b.set(meshprovisionerclient.PlansBucket, node+"."+module, []byte(fmt.Sprintf( `{"v":1,"node":%q,"module":%q,"plan":{"provisions":[{"provision":"forge-account","provider":"novox","provider-module":"gitea","as":%q}]}}`, node, module, as))) - b.set(provisions.ProvisionsBucket, node+"."+module+".forge-account", provisionKey(node, module, provisions.Asked, nil)) + b.set(meshprovisionerclient.ProvisionsBucket, node+"."+module+".forge-account", provisionKey(node, module, meshprovisionerclient.Asked, nil)) } // retire is the operator's yes to the retiring of module's forge-account on node: its plan gone, its key retiring // with the warrant (ADR 0570 clause 5), the only way the provider lets an entry go. func (b *fakeBus) retire(node, module string) { b.mu.Lock() - delete(b.buckets[provisions.PlansBucket], node+"."+module) + delete(b.buckets[meshprovisionerclient.PlansBucket], node+"."+module) b.mu.Unlock() - b.set(provisions.ProvisionsBucket, node+"."+module+".forge-account", provisionKey(node, module, provisions.Retiring, - &provisions.Warrant{Ask: "ask-1", Option: "yes", By: "operator", At: time.Date(2026, 10, 29, 12, 0, 0, 0, time.UTC)})) + b.set(meshprovisionerclient.ProvisionsBucket, node+"."+module+".forge-account", provisionKey(node, module, meshprovisionerclient.Retiring, + &meshprovisionerclient.Warrant{Ask: "ask-1", Option: "yes", By: "operator", At: time.Date(2026, 10, 29, 12, 0, 0, 0, time.UTC)})) } -func provisionKey(node, module, state string, w *provisions.Warrant) []byte { - pr := provisions.Provision{Provision: "forge-account", State: state, Warrant: w, - Consumer: provisions.End{Node: node, Module: module}, Provider: provisions.End{Node: "novox", Module: "gitea"}} - if state == provisions.Retiring { +func provisionKey(node, module, state string, w *meshprovisionerclient.Warrant) []byte { + pr := meshprovisionerclient.Provision{Provision: "forge-account", State: state, Warrant: w, + Consumer: meshprovisionerclient.End{Node: node, Module: module}, Provider: meshprovisionerclient.End{Node: "novox", Module: "gitea"}} + if state == meshprovisionerclient.Retiring { pr.Why = "no want needs it" } - raw, err := provisions.Encode(pr) + raw, err := meshprovisionerclient.Encode(pr) if err != nil { panic(err) } @@ -527,7 +527,7 @@ func TestAPassBeforeTheKeysAreLoadedRemovesAndDeletesNothing(t *testing.T) { if got := strings.Join(r.forge.titles("nox-agent"), ","); got != "mesh:g14.nox,my own" { t.Fatalf("keys = %s", got) } - if !r.bus.serves("g14.ssh-client.forge-account", provisions.Waits) { + if !r.bus.serves("g14.ssh-client.forge-account", meshprovisionerclient.Waits) { t.Fatal("the entry stopped serving before the keys were read; it waits and keeps serving") } if len(out) != 1 || !strings.Contains(out[0].Why, "not read yet") { diff --git a/modules/gitea/go.mod b/modules/gitea/go.mod index da00df0e0..eaea427ec 100644 --- a/modules/gitea/go.mod +++ b/modules/gitea/go.mod @@ -3,6 +3,7 @@ module gitea go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-delivery/contracts/go/seats/gopackageregistry v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-delivery/contracts/go/seats/npmpackageregistry v0.0.0-00010101000000-000000000000 diff --git a/modules/keycloak/cmd/keycloak-provider/admin_test.go b/modules/keycloak/cmd/keycloak-provider/admin_test.go index 8f9480618..23db5f0ab 100644 --- a/modules/keycloak/cmd/keycloak-provider/admin_test.go +++ b/modules/keycloak/cmd/keycloak-provider/admin_test.go @@ -8,7 +8,7 @@ package main import ( "context" "errors" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "strings" "testing" "time" diff --git a/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go b/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go index 0749f4f6b..59cb8f086 100644 --- a/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go +++ b/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go @@ -13,9 +13,9 @@ import ( "testing" "time" - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provider/harness" - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" ) // grantGives writes a grant file (MESH_RECEIVES) naming consumers the plans do not move (issue 937): each one's @@ -49,22 +49,22 @@ func noOpPlan(bus *bucketBus, node, module string) { // keycloak on novox the key the seat composes, asked (novox/hq ADR 0570 clauses 1 to 3). func seatPlan(bus *bucketBus, node, module string, plan map[string]any) { raw, _ := json.Marshal(map[string]any{"v": 1, "node": node, "module": module, "plan": plan}) - _ = bus.Put(ctx, provisions.PlansBucket, node+"."+module, raw) + _ = bus.Put(ctx, meshprovisionerclient.PlansBucket, node+"."+module, raw) list, _ := plan["provisions"].([]any) for _, e := range list { entry := e.(map[string]any) name, _ := entry["provision"].(string) local, _ := entry["local"].(string) - key, err := provisions.Key(node, module, name, local) + key, err := meshprovisionerclient.Key(node, module, name, local) if err != nil { panic(err) } - asked, err := provisions.Encode(provisions.Provision{Provision: name, Local: local, State: provisions.Asked, - Consumer: provisions.End{Node: node, Module: module}, Provider: provisions.End{Node: "novox", Module: "keycloak"}}) + asked, err := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: name, Local: local, State: meshprovisionerclient.Asked, + Consumer: meshprovisionerclient.End{Node: node, Module: module}, Provider: meshprovisionerclient.End{Node: "novox", Module: "keycloak"}}) if err != nil { panic(err) } - _ = bus.Put(ctx, provisions.ProvisionsBucket, key, asked) + _ = bus.Put(ctx, meshprovisionerclient.ProvisionsBucket, key, asked) } } diff --git a/modules/keycloak/cmd/keycloak-provider/main.go b/modules/keycloak/cmd/keycloak-provider/main.go index 81b274bca..84673b43c 100644 --- a/modules/keycloak/cmd/keycloak-provider/main.go +++ b/modules/keycloak/cmd/keycloak-provider/main.go @@ -8,7 +8,7 @@ package main import ( "context" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "os" "time" diff --git a/modules/keycloak/cmd/keycloak-provider/moved.go b/modules/keycloak/cmd/keycloak-provider/moved.go index 12fec0a7b..84d13647a 100644 --- a/modules/keycloak/cmd/keycloak-provider/moved.go +++ b/modules/keycloak/cmd/keycloak-provider/moved.go @@ -9,8 +9,8 @@ package main // retirement to the harness's guards (the SDK's harness retirement): the client is disabled and marked to delete, never removed. import ( - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" ) // ProvisionName is what keycloak provides, as its manifest says. diff --git a/modules/keycloak/cmd/keycloak-provider/moved_test.go b/modules/keycloak/cmd/keycloak-provider/moved_test.go index 2e47f7868..b9e4a0aac 100644 --- a/modules/keycloak/cmd/keycloak-provider/moved_test.go +++ b/modules/keycloak/cmd/keycloak-provider/moved_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" ) const testIssuer = "https://id.example.org/realms/Novox" diff --git a/modules/keycloak/cmd/keycloak-provider/oidc.go b/modules/keycloak/cmd/keycloak-provider/oidc.go index ca702b0a8..209df2f01 100644 --- a/modules/keycloak/cmd/keycloak-provider/oidc.go +++ b/modules/keycloak/cmd/keycloak-provider/oidc.go @@ -35,7 +35,7 @@ import ( "strings" "time" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" ) // Mark is the attribute marking a client as the mesh's own work. diff --git a/modules/keycloak/cmd/keycloak-provider/oidc_test.go b/modules/keycloak/cmd/keycloak-provider/oidc_test.go index 4d8f52d00..d3931fc29 100644 --- a/modules/keycloak/cmd/keycloak-provider/oidc_test.go +++ b/modules/keycloak/cmd/keycloak-provider/oidc_test.go @@ -7,7 +7,7 @@ package main import ( "encoding/json" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "reflect" "strings" "testing" diff --git a/modules/keycloak/cmd/keycloak-provider/provisioner.go b/modules/keycloak/cmd/keycloak-provider/provisioner.go index 6bf4aef62..cfdf884ab 100644 --- a/modules/keycloak/cmd/keycloak-provider/provisioner.go +++ b/modules/keycloak/cmd/keycloak-provider/provisioner.go @@ -16,7 +16,7 @@ import ( "context" "errors" "fmt" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "os" "time" ) diff --git a/modules/keycloak/go.mod b/modules/keycloak/go.mod index 8da848e10..a9965aae8 100644 --- a/modules/keycloak/go.mod +++ b/modules/keycloak/go.mod @@ -5,6 +5,7 @@ go 1.26.0 require git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/go v0.0.0-20261104174344-ae5266e77639 // indirect github.com/klauspost/compress v1.20.1 // indirect github.com/nats-io/nats.go v1.54.0 // indirect diff --git a/modules/mesh-config/go.mod b/modules/mesh-config/go.mod index fba57def9..8693a74c8 100644 --- a/modules/mesh-config/go.mod +++ b/modules/mesh-config/go.mod @@ -3,6 +3,7 @@ module mesh-config go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel v0.0.0-00010101000000-000000000000 diff --git a/modules/mesh-delivery-gate/go.mod b/modules/mesh-delivery-gate/go.mod index 1940adc9c..667ea5b78 100644 --- a/modules/mesh-delivery-gate/go.mod +++ b/modules/mesh-delivery-gate/go.mod @@ -3,6 +3,7 @@ module mesh-delivery-gate go 1.26.0 require ( + git.novox.be/novox/mesh-delivery/modules/mesh-delivery-forge-bridge/forgemsg v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f diff --git a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go index 438899cc2..eecc0c35f 100644 --- a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go +++ b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go @@ -1,7 +1,7 @@ package main import ( - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" "bytes" "context" @@ -19,7 +19,7 @@ import ( "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" - "git.novox.be/novox/mesh-sdk/go/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" ) // The provisioner's client on one node (novox/hq ADR 0349 clauses 4 and 5, design 57 P5, issue 671). @@ -44,7 +44,7 @@ import ( const ( // PlansBucket is where each module's provisioning plan on each node is read: the seat mesh-provisioner's // `plans` (novox/hq ADR 0570 clause 2), read as an assignment's value carried it (asAssignment). - PlansBucket = provisions.PlansBucket + PlansBucket = meshprovisionerclient.PlansBucket // PlacementBucket is the seat mesh-module-assigner's placement (novox/hq ADR 0567): a module it names on this node stays // here while the seat mesh-provisioner holds no plan of it (nats on novox runs without a want), filled from its // last plan, and leaves only when neither names it (issue 1126 B12; the controller's assignments mirror, read for @@ -1214,7 +1214,7 @@ func (c *Client) takePlacement(s *state, key string, value []byte, revision uint // asAssignment is a plan of the seat mesh-provisioner as the client's rules read an assignment's value: // `{node, module, provisioning: plan}`. func asAssignment(raw []byte) ([]byte, error) { - if _, err := provisions.DecodePlan(raw); err != nil { + if _, err := meshprovisionerclient.DecodePlan(raw); err != nil { return nil, err } // The plan as it is kept, its bytes unchanged: the client reads it strictly (planOf). diff --git a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/route_names_test.go b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/route_names_test.go index 53831d213..2f4482717 100644 --- a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/route_names_test.go +++ b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/route_names_test.go @@ -8,8 +8,8 @@ import ( "sync" "testing" - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" "github.com/nats-io/nats.go/jetstream" ) @@ -55,9 +55,9 @@ func (m *memBus) Delete(_ context.Context, bucket, key string) error { // as the seat mesh-provisioner keeps it (ADR 0570 clause 2). func routeEntryFor(t *testing.T, module, planEntry string) string { t.Helper() - bus := &memBus{buckets: map[string]map[string][]byte{provisions.PlansBucket: { + bus := &memBus{buckets: map[string]map[string][]byte{meshprovisionerclient.PlansBucket: { node + "." + module: []byte(`{"v":1,"node":"` + node + `","module":"` + module + `","plan":{"provisions":[` + - planEntry + `]}}`)}, provisions.ProvisionsBucket: {}}} + planEntry + `]}}`)}, meshprovisionerclient.ProvisionsBucket: {}}} // The key the seat composed for that entry, provided-for: asked of route-proxy (ADR 0570 clause 3). var b struct { Provision string `json:"provision"` @@ -66,17 +66,17 @@ func routeEntryFor(t *testing.T, module, planEntry string) string { if err := json.Unmarshal([]byte(planEntry), &b); err != nil { t.Fatal(err) } - pr := provisions.Provision{Provision: b.Provision, Local: b.Local, State: provisions.Asked, - Consumer: provisions.End{Node: node, Module: module}, Provider: provisions.End{Node: "novox", Module: "route-proxy"}} + pr := meshprovisionerclient.Provision{Provision: b.Provision, Local: b.Local, State: meshprovisionerclient.Asked, + Consumer: meshprovisionerclient.End{Node: node, Module: module}, Provider: meshprovisionerclient.End{Node: "novox", Module: "route-proxy"}} key, err := pr.Key() if err != nil { t.Fatal(err) } - raw, err := provisions.Encode(pr) + raw, err := meshprovisionerclient.Encode(pr) if err != nil { t.Fatal(err) } - bus.buckets[provisions.ProvisionsBucket][key] = raw + bus.buckets[meshprovisionerclient.ProvisionsBucket][key] = raw p := provider.New(provider.Options{Node: "novox", Module: "route-proxy", Bus: bus, Logf: t.Logf, Offers: map[string]provider.Offer{"route": {Credential: provider.NoCredential, Serves: map[string]any{}}}}) out, err := p.Pass(context.Background()) diff --git a/modules/mesh-provisioner-client/go.mod b/modules/mesh-provisioner-client/go.mod index 56f658344..6a14a1a66 100644 --- a/modules/mesh-provisioner-client/go.mod +++ b/modules/mesh-provisioner-client/go.mod @@ -3,6 +3,7 @@ module mesh-provisioner-client go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 diff --git a/modules/mesh-provisioner/cmd/mesh-provisioner/holder.go b/modules/mesh-provisioner/cmd/mesh-provisioner/holder.go index 2cb527cf0..1bf227552 100644 --- a/modules/mesh-provisioner/cmd/mesh-provisioner/holder.go +++ b/modules/mesh-provisioner/cmd/mesh-provisioner/holder.go @@ -39,17 +39,17 @@ import ( occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient" oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/catalogue" "git.novox.be/novox/mesh-sdk/go/delivery" - "git.novox.be/novox/mesh-sdk/go/provisions" ) // The states it keeps, beside Registry, Needs, Applied and Collect. RefusedState holds, by `.`, why a // placed module has no plan composed (issue 774): written while it is held, deleted once it composes again. const ( - ProvisionsState = provisions.ProvisionsState - PlansState = provisions.PlansState + ProvisionsState = meshprovisionerclient.ProvisionsState + PlansState = meshprovisionerclient.PlansState RefusedState = "refused" ) @@ -169,7 +169,7 @@ func TookSaid(took []Took) string { return strings.Join(said, ", ") } -// ComposeNode composes one node: its plans and its provisions. +// ComposeNode composes one node: its plans and its meshprovisionerclient. func (h *Holder) ComposeNode(ctx context.Context, node string) (Composed, error) { return h.ComposeNodeWith(ctx, node, false) } @@ -250,8 +250,8 @@ func (h *Holder) ComposeNodeWith(ctx context.Context, node string, retireMany bo out.Problems = append(out.Problems, err.Error()) } lap("plans written") - needed := map[string]provisions.Provision{} - elsewhere := map[string]provisions.Provision{} + needed := map[string]meshprovisionerclient.Provision{} + elsewhere := map[string]meshprovisionerclient.Provision{} // ahead are the keys only the newest build of their consumer requires: the plan written, its wanted build's, names // them not yet, and the provider binds them from the entry they carry (issue 1126). ahead := map[string]string{} @@ -259,10 +259,10 @@ func (h *Holder) ComposeNodeWith(ctx context.Context, node string, retireMany bo for i, plans := range []map[string]catalogue.Plan{atWants, newest} { for module, plan := range plans { for _, p := range plan.Provisions { - consumer := provisions.End{Module: module, Node: node} - provider := provisions.End{Module: p.ProviderModule, Node: p.Provider} - pv := provisions.Provision{Provision: p.Provision, Local: p.Local, Consumer: consumer, Provider: provider, - DependsOn: provisions.DependsOn(consumer, p, h.providerPlan(p, node, atWants))} + consumer := meshprovisionerclient.End{Module: module, Node: node} + provider := meshprovisionerclient.End{Module: p.ProviderModule, Node: p.Provider} + pv := meshprovisionerclient.Provision{Provision: p.Provision, Local: p.Local, Consumer: consumer, Provider: provider, + DependsOn: meshprovisionerclient.DependsOn(consumer, p, h.providerPlan(p, node, atWants))} key, err := pv.Key() if err != nil { out.Problems = append(out.Problems, err.Error()) @@ -281,11 +281,11 @@ func (h *Holder) ComposeNodeWith(ctx context.Context, node string, retireMany bo } // Its credential is a provision of its own, the vault's (clause 6): on the consumer's node for a value of the // consumer's own, on the provider's for the provider's one shared value. - ck, ok := provisions.CredentialKey(p.CredentialForm, consumer, provider, p.Provision, p.Local) + ck, ok := meshprovisionerclient.CredentialKey(p.CredentialForm, consumer, provider, p.Provision, p.Local) if !ok { continue } - cn, cm, cp, cl, err := provisions.ParseKey(ck) + cn, cm, cp, cl, err := meshprovisionerclient.ParseKey(ck) if err != nil { continue } @@ -293,8 +293,8 @@ func (h *Holder) ComposeNodeWith(ctx context.Context, node string, retireMany bo out.Problems = append(out.Problems, "no node runs mesh-vault, so the credential "+ck+" has no provider") continue } - cred := provisions.Provision{Provision: cp, Local: cl, Consumer: provisions.End{Module: cm, Node: cn}, - Provider: provisions.End{Module: provisions.VaultModule, Node: vaultNode}} + cred := meshprovisionerclient.Provision{Provision: cp, Local: cl, Consumer: meshprovisionerclient.End{Module: cm, Node: cn}, + Provider: meshprovisionerclient.End{Module: meshprovisionerclient.VaultModule, Node: vaultNode}} if cn == node { if _, seen := needed[ck]; !seen { needed[ck] = cred @@ -329,7 +329,7 @@ func (h *Holder) ComposeNodeWith(ctx context.Context, node string, retireMany bo func (h *Holder) writeRefused(node string, held map[string]string) error { var problems []error for _, module := range sortedKeys(held) { - key, err := provisions.PlanKey(node, module) + key, err := meshprovisionerclient.PlanKey(node, module) if err != nil { problems = append(problems, err) continue @@ -382,7 +382,7 @@ func (h *Holder) providerPlan(p catalogue.PlanProvision, node string, here map[s } return nil } - key, err := provisions.PlanKey(p.Provider, p.ProviderModule) + key, err := meshprovisionerclient.PlanKey(p.Provider, p.ProviderModule) if err != nil { return nil } @@ -390,7 +390,7 @@ func (h *Holder) providerPlan(p catalogue.PlanProvision, node string, here map[s if err != nil || e == nil { return nil } - plan, err := provisions.DecodePlan(e.Value) + plan, err := meshprovisionerclient.DecodePlan(e.Value) if err != nil { return nil } @@ -399,7 +399,7 @@ func (h *Holder) providerPlan(p catalogue.PlanProvision, node string, here map[s // vaultNode is the node mesh-vault is placed on: the provider of every credential. func (h *Holder) vaultNode() string { - nodes := h.placedOn(provisions.VaultModule) + nodes := h.placedOn(meshprovisionerclient.VaultModule) if len(nodes) == 0 { return "" } @@ -421,7 +421,7 @@ func (h *Holder) dependedOn(node string) []string { if err != nil || e == nil { continue } - if p, err := provisions.Decode(e.Value); err == nil { + if p, err := meshprovisionerclient.Decode(e.Value); err == nil { for _, d := range p.DependsOn { if strings.HasPrefix(d, node+".") { out = append(out, d) @@ -434,13 +434,13 @@ func (h *Holder) dependedOn(node string) []string { // judgeElsewhere writes each needed key of another node (a provider's shared credential), its state from its outcome; // that node's own composition keeps it while a provision depends on it. -func (h *Holder) judgeElsewhere(keys map[string]provisions.Provision, out *Composed) { +func (h *Holder) judgeElsewhere(keys map[string]meshprovisionerclient.Provision, out *Composed) { for _, key := range sortedKeys(keys) { next := keys[key] - var have provisions.Provision + var have meshprovisionerclient.Provision e, err := h.Store.Get(ProvisionsState, key) if err == nil && e != nil { - if have, err = provisions.Decode(e.Value); err == nil { + if have, err = meshprovisionerclient.Decode(e.Value); err == nil { next.Reference = have.Reference } } @@ -505,12 +505,12 @@ func (h *Holder) runningOn(node string) (map[string]string, error) { func (h *Holder) writePlans(node string, plans map[string]catalogue.Plan, held map[string]string, out *Composed) error { var problems []error for _, module := range sortedKeys(plans) { - key, err := provisions.PlanKey(node, module) + key, err := meshprovisionerclient.PlanKey(node, module) if err != nil { problems = append(problems, err) continue } - raw, err := provisions.EncodePlan(provisions.Plan{Node: node, Module: module, Plan: plans[module]}) + raw, err := meshprovisionerclient.EncodePlan(meshprovisionerclient.Plan{Node: node, Module: module, Plan: plans[module]}) if err != nil { problems = append(problems, err) continue @@ -552,7 +552,7 @@ func (h *Holder) writePlans(node string, plans map[string]catalogue.Plan, held m // untouched (held on the node, or with a want or a have and no plan read in this pass) that its composition no longer // names is left as it is: not composed is not unneeded. A pass that would retire most of the node's consumers at once retires none, said as a fault of // the mesh (issue 940), unless retireMany. -func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, ahead map[string]string, +func (h *Holder) judgeNode(node string, needed map[string]meshprovisionerclient.Provision, ahead map[string]string, untouched map[string]string, retireMany bool, out *Composed) { held := h.held(node) consumers := map[string]bool{} @@ -577,7 +577,7 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, var newly []string leaving := map[string]bool{} for key, have := range held { - if _, isNeeded := needed[key]; !isNeeded && have.State != provisions.Retiring { + if _, isNeeded := needed[key]; !isNeeded && have.State != meshprovisionerclient.Retiring { newly = append(newly, key) leaving[have.Consumer.Module] = true } @@ -607,7 +607,7 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, for _, key := range unionKeys(needed, held) { want, isNeeded := needed[key] have, isHeld := held[key] - var next provisions.Provision + var next meshprovisionerclient.Provision switch { case isNeeded: next = want @@ -615,7 +615,7 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, next.Reference = have.Reference } h.outcome(key, &next) - if module, isAhead := ahead[key]; isAhead && next.State == provisions.Asked { + if module, isAhead := ahead[key]; isAhead && next.State == meshprovisionerclient.Asked { // The reason the provider's helper says too: no plan names it yet, and it binds it from this key's entry. why := "no plan names it yet: the newest build of " + module + " requires it and its wanted build does " + "not, so its provider binds it from this key's plan entry" @@ -624,7 +624,7 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, } next.Why = why } - case have.State == provisions.Retiring: + case have.State == meshprovisionerclient.Retiring: next = have if next.Ask != "" && next.Warrant == nil && !h.askHeld(next) { out.Problems = append(out.Problems, "the router holds no ask "+next.Ask+" of "+key+": it is raised again") @@ -643,7 +643,7 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, } default: next = have - next.State, next.Why = provisions.Retiring, fmt.Sprintf("no build wanted or placed on %s requires %s of %s on %s "+ + next.State, next.Why = meshprovisionerclient.Retiring, fmt.Sprintf("no build wanted or placed on %s requires %s of %s on %s "+ "any more", node, have.Provision, have.Provider.Module, have.Provider.Node) next.Warrant = nil h.raise(&next, key, out) @@ -652,7 +652,7 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, continue } next.At = h.Now().UTC() - raw, err := provisions.Encode(next) + raw, err := meshprovisionerclient.Encode(next) if err != nil { out.Problems = append(out.Problems, err.Error()) continue @@ -666,8 +666,8 @@ func (h *Holder) judgeNode(node string, needed map[string]provisions.Provision, } // held is the node's provision keys as kept. -func (h *Holder) held(node string) map[string]provisions.Provision { - out := map[string]provisions.Provision{} +func (h *Holder) held(node string) map[string]meshprovisionerclient.Provision { + out := map[string]meshprovisionerclient.Provision{} keys, err := h.Store.Keys(ProvisionsState) if err != nil { return out @@ -680,7 +680,7 @@ func (h *Holder) held(node string) map[string]provisions.Provision { if err != nil || e == nil { continue } - if p, err := provisions.Decode(e.Value); err == nil { + if p, err := meshprovisionerclient.Decode(e.Value); err == nil { out[k] = p } } @@ -688,7 +688,7 @@ func (h *Holder) held(node string) map[string]provisions.Provision { } // same says two provisions say the same, their time aside. -func same(a, b provisions.Provision) bool { +func same(a, b meshprovisionerclient.Provision) bool { a.At, b.At, a.V, b.V = time.Time{}, time.Time{}, 0, 0 ra, _ := json.Marshal(a) rb, _ := json.Marshal(b) @@ -710,11 +710,11 @@ type entry struct { // outcome sets a needed provision's state from its provider's entry: provided, failed or waits; asked while it has // none. The holder never sets provided by itself (clause 3): a provider whose entries it does not read keeps the key // asked, said so. -func (h *Holder) outcome(key string, p *provisions.Provision) { +func (h *Holder) outcome(key string, p *meshprovisionerclient.Provision) { p.Ask, p.Warrant = "", nil keeps, err := h.keepsEntries(p.Provider.Module, p.Provision) if err != nil { - p.State, p.Why = provisions.Asked, "the manifest of "+p.Provider.Module+" cannot be read: "+err.Error() + p.State, p.Why = meshprovisionerclient.Asked, "the manifest of "+p.Provider.Module+" cannot be read: "+err.Error() return } if !keeps { @@ -722,40 +722,40 @@ func (h *Holder) outcome(key string, p *provisions.Provision) { return } if !slices.Contains(BoundReads, p.Provider.Module) { - p.State, p.Why = provisions.Asked, p.Provider.Module+" keeps its outcome in its entries, which mesh-provisioner's "+ + p.State, p.Why = meshprovisionerclient.Asked, p.Provider.Module+" keeps its outcome in its entries, which mesh-provisioner's "+ "manifest does not read yet" return } e, err := h.Store.Get(boundRead(p.Provider.Module), key) if err != nil { - p.State, p.Why = provisions.Asked, "the provider's entries cannot be read: "+err.Error() + p.State, p.Why = meshprovisionerclient.Asked, "the provider's entries cannot be read: "+err.Error() return } if e == nil { - p.State, p.Why = provisions.Asked, h.unread(p.Provider.Module) + p.State, p.Why = meshprovisionerclient.Asked, h.unread(p.Provider.Module) return } var en entry if err := json.Unmarshal(e.Value, &en); err != nil { - p.State, p.Why = provisions.Asked, "the provider's entry is not readable" + p.State, p.Why = meshprovisionerclient.Asked, "the provider's entry is not readable" return } switch { - case en.State == provisions.Failed: - p.State, p.Why = provisions.Failed, orSaid(en.Why, en.Refused, "the provider said it failed") - case en.State == provisions.Waits: - p.State, p.Why = provisions.Waits, orSaid(en.Why, en.Waits, "the provider waits for a person") + case en.State == meshprovisionerclient.Failed: + p.State, p.Why = meshprovisionerclient.Failed, orSaid(en.Why, en.Refused, "the provider said it failed") + case en.State == meshprovisionerclient.Waits: + p.State, p.Why = meshprovisionerclient.Waits, orSaid(en.Why, en.Waits, "the provider waits for a person") case en.State == "" && en.Refused != "": - p.State, p.Why = provisions.Failed, en.Refused + p.State, p.Why = meshprovisionerclient.Failed, en.Refused case en.State == "" && en.Waits != "": - p.State, p.Why = provisions.Waits, en.Waits - case en.State != "" && en.State != provisions.Provided: - p.State, p.Why = provisions.Asked, "the provider's entry says "+en.State+", which no state of a provision is" + p.State, p.Why = meshprovisionerclient.Waits, en.Waits + case en.State != "" && en.State != meshprovisionerclient.Provided: + p.State, p.Why = meshprovisionerclient.Asked, "the provider's entry says "+en.State+", which no state of a provision is" return default: - p.State, p.Why = provisions.Provided, "" + p.State, p.Why = meshprovisionerclient.Provided, "" if en.VaultName != "" || en.Generation > 0 { - p.Reference = &provisions.Reference{ID: en.VaultName, Generation: en.Generation} + p.Reference = &meshprovisionerclient.Reference{ID: en.VaultName, Generation: en.Generation} } } } @@ -773,44 +773,44 @@ func (h *Holder) unread(module string) string { var decl struct { Reads []string `json:"reads"` } - if json.Unmarshal([]byte(manifest), &decl) != nil || slices.Contains(decl.Reads, provisions.PlansRead) { + if json.Unmarshal([]byte(manifest), &decl) != nil || slices.Contains(decl.Reads, meshprovisionerclient.PlansRead) { return "" } - return module + " reads no plans of the seat (its manifest's reads do not name " + provisions.PlansRead + + return module + " reads no plans of the seat (its manifest's reads do not name " + meshprovisionerclient.PlansRead + "), so its helper never answers this key" } // haveOutcome is the outcome of a provider that makes no credential per consumer: its own have on its node (the lead's // reading of ADR 0570 clause 3, recorded as an insight). Running with health ok at the build its want names is // provided; failed is failed with the have's words; anything else is asked, waiting for the provider to run. -func (h *Holder) haveOutcome(p *provisions.Provision) { +func (h *Holder) haveOutcome(p *meshprovisionerclient.Provision) { where := p.Provider.Module + " on " + p.Provider.Node // It makes what the consumer needs only once all it depends on is provided (its credential first). for _, dep := range p.DependsOn { state := "not composed yet" if e, err := h.Store.Get(ProvisionsState, dep); err == nil && e != nil { - if d, err := provisions.Decode(e.Value); err == nil { + if d, err := meshprovisionerclient.Decode(e.Value); err == nil { state = d.State } } - if state != provisions.Provided { - p.State, p.Why = provisions.Asked, "waits for "+dep+" ("+state+") before "+where+" can provide it" + if state != meshprovisionerclient.Provided { + p.State, p.Why = meshprovisionerclient.Asked, "waits for "+dep+" ("+state+") before "+where+" can provide it" return } } key := p.Provider.Node + "." + p.Provider.Module e, err := h.Store.Get(HaveRead, key) if err != nil { - p.State, p.Why = provisions.Asked, "the have of "+where+" cannot be read: "+err.Error() + p.State, p.Why = meshprovisionerclient.Asked, "the have of "+where+" cannot be read: "+err.Error() return } if e == nil { - p.State, p.Why = provisions.Asked, "waits for "+where+" to run: it says nothing yet" + p.State, p.Why = meshprovisionerclient.Asked, "waits for "+where+" to run: it says nothing yet" return } have, err := delivery.DecodeHave(e.Value) if err != nil { - p.State, p.Why = provisions.Asked, "the have of "+where+" is not readable" + p.State, p.Why = meshprovisionerclient.Asked, "the have of "+where+" is not readable" return } wantFP := "" @@ -821,19 +821,19 @@ func (h *Holder) haveOutcome(p *provisions.Provision) { } switch { case have.Phase == delivery.PhaseFailed || have.Health == delivery.HealthFailed: - p.State, p.Why = provisions.Failed, orSaid(have.Detail, where+" failed") + p.State, p.Why = meshprovisionerclient.Failed, orSaid(have.Detail, where+" failed") case have.Phase == delivery.PhaseRunning && have.Health == delivery.HealthOK && (wantFP == "" || have.FP == wantFP): // A provider's have counts as its outcome only from a build whose manifest offers the provision (ADR 0603 clause 5). // Refused only when that manifest is known and does not offer it: a have with no builder key (an old-form build, an // adopted module) or an unreadable manifest keeps the outcome it had. if offers, known := h.buildOffers(p.Provider.Module, have.FP, p.Provision); known && !offers { - p.State, p.Why = provisions.Asked, "waits for "+where+" to run a build that offers "+p.Provision+": the build it runs ("+ + p.State, p.Why = meshprovisionerclient.Asked, "waits for "+where+" to run a build that offers "+p.Provision+": the build it runs ("+ have.FP+") does not" return } - p.State, p.Why = provisions.Provided, "" + p.State, p.Why = meshprovisionerclient.Provided, "" default: - p.State, p.Why = provisions.Asked, fmt.Sprintf("waits for %s to run healthy at the build its want names (it is %s, "+ + p.State, p.Why = meshprovisionerclient.Asked, fmt.Sprintf("waits for %s to run healthy at the build its want names (it is %s, "+ "health %s)", where, have.Phase, have.Health) } } @@ -975,7 +975,7 @@ func (h *Holder) providerManifest(module string) (string, error) { } // retired says a retiring key the operator approved is retired: its provider's entry is gone. -func (h *Holder) retired(key string, p provisions.Provision) (bool, string) { +func (h *Holder) retired(key string, p meshprovisionerclient.Provision) (bool, string) { if p.Warrant == nil || p.Warrant.Option != OptionApprove { return false, "" } @@ -1003,7 +1003,7 @@ const ( const askLasts = occ.ApproveLasts - 10*time.Minute // retiringAsk is the ask of one retiring provision, composed from the key alone. -func retiringAsk(key string, p provisions.Provision, at time.Time, id string) oc.Ask { +func retiringAsk(key string, p meshprovisionerclient.Provision, at time.Time, id string) oc.Ask { what := fmt.Sprintf("%s's access to %s on %s, for %s on %s", p.Consumer.Module, p.Provision, p.Provider.Node, p.Consumer.Module, p.Consumer.Node) a := oc.Ask{ID: id, Headline: "Remove " + p.Consumer.Module + "'s " + p.Provision + " access?", @@ -1011,7 +1011,7 @@ func retiringAsk(key string, p provisions.Provision, at time.Time, id string) oc "is handed to the resource's owner and its credential goes; the resource and its data stay.", p.Consumer.Node, p.Provision, p.Provider.Module, what), Who: occ.Operator, Expires: occ.FormatTime(at.Add(askLasts)), OnExpiry: "nothing is removed; it is asked again when it changes", - About: "provision." + key, Details: "The provision " + key + " of mesh-provisioner's state provisions."} + About: "provision." + key, Details: "The provision " + key + " of mesh-provisioner's state meshprovisionerclient."} for _, o := range []struct{ id, label, does string }{ {OptionApprove, "Remove", "the provider removes the credential; the resource and its data stay"}, {OptionDecline, "Keep", "nothing is removed, and it is not asked again while nothing changes"}, @@ -1041,7 +1041,7 @@ const askWaits = "its ask waits until fewer than 3 of mesh-provisioner's asks st var errAskWaits = errors.New(askWaits) // raise asks a retiring key and says so in out: asked, waiting for an open ask to end, or a problem. -func (h *Holder) raise(p *provisions.Provision, key string, out *Composed) { +func (h *Holder) raise(p *meshprovisionerclient.Provision, key string, out *Composed) { switch err := h.ask(p, key); { case err == nil: out.Asked = append(out.Asked, key) @@ -1053,7 +1053,7 @@ func (h *Holder) raise(p *provisions.Provision, key string, out *Composed) { // ask raises the retiring ask of a key, under mesh-provisioner's own name; one already raised stands. While // askOpenAtMost asks stand open it raises none and the key's why says so. -func (h *Holder) ask(p *provisions.Provision, key string) error { +func (h *Holder) ask(p *meshprovisionerclient.Provision, key string) error { if p.Ask != "" { return nil } @@ -1086,7 +1086,7 @@ func (h *Holder) openAsks() int { keys, _ := h.Store.Keys(ProvisionsState) for _, k := range keys { if e, err := h.Store.Get(ProvisionsState, k); err == nil && e != nil { - if p, err := provisions.Decode(e.Value); err == nil && p.State == provisions.Retiring && p.Ask != "" && + if p, err := meshprovisionerclient.Decode(e.Value); err == nil && p.State == meshprovisionerclient.Retiring && p.Ask != "" && p.Warrant == nil { n++ } @@ -1097,7 +1097,7 @@ func (h *Holder) openAsks() int { // askHeld says the router holds a key's ask, or may not have taken it yet: false only when it has no record of it // askHeldWithin after it was raised (issue 940: an ask the router refused was counted asked for good). -func (h *Holder) askHeld(p provisions.Provision) bool { +func (h *Holder) askHeld(p meshprovisionerclient.Provision) bool { if h.Asks == nil || p.Ask == "" { return true } @@ -1125,8 +1125,8 @@ func (h *Holder) Decide() []string { if err != nil || e == nil { continue } - p, err := provisions.Decode(e.Value) - if err != nil || p.State != provisions.Retiring || p.Ask == "" || p.Warrant != nil { + p, err := meshprovisionerclient.Decode(e.Value) + if err != nil || p.State != meshprovisionerclient.Retiring || p.Ask == "" || p.Warrant != nil { continue } raw, found, err := h.Asks.Record(p.Ask) @@ -1180,7 +1180,7 @@ func (h *Holder) Decide() []string { said = append(said, k+": the answer is refused: its time is not RFC 3339 ("+err.Error()+")") continue } - p.Warrant = &provisions.Warrant{Ask: p.Ask, Option: option, By: by, At: answeredAt.UTC()} + p.Warrant = &meshprovisionerclient.Warrant{Ask: p.Ask, Option: option, By: by, At: answeredAt.UTC()} h.put(k, p) said = append(said, k+": "+option+" by "+by) } @@ -1200,8 +1200,8 @@ func (h *Holder) raiseWaiting() []string { if err != nil || e == nil { continue } - p, err := provisions.Decode(e.Value) - if err != nil || p.State != provisions.Retiring || p.Ask != "" || p.Warrant != nil || !strings.Contains(p.Why, askWaits) { + p, err := meshprovisionerclient.Decode(e.Value) + if err != nil || p.State != meshprovisionerclient.Retiring || p.Ask != "" || p.Warrant != nil || !strings.Contains(p.Why, askWaits) { continue } switch err := h.ask(&p, k); { @@ -1297,9 +1297,9 @@ func (h *Holder) LastingHolds() map[string]string { return out } -func (h *Holder) put(key string, p provisions.Provision) { +func (h *Holder) put(key string, p meshprovisionerclient.Provision) { p.At = h.Now().UTC() - if raw, err := provisions.Encode(p); err == nil { + if raw, err := meshprovisionerclient.Encode(p); err == nil { if err := h.Store.Put(ProvisionsState, key, json.RawMessage(raw)); err != nil { h.Logf("[%s] %s is not written: %v", Module, key, err) } @@ -1334,7 +1334,7 @@ func (h *Holder) NodesOfModule(module string) []string { if keys, err := h.Store.Keys(ProvisionsState); err == nil { for _, k := range keys { if e, err := h.Store.Get(ProvisionsState, k); err == nil && e != nil { - if p, err := provisions.Decode(e.Value); err == nil && p.Provider.Module == module { + if p, err := meshprovisionerclient.Decode(e.Value); err == nil && p.Provider.Module == module { nodes[p.Consumer.Node] = true } } @@ -1368,7 +1368,7 @@ func (h *Holder) placedOn(module string) []string { // NodeOfEntry is the consumer's node a provider's entry key names. func NodeOfEntry(key string) []string { - if n, _, _, _, err := provisions.ParseKey(key); err == nil { + if n, _, _, _, err := meshprovisionerclient.ParseKey(key); err == nil { return []string{n} } return nil @@ -1403,11 +1403,11 @@ func (h *Holder) Rejudge(key string) (string, error) { if err != nil || e == nil { return "", err } - have, err := provisions.Decode(e.Value) + have, err := meshprovisionerclient.Decode(e.Value) if err != nil { return "", err } - if have.State == provisions.Retiring { + if have.State == meshprovisionerclient.Retiring { if gone, why := h.retired(key, have); gone { return key + " retired: " + why, h.Store.Delete(ProvisionsState, key) } diff --git a/modules/mesh-provisioner/cmd/mesh-provisioner/holder_integration_test.go b/modules/mesh-provisioner/cmd/mesh-provisioner/holder_integration_test.go index bd92726e2..d4c4706d1 100644 --- a/modules/mesh-provisioner/cmd/mesh-provisioner/holder_integration_test.go +++ b/modules/mesh-provisioner/cmd/mesh-provisioner/holder_integration_test.go @@ -22,9 +22,9 @@ import ( "github.com/nats-io/nats.go/jetstream" oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/delivery" - "git.novox.be/novox/mesh-sdk/go/provisions" "git.novox.be/novox/mesh-sdk/go/testbus" ) @@ -132,9 +132,9 @@ func TestTheHolderPlansProvidesAndAsksOnTheBus(t *testing.T) { published(t, mem, c) vaultManifest := `{"module":"mesh-vault","version":"1","state":["bound"]}` // the vault keeps its outcomes as entries vaultDigest := delivery.ManifestDigest([]byte(vaultManifest)) - vaultValue, _ := delivery.EncodeManifest(delivery.Manifest{Module: provisions.VaultModule, JSON: vaultManifest}) + vaultValue, _ := delivery.EncodeManifest(delivery.Manifest{Module: meshprovisionerclient.VaultModule, JSON: vaultManifest}) mem.write(t, ManifestsRead, mustKey(delivery.ManifestsKey(vaultDigest)), string(vaultValue)) - mem.write(t, ModulesRead, provisions.VaultModule, `{"v":1,"none2":"the test's","manifest":"`+vaultDigest+`"}`) + mem.write(t, ModulesRead, meshprovisionerclient.VaultModule, `{"v":1,"none2":"the test's","manifest":"`+vaultDigest+`"}`) for state, keys := range mem.states { for key, raw := range keys { if err := s.Put(state, key, json.RawMessage(raw)); err != nil { @@ -195,19 +195,19 @@ func TestTheHolderPlansProvidesAndAsksOnTheBus(t *testing.T) { a := &asked{} h := &Holder{Store: Watching(s, ws), Asks: a, Now: time.Now, Logf: t.Logf} h.Compose = FromCompositions(h.Store) - state := func(key string) provisions.Provision { + state := func(key string) meshprovisionerclient.Provision { e, _ := s.Get(ProvisionsState, key) if e == nil { - return provisions.Provision{} + return meshprovisionerclient.Provision{} } - p, _ := provisions.Decode(e.Value) + p, _ := meshprovisionerclient.Decode(e.Value) return p } key := node + ".restic.postgres-database" if _, err := h.ComposeNode(ctx, node); err != nil { t.Fatal(err) } - if p := state(key); p.State != provisions.Asked || p.Provider.Module != "postgres" { + if p := state(key); p.State != meshprovisionerclient.Asked || p.Provider.Module != "postgres" { t.Fatalf("the placement and the want composed %+v", p) } if e, _ := s.Get(PlansState, node+".restic"); e == nil { @@ -215,7 +215,7 @@ func TestTheHolderPlansProvidesAndAsksOnTheBus(t *testing.T) { } // The providers' outcomes: the vault provides the credential where restic has one, postgres runs healthy. for _, dep := range state(key).DependsOn { - if err := s.Put(boundRead(provisions.VaultModule), dep, map[string]any{"state": "provided"}); err != nil { + if err := s.Put(boundRead(meshprovisionerclient.VaultModule), dep, map[string]any{"state": "provided"}); err != nil { t.Fatal(err) } } @@ -248,7 +248,7 @@ func TestTheHolderPlansProvidesAndAsksOnTheBus(t *testing.T) { t.Fatal(err) } } - if p := state(key); p.State != provisions.Asked { + if p := state(key); p.State != meshprovisionerclient.Asked { t.Fatalf("a build not offering the provision turned it %s", p.State) } offered(`["postgres-database"]`) @@ -257,7 +257,7 @@ func TestTheHolderPlansProvidesAndAsksOnTheBus(t *testing.T) { t.Fatal(err) } } - if p := state(key); p.State != provisions.Provided { + if p := state(key); p.State != meshprovisionerclient.Provided { t.Fatalf("the outcomes did not turn it provided: %+v", p) } // restic leaves the node and its want goes: retiring, one ask. Its compositions stay until its engine deletes them. @@ -273,7 +273,7 @@ func TestTheHolderPlansProvidesAndAsksOnTheBus(t *testing.T) { if _, err := h.ComposeNode(ctx, node); err != nil { t.Fatal(err) } - if r := state(key); r.State != provisions.Retiring || r.Ask == "" || len(a.ids) == 0 { + if r := state(key); r.State != meshprovisionerclient.Retiring || r.Ask == "" || len(a.ids) == 0 { t.Fatalf("removing the want did not ask: %+v, asked %v", r, a.ids) } } diff --git a/modules/mesh-provisioner/cmd/mesh-provisioner/holder_test.go b/modules/mesh-provisioner/cmd/mesh-provisioner/holder_test.go index 293cd6b5c..183bb333c 100644 --- a/modules/mesh-provisioner/cmd/mesh-provisioner/holder_test.go +++ b/modules/mesh-provisioner/cmd/mesh-provisioner/holder_test.go @@ -15,10 +15,10 @@ import ( occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient" oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/catalogue" "git.novox.be/novox/mesh-sdk/go/delivery" - "git.novox.be/novox/mesh-sdk/go/provisions" ) // router is the operator's channel as the holder asks on it: it holds an ask open, or, like the router past its open @@ -114,13 +114,13 @@ var ( split = catalogue.PlanProvision{Provision: "split-dns", Provider: "g14", ProviderModule: "systemd-resolved"} ) -func (m *mesh) state(t *testing.T, key string) provisions.Provision { +func (m *mesh) state(t *testing.T, key string) meshprovisionerclient.Provision { t.Helper() e, _ := m.s.Get(ProvisionsState, key) if e == nil { - return provisions.Provision{} + return meshprovisionerclient.Provision{} } - p, err := provisions.Decode(e.Value) + p, err := meshprovisionerclient.Decode(e.Value) if err != nil { t.Fatal(err) } @@ -150,11 +150,11 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) { state string why string }{ - {"composed: asked", "", provisions.Asked, ""}, - {"the provider waits for a person", `{"waits":"the database's owner to accept"}`, provisions.Waits, "owner"}, - {"the provider refused", `{"refused":"no room on ace"}`, provisions.Failed, "no room"}, - {"the provider says failed in its state", `{"state":"failed","why":"the disk is full"}`, provisions.Failed, "disk"}, - {"the provider made it", `{"state":"provided","vault-name":"pair/gitea-postgres","generation":3}`, provisions.Provided, ""}, + {"composed: asked", "", meshprovisionerclient.Asked, ""}, + {"the provider waits for a person", `{"waits":"the database's owner to accept"}`, meshprovisionerclient.Waits, "owner"}, + {"the provider refused", `{"refused":"no room on ace"}`, meshprovisionerclient.Failed, "no room"}, + {"the provider says failed in its state", `{"state":"failed","why":"the disk is full"}`, meshprovisionerclient.Failed, "disk"}, + {"the provider made it", `{"state":"provided","vault-name":"pair/gitea-postgres","generation":3}`, meshprovisionerclient.Provided, ""}, } for _, s := range steps { if s.entry != "" { @@ -173,11 +173,11 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) { // holder alone. split := "g14.gitea.split-dns" for _, row := range []struct{ have, want, state, why string }{ - {"", "", provisions.Asked, "says nothing yet"}, - {`{"v":1,"fp":"src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","phase":"applying","health":"unknown"}`, "", provisions.Asked, "applying"}, - {`{"v":1,"fp":"src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","phase":"running","health":"ok"}`, `{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","self":true}`, provisions.Asked, "build its want"}, - {`{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","phase":"failed","health":"failed","detail":"the unit did not start"}`, "", provisions.Failed, "did not start"}, - {`{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","phase":"running","health":"ok"}`, `{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","self":true}`, provisions.Provided, ""}, + {"", "", meshprovisionerclient.Asked, "says nothing yet"}, + {`{"v":1,"fp":"src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","phase":"applying","health":"unknown"}`, "", meshprovisionerclient.Asked, "applying"}, + {`{"v":1,"fp":"src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","phase":"running","health":"ok"}`, `{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","self":true}`, meshprovisionerclient.Asked, "build its want"}, + {`{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","phase":"failed","health":"failed","detail":"the unit did not start"}`, "", meshprovisionerclient.Failed, "did not start"}, + {`{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","phase":"running","health":"ok"}`, `{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","self":true}`, meshprovisionerclient.Provided, ""}, } { if row.have != "" { m.s.write(t, HaveRead, "g14.systemd-resolved", row.have) @@ -195,8 +195,8 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) { bfp := "src2:" + strings.Repeat("bb", 32) buildKey := mustKey(delivery.BuilderBuildKey("systemd-resolved", bfp)) for _, row := range []struct{ name, provides, state, why string }{ - {"a build whose manifest does not offer it", `["other"]`, provisions.Asked, "offers split-dns"}, - {"a build whose manifest offers it", `[{"name":"split-dns"}]`, provisions.Provided, ""}, + {"a build whose manifest does not offer it", `["other"]`, meshprovisionerclient.Asked, "offers split-dns"}, + {"a build whose manifest offers it", `[{"name":"split-dns"}]`, meshprovisionerclient.Provided, ""}, } { raw := `{"module":"systemd-resolved","version":"1","provides":` + row.provides + `}` digest := delivery.ManifestDigest([]byte(raw)) @@ -238,7 +238,7 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) { c.atNewest["g14"] = c.atWant["g14"] c.compose(t, "g14") cred := c.state(t, "g14.gitea.secret-postgres-database") - if cred.Provider.Module != "mesh-vault" || cred.Provider.Node != "novox" || cred.State != provisions.Asked { + if cred.Provider.Module != "mesh-vault" || cred.Provider.Node != "novox" || cred.State != meshprovisionerclient.Asked { t.Errorf("the credential's provision is %+v", cred) } if d := c.state(t, key).DependsOn; !slices.Equal(d, []string{"g14.gitea.secret-postgres-database"}) { @@ -254,9 +254,9 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) { for _, row := range []struct { name, entry, cred, state string }{ - {"its credential still asked", "", provisions.Asked, provisions.Asked}, + {"its credential still asked", "", meshprovisionerclient.Asked, meshprovisionerclient.Asked}, {"its credential provided by the vault", `{"state":"provided","vault-name":"pair/g14/s3-bucket/g14/gitea","generation":1}`, - provisions.Provided, provisions.Provided}, + meshprovisionerclient.Provided, meshprovisionerclient.Provided}, } { if row.entry != "" { c.s.write(t, "mesh-vault.bound", s3cred, row.entry) @@ -270,7 +270,7 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) { // An entry's change judges its key alone, no composition. before := len(m.composed) m.s.write(t, "postgres.bound", key, `{"refused":"the login is locked"}`) - if said, err := m.h.Rejudge(key); err != nil || !strings.Contains(said, provisions.Failed) || len(m.composed) != before { + if said, err := m.h.Rejudge(key); err != nil || !strings.Contains(said, meshprovisionerclient.Failed) || len(m.composed) != before { t.Errorf("rejudged %q, %v, composed %d more", said, err, len(m.composed)-before) } } @@ -293,17 +293,17 @@ func TestRetiringIsAskedAndActsOnlyOnTheWarrant(t *testing.T) { removed bool }{ {"a key composed ahead of its want is asked, not retiring", func() {}, nil, - map[string]string{pg: provisions.Provided, kc: provisions.Asked}, false}, + map[string]string{pg: meshprovisionerclient.Provided, kc: meshprovisionerclient.Asked}, false}, {"one requirement removed and another added: only the removed retires", func() { m.atWant["g14"] = map[string]catalogue.Plan{"gitea": planOf(oidc)} m.atNewest["g14"] = map[string]catalogue.Plan{"gitea": planOf(oidc)} - }, []string{pg}, map[string]string{pg: provisions.Retiring, kc: provisions.Asked}, false}, - {"composed again: no second ask", func() {}, nil, map[string]string{pg: provisions.Retiring}, false}, + }, []string{pg}, map[string]string{pg: meshprovisionerclient.Retiring, kc: meshprovisionerclient.Asked}, false}, + {"composed again: no second ask", func() {}, nil, map[string]string{pg: meshprovisionerclient.Retiring}, false}, {"needed again before the warrant: back to its outcome", func() { m.atWant["g14"] = map[string]catalogue.Plan{"gitea": planOf(oidc, pgDB)} - }, nil, map[string]string{pg: provisions.Provided}, false}, + }, nil, map[string]string{pg: meshprovisionerclient.Provided}, false}, {"gone again: asked again", func() { m.atWant["g14"] = map[string]catalogue.Plan{"gitea": planOf(oidc)} }, - []string{pg}, map[string]string{pg: provisions.Retiring}, false}, + []string{pg}, map[string]string{pg: meshprovisionerclient.Retiring}, false}, } for _, s := range steps { s.change() @@ -336,7 +336,7 @@ func TestRetiringIsAskedAndActsOnlyOnTheWarrant(t *testing.T) { if w := m.state(t, pg).Warrant; w.Option != "yes" { t.Fatalf("the warrant says %q, and a provider lets go only on \"yes\"", w.Option) } - if said, _ := m.h.Rejudge(pg); said != "" || m.state(t, pg).State != provisions.Retiring { + if said, _ := m.h.Rejudge(pg); said != "" || m.state(t, pg).State != meshprovisionerclient.Retiring { t.Errorf("retired while the provider's entry stands: %q", said) } _ = m.s.Delete("postgres.bound", pg) @@ -397,7 +397,7 @@ func TestOneBadModuleDoesNotDropItsNode(t *testing.T) { if e, _ := m.s.Get(PlansState, "g14.nats"); e == nil { t.Error("the held module's last plan was removed") } - if p := m.state(t, "g14.nats.oidc-client"); p.State != provisions.Asked { + if p := m.state(t, "g14.nats.oidc-client"); p.State != meshprovisionerclient.Asked { t.Errorf("the held module's provision is %s (%s), not kept", p.State, p.Why) } got, err := m.h.read(RefusedState, "", "g14", "") @@ -539,21 +539,21 @@ func TestAProvidersOutcomeIsReadPerOffer(t *testing.T) { }{ {"gitea-read: the helper's refusal is not its outcome; gitea runs, so provided", "ace", map[string]catalogue.Plan{"claude-code": planOf(catalogue.PlanProvision{Provision: "gitea-read", Provider: "novox", ProviderModule: "gitea"})}, - "ace.claude-code.gitea-read", "gitea.bound", refused, "novox.gitea", provisions.Provided, ""}, + "ace.claude-code.gitea-read", "gitea.bound", refused, "novox.gitea", meshprovisionerclient.Provided, ""}, {"forge-account: still the helper's entry", "ace", map[string]catalogue.Plan{"mesh-build-go": planOf(catalogue.PlanProvision{Provision: "forge-account", Provider: "novox", ProviderModule: "gitea"})}, - "ace.mesh-build-go.forge-account", "gitea.bound", `{"state":"provided"}`, "", provisions.Provided, ""}, + "ace.mesh-build-go.forge-account", "gitea.bound", `{"state":"provided"}`, "", meshprovisionerclient.Provided, ""}, {"route: route-proxy's entry is read", "novox", map[string]catalogue.Plan{"gitea": planOf(catalogue.PlanProvision{Provision: "route", Provider: "novox", ProviderModule: "route-proxy"})}, - "novox.gitea.route", "route-proxy.bound", `{"state":"provided"}`, "", provisions.Provided, ""}, + "novox.gitea.route", "route-proxy.bound", `{"state":"provided"}`, "", meshprovisionerclient.Provided, ""}, {"mcp-endpoint: node-tools' entry is read", "ace", map[string]catalogue.Plan{"claude-code": planOf(catalogue.PlanProvision{Provision: "mcp-endpoint", Provider: "ace", ProviderModule: "node-tools"})}, - "ace.claude-code.mcp-endpoint", "node-tools.bound", `{"state":"provided"}`, "", provisions.Provided, ""}, + "ace.claude-code.mcp-endpoint", "node-tools.bound", `{"state":"provided"}`, "", meshprovisionerclient.Provided, ""}, // Issue 774, 2026-10-31: route-proxy's helper read the controller's assignments, never the seat's plans, so 38 // routes the seat keys stood asked with no why while the assigner withheld their consumers' builds. {"route: no entry from a provider that reads no plans of the seat is said so", "ace", map[string]catalogue.Plan{"grafana": planOf(catalogue.PlanProvision{Provision: "route", Provider: "ace", ProviderModule: "route-proxy"})}, - "ace.grafana.route", "", "", "", provisions.Asked, "reads no plans of the seat"}, + "ace.grafana.route", "", "", "", meshprovisionerclient.Asked, "reads no plans of the seat"}, } { m := newMesh() m.manifestOf("gitea", gitea) @@ -588,7 +588,7 @@ func TestAKeyAheadOfItsWantCarriesItsPlanEntryAndSaysWhy(t *testing.T) { if kc.Plan == nil || kc.Plan.Provision != "oidc-client" || kc.Plan.ProviderModule != "keycloak" || kc.Plan.As != "gitea-g14" { t.Errorf("the key ahead of its want carries %+v", kc.Plan) } - if kc.State != provisions.Asked || !strings.Contains(kc.Why, "no plan names it") { + if kc.State != meshprovisionerclient.Asked || !strings.Contains(kc.Why, "no plan names it") { t.Errorf("the key ahead of its want: %s %q", kc.State, kc.Why) } // A key a plan names carries no entry: a reader on an older mesh-sdk, which refused a field it did not know, reads it @@ -712,7 +712,7 @@ func TestARetirementIsJudgedOnlyFromAWholePicture(t *testing.T) { } retiring := 0 for i := range row.consumer { - if m.state(t, "novox."+apps[i]+".route.1").State == provisions.Retiring { + if m.state(t, "novox."+apps[i]+".route.1").State == meshprovisionerclient.Retiring { retiring++ } } diff --git a/modules/mesh-provisioner/cmd/mesh-provisioner/holdertools.go b/modules/mesh-provisioner/cmd/mesh-provisioner/holdertools.go index 7256ed64d..cbc36bd85 100644 --- a/modules/mesh-provisioner/cmd/mesh-provisioner/holdertools.go +++ b/modules/mesh-provisioner/cmd/mesh-provisioner/holdertools.go @@ -10,9 +10,9 @@ import ( "fmt" "strings" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/health" - "git.novox.be/novox/mesh-sdk/go/provisions" ) // The holder's tools. @@ -133,7 +133,7 @@ func (h *Holder) read(state, key, node, want string) (any, error) { } row := map[string]any{"key": k} if state == ProvisionsState { - p, err := provisions.Decode(e.Value) + p, err := meshprovisionerclient.Decode(e.Value) if err != nil { row["unreadable"] = err.Error() } else { diff --git a/modules/mesh-provisioner/go.mod b/modules/mesh-provisioner/go.mod index d160048cb..9c368615f 100644 --- a/modules/mesh-provisioner/go.mod +++ b/modules/mesh-provisioner/go.mod @@ -3,6 +3,7 @@ module mesh-provisioner go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient v0.0.0-00010101000000-000000000000 diff --git a/modules/mesh-vault/cmd/mesh-vault/askers.go b/modules/mesh-vault/cmd/mesh-vault/askers.go index 81783a8d4..cfc4d1c0b 100644 --- a/modules/mesh-vault/cmd/mesh-vault/askers.go +++ b/modules/mesh-vault/cmd/mesh-vault/askers.go @@ -1,7 +1,7 @@ package main import ( - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" "encoding/json" "fmt" @@ -78,14 +78,14 @@ const ProvisionerPrefix = "provisioner." // seat mesh-provisioner's state `plans`, `.` (novox/hq ADR 0570 clause 2), no longer the controller's // assignments. A plan is read as the assignment's value carried it (asAssignment), so the rules that read a plan are // unchanged. -const AssignmentsRead = provisions.PlansRead +const AssignmentsRead = meshprovisionerclient.PlansRead // asAssignment is a plan's key in the form the vault's rules read: `{node, module, provisioning: plan}`, nil for none. func asAssignment(key string, raw []byte, err error) ([]byte, error) { if err != nil || raw == nil { return raw, err } - p, err := provisions.DecodePlan(raw) + p, err := meshprovisionerclient.DecodePlan(raw) if err != nil { return nil, fmt.Errorf("the plan %s: %w", key, err) } diff --git a/modules/mesh-vault/cmd/mesh-vault/main.go b/modules/mesh-vault/cmd/mesh-vault/main.go index 67ae3fb0c..6a5ac44d6 100644 --- a/modules/mesh-vault/cmd/mesh-vault/main.go +++ b/modules/mesh-vault/cmd/mesh-vault/main.go @@ -8,7 +8,8 @@ package main import ( - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" "encoding/json" @@ -79,7 +80,7 @@ func build() *Env { Delete: func(key string) error { return stdio.State(BoundState).Delete(key) }, Keys: func() ([]string, error) { return stdio.State(BoundState).Keys() }, Provision: func(key string) ([]byte, error) { - e, err := stdio.State(provisions.ProvisionsRead).Get(key) + e, err := stdio.State(meshprovisionerclient.ProvisionsRead).Get(key) if err != nil || e == nil { return nil, err } @@ -122,11 +123,8 @@ func watchLeavers(env *Env) bool { if node, ok := leaverKey(key); ok { env.Vault.NodeLeft(node) } - }, env.Vault.PlacementChanged, func(key string, v json.RawMessage) error { - _, err := stdio.State(FindingsState).Put(key, v) - return err - }, - func(key string) error { return stdio.State(FindingsState).Delete(key) }) + }, env.Vault.PlacementChanged, + meshconditionsclient.FindingWriter{State: stdio.State(FindingsState)}) beginPlacementView(placementView) } return true @@ -222,7 +220,7 @@ func watchCredentialAsks(env *Env, kick chan<- struct{}) bool { if env.Vault == nil { return true } - err := stdio.State(provisions.ProvisionsRead).Watch("", func(c stdio.StateChange) error { + err := stdio.State(meshprovisionerclient.ProvisionsRead).Watch("", func(c stdio.StateChange) error { if !c.Current && credentialAsked(c.Value) { select { case kick <- struct{}{}: diff --git a/modules/mesh-vault/cmd/mesh-vault/outcomes.go b/modules/mesh-vault/cmd/mesh-vault/outcomes.go index 7b2013868..95659f173 100644 --- a/modules/mesh-vault/cmd/mesh-vault/outcomes.go +++ b/modules/mesh-vault/cmd/mesh-vault/outcomes.go @@ -3,7 +3,7 @@ package main // The vault's outcome for each credential it provides (novox/hq ADR 0570 clauses 3, 6, 7): an entry in its own state // `bound`, one per credential provision `..secret-[.]`, which the holder of // mesh-provisioner reads to set that key's state. The entry names the value by the vault's own name for it -// (provisions.VaultName, as its verb `own` names it) and its generation, never the value. A value the vault holds is +// (meshprovisionerclient.VaultName, as its verb `own` names it) and its generation, never the value. A value the vault holds is // provided; one only the provider's software issues, or only a person gives, waits for them; one the vault has not // made yet has no entry, and the key stays asked. An offer whose form is none has no credential and no entry. An entry // is let go only once its key is retiring with the operator's warrant, or gone. @@ -14,13 +14,13 @@ import ( "fmt" "sort" - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" ) // BoundState is the vault's state of outcome entries. const BoundState = "bound" -// Bound is the vault's own state `bound`, and what it reads of the seat's provisions. +// Bound is the vault's own state `bound`, and what it reads of the seat's meshprovisionerclient. type Bound struct { Get func(key string) ([]byte, error) Put func(key string, value []byte) error @@ -96,8 +96,8 @@ func (v *Vault) letGo(key string) bool { if raw == nil { return true } - p, err := provisions.Decode(raw) - return err == nil && p.State == provisions.Retiring && p.Warrant != nil && p.Warrant.Option == "approve" + p, err := meshprovisionerclient.Decode(raw) + return err == nil && p.State == meshprovisionerclient.Retiring && p.Warrant != nil && p.Warrant.Option == "approve" } // outcomes is every credential's outcome the plans call for, by its key. @@ -119,42 +119,42 @@ func (v *Vault) outcomes() (map[string]BoundOutcome, error) { if err := json.Unmarshal(raw, &a); err != nil || a.Provisioning == nil { // binds, not handing continue } - consumer := provisions.End{Module: a.Module, Node: a.Node} + consumer := meshprovisionerclient.End{Module: a.Module, Node: a.Node} for _, p := range a.Provisioning.Provisions { - provider := provisions.End{Module: p.ProviderModule, Node: p.Provider} - if p.ProviderModule == provisions.VaultModule && p.Provision == "secret" { + provider := meshprovisionerclient.End{Module: p.ProviderModule, Node: p.Provider} + if p.ProviderModule == meshprovisionerclient.VaultModule && p.Provision == "secret" { // The vault's own offer: a value it hands the consumer's client on request (`get`), which it serves as // soon as it runs. - key, err := provisions.Key(a.Node, a.Module, p.Provision, p.Local) + key, err := meshprovisionerclient.Key(a.Node, a.Module, p.Provision, p.Local) if err == nil { - out[key] = BoundOutcome{Provider: p.Provider, ProviderModule: provisions.VaultModule, Provision: p.Provision, - Consumer: a.Node, Module: a.Module, Local: p.Local, State: provisions.Provided, + out[key] = BoundOutcome{Provider: p.Provider, ProviderModule: meshprovisionerclient.VaultModule, Provision: p.Provision, + Consumer: a.Node, Module: a.Module, Local: p.Local, State: meshprovisionerclient.Provided, Why: "the vault hands it to the consumer's client on request"} } continue } - ck, ok := provisions.CredentialKey(p.CredentialForm, consumer, provider, p.Provision, p.Local) + ck, ok := meshprovisionerclient.CredentialKey(p.CredentialForm, consumer, provider, p.Provision, p.Local) if !ok { continue // form none: no credential, nothing minted } - parent := provisions.Provision{Provision: p.Provision, Local: p.Local, Consumer: consumer, Provider: provider} - name := provisions.VaultName(p.CredentialForm, parent) - cn, cm, cp, cl, err := provisions.ParseKey(ck) + parent := meshprovisionerclient.Provision{Provision: p.Provision, Local: p.Local, Consumer: consumer, Provider: provider} + name := meshprovisionerclient.VaultName(p.CredentialForm, parent) + cn, cm, cp, cl, err := meshprovisionerclient.ParseKey(ck) if err != nil || name == "" { continue } - o := BoundOutcome{Provider: p.Provider, ProviderModule: provisions.VaultModule, Provision: cp, Consumer: cn, + o := BoundOutcome{Provider: p.Provider, ProviderModule: meshprovisionerclient.VaultModule, Provision: cp, Consumer: cn, Module: cm, Local: cl, VaultName: name} rec, held, err := v.Store.Read(name) switch { case err != nil: - o.State, o.Why = provisions.Failed, "the vault cannot read "+name+": "+err.Error() + o.State, o.Why = meshprovisionerclient.Failed, "the vault cannot read "+name+": "+err.Error() case held: - o.State, o.Generation = provisions.Provided, rec.Generation + o.State, o.Generation = meshprovisionerclient.Provided, rec.Generation case p.CredentialForm == FormIssued: - o.State, o.Why = provisions.Waits, "the provider's software issues it (ADR 0305): `issued` brings it in" + o.State, o.Why = meshprovisionerclient.Waits, "the provider's software issues it (ADR 0305): `issued` brings it in" case p.CredentialForm == FormGiven: - o.State, o.Why = provisions.Waits, "a person gives it (ADR 0337): `accept` brings it in" + o.State, o.Why = meshprovisionerclient.Waits, "a person gives it (ADR 0337): `accept` brings it in" default: continue // not made yet: the key stays asked until the pair pass makes it } diff --git a/modules/mesh-vault/cmd/mesh-vault/pair.go b/modules/mesh-vault/cmd/mesh-vault/pair.go index 3208e1382..51710b66e 100644 --- a/modules/mesh-vault/cmd/mesh-vault/pair.go +++ b/modules/mesh-vault/cmd/mesh-vault/pair.go @@ -59,8 +59,8 @@ import ( "strings" "time" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" "git.novox.be/novox/mesh-sdk/go/catalogue" - "git.novox.be/novox/mesh-sdk/go/provisions" "git.novox.be/novox/mesh-sdk/go/seal" ) @@ -865,7 +865,7 @@ func (e *Env) credentialsState() []PairOutcome { // credentialAsked is whether a key of the seat mesh-provisioner's provisions asks the vault for a credential (ADR 0570 // §1, §6): a provision `secret-` whose provider is the vault, in state asked. func credentialAsked(raw []byte) bool { - p, err := provisions.Decode(raw) - return err == nil && p.State == provisions.Asked && p.Provider.Module == provisions.VaultModule && + p, err := meshprovisionerclient.Decode(raw) + return err == nil && p.State == meshprovisionerclient.Asked && p.Provider.Module == meshprovisionerclient.VaultModule && strings.HasPrefix(p.Provision, catalogue.CredentialProvisionPrefix) } diff --git a/modules/mesh-vault/cmd/mesh-vault/placementview.go b/modules/mesh-vault/cmd/mesh-vault/placementview.go index 111874e01..81003eb5c 100644 --- a/modules/mesh-vault/cmd/mesh-vault/placementview.go +++ b/modules/mesh-vault/cmd/mesh-vault/placementview.go @@ -37,7 +37,7 @@ var placementView *views.Follower // newPlacementView makes the follower: ask calls the tool, gone is told of a deleted key, changed of every change after // it is held (a first view's keys too). func newPlacementView(ask func(key string, body any) (json.RawMessage, error), gone func(key string), changed func(), - put func(key string, value json.RawMessage) error, drop func(key string) error) *views.Follower { + findings views.FindingWriter) *views.Follower { return &views.Follower{Owner: delivery.AssignerModule, Tool: PlacementTool, State: "placement", Logf: say, Ask: func(_ context.Context, after string) (views.Answer, error) { body := map[string]any{"values": true} @@ -55,16 +55,13 @@ func newPlacementView(ask func(key string, body any) (json.RawMessage, error), g Raise: func(s views.Status) { say("the vault has no first view of the assigner's placement: %s has not answered since %s (%s); it keeps asking", s.Tool, s.Asked.Format(time.RFC3339), s.Error) - if k, v, err := views.UnansweredFinding(Seat, s, time.Now()); err == nil { - if err := put(k, v); err != nil { - say("the finding %s is not written: %v", k, err) - } + f := views.UnansweredFinding(Seat, s, time.Now()) + if err := findings.Put(f); err != nil { + say("the finding %s is not written: %v", f.ID, err) } }, Clear: func(s views.Status) { - if k, _, err := views.UnansweredFinding(Seat, s, time.Now()); err == nil { - _ = drop(k) - } + _ = findings.Delete(views.UnansweredFinding(Seat, s, time.Now())) }, Changed: func(key string, _ json.RawMessage, deleted bool, _ time.Time) { if deleted { diff --git a/modules/mesh-vault/cmd/mesh-vault/placementview_test.go b/modules/mesh-vault/cmd/mesh-vault/placementview_test.go index d7132f10f..cb66dfa3a 100644 --- a/modules/mesh-vault/cmd/mesh-vault/placementview_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/placementview_test.go @@ -28,9 +28,7 @@ func TestAnUnansweredFirstViewOfThePlacementIsAFindingTheAnswerClears(t *testing Values: map[string]json.RawMessage{"g14.node": json.RawMessage(`{}`)}}) return raw, nil } - put := func(k string, v json.RawMessage) error { mu.Lock(); held[k] = v; mu.Unlock(); return nil } - drop := func(k string) error { mu.Lock(); delete(held, k); mu.Unlock(); return nil } - f := newPlacementView(ask, func(string) {}, nil, put, drop) + f := newPlacementView(ask, func(string) {}, nil, heldFindings{&mu, held}) f.Bound, f.Wait = 30*time.Millisecond, 10*time.Millisecond reader := viewPlacement(func() *views.Follower { return f }) if _, err := reader.Keys(); err == nil { @@ -57,3 +55,22 @@ func TestAnUnansweredFirstViewOfThePlacementIsAFindingTheAnswerClears(t *testing t.Errorf("keys %v, %v", keys, err) } } + +// heldFindings keeps the findings written, by the finding's kind and subject. +type heldFindings struct { + mu *sync.Mutex + held map[string]json.RawMessage +} + +func (h heldFindings) Put(f views.Finding) error { + h.mu.Lock() + defer h.mu.Unlock() + h.held[f.ID+"."+f.Kind] = json.RawMessage(f.Summary) + return nil +} +func (h heldFindings) Delete(f views.Finding) error { + h.mu.Lock() + defer h.mu.Unlock() + delete(h.held, f.ID+"."+f.Kind) + return nil +} diff --git a/modules/mesh-vault/cmd/mesh-vault/vault_test.go b/modules/mesh-vault/cmd/mesh-vault/vault_test.go index d5b8eca9d..1eabe93d5 100644 --- a/modules/mesh-vault/cmd/mesh-vault/vault_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/vault_test.go @@ -196,16 +196,15 @@ func TestNoBucketHoldsASecret(t *testing.T) { code = []byte(strings.Replace(string(code), "stdio.State(WantedRead).Watch(", "", 1)) code = []byte(strings.Replace(string(code), "stdio.State(WantedRead).Get(", "", 1)) // And its findings (ADR 0615 §6): the finding of a first view unanswered, written and deleted, never a secret. - code = []byte(strings.Replace(string(code), "stdio.State(FindingsState).Put(", "", 1)) - code = []byte(strings.Replace(string(code), "stdio.State(FindingsState).Delete(", "", 1)) + code = []byte(strings.Replace(string(code), "meshconditionsclient.FindingWriter{State: stdio.State(FindingsState)}", "", 1)) // And its outcome entries (novox/hq ADR 0570 clauses 3, 6): a value's name and generation, never a value; and // one read of the seat's provisions, which hold none. for _, call := range []string{"Get(", "Put(", "Delete(", "Keys("} { code = []byte(strings.Replace(string(code), "stdio.State(BoundState)."+call, "", 1)) } - code = []byte(strings.Replace(string(code), "stdio.State(provisions.ProvisionsRead).Get(", "", 1)) + code = []byte(strings.Replace(string(code), "stdio.State(meshprovisionerclient.ProvisionsRead).Get(", "", 1)) // And one watch of them, for a credential asked of the vault (issue 1126). - code = []byte(strings.Replace(string(code), "stdio.State(provisions.ProvisionsRead).Watch(", "", 1)) + code = []byte(strings.Replace(string(code), "stdio.State(meshprovisionerclient.ProvisionsRead).Watch(", "", 1)) } if m := bucket.Find(code); m != nil { t.Errorf("%s opens a bucket (%s): the vault keeps every secret in its own store only", f, m) diff --git a/modules/mesh-vault/go.mod b/modules/mesh-vault/go.mod index cb7df3b06..41e94d087 100644 --- a/modules/mesh-vault/go.mod +++ b/modules/mesh-vault/go.mod @@ -3,6 +3,7 @@ module mesh-vault go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/go/seats/meshvault v0.0.0-20261104174344-ae5266e77639 git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f github.com/nats-io/nats-server/v2 v2.11.17 diff --git a/modules/postgres/cmd/postgres-provider/harness_test.go b/modules/postgres/cmd/postgres-provider/harness_test.go index 7c04bdbae..022c09d6d 100644 --- a/modules/postgres/cmd/postgres-provider/harness_test.go +++ b/modules/postgres/cmd/postgres-provider/harness_test.go @@ -3,7 +3,7 @@ package main import ( "context" "encoding/json" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "os" "path/filepath" "strings" diff --git a/modules/postgres/cmd/postgres-provider/live_test.go b/modules/postgres/cmd/postgres-provider/live_test.go index 5e847973c..7efcdb0c3 100644 --- a/modules/postgres/cmd/postgres-provider/live_test.go +++ b/modules/postgres/cmd/postgres-provider/live_test.go @@ -12,7 +12,7 @@ package main // COMMIT (novox/hq ADR 0230). import ( - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "net/url" "os" "testing" diff --git a/modules/postgres/cmd/postgres-provider/main.go b/modules/postgres/cmd/postgres-provider/main.go index 8a5321196..166f42fe8 100644 --- a/modules/postgres/cmd/postgres-provider/main.go +++ b/modules/postgres/cmd/postgres-provider/main.go @@ -10,7 +10,7 @@ import ( "context" "encoding/json" "fmt" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "os" "time" diff --git a/modules/postgres/cmd/postgres-provider/moved.go b/modules/postgres/cmd/postgres-provider/moved.go index e9e4c392c..3efa2c1cb 100644 --- a/modules/postgres/cmd/postgres-provider/moved.go +++ b/modules/postgres/cmd/postgres-provider/moved.go @@ -16,8 +16,8 @@ package main // that cannot be read is not nobody asking (issue 241): nothing is retired until it is read again. import ( - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" ) // ProvisionName is what postgres provides, as its manifest says. diff --git a/modules/postgres/cmd/postgres-provider/provisioner.go b/modules/postgres/cmd/postgres-provider/provisioner.go index b9bbb02de..fb7c69a2a 100644 --- a/modules/postgres/cmd/postgres-provider/provisioner.go +++ b/modules/postgres/cmd/postgres-provider/provisioner.go @@ -14,7 +14,7 @@ package main import ( "context" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "time" ) diff --git a/modules/postgres/cmd/postgres-provider/retire_pg.go b/modules/postgres/cmd/postgres-provider/retire_pg.go index 24e911c8e..58b9eef49 100644 --- a/modules/postgres/cmd/postgres-provider/retire_pg.go +++ b/modules/postgres/cmd/postgres-provider/retire_pg.go @@ -28,7 +28,7 @@ import ( "context" "encoding/json" "fmt" - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "regexp" "strconv" "time" diff --git a/modules/postgres/cmd/postgres-provider/retire_pg_test.go b/modules/postgres/cmd/postgres-provider/retire_pg_test.go index 75feec900..d2daccdfd 100644 --- a/modules/postgres/cmd/postgres-provider/retire_pg_test.go +++ b/modules/postgres/cmd/postgres-provider/retire_pg_test.go @@ -4,7 +4,7 @@ package main // of it — the login refused, the data kept, a deletion dropping only its own — is live_test.go's. import ( - "git.novox.be/novox/mesh-sdk/go/provider/harness" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider/harness" "strings" "testing" "time" diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index c798e41f4..48f99494f 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -3,6 +3,7 @@ module postgres go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f github.com/jackc/pgx/v5 v5.11.0 ) diff --git a/modules/route-adapter/cmd/route-provider/main.go b/modules/route-adapter/cmd/route-provider/main.go index 013c80ae7..42673701c 100644 --- a/modules/route-adapter/cmd/route-provider/main.go +++ b/modules/route-adapter/cmd/route-provider/main.go @@ -10,8 +10,8 @@ import ( "fmt" "os" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" stdio "git.novox.be/novox/mesh-sdk/go" - "git.novox.be/novox/mesh-sdk/go/provider" ) func say(format string, args ...any) { diff --git a/modules/route-adapter/cmd/route-provider/provider.go b/modules/route-adapter/cmd/route-provider/provider.go index 5061a6680..3d5832b67 100644 --- a/modules/route-adapter/cmd/route-provider/provider.go +++ b/modules/route-adapter/cmd/route-provider/provider.go @@ -11,7 +11,7 @@ package main // mesh still gives it. import ( - "git.novox.be/novox/mesh-sdk/go/provider" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" ) // ProvisionName is what route-adapter provides, as its manifest says. diff --git a/modules/route-adapter/cmd/route-provider/provider_test.go b/modules/route-adapter/cmd/route-provider/provider_test.go index 44ac3e402..dada87368 100644 --- a/modules/route-adapter/cmd/route-provider/provider_test.go +++ b/modules/route-adapter/cmd/route-provider/provider_test.go @@ -6,8 +6,8 @@ import ( "sync" "testing" - "git.novox.be/novox/mesh-sdk/go/provider" - "git.novox.be/novox/mesh-sdk/go/provisions" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient" + "git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient/provider" ) // bucketBus is the helper's bus over in-memory buckets. @@ -51,17 +51,17 @@ func TestAConsumerOfARouteIsToldItsNamesFromItsPlanEntry(t *testing.T) { "provider-module": ModuleName, "at": "10.7.0.1", "from": "novox", "as": "mesh_g14_gitea", "names": map[string]any{"name": "git.example.org", "internal-name": "git.novox.internal", "name-web": "git.example.org"}}}}}) - if err := bus.Put(context.Background(), provisions.PlansBucket, "g14.gitea", plan); err != nil { + if err := bus.Put(context.Background(), meshprovisionerclient.PlansBucket, "g14.gitea", plan); err != nil { t.Fatal(err) } // The key the seat composed for the entry, asked of route-adapter (novox/hq ADR 0570 clauses 1, 3). - key, _ := provisions.Key("g14", "gitea", ProvisionName, "") - asked, err := provisions.Encode(provisions.Provision{Provision: ProvisionName, State: provisions.Asked, - Consumer: provisions.End{Node: "g14", Module: "gitea"}, Provider: provisions.End{Node: "novox", Module: ModuleName}}) + key, _ := meshprovisionerclient.Key("g14", "gitea", ProvisionName, "") + asked, err := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: ProvisionName, State: meshprovisionerclient.Asked, + Consumer: meshprovisionerclient.End{Node: "g14", Module: "gitea"}, Provider: meshprovisionerclient.End{Node: "novox", Module: ModuleName}}) if err != nil { t.Fatal(err) } - if err := bus.Put(context.Background(), provisions.ProvisionsBucket, key, asked); err != nil { + if err := bus.Put(context.Background(), meshprovisionerclient.ProvisionsBucket, key, asked); err != nil { t.Fatal(err) } p := newProvider("novox", bus, t.Logf) diff --git a/modules/route-adapter/go.mod b/modules/route-adapter/go.mod index 7123a273b..87a10bd8c 100644 --- a/modules/route-adapter/go.mod +++ b/modules/route-adapter/go.mod @@ -5,6 +5,7 @@ go 1.26.0 require git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174359-05b3e2e1b94f require ( + git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/go v0.0.0-20261104174344-ae5266e77639 // indirect github.com/klauspost/compress v1.20.1 // indirect github.com/nats-io/nats.go v1.54.0 // indirect