From 9448bf88340485e696aad291b6a7944380f0692f Mon Sep 17 00:00:00 2001 From: Austin Pond Date: Mon, 2 Dec 2024 11:45:40 +0100 Subject: [PATCH] [LTS v0.24] Format kind JSON the same way the manifest is formatted (#487) The same change as https://github.com/grafana/grafana-app-sdk/pull/486, but including the thema generation, targeting LTS v0.24 branch instead of main. Co-authored-by: Igor Suleymanov --- cmd/grafana-app-sdk/generate.go | 8 +- codegen/cuekind/generators_test.go | 4 +- ...customkind.custom.ext.grafana.com.json.txt | 324 +++++++++++++++++- .../testkind.test.ext.grafana.com.json.txt | 185 +++++++++- .../testkind2.test.ext.grafana.com.json.txt | 93 ++++- codegen/thema/generators_test.go | 4 +- 6 files changed, 611 insertions(+), 7 deletions(-) diff --git a/cmd/grafana-app-sdk/generate.go b/cmd/grafana-app-sdk/generate.go index 1c8802ef..74cada71 100644 --- a/cmd/grafana-app-sdk/generate.go +++ b/cmd/grafana-app-sdk/generate.go @@ -309,7 +309,9 @@ func generateCRDsThema(parser *themagen.CustomKindParser, genPath string, encodi ms = themagen.CRDGenerator(yaml.Marshal, "yaml") } else { // Assume JSON - ms = themagen.CRDGenerator(json.Marshal, "json") + ms = themagen.CRDGenerator(func(v any) ([]byte, error) { + return json.MarshalIndent(v, "", " ") + }, "json") } files, err := parser.FilteredGenerate(themagen.Filter(ms, func(c kindsys.Custom) bool { return c.Def().Properties.IsCRD @@ -383,7 +385,9 @@ func generateKindsCue(modFS fs.FS, cfg kindGenConfig, selectors ...string) (code // CRD var crdFiles codejen.Files if cfg.CRDEncoding != "none" { - encFunc := json.Marshal + encFunc := func(v any) ([]byte, error) { + return json.MarshalIndent(v, "", " ") + } if cfg.CRDEncoding == "yaml" { encFunc = yaml.Marshal } diff --git a/codegen/cuekind/generators_test.go b/codegen/cuekind/generators_test.go index 7cee3b20..1ba6ec26 100644 --- a/codegen/cuekind/generators_test.go +++ b/codegen/cuekind/generators_test.go @@ -28,7 +28,9 @@ func TestCRDGenerator(t *testing.T) { require.Nil(t, err) t.Run("JSON", func(t *testing.T) { - files, err := CRDGenerator(json.Marshal, "json").Generate(kinds...) + files, err := CRDGenerator(func(v any) ([]byte, error) { + return json.MarshalIndent(v, "", " ") + }, "json").Generate(kinds...) require.Nil(t, err) // Check number of files generated assert.Len(t, files, 2) diff --git a/codegen/testing/golden_generated/crd/customkind.custom.ext.grafana.com.json.txt b/codegen/testing/golden_generated/crd/customkind.custom.ext.grafana.com.json.txt index 558905dd..712ef1c4 100644 --- a/codegen/testing/golden_generated/crd/customkind.custom.ext.grafana.com.json.txt +++ b/codegen/testing/golden_generated/crd/customkind.custom.ext.grafana.com.json.txt @@ -1 +1,323 @@ -{"kind":"CustomResourceDefinition","apiVersion":"apiextensions.k8s.io/v1","metadata":{"name":"customkinds.custom.ext.grafana.com"},"spec":{"group":"custom.ext.grafana.com","versions":[{"name":"v0-0","served":true,"storage":false,"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"deprecatedField":{"type":"string"},"field1":{"type":"string"}},"required":["field1","deprecatedField"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}},"required":["spec"],"type":"object"}},"subresources":{"status":{}}},{"name":"v1-0","served":true,"storage":true,"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"boolField":{"default":false,"type":"boolean"},"enum":{"default":"default","enum":["default","val2","val3","val4","val1"],"type":"string"},"field1":{"type":"string"},"floatField":{"format":"double","type":"number"},"i32":{"maximum":123456,"minimum":-2147483648,"type":"integer"},"i64":{"maximum":9223372036854775807,"minimum":123456,"type":"integer"},"inner":{"properties":{"innerField1":{"type":"string"},"innerField2":{"items":{"type":"string"},"type":"array"},"innerField3":{"items":{"properties":{"details":{"additionalProperties":{},"type":"object"},"name":{"type":"string"}},"required":["name","details"],"type":"object"},"type":"array"}},"required":["innerField1","innerField2","innerField3"],"type":"object"},"map":{"additionalProperties":{"properties":{"details":{"type":"object","x-kubernetes-preserve-unknown-fields":true},"group":{"type":"string"}},"required":["group","details"],"type":"object"},"type":"object"},"timestamp":{"format":"date-time","type":"string"},"union":{"oneOf":[{"allOf":[{"required":["group"]},{"not":{"anyOf":[{"required":["group","details"]}]}}]},{"required":["group","details"]}],"properties":{"details":{"type":"object","x-kubernetes-preserve-unknown-fields":true},"group":{"type":"string"},"options":{"items":{"type":"string"},"type":"array"}},"type":"object"}},"required":["field1","inner","union","map","timestamp","enum","i32","i64","boolField","floatField"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"statusField1":{"type":"string"}},"required":["statusField1"],"type":"object","x-kubernetes-preserve-unknown-fields":true}},"required":["spec"],"type":"object"}},"subresources":{"status":{}}}],"names":{"kind":"CustomKind","plural":"customkinds"},"scope":"Namespaced"}} \ No newline at end of file +{ + "kind": "CustomResourceDefinition", + "apiVersion": "apiextensions.k8s.io/v1", + "metadata": { + "name": "customkinds.custom.ext.grafana.com" + }, + "spec": { + "group": "custom.ext.grafana.com", + "versions": [ + { + "name": "v0-0", + "served": true, + "storage": false, + "schema": { + "openAPIV3Schema": { + "properties": { + "spec": { + "properties": { + "deprecatedField": { + "type": "string" + }, + "field1": { + "type": "string" + } + }, + "required": [ + "field1", + "deprecatedField" + ], + "type": "object" + }, + "status": { + "properties": { + "additionalFields": { + "description": "additionalFields is reserved for future use", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "operatorStates": { + "additionalProperties": { + "properties": { + "descriptiveState": { + "description": "descriptiveState is an optional more descriptive state field which has no requirements on format", + "type": "string" + }, + "details": { + "description": "details contains any extra information that is operator-specific", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "lastEvaluation": { + "description": "lastEvaluation is the ResourceVersion last evaluated", + "type": "string" + }, + "state": { + "description": "state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.", + "enum": [ + "success", + "in_progress", + "failed" + ], + "type": "string" + } + }, + "required": [ + "lastEvaluation", + "state" + ], + "type": "object" + }, + "description": "operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "required": [ + "spec" + ], + "type": "object" + } + }, + "subresources": { + "status": {} + } + }, + { + "name": "v1-0", + "served": true, + "storage": true, + "schema": { + "openAPIV3Schema": { + "properties": { + "spec": { + "properties": { + "boolField": { + "default": false, + "type": "boolean" + }, + "enum": { + "default": "default", + "enum": [ + "default", + "val2", + "val3", + "val4", + "val1" + ], + "type": "string" + }, + "field1": { + "type": "string" + }, + "floatField": { + "format": "double", + "type": "number" + }, + "i32": { + "maximum": 123456, + "minimum": -2147483648, + "type": "integer" + }, + "i64": { + "maximum": 9223372036854775807, + "minimum": 123456, + "type": "integer" + }, + "inner": { + "properties": { + "innerField1": { + "type": "string" + }, + "innerField2": { + "items": { + "type": "string" + }, + "type": "array" + }, + "innerField3": { + "items": { + "properties": { + "details": { + "additionalProperties": {}, + "type": "object" + }, + "name": { + "type": "string" + } + }, + "required": [ + "name", + "details" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "innerField1", + "innerField2", + "innerField3" + ], + "type": "object" + }, + "map": { + "additionalProperties": { + "properties": { + "details": { + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "group": { + "type": "string" + } + }, + "required": [ + "group", + "details" + ], + "type": "object" + }, + "type": "object" + }, + "timestamp": { + "format": "date-time", + "type": "string" + }, + "union": { + "oneOf": [ + { + "allOf": [ + { + "required": [ + "group" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "group", + "details" + ] + } + ] + } + } + ] + }, + { + "required": [ + "group", + "details" + ] + } + ], + "properties": { + "details": { + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "group": { + "type": "string" + }, + "options": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + } + }, + "required": [ + "field1", + "inner", + "union", + "map", + "timestamp", + "enum", + "i32", + "i64", + "boolField", + "floatField" + ], + "type": "object" + }, + "status": { + "properties": { + "additionalFields": { + "description": "additionalFields is reserved for future use", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "operatorStates": { + "additionalProperties": { + "properties": { + "descriptiveState": { + "description": "descriptiveState is an optional more descriptive state field which has no requirements on format", + "type": "string" + }, + "details": { + "description": "details contains any extra information that is operator-specific", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "lastEvaluation": { + "description": "lastEvaluation is the ResourceVersion last evaluated", + "type": "string" + }, + "state": { + "description": "state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.", + "enum": [ + "success", + "in_progress", + "failed" + ], + "type": "string" + } + }, + "required": [ + "lastEvaluation", + "state" + ], + "type": "object" + }, + "description": "operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.", + "type": "object" + }, + "statusField1": { + "type": "string" + } + }, + "required": [ + "statusField1" + ], + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "required": [ + "spec" + ], + "type": "object" + } + }, + "subresources": { + "status": {} + } + } + ], + "names": { + "kind": "CustomKind", + "plural": "customkinds" + }, + "scope": "Namespaced" + } +} \ No newline at end of file diff --git a/codegen/testing/golden_generated/crd/testkind.test.ext.grafana.com.json.txt b/codegen/testing/golden_generated/crd/testkind.test.ext.grafana.com.json.txt index bcb4c816..7efb0ae2 100644 --- a/codegen/testing/golden_generated/crd/testkind.test.ext.grafana.com.json.txt +++ b/codegen/testing/golden_generated/crd/testkind.test.ext.grafana.com.json.txt @@ -1 +1,184 @@ -{"kind":"CustomResourceDefinition","apiVersion":"apiextensions.k8s.io/v1","metadata":{"name":"testkinds.test.ext.grafana.com"},"spec":{"group":"test.ext.grafana.com","versions":[{"name":"v1","served":true,"storage":true,"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"stringField":{"type":"string"}},"required":["stringField"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}},"required":["spec"],"type":"object"}},"subresources":{"status":{}}},{"name":"v2","served":true,"storage":false,"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"intField":{"format":"int64","type":"integer"},"stringField":{"type":"string"},"timeField":{"format":"date-time","type":"string"}},"required":["stringField","intField","timeField"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}},"required":["spec"],"type":"object"}},"subresources":{"status":{}},"additionalPrinterColumns":[{"name":"STRING FIELD","type":"string","jsonPath":".spec.stringField"}]}],"names":{"kind":"TestKind","plural":"testkinds"},"scope":"Namespaced"}} \ No newline at end of file +{ + "kind": "CustomResourceDefinition", + "apiVersion": "apiextensions.k8s.io/v1", + "metadata": { + "name": "testkinds.test.ext.grafana.com" + }, + "spec": { + "group": "test.ext.grafana.com", + "versions": [ + { + "name": "v1", + "served": true, + "storage": true, + "schema": { + "openAPIV3Schema": { + "properties": { + "spec": { + "properties": { + "stringField": { + "type": "string" + } + }, + "required": [ + "stringField" + ], + "type": "object" + }, + "status": { + "properties": { + "additionalFields": { + "description": "additionalFields is reserved for future use", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "operatorStates": { + "additionalProperties": { + "properties": { + "descriptiveState": { + "description": "descriptiveState is an optional more descriptive state field which has no requirements on format", + "type": "string" + }, + "details": { + "description": "details contains any extra information that is operator-specific", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "lastEvaluation": { + "description": "lastEvaluation is the ResourceVersion last evaluated", + "type": "string" + }, + "state": { + "description": "state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.", + "enum": [ + "success", + "in_progress", + "failed" + ], + "type": "string" + } + }, + "required": [ + "lastEvaluation", + "state" + ], + "type": "object" + }, + "description": "operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "required": [ + "spec" + ], + "type": "object" + } + }, + "subresources": { + "status": {} + } + }, + { + "name": "v2", + "served": true, + "storage": false, + "schema": { + "openAPIV3Schema": { + "properties": { + "spec": { + "properties": { + "intField": { + "format": "int64", + "type": "integer" + }, + "stringField": { + "type": "string" + }, + "timeField": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "stringField", + "intField", + "timeField" + ], + "type": "object" + }, + "status": { + "properties": { + "additionalFields": { + "description": "additionalFields is reserved for future use", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "operatorStates": { + "additionalProperties": { + "properties": { + "descriptiveState": { + "description": "descriptiveState is an optional more descriptive state field which has no requirements on format", + "type": "string" + }, + "details": { + "description": "details contains any extra information that is operator-specific", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "lastEvaluation": { + "description": "lastEvaluation is the ResourceVersion last evaluated", + "type": "string" + }, + "state": { + "description": "state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.", + "enum": [ + "success", + "in_progress", + "failed" + ], + "type": "string" + } + }, + "required": [ + "lastEvaluation", + "state" + ], + "type": "object" + }, + "description": "operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "required": [ + "spec" + ], + "type": "object" + } + }, + "subresources": { + "status": {} + }, + "additionalPrinterColumns": [ + { + "name": "STRING FIELD", + "type": "string", + "jsonPath": ".spec.stringField" + } + ] + } + ], + "names": { + "kind": "TestKind", + "plural": "testkinds" + }, + "scope": "Namespaced" + } +} \ No newline at end of file diff --git a/codegen/testing/golden_generated/crd/testkind2.test.ext.grafana.com.json.txt b/codegen/testing/golden_generated/crd/testkind2.test.ext.grafana.com.json.txt index 72aefe7f..e7b1ce5f 100644 --- a/codegen/testing/golden_generated/crd/testkind2.test.ext.grafana.com.json.txt +++ b/codegen/testing/golden_generated/crd/testkind2.test.ext.grafana.com.json.txt @@ -1 +1,92 @@ -{"kind":"CustomResourceDefinition","apiVersion":"apiextensions.k8s.io/v1","metadata":{"name":"testkind2s.test.ext.grafana.com"},"spec":{"group":"test.ext.grafana.com","versions":[{"name":"v1","served":true,"storage":true,"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"testField":{"type":"string"}},"required":["testField"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}},"required":["spec"],"type":"object"}},"subresources":{"status":{}}}],"names":{"kind":"TestKind2","plural":"testkind2s"},"scope":"Namespaced"}} \ No newline at end of file +{ + "kind": "CustomResourceDefinition", + "apiVersion": "apiextensions.k8s.io/v1", + "metadata": { + "name": "testkind2s.test.ext.grafana.com" + }, + "spec": { + "group": "test.ext.grafana.com", + "versions": [ + { + "name": "v1", + "served": true, + "storage": true, + "schema": { + "openAPIV3Schema": { + "properties": { + "spec": { + "properties": { + "testField": { + "type": "string" + } + }, + "required": [ + "testField" + ], + "type": "object" + }, + "status": { + "properties": { + "additionalFields": { + "description": "additionalFields is reserved for future use", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "operatorStates": { + "additionalProperties": { + "properties": { + "descriptiveState": { + "description": "descriptiveState is an optional more descriptive state field which has no requirements on format", + "type": "string" + }, + "details": { + "description": "details contains any extra information that is operator-specific", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "lastEvaluation": { + "description": "lastEvaluation is the ResourceVersion last evaluated", + "type": "string" + }, + "state": { + "description": "state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.", + "enum": [ + "success", + "in_progress", + "failed" + ], + "type": "string" + } + }, + "required": [ + "lastEvaluation", + "state" + ], + "type": "object" + }, + "description": "operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "required": [ + "spec" + ], + "type": "object" + } + }, + "subresources": { + "status": {} + } + } + ], + "names": { + "kind": "TestKind2", + "plural": "testkind2s" + }, + "scope": "Namespaced" + } +} \ No newline at end of file diff --git a/codegen/thema/generators_test.go b/codegen/thema/generators_test.go index f13d3c4c..d6112b34 100644 --- a/codegen/thema/generators_test.go +++ b/codegen/thema/generators_test.go @@ -28,7 +28,9 @@ func TestCRDGenerator(t *testing.T) { require.Nil(t, err) t.Run("JSON", func(t *testing.T) { - files, err := parser.Generate(CRDGenerator(json.Marshal, "json"), "customKind") + files, err := parser.Generate(CRDGenerator(func(v any) ([]byte, error) { + return json.MarshalIndent(v, "", " ") + }, "json"), "customKind") require.Nil(t, err) // Check number of files generated assert.Len(t, files, 1)