mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
* Feat: add pending phase in workflow step Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com> * fix test Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com> * fix lint Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com> * fix test Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2351 lines
70 KiB
Go
2351 lines
70 KiB
Go
/*
|
|
Copyright 2021 The KubeVela Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package workflow
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/pkg/errors"
|
|
corev1 "k8s.io/api/core/v1"
|
|
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
"sigs.k8s.io/yaml"
|
|
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
|
oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
|
"github.com/oam-dev/kubevela/pkg/cue/model/value"
|
|
"github.com/oam-dev/kubevela/pkg/features"
|
|
monitorContext "github.com/oam-dev/kubevela/pkg/monitor/context"
|
|
wfContext "github.com/oam-dev/kubevela/pkg/workflow/context"
|
|
"github.com/oam-dev/kubevela/pkg/workflow/tasks"
|
|
wfTypes "github.com/oam-dev/kubevela/pkg/workflow/types"
|
|
)
|
|
|
|
var _ = Describe("Test Workflow", func() {
|
|
|
|
BeforeEach(func() {
|
|
cm := &corev1.ConfigMap{}
|
|
revJson, err := yaml.YAMLToJSON([]byte(revYaml))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = json.Unmarshal(revJson, cm)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = k8sClient.Create(context.Background(), cm)
|
|
if err != nil && !kerrors.IsAlreadyExists(err) {
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
|
|
})
|
|
It("Workflow test for failed", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "failed",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateExecuting),
|
|
Steps: []common.WorkflowStepStatus{
|
|
{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "failed",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
},
|
|
},
|
|
},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
|
|
app.Status.Workflow = workflowStatus
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
app.Status.Workflow.Finished = true
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateSucceeded),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test failed with sub steps", func() {
|
|
By("Test failed with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "failed",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateExecuting),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "failed",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
},
|
|
}},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test for timeout", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
If: "status.s1.succeeded",
|
|
Type: "running",
|
|
Timeout: "1s",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s4",
|
|
If: "status.s2.timeout",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
time.Sleep(1 * time.Second)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateTerminated),
|
|
Terminated: true,
|
|
Steps: []common.WorkflowStepStatus{
|
|
{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "running",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s4",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
},
|
|
},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test for timeout with suspend", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
If: "status.s1.timeout",
|
|
Type: "suspend",
|
|
Timeout: "1s",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s4",
|
|
If: "status.s1.succeeded",
|
|
Type: "suspend",
|
|
Timeout: "1s",
|
|
},
|
|
{
|
|
Name: "s5",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
time.Sleep(1 * time.Second)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateTerminated),
|
|
Terminated: true,
|
|
Steps: []common.WorkflowStepStatus{
|
|
{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s4",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s5",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
},
|
|
},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test for timeout with sub steps", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "running",
|
|
Timeout: "1s",
|
|
},
|
|
{
|
|
Name: "s2-suspend",
|
|
Type: "suspend",
|
|
Timeout: "1s",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
time.Sleep(1 * time.Second)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateTerminated),
|
|
Terminated: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "running",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-suspend",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
}},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Timeout: "1s",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "running",
|
|
},
|
|
{
|
|
Name: "s2-suspend",
|
|
Type: "suspend",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
time.Sleep(1 * time.Second)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
workflowStatus = app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateTerminated),
|
|
Terminated: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "running",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-suspend",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
},
|
|
}},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test skipped with sub steps", func() {
|
|
By("Test skipped with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "failed-after-retries",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "failed",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Terminated: true,
|
|
Message: string(MessageTerminatedFailedAfterRetries),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "failed",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test if-always with sub steps", func() {
|
|
By("Test if-always with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "failed-after-retries",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
If: "always",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
DependsOn: []string{"s2-sub2"},
|
|
If: "always",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Terminated: true,
|
|
Message: string(MessageTerminatedFailedAfterRetries),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test success with sub steps", func() {
|
|
By("Test success with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "success",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateSucceeded),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
By("Test success with step group and empty subSteps")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateSucceeded),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test for failed after retries with suspend", func() {
|
|
By("Test failed-after-retries in StepByStep mode with suspend")
|
|
defer featuregatetesting.SetFeatureGateDuringTest(&testing.T{}, utilfeature.DefaultFeatureGate, features.EnableSuspendOnFailure, true)()
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: MessageSuspendFailedAfterRetries,
|
|
Suspend: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
By("Test failed-after-retries in DAG mode with suspend")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
workflowStatus = app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeDAG,
|
|
Message: MessageSuspendFailedAfterRetries,
|
|
Suspend: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test if always", func() {
|
|
By("Test if always in StepByStep mode")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
If: "always",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s4",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s5",
|
|
If: "always",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: MessageTerminatedFailedAfterRetries,
|
|
Suspend: false,
|
|
Terminated: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s4",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s5",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
By("Test if always in DAG mode")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
DependsOn: []string{"s2"},
|
|
If: "always",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s4",
|
|
DependsOn: []string{"s3"},
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s5",
|
|
DependsOn: []string{"s3"},
|
|
If: "always",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s6",
|
|
DependsOn: []string{"s1", "s5"},
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
workflowStatus = app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeDAG,
|
|
Message: MessageTerminatedFailedAfterRetries,
|
|
Terminated: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s4",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s5",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s6",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test if expressions", func() {
|
|
By("Test if expressions in StepByStep mode")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
If: "status.s1.failed",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
If: "status.s1.succeeded",
|
|
Type: "success",
|
|
Outputs: common.StepOutputs{
|
|
{
|
|
Name: "test",
|
|
ValueFrom: "context.name",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s4",
|
|
Inputs: common.StepInputs{
|
|
{
|
|
From: "test",
|
|
ParameterKey: "",
|
|
},
|
|
},
|
|
If: `inputs.test == "app"`,
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
workflowStatus := app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: "Succeeded",
|
|
Suspend: false,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s4",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
By("Test if expressions in DAG mode")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
If: "status.s1.failed",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
DependsOn: []string{"s2"},
|
|
If: "status.s1.succeeded",
|
|
Type: "success",
|
|
Outputs: common.StepOutputs{
|
|
{
|
|
Name: "test",
|
|
ValueFrom: "context.name",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s4",
|
|
DependsOn: []string{"s3"},
|
|
Inputs: common.StepInputs{
|
|
{
|
|
From: "test",
|
|
ParameterKey: "",
|
|
},
|
|
},
|
|
If: `inputs.test == "app"`,
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
workflowStatus = app.Status.Workflow
|
|
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + app.Name + "-context"))
|
|
workflowStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(workflowStatus)
|
|
Expect(cmp.Diff(*workflowStatus, common.WorkflowStatus{
|
|
AppRevision: workflowStatus.AppRevision,
|
|
Mode: common.WorkflowModeDAG,
|
|
Message: "Succeeded",
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s4",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Workflow test if expressions with sub steps", func() {
|
|
By("Test if expressions with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
If: "status.s1.timeout",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2_sub1",
|
|
If: "always",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2_sub2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
If: "status.s1.succeeded",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s3_sub1",
|
|
If: "status.s2_sub1.skipped",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s3_sub2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
},
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Terminated: true,
|
|
Message: string(MessageTerminatedFailedAfterRetries),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2_sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2_sub2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
},
|
|
}},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3_sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3_sub2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Test failed after retries with sub steps", func() {
|
|
By("Test failed-after-retries with step group in StepByStep mode")
|
|
defer featuregatetesting.SetFeatureGateDuringTest(&testing.T{}, utilfeature.DefaultFeatureGate, features.EnableSuspendOnFailure, true)()
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "failed-after-retries",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: MessageSuspendFailedAfterRetries,
|
|
Suspend: true,
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
},
|
|
}},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("Test get backoff time and clean", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "wait-with-set-var",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
wfCtx, err := wfContext.LoadContext(k8sClient, app.Namespace, app.Name)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
e := &engine{
|
|
status: app.Status.Workflow,
|
|
wfCtx: wfCtx,
|
|
}
|
|
interval := e.getBackoffWaitTime()
|
|
Expect(interval).Should(BeEquivalentTo(minWorkflowBackoffWaitTime))
|
|
|
|
By("Test get backoff time")
|
|
for i := 0; i < 4; i++ {
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
interval := e.getBackoffWaitTime()
|
|
Expect(interval).Should(BeEquivalentTo(minWorkflowBackoffWaitTime))
|
|
}
|
|
|
|
for i := 0; i < 6; i++ {
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
interval := e.getBackoffWaitTime()
|
|
Expect(interval).Should(BeEquivalentTo(int(0.05 * math.Pow(2, float64(i+5)))))
|
|
}
|
|
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
interval = e.getBackoffWaitTime()
|
|
Expect(interval).Should(BeEquivalentTo(wfTypes.MaxWorkflowWaitBackoffTime))
|
|
|
|
By("Test get backoff time after clean")
|
|
wfContext.CleanupMemoryStore(app.Name, app.Namespace)
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
wfCtx, err = wfContext.LoadContext(k8sClient, app.Namespace, app.Name)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
e = &engine{
|
|
status: app.Status.Workflow,
|
|
wfCtx: wfCtx,
|
|
}
|
|
interval = e.getBackoffWaitTime()
|
|
Expect(interval).Should(BeEquivalentTo(minWorkflowBackoffWaitTime))
|
|
})
|
|
|
|
It("Test get backoff time with timeout", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Timeout: "30s",
|
|
Type: "wait-with-set-var",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
By("Test get backoff time")
|
|
for i := 0; i < 10; i++ {
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
|
|
Expect(int(math.Ceil(wf.GetBackoffWaitTime().Seconds()))).Should(Equal(30))
|
|
})
|
|
|
|
It("Test get suspend backoff time", func() {
|
|
By("if there's no timeout and duration, return 0")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "suspend",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(int(math.Ceil(wf.GetSuspendBackoffWaitTime().Seconds()))).Should(Equal(0))
|
|
|
|
By("return timeout if it's specified")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "suspend",
|
|
Timeout: "1m",
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(int(math.Ceil(wf.GetSuspendBackoffWaitTime().Seconds()))).Should(Equal(60))
|
|
|
|
By("return duration if it's specified")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "suspend",
|
|
Properties: &runtime.RawExtension{Raw: []byte(`{"duration":"30s"}`)},
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(int(math.Ceil(wf.GetSuspendBackoffWaitTime().Seconds()))).Should(Equal(30))
|
|
|
|
By("return the minimum of the timeout and duration")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "suspend",
|
|
Timeout: "1m",
|
|
Properties: &runtime.RawExtension{Raw: []byte(`{"duration":"30s"}`)},
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(int(math.Ceil(wf.GetSuspendBackoffWaitTime().Seconds()))).Should(Equal(30))
|
|
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "suspend",
|
|
Timeout: "30s",
|
|
Properties: &runtime.RawExtension{Raw: []byte(`{"duration":"1m"}`)},
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(int(math.Ceil(wf.GetSuspendBackoffWaitTime().Seconds()))).Should(Equal(30))
|
|
|
|
By("return 0 if the value is invalid")
|
|
app, runners = makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "suspend",
|
|
Timeout: "test",
|
|
},
|
|
})
|
|
ctx = monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf = NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(int(math.Ceil(wf.GetSuspendBackoffWaitTime().Seconds()))).Should(Equal(0))
|
|
})
|
|
|
|
It("test for suspend", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "suspend",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
wfStatus := *app.Status.Workflow
|
|
wfStatus.ContextBackend = nil
|
|
cleanStepTimeStamp(&wfStatus)
|
|
Expect(cmp.Diff(wfStatus, common.WorkflowStatus{
|
|
AppRevision: wfStatus.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Suspend: true,
|
|
Message: string(common.WorkflowStateSuspended),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
// check suspend...
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
|
|
// check resume
|
|
app.Status.Workflow.Suspend = false
|
|
app.Status.Workflow.Steps[1].Phase = common.WorkflowStepPhaseSucceeded
|
|
// check app meta changed
|
|
app.Labels = map[string]string{"for-test": "changed"}
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateSucceeded),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
})
|
|
|
|
It("test for suspend with sub steps", func() {
|
|
By("Test suspend with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "suspend",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Suspend: true,
|
|
Message: string(common.WorkflowStateSuspended),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
},
|
|
}},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("test for terminate", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "terminate",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Terminated: true,
|
|
Message: string(common.WorkflowStateTerminated),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "terminate",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
})
|
|
|
|
It("test for terminate with sub steps", func() {
|
|
|
|
By("Test terminate with step group")
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
SubSteps: []common.WorkflowSubStep{
|
|
{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2-sub2",
|
|
Type: "terminate",
|
|
},
|
|
},
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Terminated: true,
|
|
Message: string(common.WorkflowStateTerminated),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "step-group",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
SubStepsStatus: []common.WorkflowSubStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2-sub2",
|
|
Type: "terminate",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
|
|
})
|
|
|
|
It("test for error", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "error",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeStep,
|
|
Message: string(common.WorkflowStateExecuting),
|
|
Steps: []common.WorkflowStepStatus{{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("skip workflow", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateFinished))
|
|
})
|
|
|
|
It("test for DAG", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "success",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "pending",
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Type: "success",
|
|
},
|
|
})
|
|
pending = true
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeDAG, false, nil)
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeDAG,
|
|
Message: string(common.WorkflowStateExecuting),
|
|
Steps: []common.WorkflowStepStatus{
|
|
{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "pending",
|
|
Phase: common.WorkflowStepPhasePending,
|
|
},
|
|
},
|
|
},
|
|
})).Should(BeEquivalentTo(""))
|
|
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
|
|
pending = false
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSucceeded))
|
|
app.Status.Workflow.ContextBackend = nil
|
|
cleanStepTimeStamp(app.Status.Workflow)
|
|
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
|
|
AppRevision: app.Status.Workflow.AppRevision,
|
|
Mode: common.WorkflowModeDAG,
|
|
Message: string(common.WorkflowStateSucceeded),
|
|
Steps: []common.WorkflowStepStatus{
|
|
{
|
|
StepStatus: common.StepStatus{
|
|
Name: "s1",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s3",
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
}, {
|
|
StepStatus: common.StepStatus{
|
|
Name: "s2",
|
|
Type: "pending",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
},
|
|
},
|
|
},
|
|
})).Should(BeEquivalentTo(""))
|
|
})
|
|
|
|
It("step commit data without success", func() {
|
|
app, runners := makeTestCase([]oamcore.WorkflowStep{
|
|
{
|
|
Name: "s1",
|
|
Type: "wait-with-set-var",
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Type: "success",
|
|
},
|
|
})
|
|
ctx := monitorContext.NewTraceContext(context.Background(), "test-app")
|
|
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep, false, nil)
|
|
state, err := wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateInitializing))
|
|
state, err = wf.ExecuteSteps(ctx, revision, runners)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
|
|
Expect(app.Status.Workflow.Steps[0].Phase).Should(BeEquivalentTo(common.WorkflowStepPhaseRunning))
|
|
wfCtx, err := wfContext.LoadContext(k8sClient, app.Namespace, app.Name)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
v, err := wfCtx.GetVar("saved")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
saved, err := v.CueValue().Bool()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(saved).Should(BeEquivalentTo(true))
|
|
})
|
|
})
|
|
|
|
func makeTestCase(steps []oamcore.WorkflowStep) (*oamcore.Application, []wfTypes.TaskRunner) {
|
|
app := &oamcore.Application{
|
|
ObjectMeta: metav1.ObjectMeta{UID: "test-uid"},
|
|
Spec: oamcore.ApplicationSpec{
|
|
Workflow: &oamcore.Workflow{
|
|
Steps: steps,
|
|
},
|
|
},
|
|
Status: common.AppStatus{},
|
|
}
|
|
app.Namespace = "default"
|
|
app.Name = "app"
|
|
runners := []wfTypes.TaskRunner{}
|
|
for _, step := range steps {
|
|
if step.SubSteps != nil {
|
|
subStepRunners := []wfTypes.TaskRunner{}
|
|
for _, subStep := range step.SubSteps {
|
|
step := oamcore.WorkflowStep{
|
|
Name: subStep.Name,
|
|
Type: subStep.Type,
|
|
If: subStep.If,
|
|
Timeout: subStep.Timeout,
|
|
DependsOn: subStep.DependsOn,
|
|
}
|
|
subStepRunners = append(subStepRunners, makeRunner(step, nil))
|
|
}
|
|
runners = append(runners, makeRunner(step, subStepRunners))
|
|
} else {
|
|
runners = append(runners, makeRunner(step, nil))
|
|
}
|
|
}
|
|
return app, runners
|
|
}
|
|
|
|
var pending bool
|
|
|
|
func makeRunner(step oamcore.WorkflowStep, subTaskRunners []wfTypes.TaskRunner) wfTypes.TaskRunner {
|
|
var run func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error)
|
|
switch step.Type {
|
|
case "suspend":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "suspend",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
}, &wfTypes.Operation{
|
|
Suspend: true,
|
|
}, nil
|
|
}
|
|
case "terminate":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "terminate",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
}, &wfTypes.Operation{
|
|
Terminated: true,
|
|
}, nil
|
|
}
|
|
case "success":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
v, err := value.NewValue(`"app"`, nil, "")
|
|
if err != nil {
|
|
return common.StepStatus{}, nil, err
|
|
}
|
|
if err := ctx.SetVar(v, "test"); err != nil {
|
|
return common.StepStatus{}, nil, err
|
|
}
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "success",
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
}, &wfTypes.Operation{}, nil
|
|
}
|
|
case "failed":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "failed",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
}, &wfTypes.Operation{}, nil
|
|
}
|
|
case "failed-after-retries":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "failed-after-retries",
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonFailedAfterRetries,
|
|
}, &wfTypes.Operation{
|
|
FailedAfterRetries: true,
|
|
}, nil
|
|
}
|
|
case "error":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "error",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
}, &wfTypes.Operation{}, errors.New("error for test")
|
|
}
|
|
case "wait-with-set-var":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
v, _ := value.NewValue(`saved: true`, nil, "")
|
|
err := ctx.SetVar(v)
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "wait-with-set-var",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
}, &wfTypes.Operation{}, err
|
|
}
|
|
case "step-group":
|
|
group, _ := tasks.StepGroup(step, &wfTypes.GeneratorOptions{SubTaskRunners: subTaskRunners})
|
|
run = group.Run
|
|
case "running":
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: "running",
|
|
Phase: common.WorkflowStepPhaseRunning,
|
|
}, &wfTypes.Operation{}, nil
|
|
}
|
|
default:
|
|
run = func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
return common.StepStatus{
|
|
Name: step.Name,
|
|
Type: step.Type,
|
|
Phase: common.WorkflowStepPhaseSucceeded,
|
|
}, &wfTypes.Operation{}, nil
|
|
}
|
|
|
|
}
|
|
return &testTaskRunner{
|
|
step: step,
|
|
run: run,
|
|
checkPending: func(ctx wfContext.Context, stepStatus map[string]common.StepStatus) (bool, common.StepStatus) {
|
|
if step.Type != "pending" {
|
|
return false, common.StepStatus{}
|
|
}
|
|
if pending == true {
|
|
return true, common.StepStatus{
|
|
Phase: common.WorkflowStepPhasePending,
|
|
Name: step.Name,
|
|
Type: step.Type,
|
|
}
|
|
}
|
|
return false, common.StepStatus{}
|
|
},
|
|
}
|
|
}
|
|
|
|
var (
|
|
revYaml = `apiVersion: v1
|
|
data:
|
|
components: '{"server":"{\"Scopes\":null,\"StandardWorkload\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Pod\\\",\\\"metadata\\\":{\\\"labels\\\":{\\\"app\\\":\\\"nginx\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"APP\\\",\\\"value\\\":\\\"nginx\\\"}],\\\"image\\\":\\\"nginx:1.14.2\\\",\\\"imagePullPolicy\\\":\\\"IfNotPresent\\\",\\\"name\\\":\\\"main\\\",\\\"ports\\\":[{\\\"containerPort\\\":8080,\\\"protocol\\\":\\\"TCP\\\"}]}]}}\",\"Traits\":[\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Service\\\",\\\"metadata\\\":{\\\"name\\\":\\\"my-service\\\"},\\\"spec\\\":{\\\"ports\\\":[{\\\"port\\\":80,\\\"protocol\\\":\\\"TCP\\\",\\\"targetPort\\\":8080}],\\\"selector\\\":{\\\"app\\\":\\\"nginx\\\"}}}\"]}"}'
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: app-v1
|
|
namespace: default
|
|
`
|
|
revision = &oamcore.ApplicationRevision{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app-v1",
|
|
},
|
|
}
|
|
)
|
|
|
|
type testTaskRunner struct {
|
|
step oamcore.WorkflowStep
|
|
run func(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error)
|
|
checkPending func(ctx wfContext.Context, stepStatus map[string]common.StepStatus) (bool, common.StepStatus)
|
|
}
|
|
|
|
// Name return step name.
|
|
func (tr *testTaskRunner) Name() string {
|
|
return tr.step.Name
|
|
}
|
|
|
|
// Run execute task.
|
|
func (tr *testTaskRunner) Run(ctx wfContext.Context, options *wfTypes.TaskRunOptions) (common.StepStatus, *wfTypes.Operation, error) {
|
|
if tr.step.Type != "step-group" && options != nil {
|
|
for _, hook := range options.PreCheckHooks {
|
|
result, err := hook(tr.step, &wfTypes.PreCheckOptions{
|
|
ProcessContext: options.PCtx,
|
|
})
|
|
if err != nil {
|
|
return common.StepStatus{}, nil, errors.WithMessage(err, "do preCheckHook")
|
|
}
|
|
if result.Skip {
|
|
return common.StepStatus{
|
|
Name: tr.step.Name,
|
|
Type: tr.step.Type,
|
|
Phase: common.WorkflowStepPhaseSkipped,
|
|
Reason: wfTypes.StatusReasonSkip,
|
|
}, &wfTypes.Operation{Skip: true}, nil
|
|
}
|
|
if result.Timeout {
|
|
return common.StepStatus{
|
|
Name: tr.step.Name,
|
|
Type: tr.step.Type,
|
|
Phase: common.WorkflowStepPhaseFailed,
|
|
Reason: wfTypes.StatusReasonTimeout,
|
|
}, &wfTypes.Operation{Terminated: true}, nil
|
|
}
|
|
}
|
|
}
|
|
return tr.run(ctx, options)
|
|
}
|
|
|
|
// Pending check task should be executed or not.
|
|
func (tr *testTaskRunner) Pending(ctx wfContext.Context, stepStatus map[string]common.StepStatus) (bool, common.StepStatus) {
|
|
return tr.checkPending(ctx, stepStatus)
|
|
}
|
|
|
|
func cleanStepTimeStamp(wfStatus *common.WorkflowStatus) {
|
|
wfStatus.StartTime = metav1.Time{}
|
|
for index, step := range wfStatus.Steps {
|
|
wfStatus.Steps[index].FirstExecuteTime = metav1.Time{}
|
|
wfStatus.Steps[index].LastExecuteTime = metav1.Time{}
|
|
if step.SubStepsStatus != nil {
|
|
for indexSubStep := range step.SubStepsStatus {
|
|
wfStatus.Steps[index].SubStepsStatus[indexSubStep].FirstExecuteTime = metav1.Time{}
|
|
wfStatus.Steps[index].SubStepsStatus[indexSubStep].LastExecuteTime = metav1.Time{}
|
|
}
|
|
}
|
|
}
|
|
}
|