diff --git a/operator/controllers/common/taskhandler.go b/operator/controllers/common/taskhandler.go index c34641dff5..eca635a89c 100644 --- a/operator/controllers/common/taskhandler.go +++ b/operator/controllers/common/taskhandler.go @@ -91,7 +91,9 @@ func (r TaskHandler) ReconcileTasks(ctx context.Context, phaseCtx context.Contex &taskStatus, ) if err != nil { - return nil, summary, err + // log the error, but continue to proceed with other tasks that may be created + r.Log.Error(err, "Could not create task", "task", taskDefinitionName) + continue } } else { r.handleTaskExists( diff --git a/operator/controllers/common/taskhandler_test.go b/operator/controllers/common/taskhandler_test.go index 6c319d9bef..39193c53f1 100644 --- a/operator/controllers/common/taskhandler_test.go +++ b/operator/controllers/common/taskhandler_test.go @@ -83,10 +83,50 @@ func TestTaskHandler(t *testing.T) { }, wantStatus: nil, wantSummary: apicommon.StatusSummary{Total: 1, Pending: 0}, - wantErr: controllererrors.ErrCannotGetKeptnTaskDefinition, + wantErr: nil, getSpanCalls: 0, unbindSpanCalls: 0, }, + { + name: "tasks not started - could not find taskDefinition of one task", + object: &v1alpha3.KeptnAppVersion{ + ObjectMeta: v1.ObjectMeta{ + Namespace: "namespace", + }, + Spec: v1alpha3.KeptnAppVersionSpec{ + KeptnAppSpec: v1alpha3.KeptnAppSpec{ + PreDeploymentTasks: []string{"task-def", "other-task-def"}, + }, + }, + }, + taskDef: &v1alpha3.KeptnTaskDefinition{ + ObjectMeta: v1.ObjectMeta{ + Namespace: KLTNamespace, + Name: "task-def", + }, + }, + taskObj: v1alpha3.KeptnTask{}, + createAttr: CreateTaskAttributes{ + SpanName: "", + Definition: v1alpha3.KeptnTaskDefinition{ + ObjectMeta: v1.ObjectMeta{ + Name: "task-def", + }, + }, + CheckType: apicommon.PreDeploymentCheckType, + }, + wantStatus: []v1alpha3.ItemStatus{ + { + DefinitionName: "task-def", + Status: apicommon.StatePending, + Name: "pre-task-def-", + }, + }, + wantSummary: apicommon.StatusSummary{Total: 2, Pending: 1}, + wantErr: nil, + getSpanCalls: 1, + unbindSpanCalls: 0, + }, { name: "task not started - taskDefinition in default KLT namespace", object: &v1alpha3.KeptnAppVersion{ diff --git a/operator/controllers/lifecycle/keptnappversion/controller.go b/operator/controllers/lifecycle/keptnappversion/controller.go index 6d37e9d752..d6e3d845cf 100644 --- a/operator/controllers/lifecycle/keptnappversion/controller.go +++ b/operator/controllers/lifecycle/keptnappversion/controller.go @@ -167,7 +167,6 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ span.SetStatus(codes.Error, err.Error()) return ctrl.Result{Requeue: true}, err } - // AppVersion is completed at this place return r.finishKeptnAppVersionReconcile(ctx, appVersion, spanAppTrace) diff --git a/operator/test/component/task/task_test.go b/operator/test/component/task/task_test.go index e68af7fa89..6b10c509b8 100644 --- a/operator/test/component/task/task_test.go +++ b/operator/test/component/task/task_test.go @@ -48,7 +48,7 @@ var _ = Describe("Task", Ordered, func() { }, task) g.Expect(err).To(BeNil()) g.Expect(task.Status.JobName).To(Not(BeEmpty())) - }, "10s").Should(Succeed()) + }, "20s").Should(Succeed()) createdJob := &batchv1.Job{} @@ -101,7 +101,7 @@ var _ = Describe("Task", Ordered, func() { }, task) g.Expect(err).To(BeNil()) g.Expect(task.Status.JobName).To(Not(BeEmpty())) - }, "10s").Should(Succeed()) + }, "20s").Should(Succeed()) createdJob := &batchv1.Job{} @@ -129,7 +129,7 @@ var _ = Describe("Task", Ordered, func() { }, task) g.Expect(err).To(BeNil()) g.Expect(task.Status.Status).To(Equal(apicommon.StateSucceeded)) - }, "10s").Should(Succeed()) + }, "20s").Should(Succeed()) }) It("succeed task if taskDefiniton for Container is present in default KLT namespace", func() { By("create default KLT namespace") @@ -154,7 +154,7 @@ var _ = Describe("Task", Ordered, func() { }, task) g.Expect(err).To(BeNil()) g.Expect(task.Status.JobName).To(Not(BeEmpty())) - }, "10s").Should(Succeed()) + }, "20s").Should(Succeed()) createdJob := &batchv1.Job{} @@ -182,7 +182,7 @@ var _ = Describe("Task", Ordered, func() { }, task) g.Expect(err).To(BeNil()) g.Expect(task.Status.Status).To(Equal(apicommon.StateSucceeded)) - }, "10s").Should(Succeed()) + }, "20s").Should(Succeed()) }) It("should propagate labels and annotations to the job and job pod", func() { taskDefinition = makeTaskDefinition(taskDefinitionName, namespace) @@ -197,7 +197,7 @@ var _ = Describe("Task", Ordered, func() { }, task) g.Expect(err).To(BeNil()) g.Expect(task.Status.JobName).To(Not(BeEmpty())) - }, "10s").Should(Succeed()) + }, "20s").Should(Succeed()) createdJob := &batchv1.Job{} diff --git a/test/integration/app-one-taskdefinition-not-found/00-assert.yaml b/test/integration/app-one-taskdefinition-not-found/00-assert.yaml new file mode 100644 index 0000000000..7b6da25d83 --- /dev/null +++ b/test/integration/app-one-taskdefinition-not-found/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: lifecycle.keptn.sh/v1alpha3 +kind: KeptnAppVersion +metadata: + name: podtato-head-1.3-6b86b273 +status: + currentPhase: AppPreDeployTasks + postDeploymentEvaluationStatus: Pending + postDeploymentStatus: Pending + preDeploymentEvaluationStatus: Pending + preDeploymentStatus: Unknown + status: Progressing + workloadOverallStatus: Pending +--- +apiVersion: lifecycle.keptn.sh/v1alpha3 +kind: KeptnTask +spec: + app: podtato-head + appVersion: '1.3' + checkType: pre + retries: 10 + taskDefinition: pre-task-timeout + timeout: 30s +status: + status: Succeeded diff --git a/test/integration/app-one-taskdefinition-not-found/00-install.yaml b/test/integration/app-one-taskdefinition-not-found/00-install.yaml new file mode 100644 index 0000000000..7cc21c5093 --- /dev/null +++ b/test/integration/app-one-taskdefinition-not-found/00-install.yaml @@ -0,0 +1,53 @@ +apiVersion: lifecycle.keptn.sh/v1alpha3 +kind: KeptnApp +metadata: + name: podtato-head +spec: + version: "1.3" + workloads: + - name: podtato-head-entry + version: 0.1.0 + preDeploymentTasks: + - pre-task-timeout + - pre-task-notfound +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: podtato-head-entry + labels: + app: podtato-head +spec: + selector: + matchLabels: + component: podtato-head-entry + template: + metadata: + labels: + component: podtato-head-entry + annotations: + keptn.sh/app: podtato-head + keptn.sh/workload: podtato-head-entry + keptn.sh/version: 0.1.0 + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + image: ghcr.io/podtato-head/entry:latest + imagePullPolicy: Always + ports: + - containerPort: 9000 + env: + - name: PODTATO_PORT + value: "9000" +--- +apiVersion: lifecycle.keptn.sh/v1alpha3 +kind: KeptnTaskDefinition +metadata: + name: pre-task-timeout +spec: + function: + inline: + code: | + console.log('foo') + timeout: "30s" diff --git a/test/integration/app-one-taskdefinition-not-found/00-teststep.yaml b/test/integration/app-one-taskdefinition-not-found/00-teststep.yaml new file mode 100644 index 0000000000..ad4f1d95d5 --- /dev/null +++ b/test/integration/app-one-taskdefinition-not-found/00-teststep.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1 +kind: TestStep +commands: + - script: kubectl annotate ns $NAMESPACE keptn.sh/lifecycle-toolkit='enabled' diff --git a/test/integration/app-one-taskdefinition-not-found/01-teststep-verify-number-of-tasks.yaml b/test/integration/app-one-taskdefinition-not-found/01-teststep-verify-number-of-tasks.yaml new file mode 100644 index 0000000000..ff5d480d38 --- /dev/null +++ b/test/integration/app-one-taskdefinition-not-found/01-teststep-verify-number-of-tasks.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1 +kind: TestStep +commands: + - script: ../common-scripts/verify-number-of-resources.sh "keptntask" "1" diff --git a/test/integration/common-scripts/verify-number-of-resources.sh b/test/integration/common-scripts/verify-number-of-resources.sh new file mode 100755 index 0000000000..9dd71b7e5b --- /dev/null +++ b/test/integration/common-scripts/verify-number-of-resources.sh @@ -0,0 +1,26 @@ +#!/bin/bash + + RETRY_COUNT=3 + SLEEP_TIME=5 + RESOURCE_TYPE=$1 + EXPECTED_NUMBER=$2 + + for i in $(seq 1 $RETRY_COUNT); do + NR_RESOURCES=$(kubectl get ${RESOURCE_TYPE} -n ${NAMESPACE} --no-headers | wc -l) + + if [[ ${NR_RESOURCES} -eq ${EXPECTED_NUMBER} ]]; then + echo "Found expected number of ${RESOURCE_TYPE}: ${EXPECTED_NUMBER}" + exit 0 + else + echo "Number of ${RESOURCE_TYPE} is not equal to ${EXPECTED_NUMBER}" + fi + + if [ "$i" -lt "$RETRY_COUNT" ]; then + echo "Sleeping for ${SLEEP_TIME} seconds before retrying..." + sleep ${SLEEP_TIME} + fi + done + + echo "Retried ${RETRY_COUNT} times, but expected number of ${RESOURCE_TYPE} could not be verified. Exiting..." + exit 1 + diff --git a/test/integration/simple-task/01-teststep.yaml b/test/integration/simple-task/01-teststep.yaml index 74c9ca1b55..7e58f561ff 100644 --- a/test/integration/simple-task/01-teststep.yaml +++ b/test/integration/simple-task/01-teststep.yaml @@ -1,4 +1,4 @@ apiVersion: kuttl.dev/v1 kind: TestStep commands: - - script: ./verify-tasks.sh + - script: ../common-scripts/verify-number-of-resources.sh "job" "1" diff --git a/test/integration/simple-task/verify-tasks.sh b/test/integration/simple-task/verify-tasks.sh deleted file mode 100755 index 481b09736f..0000000000 --- a/test/integration/simple-task/verify-tasks.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -RETRY_COUNT=3 -SLEEP_TIME=5 - -for i in $(seq 1 $RETRY_COUNT); do - NR_JOBS=$(kubectl get jobs -n ${NAMESPACE} --no-headers | wc -l) - - if [[ ${NR_JOBS} -eq 1 ]]; then - echo "Found exactly 1 job" - exit 0 - else - echo "Number of jobs is not equal to 1" - fi - - if [ "$i" -lt "$RETRY_COUNT" ]; then - echo "Sleeping for ${SLEEP_TIME} seconds before retrying..." - sleep ${SLEEP_TIME} - fi -done - -echo "Retried ${RETRY_COUNT} times, but expected number of resources could not be verified. Exiting..." -exit 1