From 64d5dfea00bcd98df0afc507d3bb5ada89269bbf Mon Sep 17 00:00:00 2001 From: FogDong Date: Tue, 12 Jul 2022 00:24:00 +0800 Subject: [PATCH] Feat: add helm chart and dockerfile Signed-off-by: FogDong --- .github/workflows/helm-chart.yaml | 116 +++++ .github/workflows/post-submit.yaml | 82 ++++ Dockerfile | 36 ++ Makefile | 10 +- charts/vela-workflow/.helmignore | 23 + charts/vela-workflow/Chart.yaml | 24 ++ charts/vela-workflow/README.md | 93 ++++ .../crds/core.oam.dev_workflowruns.yaml | 400 ++++++++++++++++++ .../crds/core.oam.dev_workflows.yaml | 164 +++++++ .../core.oam.dev_workflowstepdefinitions.yaml | 275 ++++++++++++ charts/vela-workflow/templates/_helpers.tpl | 74 ++++ .../templates/workflow-controller.yaml | 172 ++++++++ charts/vela-workflow/values.yaml | 148 +++++++ cmd/main.go | 15 +- controllers/workflow_test.go | 23 + controllers/workflowrun_controller.go | 2 + makefiles/dependency.mk | 13 + pkg/executor/workflow.go | 43 +- pkg/steps/generator.go | 2 + 19 files changed, 1678 insertions(+), 37 deletions(-) create mode 100644 .github/workflows/helm-chart.yaml create mode 100644 .github/workflows/post-submit.yaml create mode 100644 Dockerfile create mode 100644 charts/vela-workflow/.helmignore create mode 100644 charts/vela-workflow/Chart.yaml create mode 100644 charts/vela-workflow/README.md create mode 100644 charts/vela-workflow/crds/core.oam.dev_workflowruns.yaml create mode 100644 charts/vela-workflow/crds/core.oam.dev_workflows.yaml create mode 100644 charts/vela-workflow/crds/core.oam.dev_workflowstepdefinitions.yaml create mode 100644 charts/vela-workflow/templates/_helpers.tpl create mode 100644 charts/vela-workflow/templates/workflow-controller.yaml create mode 100644 charts/vela-workflow/values.yaml diff --git a/.github/workflows/helm-chart.yaml b/.github/workflows/helm-chart.yaml new file mode 100644 index 0000000..6fbc0b7 --- /dev/null +++ b/.github/workflows/helm-chart.yaml @@ -0,0 +1,116 @@ +name: HelmChart +on: + push: + tags: + - "v*" + workflow_dispatch: {} + +env: + BUCKET: ${{ secrets.OSS_BUCKET }} + ENDPOINT: ${{ secrets.OSS_ENDPOINT }} + ACCESS_KEY: ${{ secrets.OSS_ACCESS_KEY }} + ACCESS_KEY_SECRET: ${{ secrets.OSS_ACCESS_KEY_SECRET }} + +jobs: + publish-images: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Get the vars + id: vars + run: | + echo ::set-output name=TAG::${GITHUB_REF#refs/tags/} + - name: Login ghcr.io + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Login Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Login Alibaba Cloud ACR + uses: docker/login-action@v1 + with: + registry: kubevela-registry.cn-hangzhou.cr.aliyuncs.com + username: ${{ secrets.ACR_USERNAME }} + password: ${{ secrets.ACR_PASSWORD }} + - uses: docker/setup-qemu-action@v1 + - uses: docker/setup-buildx-action@v1 + with: + driver-opts: image=moby/buildkit:master + + - name: Build & Pushing vela-workflow for ACR + run: | + docker build --build-arg GOPROXY=https://proxy.golang.org -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-workflow:${{ steps.vars.outputs.TAG }} -f ./cmd/apiserver/Dockerfile . + docker push kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-workflow:${{ steps.vars.outputs.TAG }} + - uses: docker/build-push-action@v2 + name: Build & Pushing vela-workflow for Dockerhub and GHCR + with: + context: . + file: ./cmd/apiserver/Dockerfile + labels: |- + org.opencontainers.image.source=https://github.com/${{ github.repository }} + org.opencontainers.image.revision=${{ github.sha }} + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + build-args: | + GOPROXY=https://proxy.golang.org + tags: |- + docker.io/oamdev/vela-workflow:${{ steps.vars.outputs.TAG }} + ghcr.io/${{ github.repository }}/vela-workflow:${{ steps.vars.outputs.TAG }} + publish-charts: + env: + HELM_CHART: charts/ + LOCAL_OSS_DIRECTORY: .oss/ + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@master + - name: Get the vars + id: vars + run: | + echo ::set-output name=TAG::${GITHUB_REF#refs/tags/} + - name: Install Helm + uses: azure/setup-helm@v1 + with: + version: v3.4.0 + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: '14' + - uses: oprypin/find-latest-tag@v1 + with: + repository: kubevela/workflow + releases-only: true + id: latest_tag + - name: Tag helm chart image + run: | + latest_repo_tag=${{ steps.latest_tag.outputs.tag }} + sub="." + major="$(cut -d"$sub" -f1 <<<"$latest_repo_tag")" + minor="$(cut -d"$sub" -f2 <<<"$latest_repo_tag")" + patch="0" + current_repo_tag="$major.$minor.$patch" + image_tag=${GITHUB_REF#refs/tags/} + chart_version=$latest_repo_tag + if [[ ${GITHUB_REF} == "refs/heads/master" ]]; then + image_tag=latest + chart_version=${current_repo_tag}-nightly-build + fi + sed -i "s/latest/${image_tag}/g" $HELM_CHART/values.yaml + chart_smever=${chart_version#"v"} + sed -i "s/0.1.0/$chart_smever/g" $HELM_CHART/Chart.yaml + - name: Install ossutil + run: wget http://gosspublic.alicdn.com/ossutil/1.7.0/ossutil64 && chmod +x ossutil64 && mv ossutil64 ossutil + - name: Configure Alibaba Cloud OSSUTIL + run: ./ossutil --config-file .ossutilconfig config -i ${ACCESS_KEY} -k ${ACCESS_KEY_SECRET} -e ${ENDPOINT} -c .ossutilconfig + - name: sync cloud to local + run: ./ossutil --config-file .ossutilconfig sync oss://$BUCKET/workflow $LOCAL_OSS_DIRECTORY + - name: Package helm charts + run: | + helm package $HELM_CHART --destination $LOCAL_OSS_DIRECTORY + helm repo index --url https://$BUCKET.$ENDPOINT/workflow $LOCAL_OSS_DIRECTORY + - name: sync local to cloud + run: ./ossutil --config-file .ossutilconfig sync $LOCAL_OSS_DIRECTORY oss://$BUCKET/workflow -f \ No newline at end of file diff --git a/.github/workflows/post-submit.yaml b/.github/workflows/post-submit.yaml new file mode 100644 index 0000000..d9400ed --- /dev/null +++ b/.github/workflows/post-submit.yaml @@ -0,0 +1,82 @@ +name: PostSubmit + +on: + push: + branches: + - master + workflow_dispatch: {} + +env: + GO_VERSION: '1.17' + +jobs: + + detect-noop: + runs-on: ubuntu-20.04 + outputs: + noop: ${{ steps.noop.outputs.should_skip }} + steps: + - name: Detect No-op Changes + id: noop + uses: fkirc/skip-duplicate-actions@v3.3.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + paths_ignore: '["**.md", "**.mdx", "**.png", "**.jpg"]' + do_not_skip: '["workflow_dispatch", "schedule", "push"]' + concurrent_skipping: false + + image-multi-arch: + runs-on: ubuntu-20.04 + needs: detect-noop + if: needs.detect-noop.outputs.noop != 'true' + strategy: + matrix: + arch: [ amd64, arm64 ] + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Build Image + run: | + IMG_TAG=latest-${{ matrix.arch }} \ + OS=linux \ + ARCH=${{ matrix.arch }} \ + make image-apiserver + - name: Push Image + run: | + echo ${{ secrets.DOCKER_PASSWORD }} | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin + docker push oamdev/vela-workflow:latest-${{ matrix.arch }} + docker push oamdev/vela-workflow:latest-${{ matrix.arch }} + image-manifest: + runs-on: ubuntu-latest + needs: [ image-multi-arch ] + steps: + + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + + - name: Create Manifest + run: | + echo ${{ secrets.DOCKER_PASSWORD }} | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin + docker manifest create oamdev/vela-workflow:latest \ + oamdev/vela-workflow:latest-amd64 \ + oamdev/vela-workflow:latest-arm64 + - name: Annotate Manifest + run: | + docker manifest annotate oamdev/vela-workflow:latest \ + oamdev/vela-workflow:latest-amd64 --arch amd64 + docker manifest annotate oamdev/vela-workflow:latest \ + oamdev/vela-workflow:latest-arm64 --arch arm64 + - name: Push Manifest + run: | + docker manifest push oamdev/vela-workflow:latest \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..455f93d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +ARG BASE_IMAGE +# Build the manager binary +FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.17-alpine as builder +ARG GOPROXY +ENV GOPROXY=${GOPROXY:-https://goproxy.cn} +WORKDIR /workspace +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY cmd/main.go cmd/main.go +COPY api/ api/ +COPY controllers/ controllers/ +COPY pkg/ pkg/ + +# Build +ARG TARGETARCH + +RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} \ + go build -a -ldflags "-s -w" \ + -o vela-workflow-${TARGETARCH} cmd/main.go + +FROM ${BASE_IMAGE:-alpine:3.15} +# This is required by daemon connecting with cri +RUN apk add --no-cache ca-certificates bash expat + +WORKDIR / + +ARG TARGETARCH +COPY --from=builder /workspace/vela-workflow-${TARGETARCH} /usr/local/bin/vela-workflow + +ENTRYPOINT ["vela-workflow"] diff --git a/Makefile b/Makefile index 507551f..d4d01b6 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ help: ## Display this help. ##@ Development .PHONY: reviewable -reviewable: manifests fmt vet lint staticcheck +reviewable: manifests fmt vet lint staticcheck helm-doc-gen go mod tidy -compat=1.17 .PHONY: check-diff @@ -62,6 +62,10 @@ vet: ## Run go vet against code. test: manifests generate fmt vet envtest ## Run tests. KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile coverage.txt +.PHONY: helm-doc-gen +helm-doc-gen: helmdoc + readme-generator -v charts/vela-workflow/values.yaml -r charts/vela-workflow/README.md + ##@ Build .PHONY: build @@ -73,8 +77,8 @@ run: manifests generate fmt vet ## Run a controller from your host. go run ./cmd/main.go .PHONY: docker-build -docker-build: test ## Build docker image with the manager. - docker build -t ${IMG} . +docker-build: ## Build docker image with the manager. + docker build --build-arg=VERSION=$(VELA_VERSION) --build-arg=GITVERSION=$(GIT_COMMIT) -t $(IMG) . .PHONY: docker-push docker-push: ## Push docker image with the manager. diff --git a/charts/vela-workflow/.helmignore b/charts/vela-workflow/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/vela-workflow/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/vela-workflow/Chart.yaml b/charts/vela-workflow/Chart.yaml new file mode 100644 index 0000000..db184bf --- /dev/null +++ b/charts/vela-workflow/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: vela-workflow +description: A Helm chart for KubeVela Workflow + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: 0.1.0 + +home: https://kubevela.io +icon: https://kubevela.io/img/logo.svg diff --git a/charts/vela-workflow/README.md b/charts/vela-workflow/README.md new file mode 100644 index 0000000..8b3484d --- /dev/null +++ b/charts/vela-workflow/README.md @@ -0,0 +1,93 @@ +
+

+ +

+ Make shipping applications more enjoyable. +

+
+ +[![Go Report Card](https://goreportcard.com/badge/github.com/kubevela/workflow)](https://goreportcard.com/report/github.com/kubevela/workflow) +[![codecov](https://codecov.io/gh/kubevela/workflow/branch/main/graph/badge.svg)](https://codecov.io/gh/kubevela/workflow) +[![LICENSE](https://img.shields.io/github/license/kubevela/workflow.svg?style=flat-square)](/LICENSE) +[![Total alerts](https://img.shields.io/lgtm/alerts/g/kubevela/workflow.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/kubevela/workflow/alerts/) + +# KubeVela Workflow helm chart + +## TL;DR + +```bash +helm repo add kubevela https://charts.kubevela.net/core +helm repo update +helm install --create-namespace -n vela-system workflow kubevela/vela-workflow --wait +``` + +## Prerequisites + +- Kubernetes >= v1.19 && < v1.22 + +## Parameters + +### Core parameters + +| Name | Description | Value | +| --------------------------- | --------------------------------------------------------------------------------------------- | ----- | +| `systemDefinitionNamespace` | System definition namespace, if unspecified, will use built-in variable `.Release.Namespace`. | `nil` | +| `concurrentReconciles` | concurrentReconciles is the concurrent reconcile number of the controller | `4` | + + +### KubeVela workflow parameters + +| Name | Description | Value | +| -------------------------------------- | ------------------------------------------------------ | ------- | +| `workflow.enableSuspendOnFailure` | Enable suspend on workflow failure | `false` | +| `workflow.backoff.maxTime.waitState` | The max backoff time of workflow in a wait condition | `60` | +| `workflow.backoff.maxTime.failedState` | The max backoff time of workflow in a failed condition | `300` | +| `workflow.step.errorRetryTimes` | The max retry times of a failed workflow step | `10` | + + +### KubeVela Workflow controller parameters + +| Name | Description | Value | +| --------------------------- | ------------------------------------ | ---------------------- | +| `replicaCount` | Workflow controller replica count | `1` | +| `imageRegistry` | Image registry | `""` | +| `image.repository` | Image repository | `oamdev/vela-workflow` | +| `image.tag` | Image tag | `latest` | +| `image.pullPolicy` | Image pull policy | `Always` | +| `resources.limits.cpu` | Workflow controller's cpu limit | `500m` | +| `resources.limits.memory` | Workflow controller's memory limit | `1Gi` | +| `resources.requests.cpu` | Workflow controller's cpu request | `50m` | +| `resources.requests.memory` | Workflow controller's memory request | `20Mi` | +| `webhookService.type` | KubeVela webhook service type | `ClusterIP` | +| `webhookService.port` | KubeVela webhook service port | `9443` | +| `healthCheck.port` | KubeVela health check port | `9440` | + + +### Common parameters + +| Name | Description | Value | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------- | +| `imagePullSecrets` | Image pull secrets | `[]` | +| `nameOverride` | Override name | `""` | +| `fullnameOverride` | Fullname override | `""` | +| `serviceAccount.create` | Specifies whether a service account should be created | `true` | +| `serviceAccount.annotations` | Annotations to add to the service account | `{}` | +| `serviceAccount.name` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | `nil` | +| `nodeSelector` | Node selector | `{}` | +| `tolerations` | Tolerations | `[]` | +| `affinity` | Affinity | `{}` | +| `rbac.create` | Specifies whether a RBAC role should be created | `true` | +| `logDebug` | Enable debug logs for development purpose | `false` | +| `logFilePath` | If non-empty, write log files in this path | `""` | +| `logFileMaxSize` | Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. | `1024` | +| `kubeClient.qps` | The qps for reconcile clients, default is 50 | `50` | +| `kubeClient.burst` | The burst for reconcile clients, default is 100 | `100` | + + +## Uninstallation + +### Helm CLI + +```shell +$ helm uninstall -n vela-system workflow +``` diff --git a/charts/vela-workflow/crds/core.oam.dev_workflowruns.yaml b/charts/vela-workflow/crds/core.oam.dev_workflowruns.yaml new file mode 100644 index 0000000..afd98ef --- /dev/null +++ b/charts/vela-workflow/crds/core.oam.dev_workflowruns.yaml @@ -0,0 +1,400 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: workflowruns.core.oam.dev +spec: + group: core.oam.dev + names: + categories: + - oam + kind: WorkflowRun + listKind: WorkflowRunList + plural: workflowruns + shortNames: + - wr + singular: workflowrun + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.status + name: PHASE + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: WorkflowRun is the Schema for the workflowRun API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + mode: + description: WorkflowExecuteMode defines the mode of workflow execution + properties: + steps: + description: WorkflowMode describes the mode of workflow + type: string + subSteps: + description: WorkflowMode describes the mode of workflow + type: string + type: object + workflowRef: + type: string + workflowSpec: + description: Workflow defines workflow steps and other attributes + properties: + steps: + items: + description: WorkflowStep defines how to execute a workflow + step. + properties: + dependsOn: + description: DependsOn is the dependency of the step + items: + type: string + type: array + if: + description: If is the if condition of the step + type: string + inputs: + description: Inputs is the inputs of the step + items: + properties: + from: + type: string + parameterKey: + type: string + required: + - from + - parameterKey + type: object + type: array + meta: + description: Meta is the meta data of the workflow step. + properties: + alias: + type: string + type: object + name: + description: Name is the unique name of the workflow step. + type: string + outputs: + description: Outputs is the outputs of the step + items: + properties: + name: + type: string + valueFrom: + type: string + required: + - name + - valueFrom + type: object + type: array + properties: + description: Properties is the properties of the step + type: object + x-kubernetes-preserve-unknown-fields: true + subSteps: + items: + description: WorkflowSubStep defines how to execute a + workflow subStep. + properties: + dependsOn: + description: DependsOn is the dependency of the step + items: + type: string + type: array + if: + description: If is the if condition of the step + type: string + inputs: + description: Inputs is the inputs of the step + items: + properties: + from: + type: string + parameterKey: + type: string + required: + - from + - parameterKey + type: object + type: array + meta: + description: Meta is the meta data of the workflow + step. + properties: + alias: + type: string + type: object + name: + description: Name is the unique name of the workflow + step. + type: string + outputs: + description: Outputs is the outputs of the step + items: + properties: + name: + type: string + valueFrom: + type: string + required: + - name + - valueFrom + type: object + type: array + properties: + description: Properties is the properties of the step + type: object + x-kubernetes-preserve-unknown-fields: true + timeout: + description: Timeout is the timeout of the step + type: string + type: + description: Type is the type of the workflow step. + type: string + required: + - name + - type + type: object + type: array + timeout: + description: Timeout is the timeout of the step + type: string + type: + description: Type is the type of the workflow step. + type: string + required: + - name + - type + type: object + type: array + type: object + type: object + status: + description: WorkflowRunStatus record the status of workflow run + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's + last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from + one status to another. + type: string + status: + description: Status of this condition; is it currently True, + False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition + type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + contextBackend: + description: 'ObjectReference contains enough information to let you + inspect or modify the referred object. --- New uses of this type + are discouraged because of difficulty describing its usage when + embedded in APIs. 1. Ignored fields. It includes many fields which + are not generally honored. For instance, ResourceVersion and FieldPath + are both very rarely valid in actual usage. 2. Invalid usage help. It + is impossible to add specific help for individual usage. In most + embedded usages, there are particular restrictions like, "must refer + only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. 3. Inconsistent validation. Because + the usages are different, the validation rules are different by + usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not + a precise mapping to a URL. This can produce ambiguity during interpretation + and require a REST mapping. In most cases, the dependency is on + the group,resource tuple and the version of the actual struct is + irrelevant. 5. We cannot easily change it. Because this type is + embedded in many locations, updates to this type will affect numerous + schemas. Don''t make new APIs embed an underspecified API type + they do not control. Instead of using this type, create a locally + provided and used type that is well-focused on your reference. For + example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 + .' + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + endTime: + format: date-time + type: string + finished: + type: boolean + message: + type: string + mode: + description: WorkflowExecuteMode defines the mode of workflow execution + properties: + steps: + description: WorkflowMode describes the mode of workflow + type: string + subSteps: + description: WorkflowMode describes the mode of workflow + type: string + type: object + startTime: + format: date-time + type: string + status: + description: WorkflowRunPhase is a label for the condition of a WorkflowRun + at the current time + type: string + steps: + items: + description: WorkflowStepStatus record the status of a workflow + step, include step status and subStep status + properties: + firstExecuteTime: + description: FirstExecuteTime is the first time this step execution. + format: date-time + type: string + id: + type: string + lastExecuteTime: + description: LastExecuteTime is the last time this step execution. + format: date-time + type: string + message: + description: A human readable message indicating details about + why the workflowStep is in this state. + type: string + name: + type: string + phase: + description: WorkflowStepPhase describes the phase of a workflow + step. + type: string + reason: + description: A brief CamelCase message indicating details about + why the workflowStep is in this state. + type: string + subSteps: + items: + description: StepStatus record the base status of workflow + step, which could be workflow step or subStep + properties: + firstExecuteTime: + description: FirstExecuteTime is the first time this step + execution. + format: date-time + type: string + id: + type: string + lastExecuteTime: + description: LastExecuteTime is the last time this step + execution. + format: date-time + type: string + message: + description: A human readable message indicating details + about why the workflowStep is in this state. + type: string + name: + type: string + phase: + description: WorkflowStepPhase describes the phase of + a workflow step. + type: string + reason: + description: A brief CamelCase message indicating details + about why the workflowStep is in this state. + type: string + type: + type: string + required: + - id + type: object + type: array + type: + type: string + required: + - id + type: object + type: array + suspend: + type: boolean + suspendState: + type: string + terminated: + type: boolean + required: + - finished + - mode + - status + - suspend + - terminated + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/charts/vela-workflow/crds/core.oam.dev_workflows.yaml b/charts/vela-workflow/crds/core.oam.dev_workflows.yaml new file mode 100644 index 0000000..da503cc --- /dev/null +++ b/charts/vela-workflow/crds/core.oam.dev_workflows.yaml @@ -0,0 +1,164 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: workflows.core.oam.dev +spec: + group: core.oam.dev + names: + categories: + - oam + kind: Workflow + listKind: WorkflowList + plural: workflows + singular: workflow + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Workflow is the Schema for the workflow API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + steps: + items: + description: WorkflowStep defines how to execute a workflow step. + properties: + dependsOn: + description: DependsOn is the dependency of the step + items: + type: string + type: array + if: + description: If is the if condition of the step + type: string + inputs: + description: Inputs is the inputs of the step + items: + properties: + from: + type: string + parameterKey: + type: string + required: + - from + - parameterKey + type: object + type: array + meta: + description: Meta is the meta data of the workflow step. + properties: + alias: + type: string + type: object + name: + description: Name is the unique name of the workflow step. + type: string + outputs: + description: Outputs is the outputs of the step + items: + properties: + name: + type: string + valueFrom: + type: string + required: + - name + - valueFrom + type: object + type: array + properties: + description: Properties is the properties of the step + type: object + x-kubernetes-preserve-unknown-fields: true + subSteps: + items: + description: WorkflowSubStep defines how to execute a workflow + subStep. + properties: + dependsOn: + description: DependsOn is the dependency of the step + items: + type: string + type: array + if: + description: If is the if condition of the step + type: string + inputs: + description: Inputs is the inputs of the step + items: + properties: + from: + type: string + parameterKey: + type: string + required: + - from + - parameterKey + type: object + type: array + meta: + description: Meta is the meta data of the workflow step. + properties: + alias: + type: string + type: object + name: + description: Name is the unique name of the workflow step. + type: string + outputs: + description: Outputs is the outputs of the step + items: + properties: + name: + type: string + valueFrom: + type: string + required: + - name + - valueFrom + type: object + type: array + properties: + description: Properties is the properties of the step + type: object + x-kubernetes-preserve-unknown-fields: true + timeout: + description: Timeout is the timeout of the step + type: string + type: + description: Type is the type of the workflow step. + type: string + required: + - name + - type + type: object + type: array + timeout: + description: Timeout is the timeout of the step + type: string + type: + description: Type is the type of the workflow step. + type: string + required: + - name + - type + type: object + type: array + type: object + served: true + storage: true diff --git a/charts/vela-workflow/crds/core.oam.dev_workflowstepdefinitions.yaml b/charts/vela-workflow/crds/core.oam.dev_workflowstepdefinitions.yaml new file mode 100644 index 0000000..85957b3 --- /dev/null +++ b/charts/vela-workflow/crds/core.oam.dev_workflowstepdefinitions.yaml @@ -0,0 +1,275 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + name: workflowstepdefinitions.core.oam.dev +spec: + group: core.oam.dev + names: + categories: + - oam + kind: WorkflowStepDefinition + listKind: WorkflowStepDefinitionList + plural: workflowstepdefinitions + shortNames: + - workflowstep + singular: workflowstepdefinition + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: WorkflowStepDefinition is the Schema for the workflowstepdefinitions + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: WorkflowStepDefinitionSpec defines the desired state of WorkflowStepDefinition + properties: + definitionRef: + description: Reference to the CustomResourceDefinition that defines + this trait kind. + properties: + name: + description: Name of the referenced CustomResourceDefinition. + type: string + version: + description: Version indicate which version should be used if + CRD has multiple versions by default it will use the first one + if not specified + type: string + required: + - name + type: object + schematic: + description: Schematic defines the data format and template of the + encapsulation of the workflow step definition + properties: + cue: + description: CUE defines the encapsulation in CUE format + properties: + template: + description: Template defines the abstraction template data + of the capability, it will replace the old CUE template + in extension field. Template is a required field if CUE + is defined in Capability Definition. + type: string + required: + - template + type: object + helm: + description: A Helm represents resources used by a Helm module + properties: + release: + description: Release records a Helm release used by a Helm + module workload. + type: object + x-kubernetes-preserve-unknown-fields: true + repository: + description: HelmRelease records a Helm repository used by + a Helm module workload. + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - release + - repository + type: object + kube: + description: Kube defines the encapsulation in raw Kubernetes + resource format + properties: + parameters: + description: Parameters defines configurable parameters + items: + description: A KubeParameter defines a configurable parameter + of a component. + properties: + description: + description: Description of this parameter. + type: string + fieldPaths: + description: "FieldPaths specifies an array of fields + within this workload that will be overwritten by the + value of this parameter. \tAll fields must be of the + same type. Fields are specified as JSON field paths + without a leading dot, for example 'spec.replicas'." + items: + type: string + type: array + name: + description: Name of this parameter + type: string + required: + default: false + description: Required specifies whether or not a value + for this parameter must be supplied when authoring + an Application. + type: boolean + type: + description: 'ValueType indicates the type of the parameter + value, and only supports basic data types: string, + number, boolean.' + enum: + - string + - number + - boolean + type: string + required: + - fieldPaths + - name + - type + type: object + type: array + template: + description: Template defines the raw Kubernetes resource + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - template + type: object + terraform: + description: Terraform is the struct to describe cloud resources + managed by Hashicorp Terraform + properties: + configuration: + description: Configuration is Terraform Configuration + type: string + customRegion: + description: Region is cloud provider's region. It will override + the region in the region field of ProviderReference + type: string + deleteResource: + default: true + description: DeleteResource will determine whether provisioned + cloud resources will be deleted when CR is deleted + type: boolean + path: + description: Path is the sub-directory of remote git repository. + It's valid when remote is set + type: string + providerRef: + description: ProviderReference specifies the reference to + Provider + properties: + name: + description: Name of the referenced object. + type: string + namespace: + default: default + description: Namespace of the referenced object. + type: string + required: + - name + type: object + type: + default: hcl + description: Type specifies which Terraform configuration + it is, HCL or JSON syntax + enum: + - hcl + - json + - remote + type: string + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the + namespace and name of a Secret to which any connection details + for this managed resource should be written. Connection + details frequently include the endpoint, username, and password + required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + type: object + required: + - configuration + type: object + type: object + type: object + status: + description: WorkflowStepDefinitionStatus is the status of WorkflowStepDefinition + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's + last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from + one status to another. + type: string + status: + description: Status of this condition; is it currently True, + False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition + type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + configMapRef: + description: ConfigMapRef refer to a ConfigMap which contains OpenAPI + V3 JSON schema of Component parameters. + type: string + latestRevision: + description: LatestRevision of the component definition + properties: + name: + type: string + revision: + format: int64 + type: integer + revisionHash: + description: RevisionHash record the hash value of the spec of + ApplicationRevision object. + type: string + required: + - name + - revision + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/vela-workflow/templates/_helpers.tpl b/charts/vela-workflow/templates/_helpers.tpl new file mode 100644 index 0000000..a1cf376 --- /dev/null +++ b/charts/vela-workflow/templates/_helpers.tpl @@ -0,0 +1,74 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "kubevela.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "kubevela.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kubevela.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "kubevela.labels" -}} +helm.sh/chart: {{ include "kubevela.chart" . }} +{{ include "kubevela.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "kubevela.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kubevela.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kubevela.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "kubevela.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +systemDefinitionNamespace value defaulter +*/}} +{{- define "systemDefinitionNamespace" -}} +{{- if .Values.systemDefinitionNamespace -}} + {{ .Values.systemDefinitionNamespace }} +{{- else -}} + {{ .Release.Namespace }} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/vela-workflow/templates/workflow-controller.yaml b/charts/vela-workflow/templates/workflow-controller.yaml new file mode 100644 index 0000000..e3368ef --- /dev/null +++ b/charts/vela-workflow/templates/workflow-controller.yaml @@ -0,0 +1,172 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "kubevela.serviceAccountName" . }} + labels: + {{- include "kubevela.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "kubevela.fullname" . }}:manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: "cluster-admin" +subjects: + - kind: ServiceAccount + name: {{ include "kubevela.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + +--- + +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "kubevela.fullname" . }}:leader-election-role +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "kubevela.fullname" . }}:leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "kubevela.fullname" . }}:leader-election-role +subjects: + - kind: ServiceAccount + name: {{ include "kubevela.serviceAccountName" . }} + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "kubevela.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + controller.oam.dev/name: vela-workflow + {{- include "kubevela.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "kubevela.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "kubevela.selectorLabels" . | nindent 8 }} + annotations: + prometheus.io/path: /metrics + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "kubevela.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Release.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + args: + {{ if .Values.admissionWebhooks.enabled }} + - "--use-webhook=true" + - "--webhook-port={{ .Values.webhookService.port }}" + - "--webhook-cert-dir={{ .Values.admissionWebhooks.certificate.mountPath }}" + {{ end }} + # - "--health-addr=:{{ .Values.healthCheck.port }}" + # - "--concurrent-reconciles={{ .Values.concurrentReconciles }}" + # - "--kube-api-qps={{ .Values.kubeClient.qps }}" + # - "--kube-api-burst={{ .Values.kubeClient.burst }}" + - "--max-workflow-wait-backoff-time={{ .Values.workflow.backoff.maxTime.waitState }}" + - "--max-workflow-failed-backoff-time={{ .Values.workflow.backoff.maxTime.failedState }}" + - "--max-workflow-step-error-retry-times={{ .Values.workflow.step.errorRetryTimes }}" + - "--feature-gates=EnableSuspendOnFailure={{- .Values.workflow.enableSuspendOnFailure | toString -}}" + image: {{ .Values.imageRegistry }}{{ .Values.image.repository }}:{{ .Values.image.tag }} + imagePullPolicy: {{ quote .Values.image.pullPolicy }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{ if .Values.admissionWebhooks.enabled }} + ports: + - containerPort: {{ .Values.webhookService.port }} + name: webhook-server + protocol: TCP + - containerPort: {{ .Values.healthCheck.port }} + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + initialDelaySeconds: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 90 + periodSeconds: 5 + volumeMounts: + - mountPath: {{ .Values.admissionWebhooks.certificate.mountPath }} + name: tls-cert-vol + readOnly: true + {{ end }} + {{ if .Values.admissionWebhooks.enabled }} + volumes: + - name: tls-cert-vol + secret: + defaultMode: 420 + secretName: {{ template "kubevela.fullname" . }}-admission + {{ end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/vela-workflow/values.yaml b/charts/vela-workflow/values.yaml new file mode 100644 index 0000000..fb6f290 --- /dev/null +++ b/charts/vela-workflow/values.yaml @@ -0,0 +1,148 @@ +# Default values for kubevela. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +## @section Core parameters + +## @param systemDefinitionNamespace System definition namespace, if unspecified, will use built-in variable `.Release.Namespace`. +systemDefinitionNamespace: + +## @param concurrentReconciles concurrentReconciles is the concurrent reconcile number of the controller +concurrentReconciles: 4 + +## @section KubeVela workflow parameters + +## @param workflow.enableSuspendOnFailure Enable suspend on workflow failure +## @param workflow.backoff.maxTime.waitState The max backoff time of workflow in a wait condition +## @param workflow.backoff.maxTime.failedState The max backoff time of workflow in a failed condition +## @param workflow.step.errorRetryTimes The max retry times of a failed workflow step +workflow: + enableSuspendOnFailure: false + backoff: + maxTime: + waitState: 60 + failedState: 300 + step: + errorRetryTimes: 10 + + +## @section KubeVela Workflow controller parameters + +## @param replicaCount Workflow controller replica count +replicaCount: 1 + +## @param imageRegistry Image registry +imageRegistry: "" +## @param image.repository Image repository +## @param image.tag Image tag +## @param image.pullPolicy Image pull policy +image: + repository: oamdev/vela-workflow + tag: latest + pullPolicy: Always + +## @param resources.limits.cpu Workflow controller's cpu limit +## @param resources.limits.memory Workflow controller's memory limit +## @param resources.requests.cpu Workflow controller's cpu request +## @param resources.requests.memory Workflow controller's memory request +resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 50m + memory: 20Mi + +## @param webhookService.type KubeVela webhook service type +## @param webhookService.port KubeVela webhook service port +webhookService: + type: ClusterIP + port: 9443 + +## @param healthCheck.port KubeVela health check port +healthCheck: + port: 9440 + + +## @section Common parameters + +## @param imagePullSecrets Image pull secrets +imagePullSecrets: [] +## @param nameOverride Override name +nameOverride: "" +## @param fullnameOverride Fullname override +fullnameOverride: "" + +## @param serviceAccount.create Specifies whether a service account should be created +## @param serviceAccount.annotations Annotations to add to the service account +## @param serviceAccount.name The name of the service account to use. If not set and create is true, a name is generated using the fullname template +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + +## @skip podSecurityContext +podSecurityContext: {} + # fsGroup: 2000 + +## @skip securityContext +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +## @param nodeSelector Node selector +nodeSelector: {} + +## @param tolerations Tolerations +tolerations: [] + +## @param affinity Affinity +affinity: {} + +## @param rbac.create Specifies whether a RBAC role should be created +rbac: + create: true + +## @param logDebug Enable debug logs for development purpose +logDebug: false + +## @param logFilePath If non-empty, write log files in this path +logFilePath: "" + +## @param logFileMaxSize Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. +logFileMaxSize: 1024 + +## @skip admissionWebhooks +admissionWebhooks: + enabled: false + failurePolicy: Fail + certificate: + mountPath: /etc/k8s-webhook-certs + patch: + enabled: true + image: + repository: oamdev/kube-webhook-certgen + tag: v2.4.1 + pullPolicy: IfNotPresent + nodeSelector: {} + affinity: {} + tolerations: [] + appConversion: + enabled: false + certManager: + enabled: false + revisionHistoryLimit: 3 + +## @param kubeClient.qps The qps for reconcile clients, default is 50 +## @param kubeClient.burst The burst for reconcile clients, default is 100 +kubeClient: + qps: 50 + burst: 100 diff --git a/cmd/main.go b/cmd/main.go index b4144ec..9410217 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -17,18 +17,17 @@ limitations under the License. package main import ( - "flag" "os" "github.com/crossplane/crossplane-runtime/pkg/event" - "github.com/spf13/pflag" + flag "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/util/feature" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/klog" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/log/zap" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" @@ -64,14 +63,10 @@ func main() { flag.IntVar(&types.MaxWorkflowWaitBackoffTime, "max-workflow-wait-backoff-time", 60, "Set the max workflow wait backoff time, default is 60") flag.IntVar(&types.MaxWorkflowFailedBackoffTime, "max-workflow-failed-backoff-time", 300, "Set the max workflow wait backoff time, default is 300") flag.IntVar(&types.MaxWorkflowStepErrorRetryTimes, "max-workflow-step-error-retry-times", 10, "Set the max workflow step error retry times, default is 10") - feature.DefaultMutableFeatureGate.AddFlag(pflag.CommandLine) - opts := zap.Options{ - Development: true, - } - opts.BindFlags(flag.CommandLine) - flag.Parse() + feature.DefaultMutableFeatureGate.AddFlag(flag.CommandLine) - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + flag.Parse() + klog.InitFlags(nil) mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, diff --git a/controllers/workflow_test.go b/controllers/workflow_test.go index 69b59cc..3376a52 100644 --- a/controllers/workflow_test.go +++ b/controllers/workflow_test.go @@ -155,6 +155,29 @@ var _ = Describe("Test Workflow", func() { Expect(wrObj.Status.Phase).Should(BeEquivalentTo(v1alpha1.WorkflowRunSuspending)) }) + It("get failed to generate", func() { + wr := wrTemplate.DeepCopy() + wr.Name = "failed-generate" + wr.Spec.WorkflowSpec.Steps = []v1alpha1.WorkflowStep{ + { + WorkflowStepBase: v1alpha1.WorkflowStepBase{ + Name: "failed-generate", + Type: "invalid", + }, + }} + Expect(k8sClient.Create(ctx, wr)).Should(BeNil()) + + err := reconcileWithReturn(reconciler, wr.Name, wr.Namespace) + Expect(err).ShouldNot(BeNil()) + + events, err := recorder.GetEventsWithName(wr.Name) + Expect(err).Should(BeNil()) + Expect(len(events)).Should(Equal(1)) + Expect(events[0].EventType).Should(Equal(corev1.EventTypeWarning)) + Expect(events[0].Reason).Should(Equal(v1alpha1.ReasonGenerate)) + Expect(events[0].Message).Should(ContainSubstring(v1alpha1.MessageFailedGenerate)) + }) + It("should create workflow context ConfigMap", func() { wr := wrTemplate.DeepCopy() Expect(k8sClient.Create(ctx, wr)).Should(BeNil()) diff --git a/controllers/workflowrun_controller.go b/controllers/workflowrun_controller.go index 2e288a8..6ceca3e 100644 --- a/controllers/workflowrun_controller.go +++ b/controllers/workflowrun_controller.go @@ -99,6 +99,8 @@ func (r *WorkflowRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, nil } + executor.InitializeWorkflowRun(run) + runners, err := steps.Generate(logCtx, run, types.StepGeneratorOptions{ PackageDiscover: r.PackageDiscover, Client: r.Client, diff --git a/makefiles/dependency.mk b/makefiles/dependency.mk index e0d2230..311be75 100644 --- a/makefiles/dependency.mk +++ b/makefiles/dependency.mk @@ -78,6 +78,19 @@ else GOLANGCILINT=$(GOBIN)/golangci-lint endif +.PHONY: helmdoc +helmdoc: +ifeq (, $(shell which readme-generator)) + @{ \ + set -e ;\ + echo 'installing readme-generator-for-helm' ;\ + npm install -g readme-generator-for-helm ;\ + } +else + @$(OK) readme-generator-for-helm is already installed +HELMDOC=$(shell which readme-generator) +endif + .PHONY: controller-gen controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. $(CONTROLLER_GEN): $(LOCALBIN) diff --git a/pkg/executor/workflow.go b/pkg/executor/workflow.go index 21f1c9d..00a3c02 100644 --- a/pkg/executor/workflow.go +++ b/pkg/executor/workflow.go @@ -69,21 +69,33 @@ func New(wr *v1alpha1.WorkflowRun, cli client.Client) WorkflowExecutor { } } -func (w *workflowExecutor) workflowRunInitializing() { - if w.wr.Status.StartTime.IsZero() && len(w.wr.Status.Steps) == 0 { +func InitializeWorkflowRun(wr *v1alpha1.WorkflowRun) { + if wr.Status.StartTime.IsZero() && len(wr.Status.Steps) == 0 { metrics.WorkflowRunInitializedCounter.WithLabelValues().Inc() - w.wr.Status = v1alpha1.WorkflowRunStatus{ - Mode: w.getExecuteMode(), + mode := v1alpha1.WorkflowExecuteMode{ + Steps: v1alpha1.WorkflowModeStep, + SubSteps: v1alpha1.WorkflowModeDAG, + } + if wr.Spec.Mode != nil { + if wr.Spec.Mode.Steps != "" { + mode.Steps = wr.Spec.Mode.Steps + } + if wr.Spec.Mode.SubSteps != "" { + mode.SubSteps = wr.Spec.Mode.SubSteps + } + } + wr.Status = v1alpha1.WorkflowRunStatus{ + Mode: mode, StartTime: metav1.Now(), } - StepStatusCache.Delete(fmt.Sprintf("%s-%s", w.wr.Name, w.wr.Namespace)) - wfContext.CleanupMemoryStore(w.wr.Name, w.wr.Namespace) + StepStatusCache.Delete(fmt.Sprintf("%s-%s", wr.Name, wr.Namespace)) + wfContext.CleanupMemoryStore(wr.Name, wr.Namespace) } } // ExecuteRunners execute workflow task runners in order. func (w *workflowExecutor) ExecuteRunners(ctx monitorContext.Context, taskRunners []types.TaskRunner) (types.WorkflowState, error) { - w.workflowRunInitializing() + InitializeWorkflowRun(w.wr) status := &w.wr.Status dagMode := status.Mode.Steps == v1alpha1.WorkflowModeDAG cacheKey := fmt.Sprintf("%s-%s", w.wr.Name, w.wr.Namespace) @@ -91,7 +103,6 @@ func (w *workflowExecutor) ExecuteRunners(ctx monitorContext.Context, taskRunner allTasksDone, allTasksSucceeded := w.allDone(taskRunners) if status.Finished { StepStatusCache.Delete(cacheKey) - // return types.WorkflowStateFinished, nil } if checkWorkflowTerminated(status, allTasksDone) { return types.WorkflowStateTerminated, nil @@ -146,22 +157,6 @@ func (w *workflowExecutor) ExecuteRunners(ctx monitorContext.Context, taskRunner return types.WorkflowStateExecuting, nil } -func (w *workflowExecutor) getExecuteMode() v1alpha1.WorkflowExecuteMode { - mode := v1alpha1.WorkflowExecuteMode{ - Steps: v1alpha1.WorkflowModeStep, - SubSteps: v1alpha1.WorkflowModeDAG, - } - if w.wr.Spec.Mode != nil { - if w.wr.Spec.Mode.Steps != "" { - mode.Steps = w.wr.Spec.Mode.Steps - } - if w.wr.Spec.Mode.SubSteps != "" { - mode.SubSteps = w.wr.Spec.Mode.SubSteps - } - } - return mode -} - func checkWorkflowTerminated(status *v1alpha1.WorkflowRunStatus, allTasksDone bool) bool { // if all tasks are done, and the terminated is true, then the workflow is terminated return status.Terminated && allTasksDone diff --git a/pkg/steps/generator.go b/pkg/steps/generator.go index 3b0eb03..28152e3 100644 --- a/pkg/steps/generator.go +++ b/pkg/steps/generator.go @@ -29,6 +29,7 @@ import ( "github.com/kubevela/workflow/pkg/monitor/metrics" "github.com/kubevela/workflow/pkg/providers" "github.com/kubevela/workflow/pkg/providers/email" + "github.com/kubevela/workflow/pkg/providers/http" "github.com/kubevela/workflow/pkg/providers/kube" "github.com/kubevela/workflow/pkg/providers/util" "github.com/kubevela/workflow/pkg/providers/workspace" @@ -79,6 +80,7 @@ func installBuiltinProviders(ctx monitorContext.Context, wr *v1alpha1.WorkflowRu workspace.Install(providerHandlers) email.Install(providerHandlers) util.Install(providerHandlers) + http.Install(providerHandlers, client, wr.Namespace) kube.Install(providerHandlers, client, nil, []metav1.OwnerReference{ { APIVersion: v1alpha1.SchemeGroupVersion.String(),