Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add yaml outputs of resources to streaming logs and add import&update steps to uptest #136

Merged
merged 7 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/pr-comment-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ on:
default: 'provider'
required: false
type: string
update-test-parameter:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We may consider adding a description to the new parameter.

Let's also document that the update parameter should be a serialized JSON object and if the JSON object has nested children, then there must be only one leaf.

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'
Expand Down Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -80,4 +86,10 @@ type Resource struct {
PostAssertScriptPath string
PreDeleteScriptPath string
PostDeleteScriptPath string

UpdateParameter string
UpdateAssertKey string
UpdateAssertValue string

Root bool
}
1 change: 1 addition & 0 deletions internal/templates/00-apply.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This file belongs to the resource apply step.
{{ if .TestCase.SetupScriptPath -}}
apiVersion: kuttl.dev/v1beta1
kind: TestStep
Expand Down
3 changes: 3 additions & 0 deletions internal/templates/00-assert.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -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}}
Expand Down
15 changes: 8 additions & 7 deletions internal/templates/01-assert.yaml.tmpl
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put a YAML comment at the top of this file telling that this assert step belongs to the resource update test.

Original file line number Diff line number Diff line change
@@ -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 }}
17 changes: 17 additions & 0 deletions internal/templates/01-update.yaml.tmpl
sergenyalcin marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -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 }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next iteration, we can consider adding claim update tests.

{{- if $resource.Root }}
- command: ${KUBECTL} patch {{ $resource.KindGroup }}/{{ $resource.Name }} --type=merge -p '{"spec":{"forProvider":{{ $resource.UpdateParameter }}}}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We constrain the update parameter to be a direct child of spec.forProvider.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had better only patch the target manifest in the update tests.

{{- end }}
{{- end }}
{{- end }}
19 changes: 19 additions & 0 deletions internal/templates/02-assert.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -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 }}
17 changes: 17 additions & 0 deletions internal/templates/02-import.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +12 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We have better scale the provider deployment down before updating the status and putting the annotation here.

{{- 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
21 changes: 21 additions & 0 deletions internal/templates/03-assert.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -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 }}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This file belongs to the resource delete step.
apiVersion: kuttl.dev/v1beta1
kind: TestStep
commands:
Expand Down
24 changes: 22 additions & 2 deletions internal/templates/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
//go:embed 01-assert.yaml.tmpl
//go:embed 01-assert-update.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
8 changes: 6 additions & 2 deletions internal/templates/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
108 changes: 94 additions & 14 deletions internal/templates/renderer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
`,
},
},
Expand Down Expand Up @@ -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
`,
},
},
Expand Down
Loading
Loading