//go:build integration package main import ( "encoding/json" "fmt" "strings" "testing" "git.novox.be/novox/mesh-sdk/go/catalogue" sdkdecl "git.novox.be/novox/mesh-sdk/go/declaration" "git.novox.be/novox/mesh-sdk/go/overlay" "git.novox.be/novox/mesh-sdk/go/compose" ) // 1696/AC2, ADR 0486 ยง5: a node is sent a file by digest only when its profile reports the capability. A node whose profile lacks // it, and a node the mesh has no profile of, are sent every content inline; a node that reports it is sent the reference. The test // goes through composeQuestion and composeSend, the two places readsFileReferences is read (compose_sdk.go). func TestAFileTravelsByDigestOnlyToANodeThatReportsTheCapability(t *testing.T) { open := aMesh(t) // anchor and laptop report no file-references ctx := t.Context() big := strings.Repeat("0123456789abcdef", 8<<10) // 128 KiB register(t, open, catalogue.Manifest{Module: "bigfile", Version: "1", Resources: []map[string]any{{"id": "blob", "type": "file", "path": "/etc/bigfile/blob", "mode": "0644", "content": big}}}) // reader reports the capability; bare has never reported a profile at all. for i, n := range []struct { name string profile map[string]any }{ {"reader", map[string]any{"capabilities": []any{ map[string]any{"name": "container-runtime", "present": true}, map[string]any{"name": "systemd", "present": true}, map[string]any{"name": sdkdecl.FileReferencesCapability, "present": true}}}}, {"bare", nil}, } { record, err := open.inventory.AddNode(ctx, n.name) if err != nil { t.Fatal(err) } if err := open.inventory.SetPlace(ctx, n.name, n.name+".example:51820", "here", false, fmt.Sprintf("10.77.0.%d", i+10)); err != nil { t.Fatal(err) } if n.profile != nil { if err := open.inventory.RecordProfile(ctx, record.ID, n.profile); err != nil { t.Fatal(err) } } if err := open.inventory.RecordSealingKey(ctx, record.ID, aPublicKey(t)); err != nil { t.Fatal(err) } if err := open.inventory.RecordOverlayKey(ctx, record.ID, aPublicKey(t)); err != nil { t.Fatal(err) } if _, err := open.inventory.Assign(ctx, n.name, overlay.Name); err != nil { t.Fatal(err) } } for _, node := range []string{"laptop", "reader", "bare"} { if _, err := assign(ctx, open, node, "bigfile"); err != nil { t.Fatalf("assign %s: %v", node, err) } } byDigest := map[string]bool{"laptop": false, "bare": false, "reader": true} for node, want := range byDigest { asked, _, err := composeQuestion(ctx, open, node, compose.Reading, false) if err != nil { t.Fatalf("%s: %v", node, err) } sent, err := composeSend(ctx, open, node) if err != nil { t.Fatalf("%s: %v", node, err) } for what, s := range map[string]sendable{"question": asked, "send": sent} { if s.fileReferences != want { t.Fatalf("%s, %s: fileReferences %v, want %v", node, what, s.fileReferences, want) } body, err := s.Body() if err != nil { t.Fatal(err) } var got struct { Resources []map[string]any `json:"resources"` } if err := json.Unmarshal(body, &got); err != nil { t.Fatal(err) } var found bool for _, r := range got.Resources { if r["path"] != "/etc/bigfile/blob" { continue } found = true inline := r["content"] == big if want && (inline || r["digest"] == nil || r["size"] == nil) { t.Fatalf("%s, %s: a node that reads references is sent the content inline", node, what) } if !want && (!inline || r["digest"] != nil) { t.Fatalf("%s, %s: a node that does not report the capability is sent a reference", node, what) } } if !found { t.Fatalf("%s, %s: the file is not in the declaration", node, what) } } } }