diff --git a/cmd/troubleshoot/cli/run.go b/cmd/troubleshoot/cli/run.go index 5dc0781bb..de777d5b7 100644 --- a/cmd/troubleshoot/cli/run.go +++ b/cmd/troubleshoot/cli/run.go @@ -362,6 +362,12 @@ func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface) additionalRedactors.Spec.Redactors = util.Append(additionalRedactors.Spec.Redactors, r.Spec.Redactors) } + // dedupe specs + mainBundle.Spec.Collectors = util.Dedup(mainBundle.Spec.Collectors) + mainBundle.Spec.Analyzers = util.Dedup(mainBundle.Spec.Analyzers) + mainBundle.Spec.HostCollectors = util.Dedup(mainBundle.Spec.HostCollectors) + mainBundle.Spec.HostAnalyzers = util.Dedup(mainBundle.Spec.HostAnalyzers) + return mainBundle, additionalRedactors, nil } diff --git a/cmd/troubleshoot/cli/run_test.go b/cmd/troubleshoot/cli/run_test.go index dfc3b715d..6692a906e 100644 --- a/cmd/troubleshoot/cli/run_test.go +++ b/cmd/troubleshoot/cli/run_test.go @@ -343,3 +343,31 @@ spec: }) } } + +func Test_loadDuplicatedBundleSpecs(t *testing.T) { + spec := testutils.ServeFromFilePath(t, ` +apiVersion: troubleshoot.sh/v1beta2 +kind: SupportBundle +metadata: + name: sb +spec: + collectors: + - helm: {} + analyzers: + - clusterVersion: {} + hostCollectors: + - cpu: {} + hostAnalyzers: + - cpu: {} +`) + args := []string{spec, spec} + + ctx := context.Background() + client := testclient.NewSimpleClientset() + sb, _, err := loadSpecs(ctx, args, client) + require.NoError(t, err) + assert.Len(t, sb.Spec.Collectors, 1+2) // default clusterInfo + clusterResources + assert.Len(t, sb.Spec.Analyzers, 1) + assert.Len(t, sb.Spec.HostCollectors, 1) + assert.Len(t, sb.Spec.HostAnalyzers, 1) +} diff --git a/internal/util/util.go b/internal/util/util.go index e70e9acee..e10f80856 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -3,6 +3,7 @@ package util import ( "bufio" "bytes" + "encoding/json" "fmt" "net/url" "os" @@ -145,3 +146,26 @@ func PromptYesNo(question string) bool { } } } + +func Dedup[T any](objs []T) []T { + seen := make(map[string]bool) + out := []T{} + + if len(objs) == 0 { + return objs + } + + for _, o := range objs { + data, err := json.Marshal(o) + if err != nil { + out = append(out, o) + continue + } + key := string(data) + if _, ok := seen[key]; !ok { + out = append(out, o) + seen[key] = true + } + } + return out +}