diff --git a/internal/composer/composer.go b/internal/composer/composer.go index d5bba7c..f32a233 100644 --- a/internal/composer/composer.go +++ b/internal/composer/composer.go @@ -134,6 +134,16 @@ func runCase(r Request, c Case, depth string) (CaseVerdict, error) { if err != nil { return CaseVerdict{}, fmt.Errorf("composer: the case %q: %w", c.Name, err) } + // The module the mesh provides itself (the private network) has no repository the indexer reads, so no case carries + // it: its manifest comes with mesh-sdk and always wins, as the bus reader has it (frombus readBase). Without it a node + // it is assigned to composed nothing (issue 1126, check of mesh-host #200: "nothing provides mesh-wireguard"). + for _, name := range delivery.ProvidedModules() { + m, _, err := delivery.ProvidedManifest(name) + if err != nil { + return CaseVerdict{}, fmt.Errorf("composer: %w", err) + } + shelf[name] = m + } in.Catalogue = shelf in.Nodes = slices.Clone(in.Nodes) in.Holdings = slices.Clone(in.Holdings) diff --git a/internal/composer/composer_test.go b/internal/composer/composer_test.go index dcce0ac..0e3e7cf 100644 --- a/internal/composer/composer_test.go +++ b/internal/composer/composer_test.go @@ -60,6 +60,16 @@ func TestARequestItCannotRunIsRefused(t *testing.T) { if _, err := Run(placed); err == nil || !strings.Contains(err.Error(), "holds no node for") { t.Errorf("a case placing a node the input lacks: %v", err) } + // Issue 1126 (check of mesh-host #200): the module the mesh provides itself (the private network) comes from mesh-sdk, + // a second source beside the indexer's manifests the cases carry, and the input carries no catalogue: a node it is + // assigned to still composes, and what it provides is provided. + wg := delivery.ProvidedModules()[0] + provided := withInput(t, Request{V: Version, Machines: []string{"a"}, Depth: DepthResolve, + Cases: []Case{{Name: "change", Manifests: map[string]Manifest{"demo": {Raw: json.RawMessage(demo)}}}}}, + compose.Input{Nodes: []compose.Node{{Name: "a", Assigned: []string{wg, "demo"}}}}) + if v, err := Run(provided); err != nil || !v.Cases[0].Machines["a"].Composes { + t.Errorf("a node assigned the mesh's own module: %+v, %v", v, err) + } v, err := Run(Request{V: Version, Cases: []Case{{Name: "only-read", Manifests: map[string]Manifest{"demo": {Raw: json.RawMessage(demo)}}}}}) if err != nil || len(v.Cases) != 1 || !v.Cases[0].Manifests["demo"].Accepted || v.Cases[0].Machines != nil || v.SDK == "" { t.Fatalf("a request with no machines: %+v, %v", v, err)