feat(supportbundle): support secret/... redactor URIs (#2111)

Co-authored-by: ElasticClaw Factory <factory@replicated.com>
This commit is contained in:
Xav Paice
2026-08-20 08:40:11 +12:00
committed by GitHub
co-authored by ElasticClaw Factory
parent 0bb4a21f22
commit 207cb90b53
2 changed files with 86 additions and 0 deletions
+26
View File
@@ -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, "/")
+60
View File
@@ -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)
}
})
}
}