From 5e4e8fd76507062d587e5f96af196dabc8d7bf72 Mon Sep 17 00:00:00 2001 From: Puskar Basu <45908484+pskrbasu@users.noreply.github.com> Date: Tue, 25 Jan 2022 22:25:40 +0530 Subject: [PATCH] Add JSON template for check export. Closes #1337 --- cmd/check.go | 12 - control/controldisplay/formatter.go | 6 +- .../controldisplay/templates/json/output.tmpl | 3 + .../templates/expected_check_json.json | 496 +++++++++--------- tests/acceptance/test_files/008.check.bats | 6 +- 5 files changed, 256 insertions(+), 267 deletions(-) create mode 100644 control/controldisplay/templates/json/output.tmpl diff --git a/cmd/check.go b/cmd/check.go index ccbff0c7b..9467a6624 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -6,7 +6,6 @@ import ( "io" "log" "os" - "path/filepath" "strings" "sync" "time" @@ -470,17 +469,6 @@ func parseExportArg(arg string) (formatter controldisplay.Formatter, targetFileN return } - // no defined formatter - // Tactical fix to resolve CSV and JSON filename exports - // We need this till we build out the templates for CSV and JSON - ext := filepath.Ext(arg) - if ext == constants.CsvExtension { - return controldisplay.CSVFormatter{}, arg, nil - } - if ext == constants.JsonExtension && !strings.HasSuffix(arg, "asff.json") { - return controldisplay.JSONFormatter{}, arg, nil - } - return controldisplay.GetTemplateExportFormatter(arg, true) } diff --git a/control/controldisplay/formatter.go b/control/controldisplay/formatter.go index d89c27d77..6388c5f75 100644 --- a/control/controldisplay/formatter.go +++ b/control/controldisplay/formatter.go @@ -20,14 +20,12 @@ type FormatterMap map[string]Formatter var outputFormatters FormatterMap = FormatterMap{ constants.CheckOutputFormatNone: &NullFormatter{}, constants.CheckOutputFormatCSV: &CSVFormatter{}, - constants.CheckOutputFormatJSON: &JSONFormatter{}, constants.CheckOutputFormatText: &TextFormatter{}, constants.CheckOutputFormatBrief: &TextFormatter{}, } var exportFormatters FormatterMap = FormatterMap{ - constants.CheckOutputFormatCSV: &CSVFormatter{}, - constants.CheckOutputFormatJSON: &JSONFormatter{}, + constants.CheckOutputFormatCSV: &CSVFormatter{}, } type CheckExportTarget struct { @@ -80,7 +78,7 @@ func (j *NullFormatter) FileExtension() string { } func templateFuncs() template.FuncMap { - useFromSprigMap := []string{"upper", "toJson", "quote", "dict", "add", "now"} + useFromSprigMap := []string{"upper", "toJson", "quote", "dict", "add", "now", "toPrettyJson"} var funcs template.FuncMap = template.FuncMap{} sprigMap := sprig.TxtFuncMap() diff --git a/control/controldisplay/templates/json/output.tmpl b/control/controldisplay/templates/json/output.tmpl new file mode 100644 index 000000000..6ad47cf7c --- /dev/null +++ b/control/controldisplay/templates/json/output.tmpl @@ -0,0 +1,3 @@ +{{ define "output" -}} + {{ toPrettyJson .Data.Root }} +{{ end }} diff --git a/tests/acceptance/test_data/templates/expected_check_json.json b/tests/acceptance/test_data/templates/expected_check_json.json index fe8ad894d..938a46376 100644 --- a/tests/acceptance/test_data/templates/expected_check_json.json +++ b/tests/acceptance/test_data/templates/expected_check_json.json @@ -4,255 +4,255 @@ "description": "", "tags": {}, "summary": { - "status": { - "alarm": 5, - "ok": 10, - "info": 3, - "skip": 1, - "error": 2 - } + "status": { + "alarm": 5, + "ok": 10, + "info": 3, + "skip": 1, + "error": 2 + } }, "groups": [], "controls": [ - { - "results": [ - { - "reason": "Resource has some error", - "resource": "steampipe", - "status": "error", - "dimensions": [ - { - "key": "id", - "value": "16" - } - ] - }, - { - "reason": "Resource has some error", - "resource": "steampipe", - "status": "error", - "dimensions": [ - { - "key": "id", - "value": "17" - } - ] - }, - { - "reason": "Resource does not satisfy condition", - "resource": "steampipe", - "status": "alarm", - "dimensions": [ - { - "key": "id", - "value": "11" - } - ] - }, - { - "reason": "Resource does not satisfy condition", - "resource": "steampipe", - "status": "alarm", - "dimensions": [ - { - "key": "id", - "value": "12" - } - ] - }, - { - "reason": "Resource does not satisfy condition", - "resource": "steampipe", - "status": "alarm", - "dimensions": [ - { - "key": "id", - "value": "13" - } - ] - }, - { - "reason": "Resource does not satisfy condition", - "resource": "steampipe", - "status": "alarm", - "dimensions": [ - { - "key": "id", - "value": "14" - } - ] - }, - { - "reason": "Resource does not satisfy condition", - "resource": "steampipe", - "status": "alarm", - "dimensions": [ - { - "key": "id", - "value": "15" - } - ] - }, - { - "reason": "Information", - "resource": "steampipe", - "status": "info", - "dimensions": [ - { - "key": "id", - "value": "19" - } - ] - }, - { - "reason": "Information", - "resource": "steampipe", - "status": "info", - "dimensions": [ - { - "key": "id", - "value": "20" - } - ] - }, - { - "reason": "Information", - "resource": "steampipe", - "status": "info", - "dimensions": [ - { - "key": "id", - "value": "21" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "1" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "2" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "3" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "4" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "5" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "6" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "7" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "8" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "9" - } - ] - }, - { - "reason": "Resource satisfies condition", - "resource": "steampipe", - "status": "ok", - "dimensions": [ - { - "key": "id", - "value": "10" - } - ] - }, - { - "reason": "Resource is skipped", - "resource": "steampipe", - "status": "skip", - "dimensions": [ - { - "key": "id", - "value": "18" - } - ] - } - ], - "control_id": "control.sample_control_mixed_results_1", - "description": "Sample control that returns 10 OK, 5 ALARM, 2 ERROR, 1 SKIP and 3 INFO", - "severity": "high", - "tags": {}, - "title": "Sample control with all possible statuses(severity=high)" - } + { + "results": [ + { + "reason": "Resource has some error", + "resource": "steampipe", + "status": "error", + "dimensions": [ + { + "key": "id", + "value": "16" + } + ] + }, + { + "reason": "Resource has some error", + "resource": "steampipe", + "status": "error", + "dimensions": [ + { + "key": "id", + "value": "17" + } + ] + }, + { + "reason": "Resource does not satisfy condition", + "resource": "steampipe", + "status": "alarm", + "dimensions": [ + { + "key": "id", + "value": "11" + } + ] + }, + { + "reason": "Resource does not satisfy condition", + "resource": "steampipe", + "status": "alarm", + "dimensions": [ + { + "key": "id", + "value": "12" + } + ] + }, + { + "reason": "Resource does not satisfy condition", + "resource": "steampipe", + "status": "alarm", + "dimensions": [ + { + "key": "id", + "value": "13" + } + ] + }, + { + "reason": "Resource does not satisfy condition", + "resource": "steampipe", + "status": "alarm", + "dimensions": [ + { + "key": "id", + "value": "14" + } + ] + }, + { + "reason": "Resource does not satisfy condition", + "resource": "steampipe", + "status": "alarm", + "dimensions": [ + { + "key": "id", + "value": "15" + } + ] + }, + { + "reason": "Information", + "resource": "steampipe", + "status": "info", + "dimensions": [ + { + "key": "id", + "value": "19" + } + ] + }, + { + "reason": "Information", + "resource": "steampipe", + "status": "info", + "dimensions": [ + { + "key": "id", + "value": "20" + } + ] + }, + { + "reason": "Information", + "resource": "steampipe", + "status": "info", + "dimensions": [ + { + "key": "id", + "value": "21" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "1" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "2" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "3" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "4" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "5" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "6" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "7" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "8" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "9" + } + ] + }, + { + "reason": "Resource satisfies condition", + "resource": "steampipe", + "status": "ok", + "dimensions": [ + { + "key": "id", + "value": "10" + } + ] + }, + { + "reason": "Resource is skipped", + "resource": "steampipe", + "status": "skip", + "dimensions": [ + { + "key": "id", + "value": "18" + } + ] + } + ], + "control_id": "control.sample_control_mixed_results_1", + "description": "Sample control that returns 10 OK, 5 ALARM, 2 ERROR, 1 SKIP and 3 INFO", + "severity": "high", + "tags": {}, + "title": "Sample control with all possible statuses(severity=high)" + } ] - } +} diff --git a/tests/acceptance/test_files/008.check.bats b/tests/acceptance/test_files/008.check.bats index a7dda25c2..b4dc9e721 100644 --- a/tests/acceptance/test_files/008.check.bats +++ b/tests/acceptance/test_files/008.check.bats @@ -80,9 +80,9 @@ load "$LIB_BATS_SUPPORT/load.bash" @test "steampipe check - export json" { cd $CONTROL_RENDERING_TEST_MOD - run steampipe check control.sample_control_mixed_results_1 --export=json --progress=false - assert_equal "$(cat *.json)" "$(cat $TEST_DATA_DIR/expected_check_json.json)" - rm -f *.json + run steampipe check control.sample_control_mixed_results_1 --export test.json --progress=false + assert_equal "$(cat test.json)" "$(cat $TEST_DATA_DIR/expected_check_json.json)" + rm -f test.json cd - }