From 207cb90b531b41d7e5515155014c106d78672633 Mon Sep 17 00:00:00 2001 From: Xav Paice Date: Thu, 20 Aug 2026 08:40:11 +1200 Subject: [PATCH] feat(supportbundle): support secret/... redactor URIs (#2111) Co-authored-by: ElasticClaw Factory --- pkg/supportbundle/load.go | 26 +++++++++++++++ pkg/supportbundle/load_test.go | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/pkg/supportbundle/load.go b/pkg/supportbundle/load.go index c3b85d10..22c7a693 100644 --- a/pkg/supportbundle/load.go +++ b/pkg/supportbundle/load.go @@ -20,6 +20,9 @@ import ( "k8s.io/klog/v2" ) +// loadFromSecret is a package-level hook so tests can stub out cluster access. +var loadFromSecret = specs.LoadFromSecret + // GetSupportBundleFromURI downloads and parses a support bundle from a URI and returns a SupportBundle object func GetSupportBundleFromURI(bundleURI string) (*troubleshootv1beta2.SupportBundle, error) { collectorContent, err := LoadSupportBundleSpec(bundleURI) @@ -165,6 +168,29 @@ func LoadSupportBundleSpec(arg string) ([]byte, error) { } func LoadRedactorSpec(arg string) ([]byte, error) { + if strings.HasPrefix(arg, "secret/") { + // format secret/namespace-name/secret-name[/data-key] + pathParts := strings.Split(arg, "/") + if len(pathParts) > 4 { + return nil, errors.Errorf("secret path %s must have at most 4 components", arg) + } + if len(pathParts) < 3 { + return nil, errors.Errorf("secret path %s must have at least 3 components", arg) + } + + dataKey := "redactor-spec" + if len(pathParts) == 4 { + dataKey = pathParts[3] + } + + spec, err := loadFromSecret(pathParts[1], pathParts[2], dataKey) + if err != nil { + return nil, errors.Wrap(err, "failed to get spec from secret") + } + + return spec, nil + } + if strings.HasPrefix(arg, "configmap/") { // format configmap/namespace-name/configmap-name[/data-key] pathParts := strings.Split(arg, "/") diff --git a/pkg/supportbundle/load_test.go b/pkg/supportbundle/load_test.go index e4d54911..33373e45 100644 --- a/pkg/supportbundle/load_test.go +++ b/pkg/supportbundle/load_test.go @@ -1,7 +1,9 @@ package supportbundle import ( + "fmt" "reflect" + "strings" "testing" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" @@ -92,3 +94,61 @@ spec: }) } } + +func TestLoadRedactorSpec(t *testing.T) { + origLoadFromSecret := loadFromSecret + defer func() { loadFromSecret = origLoadFromSecret }() + + loadFromSecret = func(namespace, secretName, key string) ([]byte, error) { + return []byte(fmt.Sprintf("namespace=%s,secret=%s,key=%s", namespace, secretName, key)), nil + } + + tests := []struct { + name string + uri string + wantContent string + wantErr string + }{ + { + name: "secret URI with default key", + uri: "secret/default/my-redactor", + wantContent: "namespace=default,secret=my-redactor,key=redactor-spec", + }, + { + name: "secret URI with custom key", + uri: "secret/default/my-redactor/custom-key", + wantContent: "namespace=default,secret=my-redactor,key=custom-key", + }, + { + name: "secret URI with too few components", + uri: "secret/default", + wantErr: "must have at least 3 components", + }, + { + name: "secret URI with too many components", + uri: "secret/default/my-redactor/custom-key/extra", + wantErr: "must have at most 4 components", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := LoadRedactorSpec(tt.uri) + if tt.wantErr != "" { + if err == nil { + t.Fatalf("LoadRedactorSpec() expected error, got nil") + } + if !strings.Contains(err.Error(), tt.wantErr) { + t.Errorf("LoadRedactorSpec() error = %q, want containing %q", err.Error(), tt.wantErr) + } + return + } + if err != nil { + t.Fatalf("LoadRedactorSpec() unexpected error = %v", err) + } + if string(got) != tt.wantContent { + t.Errorf("LoadRedactorSpec() = %q, want %q", string(got), tt.wantContent) + } + }) + } +}