diff --git a/cmd/validate/image.go b/cmd/validate/image.go index 2538ada80..68cc2b117 100644 --- a/cmd/validate/image.go +++ b/cmd/validate/image.go @@ -400,7 +400,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { close(jobs) var components []applicationsnapshot.Component - var manyData [][]evaluator.Data + var evaluatorData [][]evaluator.Data var manyPolicyInput [][]byte var allErrors error = nil for i := 0; i < numComponents; i++ { @@ -410,7 +410,10 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { allErrors = errors.Join(allErrors, e) } else { components = append(components, r.component) - manyData = append(manyData, r.data) + // evaluator data is duplicated per component, so only collect it once. + if len(evaluatorData) == 0 && containsData(data.output) { + evaluatorData = append(evaluatorData, r.data) + } manyPolicyInput = append(manyPolicyInput, r.policyInput) } } @@ -428,7 +431,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { data.output = append(data.output, fmt.Sprintf("%s=%s", applicationsnapshot.JSON, data.outputFile)) } - report, err := applicationsnapshot.NewReport(data.snapshot, components, data.policy, manyData, manyPolicyInput, showSuccesses) + report, err := applicationsnapshot.NewReport(data.snapshot, components, data.policy, evaluatorData, manyPolicyInput, showSuccesses) if err != nil { return err } @@ -538,3 +541,14 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command { return cmd } + +// find if the slice contains "data" output +func containsData(data []string) bool { + for _, item := range data { + newItem := strings.Split(item, "=") + if newItem[0] == "data" { + return true + } + } + return false +} diff --git a/cmd/validate/image_test.go b/cmd/validate/image_test.go index be44dada2..b7ad09d3f 100644 --- a/cmd/validate/image_test.go +++ b/cmd/validate/image_test.go @@ -1302,3 +1302,27 @@ func TestValidateImageDefaultOutput(t *testing.T) { assert.Equal(t, c.expected, out.String()) } } + +// TestContainsData validates containsData behavior +func TestContainsData(t *testing.T) { + tests := []struct { + input []string + expected bool + name string + }{ + {[]string{"data"}, true, "Match single data"}, + {[]string{"data=something"}, true, "Match data=something"}, + {[]string{"text=data-file.txt"}, false, "Do not match text=data-file.txt"}, + {[]string{"json", "data=custom-data.yaml"}, true, "Match data in slice with multiple values"}, + {[]string{"data text"}, false, "Do not match data text"}, + {[]string{"dat"}, false, "Do not match dat"}, + {[]string{"data123"}, false, "Do not match data123"}, + {[]string{"data="}, true, "Match data="}, + {[]string{""}, false, "Do not match empty string"}, + } + + for _, test := range tests { + result := containsData(test.input) + assert.Equal(t, test.expected, result, test.name) + } +} diff --git a/cmd/validate/input.go b/cmd/validate/input.go index 2259a5bd2..e9550c6ff 100644 --- a/cmd/validate/input.go +++ b/cmd/validate/input.go @@ -166,7 +166,7 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { close(ch) var inputs []input.Input - var manyData [][]evaluator.Data + var evaluatorData [][]evaluator.Data var manyPolicyInput [][]byte var allErrors error = nil @@ -176,7 +176,10 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { allErrors = errors.Join(allErrors, e) } else { inputs = append(inputs, r.input) - manyData = append(manyData, r.data) + // evaluator data is duplicated per component, so only collect it once. + if len(evaluatorData) == 0 && containsData(data.output) { + evaluatorData = append(evaluatorData, r.data) + } manyPolicyInput = append(manyPolicyInput, r.policyInput) } } @@ -189,7 +192,7 @@ func validateInputCmd(validate InputValidationFunc) *cobra.Command { return inputs[i].FilePath > inputs[j].FilePath }) - report, err := input.NewReport(inputs, data.policy, manyData, manyPolicyInput) + report, err := input.NewReport(inputs, data.policy, evaluatorData, manyPolicyInput) if err != nil { return err }