Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions pkg/proxy/discovery/metadata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package discovery

import (
"context"
"os"
"path/filepath"
"testing"
)

// pack_versions must list every linux-inventory-v<N>.yaml in pack_dir,
// ascending, ignoring unrelated files — the server picks a version from this
// list to pin in discovery_inventory requests, since content_pack_version is
// a required request param with no "latest" default.
func TestCollectMetadata_ReportsPackVersions(t *testing.T) {
dir := t.TempDir()
for _, name := range []string{
"linux-inventory-v2.yaml",
"linux-inventory-v10.yaml",
"linux-inventory-vX.yaml", // non-numeric — ignored
"windows-inventory-v1.yaml",
"README.md",
} {
if err := os.WriteFile(filepath.Join(dir, name), []byte("x"), 0o600); err != nil {
t.Fatalf("writing %s: %v", name, err)
}
}

p, _ := newTestProxy(t, map[string]any{"pack_dir": dir}, nil)

meta, err := p.CollectMetadata(context.Background())
if err != nil {
t.Fatalf("CollectMetadata: %v", err)
}
versions, ok := meta["pack_versions"].([]int)
if !ok {
t.Fatalf("pack_versions missing or wrong type: %#v", meta["pack_versions"])
}
if len(versions) != 2 || versions[0] != 2 || versions[1] != 10 {
t.Fatalf("pack_versions = %v, want [2 10]", versions)
}
}

// Without a pack_dir there is nothing to report — the key must be absent,
// not an empty list, so the server treats it the same as an older agent
// that predates the field.
func TestCollectMetadata_NoPackDirOmitsPackVersions(t *testing.T) {
p, _ := newTestProxy(t, map[string]any{}, nil)

meta, err := p.CollectMetadata(context.Background())
if err != nil {
t.Fatalf("CollectMetadata: %v", err)
}
if _, present := meta["pack_versions"]; present {
t.Fatalf("pack_versions should be absent without pack_dir, got %#v", meta["pack_versions"])
}
}
58 changes: 56 additions & 2 deletions pkg/proxy/discovery/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
"net/netip"
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -658,9 +661,60 @@ func (p *Proxy) Actions() []string {
}

// CollectMetadata satisfies proxy.MetadataCollector so the supported actions
// reach the server alongside the datasource inventory.
// reach the server alongside the datasource inventory. pack_versions lists
// the content pack versions present in pack_dir so the server can pick a
// version to pin in discovery_inventory requests (content_pack_version is a
// required request param with no "latest" default). Presence means the file
// exists — signature verification still happens at execution time.
func (p *Proxy) CollectMetadata(ctx context.Context) (map[string]any, error) {
return map[string]any{"actions": p.Actions()}, nil
meta := map[string]any{"actions": p.Actions()}
if versions := p.packVersions(); len(versions) > 0 {
meta["pack_versions"] = versions
}
return meta, nil
}

// packVersionPattern matches cached pack filenames (linux-inventory-v<N>.yaml),
// mirroring the path resolvePack reads.
var packVersionPattern = regexp.MustCompile(`^linux-inventory-v(\d+)\.yaml$`)

// packVersions lists content pack versions available in pack_dir, ascending.
func (p *Proxy) packVersions() []int {
p.mu.RLock()
packDir := p.cfg.PackDir
p.mu.RUnlock()
if packDir == "" {
return nil
}

entries, err := os.ReadDir(packDir)
if err != nil {
// A configured-but-not-yet-created pack_dir is a normal fresh-install
// state (packs arrive via the distribution pipeline) — don't warn on
// every metadata cycle for it.
if !os.IsNotExist(err) {
p.logger.Warn("discovery: cannot list pack_dir for metadata", "err", err)
}
return nil
}
Comment thread
mayankpande88 marked this conversation as resolved.

var versions []int
for _, e := range entries {
if e.IsDir() {
continue
}
m := packVersionPattern.FindStringSubmatch(e.Name())
if m == nil {
continue
}
v, err := strconv.Atoi(m[1])
if err != nil || v <= 0 {
continue
}
versions = append(versions, v)
}
sort.Ints(versions)
return versions
}

func (p *Proxy) Close() error {
Expand Down
Loading