diff --git a/.github/workflows/pr-comment-trigger.yml b/.github/workflows/pr-comment-trigger.yml index b150438..52376f3 100644 --- a/.github/workflows/pr-comment-trigger.yml +++ b/.github/workflows/pr-comment-trigger.yml @@ -17,6 +17,16 @@ on: default: 'provider' required: false type: string + update-test-parameter: + description: 'Input parameter to use during update step. If this field + is empty, then the update step will be skipped. + The update parameter should be a serialized JSON object and if the JSON + object has nested children, then there must be only one leaf. + Example: {"tags":{"uptest":"update"}} + This parameter will add a tag to the test resource.' + default: '' + required: false + type: string secrets: UPTEST_CLOUD_CREDENTIALS: description: 'Uptest cloud credentials to be passed to the uptest target as environment variable' @@ -158,6 +168,7 @@ jobs: UPTEST_EXAMPLE_LIST: ${{ needs.get-example-list.outputs.example_list }} UPTEST_TEST_DIR: ./_output/controlplane-dump UPTEST_DATASOURCE_PATH: .work/uptest-datasource.yaml + UPTEST_UPDATE_PARAMETER: ${{ inputs.update-test-parameter }} run: | mkdir -p .work && echo "${{ secrets.UPTEST_DATASOURCE }}" > .work/uptest-datasource.yaml make e2e diff --git a/internal/config/config.go b/internal/config/config.go index 57756bf..05e9ede 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -35,6 +35,12 @@ const ( // AnnotationKeyPostDeleteHook defines the path to a post-delete // hook script to be executed after the tested resource is deleted. AnnotationKeyPostDeleteHook = "uptest.upbound.io/post-delete-hook" + // AnnotationKeyUpdateParameter defines the update parameter that will be + // used during the update step + AnnotationKeyUpdateParameter = "uptest.upbound.io/update-parameter" + // AnnotationKeyExampleID is id of example that populated from example + // manifest. This information will be used for determining the root resource + AnnotationKeyExampleID = "meta.upbound.io/example-id" ) // AutomatedTest represents an automated test of resource example @@ -80,4 +86,10 @@ type Resource struct { PostAssertScriptPath string PreDeleteScriptPath string PostDeleteScriptPath string + + UpdateParameter string + UpdateAssertKey string + UpdateAssertValue string + + Root bool } diff --git a/internal/templates/00-apply.yaml.tmpl b/internal/templates/00-apply.yaml.tmpl index a6cc12c..2734913 100644 --- a/internal/templates/00-apply.yaml.tmpl +++ b/internal/templates/00-apply.yaml.tmpl @@ -1,3 +1,4 @@ +# This file belongs to the resource apply step. {{ if .TestCase.SetupScriptPath -}} apiVersion: kuttl.dev/v1beta1 kind: TestStep diff --git a/internal/templates/00-assert.yaml.tmpl b/internal/templates/00-assert.yaml.tmpl index f21d0fb..95b184a 100644 --- a/internal/templates/00-assert.yaml.tmpl +++ b/internal/templates/00-assert.yaml.tmpl @@ -1,8 +1,11 @@ +# This assert file belongs to the resource apply step. apiVersion: kuttl.dev/v1beta1 kind: TestAssert timeout: {{ .TestCase.Timeout }} commands: - command: ${KUBECTL} annotate managed --all upjet.upbound.io/test=true --overwrite +- script: echo "Dump MR manifests for the apply assertion step:"; ${KUBECTL} get managed -o yaml +- script: echo "Dump Claim manifests for the apply assertion step:" || ${KUBECTL} get claim --all-namespaces -o yaml {{- range $resource := .Resources }} {{- if eq $resource.KindGroup "secret." -}} {{continue}} diff --git a/internal/templates/01-assert.yaml.tmpl b/internal/templates/01-assert.yaml.tmpl index 0c95074..a4dc2c5 100644 --- a/internal/templates/01-assert.yaml.tmpl +++ b/internal/templates/01-assert.yaml.tmpl @@ -1,18 +1,19 @@ +# This assert file belongs to the resource update step. apiVersion: kuttl.dev/v1beta1 kind: TestAssert timeout: {{ .TestCase.Timeout }} commands: +- script: echo "Dump MR manifests for the update assertion step:"; ${KUBECTL} get managed -o yaml {{- range $resource := .Resources }} +{{- if eq $resource.UpdateParameter "" -}} + {{continue}} +{{- end -}} {{- if eq $resource.KindGroup "secret." -}} {{continue}} {{- end -}} -{{- if $resource.Namespace }} -- command: ${KUBECTL} wait {{ $resource.KindGroup }}/{{ $resource.Name }} --for=delete --timeout 10s --namespace {{ $resource.Namespace }} -{{- else }} -- command: ${KUBECTL} wait {{ $resource.KindGroup }}/{{ $resource.Name }} --for=delete --timeout 10s +{{- if not $resource.Namespace }} +{{- if $resource.Root }} +- script: ${KUBECTL} get {{ $resource.KindGroup }}/{{ $resource.Name }} -o=jsonpath='{.status.atProvider{{ $resource.UpdateAssertKey }}}' | grep -q "^{{ $resource.UpdateAssertValue }}$" {{- end }} {{- end }} -- command: ${KUBECTL} wait managed --all --for=delete --timeout 10s -{{- if .TestCase.TeardownScriptPath }} -- command: {{ .TestCase.TeardownScriptPath }} {{- end }} diff --git a/internal/templates/01-update.yaml.tmpl b/internal/templates/01-update.yaml.tmpl new file mode 100644 index 0000000..77a6280 --- /dev/null +++ b/internal/templates/01-update.yaml.tmpl @@ -0,0 +1,17 @@ +# This file belongs to the resource update step. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: +{{- range $resource := .Resources }} +{{- if eq $resource.UpdateParameter "" -}} + {{continue}} +{{- end -}} +{{- if eq $resource.KindGroup "secret." -}} + {{continue}} +{{- end -}} +{{- if not $resource.Namespace }} +{{- if $resource.Root }} +- command: ${KUBECTL} patch {{ $resource.KindGroup }}/{{ $resource.Name }} --type=merge -p '{"spec":{"forProvider":{{ $resource.UpdateParameter }}}}' +{{- end }} +{{- end }} +{{- end }} diff --git a/internal/templates/02-assert.yaml.tmpl b/internal/templates/02-assert.yaml.tmpl new file mode 100644 index 0000000..d1c8deb --- /dev/null +++ b/internal/templates/02-assert.yaml.tmpl @@ -0,0 +1,19 @@ +# This assert file belongs to the resource import step. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: {{ .TestCase.Timeout }} +commands: +- script: echo "Dump MR manifests for the import assertion step:"; ${KUBECTL} get managed -o yaml +{{- range $resource := .Resources }} +{{- if eq $resource.KindGroup "secret." -}} + {{continue}} +{{- end -}} +{{- range $condition := $resource.Conditions }} +{{- if not $resource.Namespace }} +- command: ${KUBECTL} wait {{ $resource.KindGroup }}/{{ $resource.Name }} --for=condition={{ $condition }} --timeout 10s +{{- end }} +{{- end }} +{{- if not $resource.Namespace }} +- script: new_id=$(${KUBECTL} get {{ $resource.KindGroup }}/{{ $resource.Name }} -o=jsonpath='{.status.atProvider.id}') && old_id=$(${KUBECTL} get {{ $resource.KindGroup }}/{{ $resource.Name }} -o=jsonpath='{.metadata.annotations.uptest-old-id}') && [ "$new_id" == "$old_id" ] +{{- end }} +{{- end }} diff --git a/internal/templates/02-import.yaml.tmpl b/internal/templates/02-import.yaml.tmpl new file mode 100644 index 0000000..d392e60 --- /dev/null +++ b/internal/templates/02-import.yaml.tmpl @@ -0,0 +1,17 @@ +# This file belongs to the resource import step. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: +- command: ${KUBECTL} scale deployment crossplane -n upbound-system --replicas=0 +- script: ${KUBECTL} -n upbound-system get deploy --no-headers -o custom-columns=":metadata.name" | grep "provider-" | xargs ${KUBECTL} -n upbound-system scale deploy --replicas=0 +{{- range $resource := .Resources }} +{{- if eq $resource.KindGroup "secret." -}} + {{continue}} +{{- end -}} +{{- if not $resource.Namespace }} +- command: ${KUBECTL} --subresource=status patch {{ $resource.KindGroup }}/{{ $resource.Name }} --type=merge -p '{"status":{"conditions":[]}}' +- script: ${KUBECTL} annotate {{ $resource.KindGroup }}/{{ $resource.Name }} uptest-old-id=$(${KUBECTL} get {{ $resource.KindGroup }}/{{ $resource.Name }} -o=jsonpath='{.status.atProvider.id}') --overwrite +{{- end }} +{{- end }} +- command: ${KUBECTL} scale deployment crossplane -n upbound-system --replicas=1 +- script: ${KUBECTL} -n upbound-system get deploy --no-headers -o custom-columns=":metadata.name" | grep "provider-" | xargs ${KUBECTL} -n upbound-system scale deploy --replicas=1 diff --git a/internal/templates/03-assert.yaml.tmpl b/internal/templates/03-assert.yaml.tmpl new file mode 100644 index 0000000..97849fe --- /dev/null +++ b/internal/templates/03-assert.yaml.tmpl @@ -0,0 +1,21 @@ +# This assert file belongs to the resource delete step. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: {{ .TestCase.Timeout }} +commands: +- script: echo "Dump MR manifests for the delete assertion step:"; ${KUBECTL} get managed -o yaml +- script: echo "Dump Claim manifests for the delete assertion step:" || ${KUBECTL} get claim --all-namespaces -o yaml +{{- range $resource := .Resources }} +{{- if eq $resource.KindGroup "secret." -}} + {{continue}} +{{- end -}} +{{- if $resource.Namespace }} +- script: ${KUBECTL} wait {{ $resource.KindGroup }}/{{ $resource.Name }} --for=delete --timeout 10s --namespace {{ $resource.Namespace }} +{{- else }} +- command: ${KUBECTL} wait {{ $resource.KindGroup }}/{{ $resource.Name }} --for=delete --timeout 10s +{{- end }} +{{- end }} +- command: ${KUBECTL} wait managed --all --for=delete --timeout 10s +{{- if .TestCase.TeardownScriptPath }} +- command: {{ .TestCase.TeardownScriptPath }} +{{- end }} diff --git a/internal/templates/01-delete.yaml.tmpl b/internal/templates/03-delete.yaml.tmpl similarity index 93% rename from internal/templates/01-delete.yaml.tmpl rename to internal/templates/03-delete.yaml.tmpl index 6a572f1..c291505 100644 --- a/internal/templates/01-delete.yaml.tmpl +++ b/internal/templates/03-delete.yaml.tmpl @@ -1,3 +1,4 @@ +# This file belongs to the resource delete step. apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: diff --git a/internal/templates/embed.go b/internal/templates/embed.go index 6996d40..ccc07a3 100644 --- a/internal/templates/embed.go +++ b/internal/templates/embed.go @@ -26,12 +26,32 @@ var inputFileTemplate string //go:embed 00-assert.yaml.tmpl var assertFileTemplate string +// updateFileTemplate is the template for the update file. +// +//go:embed 01-update.yaml.tmpl +var updateFileTemplate string + +// assertUpdatedFileTemplate is the template for update assert file. +// +//go:embed 01-assert.yaml.tmpl +var assertUpdatedFileTemplate string + +// deleteFileTemplate is the template for the import file. +// +//go:embed 02-import.yaml.tmpl +var importFileTemplate string + +// assertDeletedFileTemplate is the template for import assert file. +// +//go:embed 02-assert.yaml.tmpl +var assertImportedFileTemplate string + // deleteFileTemplate is the template for the delete file. // -//go:embed 01-delete.yaml.tmpl +//go:embed 03-delete.yaml.tmpl var deleteFileTemplate string // assertDeletedFileTemplate is the template for delete assert file. // -//go:embed 01-assert.yaml.tmpl +//go:embed 03-assert.yaml.tmpl var assertDeletedFileTemplate string diff --git a/internal/templates/renderer.go b/internal/templates/renderer.go index b71870d..37371bd 100644 --- a/internal/templates/renderer.go +++ b/internal/templates/renderer.go @@ -28,8 +28,12 @@ import ( var fileTemplates = map[string]string{ "00-apply.yaml": inputFileTemplate, "00-assert.yaml": assertFileTemplate, - "01-delete.yaml": deleteFileTemplate, - "01-assert.yaml": assertDeletedFileTemplate, + "01-update.yaml": updateFileTemplate, + "01-assert.yaml": assertUpdatedFileTemplate, + "02-import.yaml": importFileTemplate, + "02-assert.yaml": assertImportedFileTemplate, + "03-delete.yaml": deleteFileTemplate, + "03-assert.yaml": assertDeletedFileTemplate, } // Render renders the specified list of resources as a test case diff --git a/internal/templates/renderer_test.go b/internal/templates/renderer_test.go index 15ed767..a44206c 100644 --- a/internal/templates/renderer_test.go +++ b/internal/templates/renderer_test.go @@ -84,25 +84,65 @@ func TestRender(t *testing.T) { }, want: want{ out: map[string]string{ - "00-apply.yaml": "---\n" + bucketManifest, - "00-assert.yaml": `apiVersion: kuttl.dev/v1beta1 + "00-apply.yaml": "# This file belongs to the resource apply step.\n---\n" + bucketManifest, + "00-assert.yaml": `# This assert file belongs to the resource apply step. +apiVersion: kuttl.dev/v1beta1 kind: TestAssert timeout: 10 commands: - command: ${KUBECTL} annotate managed --all upjet.upbound.io/test=true --overwrite +- script: echo "Dump MR manifests for the apply assertion step:"; ${KUBECTL} get managed -o yaml +- script: echo "Dump Claim manifests for the apply assertion step:" || ${KUBECTL} get claim --all-namespaces -o yaml - command: ${KUBECTL} wait s3.aws.upbound.io/example-bucket --for=condition=Test --timeout 10s `, - "01-delete.yaml": `apiVersion: kuttl.dev/v1beta1 + "01-update.yaml": `# This file belongs to the resource update step. +apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: -- command: ${KUBECTL} delete s3.aws.upbound.io/example-bucket --wait=false --ignore-not-found `, - "01-assert.yaml": `apiVersion: kuttl.dev/v1beta1 + "01-assert.yaml": `# This assert file belongs to the resource update step. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 10 +commands: +- script: echo "Dump MR manifests for the update assertion step:"; ${KUBECTL} get managed -o yaml +`, + "02-assert.yaml": `# This assert file belongs to the resource import step. +apiVersion: kuttl.dev/v1beta1 kind: TestAssert timeout: 10 commands: +- script: echo "Dump MR manifests for the import assertion step:"; ${KUBECTL} get managed -o yaml +- command: ${KUBECTL} wait s3.aws.upbound.io/example-bucket --for=condition=Test --timeout 10s +- script: new_id=$(${KUBECTL} get s3.aws.upbound.io/example-bucket -o=jsonpath='{.status.atProvider.id}') && old_id=$(${KUBECTL} get s3.aws.upbound.io/example-bucket -o=jsonpath='{.metadata.annotations.uptest-old-id}') && [ "$new_id" == "$old_id" ] +`, + "02-import.yaml": `# This file belongs to the resource import step. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: +- command: ${KUBECTL} scale deployment crossplane -n upbound-system --replicas=0 +- script: ${KUBECTL} -n upbound-system get deploy --no-headers -o custom-columns=":metadata.name" | grep "provider-" | xargs ${KUBECTL} -n upbound-system scale deploy --replicas=0 +- command: ${KUBECTL} --subresource=status patch s3.aws.upbound.io/example-bucket --type=merge -p '{"status":{"conditions":[]}}' +- script: ${KUBECTL} annotate s3.aws.upbound.io/example-bucket uptest-old-id=$(${KUBECTL} get s3.aws.upbound.io/example-bucket -o=jsonpath='{.status.atProvider.id}') --overwrite +- command: ${KUBECTL} scale deployment crossplane -n upbound-system --replicas=1 +- script: ${KUBECTL} -n upbound-system get deploy --no-headers -o custom-columns=":metadata.name" | grep "provider-" | xargs ${KUBECTL} -n upbound-system scale deploy --replicas=1 +`, + + "03-assert.yaml": `# This assert file belongs to the resource delete step. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 10 +commands: +- script: echo "Dump MR manifests for the delete assertion step:"; ${KUBECTL} get managed -o yaml +- script: echo "Dump Claim manifests for the delete assertion step:" || ${KUBECTL} get claim --all-namespaces -o yaml - command: ${KUBECTL} wait s3.aws.upbound.io/example-bucket --for=delete --timeout 10s - command: ${KUBECTL} wait managed --all --for=delete --timeout 10s +`, + "03-delete.yaml": `# This file belongs to the resource delete step. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: +- command: ${KUBECTL} delete s3.aws.upbound.io/example-bucket --wait=false --ignore-not-found `, }, }, @@ -142,38 +182,78 @@ commands: }, want: want{ out: map[string]string{ - "00-apply.yaml": `apiVersion: kuttl.dev/v1beta1 + "00-apply.yaml": `# This file belongs to the resource apply step. +apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - command: /tmp/setup.sh ` + "---\n" + bucketManifest + "---\n" + claimManifest + "---\n" + secretManifest, - "00-assert.yaml": `apiVersion: kuttl.dev/v1beta1 + "00-assert.yaml": `# This assert file belongs to the resource apply step. +apiVersion: kuttl.dev/v1beta1 kind: TestAssert timeout: 10 commands: - command: ${KUBECTL} annotate managed --all upjet.upbound.io/test=true --overwrite +- script: echo "Dump MR manifests for the apply assertion step:"; ${KUBECTL} get managed -o yaml +- script: echo "Dump Claim manifests for the apply assertion step:" || ${KUBECTL} get claim --all-namespaces -o yaml - command: /tmp/bucket/pre-assert.sh - command: ${KUBECTL} wait s3.aws.upbound.io/example-bucket --for=condition=Test --timeout 10s - command: ${KUBECTL} wait cluster.gcp.platformref.upbound.io/test-cluster-claim --for=condition=Ready --timeout 10s --namespace upbound-system - command: ${KUBECTL} wait cluster.gcp.platformref.upbound.io/test-cluster-claim --for=condition=Synced --timeout 10s --namespace upbound-system - command: /tmp/claim/post-assert.sh `, - "01-delete.yaml": `apiVersion: kuttl.dev/v1beta1 + "01-update.yaml": `# This file belongs to the resource update step. +apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: -- command: ${KUBECTL} delete s3.aws.upbound.io/example-bucket --wait=false --ignore-not-found -- command: /tmp/bucket/post-delete.sh -- command: /tmp/claim/pre-delete.sh -- command: ${KUBECTL} delete cluster.gcp.platformref.upbound.io/test-cluster-claim --wait=false --namespace upbound-system --ignore-not-found `, - "01-assert.yaml": `apiVersion: kuttl.dev/v1beta1 + "01-assert.yaml": `# This assert file belongs to the resource update step. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 10 +commands: +- script: echo "Dump MR manifests for the update assertion step:"; ${KUBECTL} get managed -o yaml +`, + "02-assert.yaml": `# This assert file belongs to the resource import step. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 10 +commands: +- script: echo "Dump MR manifests for the import assertion step:"; ${KUBECTL} get managed -o yaml +- command: ${KUBECTL} wait s3.aws.upbound.io/example-bucket --for=condition=Test --timeout 10s +- script: new_id=$(${KUBECTL} get s3.aws.upbound.io/example-bucket -o=jsonpath='{.status.atProvider.id}') && old_id=$(${KUBECTL} get s3.aws.upbound.io/example-bucket -o=jsonpath='{.metadata.annotations.uptest-old-id}') && [ "$new_id" == "$old_id" ] +`, + "02-import.yaml": `# This file belongs to the resource import step. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: +- command: ${KUBECTL} scale deployment crossplane -n upbound-system --replicas=0 +- script: ${KUBECTL} -n upbound-system get deploy --no-headers -o custom-columns=":metadata.name" | grep "provider-" | xargs ${KUBECTL} -n upbound-system scale deploy --replicas=0 +- command: ${KUBECTL} --subresource=status patch s3.aws.upbound.io/example-bucket --type=merge -p '{"status":{"conditions":[]}}' +- script: ${KUBECTL} annotate s3.aws.upbound.io/example-bucket uptest-old-id=$(${KUBECTL} get s3.aws.upbound.io/example-bucket -o=jsonpath='{.status.atProvider.id}') --overwrite +- command: ${KUBECTL} scale deployment crossplane -n upbound-system --replicas=1 +- script: ${KUBECTL} -n upbound-system get deploy --no-headers -o custom-columns=":metadata.name" | grep "provider-" | xargs ${KUBECTL} -n upbound-system scale deploy --replicas=1 +`, + "03-assert.yaml": `# This assert file belongs to the resource delete step. +apiVersion: kuttl.dev/v1beta1 kind: TestAssert timeout: 10 commands: +- script: echo "Dump MR manifests for the delete assertion step:"; ${KUBECTL} get managed -o yaml +- script: echo "Dump Claim manifests for the delete assertion step:" || ${KUBECTL} get claim --all-namespaces -o yaml - command: ${KUBECTL} wait s3.aws.upbound.io/example-bucket --for=delete --timeout 10s -- command: ${KUBECTL} wait cluster.gcp.platformref.upbound.io/test-cluster-claim --for=delete --timeout 10s --namespace upbound-system +- script: ${KUBECTL} wait cluster.gcp.platformref.upbound.io/test-cluster-claim --for=delete --timeout 10s --namespace upbound-system - command: ${KUBECTL} wait managed --all --for=delete --timeout 10s - command: /tmp/teardown.sh +`, + "03-delete.yaml": `# This file belongs to the resource delete step. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: +- command: ${KUBECTL} delete s3.aws.upbound.io/example-bucket --wait=false --ignore-not-found +- command: /tmp/bucket/post-delete.sh +- command: /tmp/claim/pre-delete.sh +- command: ${KUBECTL} delete cluster.gcp.platformref.upbound.io/test-cluster-claim --wait=false --namespace upbound-system --ignore-not-found `, }, }, diff --git a/internal/tester.go b/internal/tester.go index 2833da6..7d89525 100644 --- a/internal/tester.go +++ b/internal/tester.go @@ -16,6 +16,7 @@ package internal import ( "bufio" + "encoding/json" "fmt" "io/fs" "os" @@ -70,7 +71,8 @@ func (t *tester) prepareConfig() (*config.TestCase, []config.Resource, error) { for _, m := range t.manifests { obj := m.Object - kg := strings.ToLower(obj.GroupVersionKind().Kind + "." + obj.GroupVersionKind().Group) + groupVersionKind := obj.GroupVersionKind() + kg := strings.ToLower(groupVersionKind.Kind + "." + groupVersionKind.Group) example := config.Resource{ Name: obj.GetName(), @@ -125,6 +127,25 @@ func (t *tester) prepareConfig() (*config.TestCase, []config.Resource, error) { } } + updateParameter, ok := annotations[config.AnnotationKeyUpdateParameter] + if !ok { + updateParameter = os.Getenv("UPTEST_UPDATE_PARAMETER") + } + if updateParameter != "" { + example.UpdateParameter = updateParameter + var data map[string]interface{} + if err := json.Unmarshal([]byte(updateParameter), &data); err != nil { + return nil, nil, errors.Wrapf(err, "cannot unmarshal JSON object: %s", updateParameter) + } + example.UpdateAssertKey, example.UpdateAssertValue = convertToJSONPath(data, "") + } + + if exampleID, ok := annotations[config.AnnotationKeyExampleID]; ok { + if exampleID == strings.ToLower(fmt.Sprintf("%s/%s/%s", strings.Split(groupVersionKind.Group, ".")[0], groupVersionKind.Version, groupVersionKind.Kind)) { + example.Root = true + } + } + examples = append(examples, example) } @@ -150,3 +171,16 @@ func (t *tester) writeKuttlFiles() error { return nil } + +func convertToJSONPath(data map[string]interface{}, currentPath string) (string, string) { + for key, value := range data { + newPath := currentPath + "." + key + switch v := value.(type) { + case map[string]interface{}: + return convertToJSONPath(v, newPath) + default: + return newPath, fmt.Sprintf("%v", v) + } + } + return currentPath, "" +}