From 7522961ae3b0cb4477afb876758d119655ced05d Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 30 Oct 2026 21:42:03 +0100 Subject: [PATCH] Let a plan of provisions alone fill nothing, so a module not handed can have one for its route (issue 774) A plan with no templates archive made the client fetch an empty source and fail the module's report. The next mesh-provisioner composes such plans (a module not handed gets one for what a provider's helper answers, its route), so this reaches the nodes first. Quick fix: none (a failed report per routed module). Thorough fix (chosen): a plan with no archive is read as provisions alone by the one client every node runs. --- .../cmd/mesh-provisioner-client/client_test.go | 16 ++++++++++++++++ .../cmd/mesh-provisioner-client/template.go | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go index 39bbd12b..37650d8d 100644 --- a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go +++ b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go @@ -855,3 +855,19 @@ func TestAFailureKeepsWhenItBeganWhileItsWordsChange(t *testing.T) { } } } + +// A plan of provisions alone, a module not handed whose route the helper answers (issue 774), names no templates: +// nothing is fetched and nothing filled, where a fetch of no source failed the module's report. +func TestAPlanOfProvisionsAloneFetchesNoTemplates(t *testing.T) { + s := &templateStore{dir: t.TempDir(), fetch: func(context.Context, string) ([]byte, error) { + t.Fatal("a plan with no templates fetched") + return nil, nil + }} + texts, err := s.load(context.Background(), Templates{}) + if err != nil || len(texts) != 0 { + t.Fatalf("loaded %v: %v", texts, err) + } + if targets, wrong := fillTargets(Plan{}, texts); wrong != "" || len(targets) != 0 { + t.Fatalf("filled %v: %s", targets, wrong) + } +} diff --git a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/template.go b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/template.go index 1e3f3033..302b1575 100644 --- a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/template.go +++ b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/template.go @@ -69,7 +69,13 @@ type templateStore struct { } // load is every template's text of the archive the plan names, by its path inside the archive. +// +// A plan that names no archive is a plan of provisions alone (issue 774: a module not handed has one for what a +// provider's helper answers of it, its route): there is nothing to fetch and nothing to fill. func (s *templateStore) load(ctx context.Context, t Templates) (map[string]string, error) { + if t.Source == "" && t.Digest == "" { + return map[string]string{}, nil + } if texts, ok := s.texts[t.Digest]; ok { return texts, nil }