From 5b19734d750b969097193bb557a500e20cb7891a Mon Sep 17 00:00:00 2001 From: Anna Koshlakova Date: Thu, 17 Sep 2026 18:18:47 +0200 Subject: [PATCH 1/3] feat(must-gather): add version file collector Add version file collector to write /version containing the product name and build version, as required by the must-gather enhancement spec for programmatic analysis. Co-Authored-By: Claude Opus 4.6 --- must-gather/gather.go | 4 ++ must-gather/internal/version/suite_test.go | 13 ++++++ .../internal/version/version_collector.go | 37 +++++++++++++++ .../version/version_collector_test.go | 46 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 must-gather/internal/version/suite_test.go create mode 100644 must-gather/internal/version/version_collector.go create mode 100644 must-gather/internal/version/version_collector_test.go diff --git a/must-gather/gather.go b/must-gather/gather.go index eb173191a..93e10047f 100644 --- a/must-gather/gather.go +++ b/must-gather/gather.go @@ -16,6 +16,7 @@ import ( "github.com/openshift/cluster-logging-operator/must-gather/internal/metrics" "github.com/openshift/cluster-logging-operator/must-gather/internal/namespace" "github.com/openshift/cluster-logging-operator/must-gather/internal/ui" + "github.com/openshift/cluster-logging-operator/must-gather/internal/version" ) var ( @@ -102,6 +103,9 @@ func (g *Gather) Run(ctx context.Context) error { func (g *Gather) createCollectors() []api.Collector { collectors := make([]api.Collector, 0) + // Version collector + collectors = append(collectors, version.NewCollector(g.logger, g.config.DestDir)) + // Cluster-scoped resources collector collectors = append(collectors, cluster.NewCollector(g.client, g.logger, g.config.DestDir)) diff --git a/must-gather/internal/version/suite_test.go b/must-gather/internal/version/suite_test.go new file mode 100644 index 000000000..1c68a5ce2 --- /dev/null +++ b/must-gather/internal/version/suite_test.go @@ -0,0 +1,13 @@ +package version_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestSuite(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "must-gather/internal/version suite") +} diff --git a/must-gather/internal/version/version_collector.go b/must-gather/internal/version/version_collector.go new file mode 100644 index 000000000..53ec16194 --- /dev/null +++ b/must-gather/internal/version/version_collector.go @@ -0,0 +1,37 @@ +package version + +import ( + "context" + "fmt" + + "github.com/openshift/cluster-logging-operator/must-gather/internal/api" + "github.com/openshift/cluster-logging-operator/version" + + "k8s.io/apimachinery/pkg/runtime/schema" +) + +const productName = "Red Hat OpenShift Logging" + +type Collector struct { + logger api.Logger + destDir api.Path +} + +func NewCollector(logger api.Logger, destDir api.Path) *Collector { + return &Collector{ + logger: logger, + destDir: destDir, + } +} + +func (c *Collector) Name() string { + return "VersionCollector" +} + +func (c *Collector) Collect(_ context.Context, _ ...schema.GroupVersionResource) error { + defer c.logger.Begin("writing version file ...")() + + content := fmt.Sprintf("%s/must-gather\n%s\n", productName, version.Version) + versionFile := c.destDir.Add("version") + return versionFile.WriteFile([]byte(content)) +} diff --git a/must-gather/internal/version/version_collector_test.go b/must-gather/internal/version/version_collector_test.go new file mode 100644 index 000000000..26cd57a17 --- /dev/null +++ b/must-gather/internal/version/version_collector_test.go @@ -0,0 +1,46 @@ +package version_test + +import ( + "context" + "os" + "path/filepath" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/openshift/cluster-logging-operator/must-gather/internal/api" + "github.com/openshift/cluster-logging-operator/must-gather/internal/version" + projectVersion "github.com/openshift/cluster-logging-operator/version" +) + +var _ = Describe("VersionCollector", func() { + var ( + tmpDir string + destDir api.Path + ) + + BeforeEach(func() { + var err error + tmpDir, err = os.MkdirTemp("", "version-collector-test") + Expect(err).ToNot(HaveOccurred()) + destDir = api.NewPath(tmpDir) + }) + + AfterEach(func() { + os.RemoveAll(tmpDir) + }) + + It("should write a version file with the product name and version", func() { + collector := version.NewCollector(api.NewLogger(GinkgoWriter), destDir) + err := collector.Collect(context.Background()) + Expect(err).ToNot(HaveOccurred()) + + content, err := os.ReadFile(filepath.Join(tmpDir, "version")) + Expect(err).ToNot(HaveOccurred()) + Expect(string(content)).To(Equal("Red Hat OpenShift Logging/must-gather\n" + projectVersion.Version + "\n")) + }) + + It("should report its name", func() { + collector := version.NewCollector(api.NewLogger(GinkgoWriter), destDir) + Expect(collector.Name()).To(Equal("VersionCollector")) + }) +}) From 2fa17299a6b8a19db80f07d5ee67dd5f634cfa8d Mon Sep 17 00:00:00 2001 From: ann0ra <91992306+ann0ra@users.noreply.github.com> Date: Mon, 21 Sep 2026 11:44:45 +0200 Subject: [PATCH 2/3] Update must-gather/internal/version/version_collector_test.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- must-gather/internal/version/version_collector_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/must-gather/internal/version/version_collector_test.go b/must-gather/internal/version/version_collector_test.go index 26cd57a17..8e9c6ba80 100644 --- a/must-gather/internal/version/version_collector_test.go +++ b/must-gather/internal/version/version_collector_test.go @@ -26,7 +26,7 @@ var _ = Describe("VersionCollector", func() { }) AfterEach(func() { - os.RemoveAll(tmpDir) + Expect(os.RemoveAll(tmpDir)).To(Succeed()) }) It("should write a version file with the product name and version", func() { From b318f148652aeae7f99278f4605ce9d811063e20 Mon Sep 17 00:00:00 2001 From: Anna Koshlakova Date: Wed, 23 Sep 2026 22:08:02 +0200 Subject: [PATCH 3/3] docs(must-gather): update README tree to show version file at archive root The version collector writes to /version (the archive root), not cluster-logging/clo/version as the tree previously showed. --- must-gather/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/must-gather/README.md b/must-gather/README.md index a0769e011..9613a44be 100644 --- a/must-gather/README.md +++ b/must-gather/README.md @@ -47,8 +47,7 @@ Example must-gather for cluster-logging output (use `tree` for up-to-date struct ``` ├── cluster-logging │  ├── clo -│  │  ├── cluster-logging-operator-xxxxxxxxxx-xxxxx -│  │  └── version +│  │  └── cluster-logging-operator-xxxxxxxxxx-xxxxx │  └── namespaces │ │ └── [nampespace_name] ## including openshift-logging │ │ ├── collector-xxxxx.describe @@ -171,4 +170,5 @@ Example must-gather for cluster-logging output (use `tree` for up-to-date struct │   ├── [...] │  └── openshift-operators-redhat │   ├── [...] -└── timestamp +├── timestamp +└── version