From facd56fd4fb57630362c514861f1789fcc2b6013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E5=85=83?= Date: Fri, 2 Jul 2021 15:06:34 +0800 Subject: [PATCH] improve workflow docs and update workflow API --- apis/core.oam.dev/common/types.go | 7 +- .../common/zz_generated.deepcopy.go | 24 ++- .../core.oam.dev/v1beta1/application_types.go | 7 +- .../v1beta1/zz_generated.deepcopy.go | 28 +++- .../core.oam.dev_applicationrevisions.yaml | 147 ++++++++++-------- .../crds/core.oam.dev_applications.yaml | 147 ++++++++++-------- .../crds/core.oam.dev_initializers.yaml | 90 ++++++----- design/vela-core/workflow_policy.md | 50 ++++-- .../core.oam.dev_applicationrevisions.yaml | 147 ++++++++++-------- .../crds/core.oam.dev_applications.yaml | 147 ++++++++++-------- .../crds/core.oam.dev_initializers.yaml | 90 ++++++----- pkg/appfile/parser.go | 6 +- .../v1alpha2/application/apply.go | 2 +- .../v1alpha2/application/workflow_test.go | 20 +-- pkg/workflow/workflow.go | 11 +- pkg/workflow/workflow_test.go | 8 +- 16 files changed, 530 insertions(+), 401 deletions(-) diff --git a/apis/core.oam.dev/common/types.go b/apis/core.oam.dev/common/types.go index 7003b200e..0fb3a2d80 100644 --- a/apis/core.oam.dev/common/types.go +++ b/apis/core.oam.dev/common/types.go @@ -213,6 +213,11 @@ type WorkflowStepStatus struct { ResourceRef runtimev1alpha1.TypedReference `json:"resourceRef,omitempty"` } +// WorkflowStatus record the status of workflow +type WorkflowStatus struct { + Steps []WorkflowStepStatus `json:"steps,omitempty"` +} + // AppStatus defines the observed state of Application type AppStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster @@ -233,7 +238,7 @@ type AppStatus struct { ResourceTracker *runtimev1alpha1.TypedReference `json:"resourceTracker,omitempty"` // Workflow record the status of workflow steps - Workflow []WorkflowStepStatus `json:"workflow,omitempty"` + Workflow *WorkflowStatus `json:"workflow,omitempty"` // LatestRevision of the application configuration it generates // +optional diff --git a/apis/core.oam.dev/common/zz_generated.deepcopy.go b/apis/core.oam.dev/common/zz_generated.deepcopy.go index 50c229c7d..97503b252 100644 --- a/apis/core.oam.dev/common/zz_generated.deepcopy.go +++ b/apis/core.oam.dev/common/zz_generated.deepcopy.go @@ -64,8 +64,8 @@ func (in *AppStatus) DeepCopyInto(out *AppStatus) { } if in.Workflow != nil { in, out := &in.Workflow, &out.Workflow - *out = make([]WorkflowStepStatus, len(*in)) - copy(*out, *in) + *out = new(WorkflowStatus) + (*in).DeepCopyInto(*out) } if in.LatestRevision != nil { in, out := &in.LatestRevision, &out.LatestRevision @@ -343,6 +343,26 @@ func (in *Terraform) DeepCopy() *Terraform { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkflowStatus) DeepCopyInto(out *WorkflowStatus) { + *out = *in + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]WorkflowStepStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowStatus. +func (in *WorkflowStatus) DeepCopy() *WorkflowStatus { + if in == nil { + return nil + } + out := new(WorkflowStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkflowStepStatus) DeepCopyInto(out *WorkflowStepStatus) { *out = *in diff --git a/apis/core.oam.dev/v1beta1/application_types.go b/apis/core.oam.dev/v1beta1/application_types.go index c8c9b467e..504b63601 100644 --- a/apis/core.oam.dev/v1beta1/application_types.go +++ b/apis/core.oam.dev/v1beta1/application_types.go @@ -71,6 +71,11 @@ type WorkflowStep struct { Properties runtime.RawExtension `json:"properties,omitempty"` } +// Workflow defines workflow steps and other attributes +type Workflow struct { + Steps []WorkflowStep `json:"steps,omitempty"` +} + // ApplicationSpec is the spec of Application type ApplicationSpec struct { Components []ApplicationComponent `json:"components"` @@ -85,7 +90,7 @@ type ApplicationSpec struct { // Workflow steps are executed in array order, and each step: // - will have a context in annotation. // - should mark "finish" phase in status.conditions. - Workflow []WorkflowStep `json:"workflow,omitempty"` + Workflow *Workflow `json:"workflow,omitempty"` // TODO(wonderflow): we should have application level scopes supported here diff --git a/apis/core.oam.dev/v1beta1/zz_generated.deepcopy.go b/apis/core.oam.dev/v1beta1/zz_generated.deepcopy.go index 49798b161..724018811 100644 --- a/apis/core.oam.dev/v1beta1/zz_generated.deepcopy.go +++ b/apis/core.oam.dev/v1beta1/zz_generated.deepcopy.go @@ -473,10 +473,8 @@ func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) { } if in.Workflow != nil { in, out := &in.Workflow, &out.Workflow - *out = make([]WorkflowStep, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + *out = new(Workflow) + (*in).DeepCopyInto(*out) } if in.RolloutPlan != nil { in, out := &in.RolloutPlan, &out.RolloutPlan @@ -1523,6 +1521,28 @@ func (in *WeightedTarget) DeepCopy() *WeightedTarget { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Workflow) DeepCopyInto(out *Workflow) { + *out = *in + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]WorkflowStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workflow. +func (in *Workflow) DeepCopy() *Workflow { + if in == nil { + return nil + } + out := new(Workflow) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkflowStep) DeepCopyInto(out *WorkflowStep) { *out = *in diff --git a/charts/vela-core/crds/core.oam.dev_applicationrevisions.yaml b/charts/vela-core/crds/core.oam.dev_applicationrevisions.yaml index 1043f1d74..8966902f9 100644 --- a/charts/vela-core/crds/core.oam.dev_applicationrevisions.yaml +++ b/charts/vela-core/crds/core.oam.dev_applicationrevisions.yaml @@ -544,38 +544,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object applicationConfiguration: @@ -1566,22 +1569,25 @@ spec: type: object workflow: description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.' - items: - description: WorkflowStep defines how to execute a workflow step. - properties: - name: - description: Name is the unique name of the workflow step. - type: string - properties: + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + name: + description: Name is the unique name of the workflow step. + type: string + properties: + type: object + x-kubernetes-preserve-unknown-fields: true + type: + type: string + required: + - name + - type type: object - x-kubernetes-preserve-unknown-fields: true - type: - type: string - required: - - name - - type - type: object - type: array + type: array + type: object required: - components type: object @@ -1819,38 +1825,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object applicationConfiguration: diff --git a/charts/vela-core/crds/core.oam.dev_applications.yaml b/charts/vela-core/crds/core.oam.dev_applications.yaml index 7592b55d5..c21b58fa8 100644 --- a/charts/vela-core/crds/core.oam.dev_applications.yaml +++ b/charts/vela-core/crds/core.oam.dev_applications.yaml @@ -556,38 +556,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object served: true @@ -903,22 +906,25 @@ spec: type: object workflow: description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.' - items: - description: WorkflowStep defines how to execute a workflow step. - properties: - name: - description: Name is the unique name of the workflow step. - type: string - properties: + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + name: + description: Name is the unique name of the workflow step. + type: string + properties: + type: object + x-kubernetes-preserve-unknown-fields: true + type: + type: string + required: + - name + - type type: object - x-kubernetes-preserve-unknown-fields: true - type: - type: string - required: - - name - - type - type: object - type: array + type: array + type: object required: - components type: object @@ -1156,38 +1162,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object served: true diff --git a/charts/vela-core/crds/core.oam.dev_initializers.yaml b/charts/vela-core/crds/core.oam.dev_initializers.yaml index e5c40e9ef..4edd5dedf 100644 --- a/charts/vela-core/crds/core.oam.dev_initializers.yaml +++ b/charts/vela-core/crds/core.oam.dev_initializers.yaml @@ -323,22 +323,25 @@ spec: type: object workflow: description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.' - items: - description: WorkflowStep defines how to execute a workflow step. - properties: - name: - description: Name is the unique name of the workflow step. - type: string - properties: + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + name: + description: Name is the unique name of the workflow step. + type: string + properties: + type: object + x-kubernetes-preserve-unknown-fields: true + type: + type: string + required: + - name + - type type: object - x-kubernetes-preserve-unknown-fields: true - type: - type: string - required: - - name - - type - type: object - type: array + type: array + type: object required: - components type: object @@ -576,38 +579,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object dependsOn: diff --git a/design/vela-core/workflow_policy.md b/design/vela-core/workflow_policy.md index f2f295714..9e8076aa7 100644 --- a/design/vela-core/workflow_policy.md +++ b/design/vela-core/workflow_policy.md @@ -26,12 +26,14 @@ spec: # Policies are rendered after components are rendered but before workflow are started policies: - type: security + name: my-rule properties: rbac: ... audit: enabled secretBackend: vault - type: deployment-insights + name: my-deploy-insight properties: leadTime: enabled frequency: enabled @@ -43,6 +45,12 @@ spec: # - will have a context in annotation. # - should mark "finish" phase in status.conditions. workflow: + + # suspend can manually stop the workflow and resume. it will also allow suspend policy for workflow. + suspend: + manual: true + + steps: # blue-green rollout - type: blue-green-rollout @@ -127,19 +135,22 @@ To support policies and workflow, the application controller will be modified as } ...more json-marshalled resources... ``` -- If workflow is specified, the controller will then apply the ApplicationRevision, but skip applying ApplicationContext. In this way, the resources won't be applied by Vela controller. +- If workflow is specified, the controller will then apply the ApplicationRevision, but skip applying Resources. + In this way, the resources won't be created by Vela controller. - The controller will then reconcile the workflow step by step. Each workflow step will be recorded in the Application.status: ```yaml kind: Application status: workflow: - - type: rollout-promotion - phase: running # succeeded | failed | stopped - resourceRef: - kind: Rollout - name: ... + steps: + - type: rollout-promotion + phase: running # succeeded | failed | stopped + resourceRef: + kind: Rollout + name: ... ``` -- Note that each workflow step must be idempotent, which means it should be able to process an object that are already submitted and processed. A non-idempotent example would be a controller that keeps appending item to an array field. +- Note that each workflow step must be idempotent, which means it should be able to process an object that are already submitted and processed. + A non-idempotent example would be a controller that keeps appending item to an array field. Each workflow step has the following interactions with the app controller: - The controller will apply the workflow object with annotation `app.oam.dev/workflow-context`. This annotation will pass in the context marshalled in json defined as the following: @@ -175,6 +186,7 @@ In this case, users want to distribute workflow to multiple clusters. The dispat ```yaml workflow: + steps: - type: open-cluster-management properties: placement: @@ -197,6 +209,7 @@ In this case, users want to rollout a new version of the application components ```yaml workflow: + steps: # blue-green rollout - type: blue-green-rollout properties: @@ -232,10 +245,11 @@ The process goes as: kind: Application status: workflow: - - type: rollout-promotion - resourceRef: - kind: Rollout - name: ... + steps: + - type: rollout-promotion + resourceRef: + kind: Rollout + name: ... ``` ### Case 3: Data Passing @@ -253,6 +267,7 @@ components: workflow: + steps: - type: apply-component properties: name: my-db @@ -290,11 +305,12 @@ In this case, users just want Vela to provide final k8s resources and push them ```yaml workflow: -- type: gitops # This part configures how to push resources to Git repo - properties: - gitRepo: git-repo-url - branch: branch - credentials: ... + steps: + - type: gitops # This part configures how to push resources to Git repo + properties: + gitRepo: git-repo-url + branch: branch + credentials: ... ``` The process goes as: @@ -307,6 +323,7 @@ In this case, a template for Application object has already been defined. Instea ```yaml workflow: + steps: - type: helm-template stage: pre-render properties: @@ -317,6 +334,7 @@ workflow: replicas: 3 --- workflow: + steps: - type: kustomize-patch stage: pre-render properties: diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationrevisions.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationrevisions.yaml index d3fd09537..0ce947cfa 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationrevisions.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationrevisions.yaml @@ -546,38 +546,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object applicationConfiguration: @@ -1563,22 +1566,25 @@ spec: type: object workflow: description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.' - items: - description: WorkflowStep defines how to execute a workflow step. - properties: - name: - description: Name is the unique name of the workflow step. - type: string - properties: + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + name: + description: Name is the unique name of the workflow step. + type: string + properties: + type: object + + type: + type: string + required: + - name + - type type: object - - type: - type: string - required: - - name - - type - type: object - type: array + type: array + type: object required: - components type: object @@ -1816,38 +1822,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object applicationConfiguration: diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_applications.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_applications.yaml index f92b5fb31..949d9fab2 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_applications.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_applications.yaml @@ -548,38 +548,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object served: true @@ -874,22 +877,25 @@ spec: type: object workflow: description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.' - items: - description: WorkflowStep defines how to execute a workflow step. - properties: - name: - description: Name is the unique name of the workflow step. - type: string - properties: + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + name: + description: Name is the unique name of the workflow step. + type: string + properties: + type: object + + type: + type: string + required: + - name + - type type: object - - type: - type: string - required: - - name - - type - type: object - type: array + type: array + type: object required: - components type: object @@ -1127,38 +1133,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object served: true diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_initializers.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_initializers.yaml index 98de5a4a1..4fa212d55 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_initializers.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_initializers.yaml @@ -323,22 +323,25 @@ spec: type: object workflow: description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.' - items: - description: WorkflowStep defines how to execute a workflow step. - properties: - name: - description: Name is the unique name of the workflow step. - type: string - properties: + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + name: + description: Name is the unique name of the workflow step. + type: string + properties: + type: object + + type: + type: string + required: + - name + - type type: object - - type: - type: string - required: - - name - - type - type: object - type: array + type: array + type: object required: - components type: object @@ -576,38 +579,41 @@ spec: type: string workflow: description: Workflow record the status of workflow steps - items: - description: WorkflowStepStatus record the status of a workflow step - properties: - name: - type: string - phase: - description: WorkflowStepPhase describes the phase of a workflow step. - type: string - resourceRef: - description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + steps: + items: + description: WorkflowStepStatus record the status of a workflow step properties: - apiVersion: - description: APIVersion of the referenced object. - type: string - kind: - description: Kind of the referenced object. - type: string name: - description: Name of the referenced object. type: string - uid: - description: UID of the referenced object. + phase: + description: WorkflowStepPhase describes the phase of a workflow step. + type: string + resourceRef: + description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known. + properties: + apiVersion: + description: APIVersion of the referenced object. + type: string + kind: + description: Kind of the referenced object. + type: string + name: + description: Name of the referenced object. + type: string + uid: + description: UID of the referenced object. + type: string + required: + - apiVersion + - kind + - name + type: object + type: type: string - required: - - apiVersion - - kind - - name type: object - type: - type: string - type: object - type: array + type: array + type: object type: object type: object dependsOn: diff --git a/pkg/appfile/parser.go b/pkg/appfile/parser.go index 960be54c5..1523b2d01 100644 --- a/pkg/appfile/parser.go +++ b/pkg/appfile/parser.go @@ -134,7 +134,11 @@ func (p *Parser) parsePolicies(ctx context.Context, policies []v1beta1.AppPolicy return ws, nil } -func (p *Parser) parseWorkflow(ctx context.Context, steps []v1beta1.WorkflowStep) ([]*Workload, error) { +func (p *Parser) parseWorkflow(ctx context.Context, workflow *v1beta1.Workflow) ([]*Workload, error) { + if workflow == nil { + return []*Workload{}, nil + } + steps := workflow.Steps ws := []*Workload{} for _, step := range steps { w, err := p.makeWorkload(ctx, step.Name, step.Type, types.TypeWorkflowStep, step.Properties) diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/apply.go b/pkg/controller/core.oam.dev/v1alpha2/application/apply.go index 2a988b894..0f5a8d1aa 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/apply.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/apply.go @@ -70,7 +70,7 @@ func (h *appHandler) handleErr(err error) (ctrl.Result, error) { func (h *appHandler) applyAppManifests(ctx context.Context, comps []*types.ComponentManifest, policies []*unstructured.Unstructured) error { appRev := h.currentAppRev - if h.app.Spec.Workflow != nil || h.app.Annotations[oam.AnnotationAppRevisionOnly] == "true" { + if (h.app.Spec.Workflow != nil && len(h.app.Spec.Workflow.Steps) > 0) || h.app.Annotations[oam.AnnotationAppRevisionOnly] == "true" { return h.createResourcesConfigMap(ctx, appRev, comps, policies) } if appWillRollout(h.app) { diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/workflow_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/workflow_test.go index cc7b30866..8f65eeffb 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/workflow_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/workflow_test.go @@ -56,15 +56,17 @@ var _ = Describe("Test Workflow", func() { Type: "worker", Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)}, }}, - Workflow: []oamcore.WorkflowStep{{ - Name: "test-wf1", - Type: "foowf", - Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)}, - }, { - Name: "test-wf2", - Type: "foowf", - Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)}, - }}, + Workflow: &oamcore.Workflow{ + Steps: []oamcore.WorkflowStep{{ + Name: "test-wf1", + Type: "foowf", + Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)}, + }, { + Name: "test-wf2", + Type: "foowf", + Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)}, + }}, + }, }, } appWithWorkflowAndPolicy := appWithWorkflow.DeepCopy() diff --git a/pkg/workflow/workflow.go b/pkg/workflow/workflow.go index c3d959e82..f919ab451 100644 --- a/pkg/workflow/workflow.go +++ b/pkg/workflow/workflow.go @@ -48,15 +48,20 @@ func NewWorkflow(app *oamcore.Application, applicator apply.Applicator) Workflow } func (w *workflow) ExecuteSteps(ctx context.Context, rev string, objects []*unstructured.Unstructured) (bool, error) { - steps := w.app.Spec.Workflow + if w.app.Spec.Workflow == nil { + return true, nil + } + steps := w.app.Spec.Workflow.Steps if len(steps) == 0 { return true, nil } w.app.Status.Phase = common.ApplicationRunningWorkflow - w.app.Status.Workflow = []common.WorkflowStepStatus{} + w.app.Status.Workflow = &common.WorkflowStatus{ + Steps: []common.WorkflowStepStatus{}, + } for i, step := range steps { obj := objects[i].DeepCopy() obj.SetName(step.Name) @@ -81,7 +86,7 @@ func (w *workflow) ExecuteSteps(ctx context.Context, rev string, objects []*unst return false, err } - w.app.Status.Workflow = append(w.app.Status.Workflow, *status) + w.app.Status.Workflow.Steps = append(w.app.Status.Workflow.Steps, *status) switch status.Phase { case common.WorkflowStepPhaseSucceeded: // This one is done. Continue case common.WorkflowStepPhaseRunning: // Need to retry shortly. diff --git a/pkg/workflow/workflow_test.go b/pkg/workflow/workflow_test.go index 9dcf8a446..e2da44cbf 100644 --- a/pkg/workflow/workflow_test.go +++ b/pkg/workflow/workflow_test.go @@ -38,18 +38,20 @@ func TestExecuteSteps(t *testing.T) { Namespace: "test", }, Spec: oamcore.ApplicationSpec{ - Workflow: []oamcore.WorkflowStep{}, + Workflow: &oamcore.Workflow{ + Steps: []oamcore.WorkflowStep{}, + }, }, } onestepApp := zerostepApp.DeepCopy() - onestepApp.Spec.Workflow = []oamcore.WorkflowStep{{ + onestepApp.Spec.Workflow.Steps = []oamcore.WorkflowStep{{ Name: "test", Type: "test", }} twostepsApp := onestepApp.DeepCopy() - twostepsApp.Spec.Workflow = append(twostepsApp.Spec.Workflow, oamcore.WorkflowStep{ + twostepsApp.Spec.Workflow.Steps = append(twostepsApp.Spec.Workflow.Steps, oamcore.WorkflowStep{ Name: "test2", Type: "test2", })