Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow arbitrary data in Details map in results
The previous `Details` structure in the Sonobuoy results format was a `map[string]string`. As we are creating more plugins that are providing reports in the Sonobuoy results format, this structure is limiting. To allow more flexibility, the type is being changed to `map[string]interface{}` to allow plugins to provide arbitrary data in the `Details` field. The version of the YAML library used when parsing the results in a results tarball has been upgraded to v3. This is due to the fact that it unmarshals data into a `map[string]interface{}` type when all the keys are strings. In v2, the behaviour was to always marshal to `map[interface{}]interface{}`. This is important as if the keys are not strings then marshalling to JSON will fail when using the `--detailed` mode of the `results` command. Signed-off-by: Bridget McErlean <bmcerlean@vmware.com>
- Loading branch information
Showing
23 changed files
with
458 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package results | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
func checkItem(expected Item, actual Item) error { | ||
if expected.Name != actual.Name { | ||
return fmt.Errorf("expected item name to be %q, got %q", expected.Name, actual.Name) | ||
} | ||
|
||
if expected.Status != actual.Status { | ||
return fmt.Errorf("expected item status to be %q, got %q", expected.Status, actual.Status) | ||
} | ||
|
||
for k, v := range expected.Metadata { | ||
if actual.Metadata[k] != v { | ||
return fmt.Errorf("expected item metadata %q to be %q, got %q", k, v, actual.Metadata[k]) | ||
} | ||
} | ||
|
||
// Check that the unmarshalled Details object matches. This check will fail if the types don't match even if the values are the same | ||
// e.g. (string vs interface{}) | ||
if !reflect.DeepEqual(expected.Details, actual.Details) { | ||
return fmt.Errorf("expected item details to be %q (%v), got %q (%v)", expected.Details, reflect.TypeOf(expected.Details), actual.Details, reflect.TypeOf(actual.Details)) | ||
} | ||
|
||
if len(expected.Items) != len(actual.Items) { | ||
return fmt.Errorf("unexpected number of items, expected %v, got %v", len(expected.Items), len(actual.Items)) | ||
} | ||
|
||
for i, item := range expected.Items { | ||
err := checkItem(item, actual.Items[i]) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func TestManualProcessFile(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
pluginDir string | ||
currentFile string | ||
expectedError string | ||
expectMetadataError bool | ||
expectedItem Item | ||
}{ | ||
{ | ||
name: "missing file includes error in metadata and unknown status", | ||
pluginDir: "./testdata/mockResults/manualProcessing", | ||
currentFile: "./testdata/mockResults/manualProcessing/missingFile.yaml", | ||
expectedError: "opening file ./testdata/mockResults/manualProcessing/missingFile.yaml", | ||
expectMetadataError: true, | ||
expectedItem: Item{ | ||
Name: "missingFile.yaml", | ||
Status: StatusUnknown, | ||
Metadata: map[string]string{ | ||
metadataFileKey: "missingFile.yaml", | ||
metadataTypeKey: metadataTypeFile, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "invalid yaml file includes error in metadata and unknown status", | ||
pluginDir: "./testdata/mockResults/manualProcessing", | ||
currentFile: "./testdata/mockResults/manualProcessing/invalid-results.yaml", | ||
expectedError: "error processing manual results", | ||
expectedItem: Item{ | ||
Name: "invalid-results.yaml", | ||
Status: StatusUnknown, | ||
Metadata: map[string]string{ | ||
metadataFileKey: "invalid-results.yaml", | ||
metadataTypeKey: metadataTypeFile, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "status is taken from the manual results", | ||
pluginDir: "./testdata/mockResults/manualProcessing", | ||
currentFile: "./testdata/mockResults/manualProcessing/manual-results.yaml", | ||
expectedItem: Item{ | ||
Name: "manual-results.yaml", | ||
Status: "status-from-manual-results", | ||
Metadata: map[string]string{ | ||
metadataFileKey: "manual-results.yaml", | ||
metadataTypeKey: metadataTypeFile, | ||
}, | ||
Items: []Item{ | ||
{ | ||
Name: "a test file", | ||
Status: "status 1", | ||
}, | ||
{ | ||
Name: "another test file", | ||
Status: "status 2", | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "result item with arbitrary details is valid", | ||
pluginDir: "./testdata/mockResults/manualProcessing", | ||
currentFile: "./testdata/mockResults/manualProcessing/manual-results-arbitrary-details.yaml", | ||
expectedItem: Item{ | ||
Name: "manual-results-arbitrary-details.yaml", | ||
Status: "status-from-manual-results", | ||
Metadata: map[string]string{ | ||
metadataFileKey: "manual-results-arbitrary-details.yaml", | ||
metadataTypeKey: metadataTypeFile, | ||
}, | ||
Details: map[string]interface{}{ | ||
"arbitrary-data": map[interface{}]interface{}{ | ||
"key": "value", | ||
"array-of-integers": []interface{}{ | ||
1, | ||
2, | ||
3, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
item, err := manualProcessFile(tc.pluginDir, tc.currentFile) | ||
if tc.expectedError != "" && err == nil { | ||
t.Fatalf("expected error %q but err was nil", tc.expectedError) | ||
} | ||
if err != nil { | ||
if tc.expectedError != "" { | ||
if _, ok := item.Metadata["error"]; !ok && tc.expectMetadataError { | ||
t.Errorf("expected metadata error field to be set") | ||
} | ||
|
||
if !strings.Contains(err.Error(), tc.expectedError) { | ||
t.Errorf("expected error %q to contain %q", err.Error(), tc.expectedError) | ||
} | ||
} else { | ||
t.Errorf("unexpected error %q", err) | ||
} | ||
} | ||
|
||
checkErr := checkItem(tc.expectedItem, item) | ||
if checkErr != nil { | ||
t.Error(checkErr) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
pkg/client/results/testdata/mockResults/manualProcessing/invalid-results.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name: invalid-results | ||
status: status-from-manual-results | ||
meta: | ||
type: summary | ||
items: | ||
- name: a test file | ||
status: status 1 | ||
meta: | ||
- invalid: data |
11 changes: 11 additions & 0 deletions
11
...lient/results/testdata/mockResults/manualProcessing/manual-results-arbitrary-details.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
name: manual-results | ||
status: status-from-manual-results | ||
meta: | ||
type: summary | ||
details: | ||
arbitrary-data: | ||
key: value | ||
array-of-integers: | ||
- 1 | ||
- 2 | ||
- 3 |
15 changes: 15 additions & 0 deletions
15
pkg/client/results/testdata/mockResults/manualProcessing/manual-results.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: manual-results | ||
status: status-from-manual-results | ||
meta: | ||
type: summary | ||
items: | ||
- name: a test file | ||
status: status 1 | ||
meta: | ||
file: results/global/junit_01.xml | ||
type: file | ||
- name: another test file | ||
status: status 2 | ||
meta: | ||
file: results/global/junit_01.xml | ||
type: file |
Oops, something went wrong.