From cd9ac7253173e2521a032faf7ced7929f93a18c4 Mon Sep 17 00:00:00 2001 From: Tianxin Dong Date: Fri, 16 Sep 2022 16:28:35 +0800 Subject: [PATCH] Chore: update cue version to attr and notification (#4734) * Chore: update cue version to attr and notification Signed-off-by: FogDong * Fix: docgen test Signed-off-by: Somefive Signed-off-by: FogDong Signed-off-by: FogDong Signed-off-by: Somefive Co-authored-by: Somefive --- .../defwithtemplate/notification.yaml | 29 +- .../defwithtemplate/webhook-notification.yaml | 259 ------------ .../templates/defwithtemplate/webhook.yaml | 9 +- .../defwithtemplate/notification.yaml | 29 +- .../defwithtemplate/webhook-notification.yaml | 249 ------------ .../templates/defwithtemplate/webhook.yaml | 9 +- go.mod | 10 +- go.sum | 23 +- pkg/cue/convert.go | 1 + pkg/cue/definition/template.go | 3 +- pkg/definition/go_gen_test.go | 1 - pkg/utils/common/common.go | 1 + references/docgen/cluster_test.go | 32 +- .../docgen/def-doc/workflowstep/suspend.eg.md | 8 +- test/e2e-test/application_test.go | 378 +++++++++--------- test/e2e-test/definition_test.go | 29 ++ .../testdata/app/app_notification.yaml | 17 + .../testdata/app/app_notification_secret.yaml | 19 + .../deprecated/webhook-notification.cue | 264 ------------ .../internal/workflowstep/notification.cue | 29 +- .../internal/workflowstep/webhook.cue | 9 +- 21 files changed, 356 insertions(+), 1052 deletions(-) delete mode 100644 charts/vela-core/templates/defwithtemplate/webhook-notification.yaml delete mode 100644 charts/vela-minimal/templates/defwithtemplate/webhook-notification.yaml create mode 100644 test/e2e-test/testdata/app/app_notification.yaml create mode 100644 test/e2e-test/testdata/app/app_notification_secret.yaml delete mode 100644 vela-templates/definitions/deprecated/webhook-notification.cue diff --git a/charts/vela-core/templates/defwithtemplate/notification.yaml b/charts/vela-core/templates/defwithtemplate/notification.yaml index 36832e766..4152aacf9 100644 --- a/charts/vela-core/templates/defwithtemplate/notification.yaml +++ b/charts/vela-core/templates/defwithtemplate/notification.yaml @@ -14,16 +14,17 @@ spec: import ( "vela/op" "encoding/base64" + "encoding/json" ) parameter: { // +usage=Please fulfill its url and message if you want to send Lark messages lark?: { // +usage=Specify the the lark url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -42,10 +43,10 @@ spec: // +usage=Please fulfill its url and message if you want to send DingTalk messages dingding?: { // +usage=Specify the the dingding url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -100,10 +101,10 @@ spec: // +usage=Please fulfill its url and message if you want to send Slack messages slack?: { // +usage=Specify the the slack url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -134,10 +135,10 @@ spec: // +usage=The alias is the email alias to show after sending the email alias?: string // +usage=Specify the password of the email, you can either sepcify it in value or use secretRef - password: { + password: close({ // +usage=the password content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -237,8 +238,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key])} ding2: op.#DingTalk & { message: parameter.dingding.message dingUrl: stringValue.str @@ -266,8 +266,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key])} lark2: op.#Lark & { message: parameter.lark.message larkUrl: stringValue.str @@ -295,8 +294,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key])} slack2: op.#Slack & { message: parameter.slack.message slackUrl: stringValue.str @@ -334,8 +332,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key])} email2: op.#SendEmail & { from: { address: parameter.email.from.address diff --git a/charts/vela-core/templates/defwithtemplate/webhook-notification.yaml b/charts/vela-core/templates/defwithtemplate/webhook-notification.yaml deleted file mode 100644 index 1a6853d58..000000000 --- a/charts/vela-core/templates/defwithtemplate/webhook-notification.yaml +++ /dev/null @@ -1,259 +0,0 @@ -# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. -# Definition source cue file: vela-templates/definitions/deprecated/webhook-notification.cue -apiVersion: core.oam.dev/v1beta1 -kind: WorkflowStepDefinition -metadata: - annotations: - definition.oam.dev/description: Send message to webhook. This definition is DEPRECATED, please use 'notification' instead. - labels: - custom.definition.oam.dev/deprecated: "true" - name: webhook-notification - namespace: {{ include "systemDefinitionNamespace" . }} -spec: - schematic: - cue: - template: | - import ( - "vela/op" - "encoding/base64" - ) - - parameter: { - dingding?: { - url: value | secretRef - message: { - text?: *null | { - content: string - } - // +usage=msgType can be text, link, mardown, actionCard, feedCard - msgtype: string - link?: *null | { - text?: string - title?: string - messageUrl?: string - picUrl?: string - } - markdown?: *null | { - text: string - title: string - } - at?: *null | { - atMobiles?: *null | [...string] - isAtAll?: bool - } - actionCard?: *null | { - text: string - title: string - hideAvatar: string - btnOrientation: string - singleTitle: string - singleURL: string - btns: *null | [...*null | { - title: string - actionURL: string - }] - } - feedCard?: *null | { - links: *null | [...*null | { - text?: string - title?: string - messageUrl?: string - picUrl?: string - }] - } - } - } - - slack?: { - url: value | secretRef - message: { - text: string - blocks?: *null | [...block] - attachments?: *null | { - blocks?: *null | [...block] - color?: string - } - thread_ts?: string - mrkdwn?: *true | bool - } - } - - email?: { - from: { - address: string - alias?: string - password: value | secretRef - host: string - port: *587 | int - } - to: [...string] - content: { - subject: string - body: string - } - } - } - block: { - type: string - block_id?: string - elements?: [...{ - type: string - action_id?: string - url?: string - value?: string - style?: string - text?: textType - confirm?: { - title: textType - text: textType - confirm: textType - deny: textType - style?: string - } - options?: [...option] - initial_options?: [...option] - placeholder?: textType - initial_date?: string - image_url?: string - alt_text?: string - option_groups?: [...option] - max_selected_items?: int - initial_value?: string - multiline?: bool - min_length?: int - max_length?: int - dispatch_action_config?: trigger_actions_on?: [...string] - initial_time?: string - }] - } - textType: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - option: { - text: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - value: string - description?: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - url?: string - } - secretRef: { - name: string - key: string - } - value: string - // send webhook notification - ding: op.#Steps & { - if parameter.dingding != _|_ { - if parameter.dingding.url.value != _|_ { - ding1: op.#DingTalk & { - message: parameter.dingding.message - dingUrl: parameter.dingding.url.value - } - } - if parameter.dingding.url.secretRef != _|_ && parameter.dingding.url.value == _|_ { - read: op.#Read & { - value: { - apiVersion: "v1" - kind: "Secret" - metadata: { - name: parameter.dingding.url.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - ding2: op.#DingTalk & { - message: parameter.dingding.message - dingUrl: stringValue.str - } - } - } - } - slack: op.#Steps & { - if parameter.slack != _|_ { - if parameter.slack.url.value != _|_ { - slack1: op.#Slack & { - message: parameter.slack.message - slackUrl: parameter.slack.url.value - } - } - if parameter.slack.url.secretRef != _|_ && parameter.slack.url.value == _|_ { - read: op.#Read & { - value: { - kind: "Secret" - apiVersion: "v1" - metadata: { - name: parameter.slack.url.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - slack2: op.#Slack & { - message: parameter.slack.message - slackUrl: stringValue.str - } - } - } - } - email: op.#Steps & { - if parameter.email != _|_ { - if parameter.email.from.password.value != _|_ { - email1: op.#SendEmail & { - from: { - address: parameter.email.from.value - alias: parameter.email.from.alias - password: parameter.email.from.password.value - host: parameter.email.from.host - port: parameter.email.from.port - } - to: parameter.email.to - content: parameter.email.content - } - } - - if parameter.email.from.password.secretRef != _|_ && parameter.email.from.password.value == _|_ { - read: op.#Read & { - value: { - kind: "Secret" - apiVersion: "v1" - metadata: { - name: parameter.email.from.password.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - email2: op.#SendEmail & { - from: { - address: parameter.email.from.value - alias: parameter.email.from.alias - password: stringValue.str - host: parameter.email.from.host - port: parameter.email.from.port - } - to: parameter.email.to - content: parameter.email.content - } - } - } - } - diff --git a/charts/vela-core/templates/defwithtemplate/webhook.yaml b/charts/vela-core/templates/defwithtemplate/webhook.yaml index 982f5e643..7619a6cd6 100644 --- a/charts/vela-core/templates/defwithtemplate/webhook.yaml +++ b/charts/vela-core/templates/defwithtemplate/webhook.yaml @@ -57,22 +57,21 @@ spec: } } @step(5) - decoded: base64.Decode(null, read.value.data[parameter.url.secretRef.key]) @step(6) - stringValue: op.#ConvertString & {bt: decoded} @step(7) + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} @step(6) http: op.#HTTPPost & { url: stringValue.str request: { body: data.value header: "Content-Type": "application/json" } - } @step(8) + } @step(7) } } parameter: { // +usage=Specify the webhook url - url: { + url: close({ value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string diff --git a/charts/vela-minimal/templates/defwithtemplate/notification.yaml b/charts/vela-minimal/templates/defwithtemplate/notification.yaml index 36832e766..4152aacf9 100644 --- a/charts/vela-minimal/templates/defwithtemplate/notification.yaml +++ b/charts/vela-minimal/templates/defwithtemplate/notification.yaml @@ -14,16 +14,17 @@ spec: import ( "vela/op" "encoding/base64" + "encoding/json" ) parameter: { // +usage=Please fulfill its url and message if you want to send Lark messages lark?: { // +usage=Specify the the lark url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -42,10 +43,10 @@ spec: // +usage=Please fulfill its url and message if you want to send DingTalk messages dingding?: { // +usage=Specify the the dingding url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -100,10 +101,10 @@ spec: // +usage=Please fulfill its url and message if you want to send Slack messages slack?: { // +usage=Specify the the slack url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -134,10 +135,10 @@ spec: // +usage=The alias is the email alias to show after sending the email alias?: string // +usage=Specify the password of the email, you can either sepcify it in value or use secretRef - password: { + password: close({ // +usage=the password content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -237,8 +238,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key])} ding2: op.#DingTalk & { message: parameter.dingding.message dingUrl: stringValue.str @@ -266,8 +266,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key])} lark2: op.#Lark & { message: parameter.lark.message larkUrl: stringValue.str @@ -295,8 +294,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key])} slack2: op.#Slack & { message: parameter.slack.message slackUrl: stringValue.str @@ -334,8 +332,7 @@ spec: } } - decoded: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key])} email2: op.#SendEmail & { from: { address: parameter.email.from.address diff --git a/charts/vela-minimal/templates/defwithtemplate/webhook-notification.yaml b/charts/vela-minimal/templates/defwithtemplate/webhook-notification.yaml deleted file mode 100644 index 9756efc62..000000000 --- a/charts/vela-minimal/templates/defwithtemplate/webhook-notification.yaml +++ /dev/null @@ -1,249 +0,0 @@ -# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. -# Definition source cue file: vela-templates/definitions/deprecated/webhook-notification.cue -apiVersion: core.oam.dev/v1beta1 -kind: WorkflowStepDefinition -metadata: - annotations: - definition.oam.dev/description: Send message to webhook. This definition is DEPRECATED, please use 'notification' instead. - labels: - custom.definition.oam.dev/deprecated: "true" - name: webhook-notification - namespace: {{ include "systemDefinitionNamespace" . }} -spec: - schematic: - cue: - template: | - import ( - "vela/op" - "encoding/base64" - ) - - parameter: { - dingding?: { - url: value | secretRef - message: { - text?: *null | { - content: string - } - // +usage=msgType can be text, link, mardown, actionCard, feedCard - msgtype: string - link?: *null | { - text?: string - title?: string - messageUrl?: string - picUrl?: string - } - markdown?: *null | { - text: string - title: string - } - at?: *null | { - atMobiles?: *null | [...string] - isAtAll?: bool - } - actionCard?: *null | { - text: string - title: string - hideAvatar: string - btnOrientation: string - singleTitle: string - singleURL: string - btns: *null | [...*null | { - title: string - actionURL: string - }] - } - feedCard?: *null | { - links: *null | [...*null | { - text?: string - title?: string - messageUrl?: string - picUrl?: string - }] - } - } - } - - slack?: { - url: value | secretRef - message: { - text: string - blocks?: *null | [...block] - attachments?: *null | { - blocks?: *null | [...block] - color?: string - } - thread_ts?: string - mrkdwn?: *true | bool - } - } - - email?: { - from: { - address: string - alias?: string - password: value | secretRef - host: string - port: *587 | int - } - to: [...string] - content: { - subject: string - body: string - } - } - } - block: { - type: string - block_id?: string - elements?: [...{ - type: string - action_id?: string - url?: string - value?: string - style?: string - text?: textType - confirm?: { - title: textType - text: textType - confirm: textType - deny: textType - style?: string - } - options?: [...option] - initial_options?: [...option] - placeholder?: textType - initial_date?: string - image_url?: string - alt_text?: string - option_groups?: [...option] - max_selected_items?: int - initial_value?: string - multiline?: bool - min_length?: int - max_length?: int - dispatch_action_config?: trigger_actions_on?: [...string] - initial_time?: string - }] - } - textType: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - option: { - text: textType - value: string - description?: textType - url?: string - } - secretRef: { - name: string - key: string - } - value: string - // send webhook notification - ding: op.#Steps & { - if parameter.dingding != _|_ { - if parameter.dingding.url.value != _|_ { - ding1: op.#DingTalk & { - message: parameter.dingding.message - dingUrl: parameter.dingding.url.value - } - } - if parameter.dingding.url.secretRef != _|_ && parameter.dingding.url.value == _|_ { - read: op.#Read & { - value: { - apiVersion: "v1" - kind: "Secret" - metadata: { - name: parameter.dingding.url.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - ding2: op.#DingTalk & { - message: parameter.dingding.message - dingUrl: stringValue.str - } - } - } - } - slack: op.#Steps & { - if parameter.slack != _|_ { - if parameter.slack.url.value != _|_ { - slack1: op.#Slack & { - message: parameter.slack.message - slackUrl: parameter.slack.url.value - } - } - if parameter.slack.url.secretRef != _|_ && parameter.slack.url.value == _|_ { - read: op.#Read & { - value: { - kind: "Secret" - apiVersion: "v1" - metadata: { - name: parameter.slack.url.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - slack2: op.#Slack & { - message: parameter.slack.message - slackUrl: stringValue.str - } - } - } - } - email: op.#Steps & { - if parameter.email != _|_ { - if parameter.email.from.password.value != _|_ { - email1: op.#SendEmail & { - from: { - address: parameter.email.from.value - alias: parameter.email.from.alias - password: parameter.email.from.password.value - host: parameter.email.from.host - port: parameter.email.from.port - } - to: parameter.email.to - content: parameter.email.content - } - } - - if parameter.email.from.password.secretRef != _|_ && parameter.email.from.password.value == _|_ { - read: op.#Read & { - value: { - kind: "Secret" - apiVersion: "v1" - metadata: { - name: parameter.email.from.password.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - email2: op.#SendEmail & { - from: { - address: parameter.email.from.value - alias: parameter.email.from.alias - password: stringValue.str - host: parameter.email.from.host - port: parameter.email.from.port - } - to: parameter.email.to - content: parameter.email.content - } - } - } - } - diff --git a/charts/vela-minimal/templates/defwithtemplate/webhook.yaml b/charts/vela-minimal/templates/defwithtemplate/webhook.yaml index 982f5e643..7619a6cd6 100644 --- a/charts/vela-minimal/templates/defwithtemplate/webhook.yaml +++ b/charts/vela-minimal/templates/defwithtemplate/webhook.yaml @@ -57,22 +57,21 @@ spec: } } @step(5) - decoded: base64.Decode(null, read.value.data[parameter.url.secretRef.key]) @step(6) - stringValue: op.#ConvertString & {bt: decoded} @step(7) + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} @step(6) http: op.#HTTPPost & { url: stringValue.str request: { body: data.value header: "Content-Type": "application/json" } - } @step(8) + } @step(7) } } parameter: { // +usage=Specify the webhook url - url: { + url: close({ value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string diff --git a/go.mod b/go.mod index a79535cef..ec1f2c724 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/oam-dev/kubevela go 1.17 require ( - cuelang.org/go v0.4.4-0.20220729051708-0a46a1624353 + cuelang.org/go v0.4.4-0.20220914123050-d3959ebce916 github.com/AlecAivazis/survey/v2 v2.1.1 github.com/FogDong/uitable v0.0.5 github.com/Masterminds/semver/v3 v3.1.1 @@ -55,7 +55,7 @@ require ( github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c github.com/kubevela/pkg v0.0.0-20220913093640-a41193098f92 github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f - github.com/kubevela/workflow v0.0.0-20220905111757-ae9387b554de + github.com/kubevela/workflow v0.0.0-20220915143429-7b383f5062c8 github.com/kyokomi/emoji v2.2.4+incompatible github.com/mitchellh/hashstructure/v2 v2.0.1 github.com/oam-dev/cluster-gateway v1.4.0 @@ -70,7 +70,7 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/rivo/tview v0.0.0-20220709181631-73bf2902b59a github.com/robfig/cron/v3 v3.0.1 - github.com/rogpeppe/go-internal v1.8.1 + github.com/rogpeppe/go-internal v1.9.0 github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 @@ -147,7 +147,7 @@ require ( github.com/blang/semver v3.5.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect - github.com/cockroachdb/apd/v2 v2.0.1 // indirect + github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/containerd/continuity v0.1.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect @@ -285,7 +285,7 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9 // indirect golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect diff --git a/go.sum b/go.sum index 69a60d461..a7e140b66 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -cuelang.org/go v0.4.4-0.20220729051708-0a46a1624353 h1:zKp5hMLvsOulekPnhK2HaXKeXBTTfSzy209Yc01DPD8= -cuelang.org/go v0.4.4-0.20220729051708-0a46a1624353/go.mod h1:LGl1HbaGIFxblk2o2nM53YSW5KN3jmjh4c5jpHMs7rc= +cuelang.org/go v0.4.4-0.20220914123050-d3959ebce916 h1:3CQ0Z4qfmd9jwujD6nf+gXSjjTJ+vkIWTXXx7onV8Y8= +cuelang.org/go v0.4.4-0.20220914123050-d3959ebce916/go.mod h1:nxWFAPWKYvZJ+eYayxArWqKKjdBTeU1N52vJpML/c6w= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/AlecAivazis/survey/v2 v2.1.1 h1:LEMbHE0pLj75faaVEKClEX1TM4AJmmnOh9eimREzLWI= @@ -405,10 +405,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/apd/v2 v2.0.1 h1:y1Rh3tEU89D+7Tgbw+lp52T6p/GJLpDmNvr10UWqLTE= -github.com/cockroachdb/apd/v2 v2.0.1/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= @@ -1378,13 +1376,13 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kubevela/pkg v0.0.0-20220905083925-331e331a12e1/go.mod h1:281yP5rMV+jYzxngUtM/FeZvAbqWEIow9tSamHHcDvI= +github.com/kubevela/pkg v0.0.0-20220908032550-a8e915458e61/go.mod h1:281yP5rMV+jYzxngUtM/FeZvAbqWEIow9tSamHHcDvI= github.com/kubevela/pkg v0.0.0-20220913093640-a41193098f92 h1:B4GkHf6rdLC4x2Clya1GKAGGo683fHgNDE4IHAOSSKQ= github.com/kubevela/pkg v0.0.0-20220913093640-a41193098f92/go.mod h1:mGQEK3fAX9MkOGexLOm7H+h99SdqZSsUzTmVLgzpSdg= github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f h1:1lUtU1alPThdcsn4MI6XjPb7eJLuZPpmlEdgjtnUMKw= github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f/go.mod h1:m724/7ANnB/iukyHW20+DicpeJMEC/JA0ZhgsHY10MA= -github.com/kubevela/workflow v0.0.0-20220905111757-ae9387b554de h1:n5vkROgxW64Jq+Or6Ku9w/PDPRNypav2Ud1vJDxukWs= -github.com/kubevela/workflow v0.0.0-20220905111757-ae9387b554de/go.mod h1:8Mb05FAcLgYgLORBDgZQOqvrSt72KAum0zP4kuUE7LU= +github.com/kubevela/workflow v0.0.0-20220915143429-7b383f5062c8 h1:UKDlR6uZ2NR4QvVx7U8G8QyOGkWI24HNc7m6qkRZJrc= +github.com/kubevela/workflow v0.0.0-20220915143429-7b383f5062c8/go.mod h1:WoXQ2Y+1mSqJSCuNhAAvUvH6r6AGlLbE6PPgFyjoy5w= github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30= github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= @@ -1880,8 +1878,8 @@ github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubenv/sql-migrate v0.0.0-20210614095031-55d5740dbbcc h1:BD7uZqkN8CpjJtN/tScAKiccBikU4dlqe/gNrkRaPY4= @@ -2350,8 +2348,9 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9 h1:VtCrPQXM5Wo9l7XN64SjBMczl48j8mkP+2e3OhYlz+0= +golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/pkg/cue/convert.go b/pkg/cue/convert.go index cdeb477e1..4bfcf6a4e 100644 --- a/pkg/cue/convert.go +++ b/pkg/cue/convert.go @@ -34,6 +34,7 @@ import ( var ErrParameterNotExist = errors.New("parameter not exist") // GetParameters get parameter from cue template +// nolint:staticcheck func GetParameters(templateStr string, pd *packages.PackageDiscover) ([]types.Parameter, error) { template, err := value.NewValue(templateStr+BaseTemplate, pd, "") if err != nil { diff --git a/pkg/cue/definition/template.go b/pkg/cue/definition/template.go index 044f67da4..44361c41b 100644 --- a/pkg/cue/definition/template.go +++ b/pkg/cue/definition/template.go @@ -91,6 +91,7 @@ func NewWorkloadAbstractEngine(name string, pd *packages.PackageDiscover) Abstra } // Complete do workload definition's rendering +// nolint:staticcheck func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string, params interface{}) error { bi := build.NewContext().NewInstance("", nil) if err := value.AddFile(bi, "-", renderTemplate(abstractTemplate)); err != nil { @@ -288,7 +289,7 @@ func NewTraitAbstractEngine(name string, pd *packages.PackageDiscover) AbstractE } // Complete do trait definition's rendering -// nolint:gocyclo +// nolint:staticcheck,gocyclo func (td *traitDef) Complete(ctx process.Context, abstractTemplate string, params interface{}) error { bi := build.NewContext().NewInstance("", nil) buff := abstractTemplate + "\n" diff --git a/pkg/definition/go_gen_test.go b/pkg/definition/go_gen_test.go index 336f3219f..c50dc4939 100644 --- a/pkg/definition/go_gen_test.go +++ b/pkg/definition/go_gen_test.go @@ -317,7 +317,6 @@ func TestGenAllDef(t *testing.T) { "export2config.cue", "webhook.cue", "notification.cue", - "webhook-notification.cue", "env.cue", "command.cue", diff --git a/pkg/utils/common/common.go b/pkg/utils/common/common.go index 0e9c730dc..7a58a993a 100644 --- a/pkg/utils/common/common.go +++ b/pkg/utils/common/common.go @@ -234,6 +234,7 @@ func HTTPGetKubernetesObjects(ctx context.Context, url string) ([]*unstructured. } // GetCUEParameterValue converts definitions to cue format +// nolint:staticcheck func GetCUEParameterValue(cueStr string, pd *packages.PackageDiscover) (cue.Value, error) { template, err := value.NewValue(cueStr+velacue.BaseTemplate, pd, "") if err != nil { diff --git a/references/docgen/cluster_test.go b/references/docgen/cluster_test.go index d1cbffb76..df0ec6bc6 100644 --- a/references/docgen/cluster_test.go +++ b/references/docgen/cluster_test.go @@ -30,9 +30,11 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" corev1beta1 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" @@ -233,6 +235,16 @@ var _ = Describe("test GetCapabilityByName", func() { Expect(k8sClient.Create(ctx, &td2)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) }) + AfterEach(func() { + for _, obj := range []client.Object{&cd1, &cd2, &cd3, &cd4, &td1, &td2, &td3} { + key := client.ObjectKeyFromObject(obj) + Expect(k8sClient.Delete(ctx, obj)).Should(Succeed()) + Eventually(func(g Gomega) { + g.Expect(k8sClient.Get(ctx, key, obj)).Should(Satisfy(errors.IsNotFound)) + }, 10*time.Second).Should(Succeed()) + } + }) + It("get capability", func() { Context("ComponentDefinition is in the current namespace", func() { _, err := GetCapabilityByName(ctx, c, component1, ns, nil) @@ -301,15 +313,9 @@ var _ = Describe("test GetNamespacedCapabilitiesFromCluster", func() { component1 = "cd1" component2 = "cd2" - By("clean namespace") - _ = k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}) - _ = k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: defaultNS}}) - By("create namespace") - Eventually(func(g Gomega) { - g.Expect(k8sClient.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}})).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - g.Expect(k8sClient.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: defaultNS}})).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - }, 15*time.Second).Should(Succeed()) + Expect(k8sClient.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}})).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + Expect(k8sClient.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: defaultNS}})).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) By("create ComponentDefinition") data, _ := os.ReadFile("testdata/componentDef.yaml") @@ -325,6 +331,16 @@ var _ = Describe("test GetNamespacedCapabilitiesFromCluster", func() { }) + AfterEach(func() { + for _, obj := range []client.Object{&cd1, &cd2} { + key := client.ObjectKeyFromObject(obj) + Expect(k8sClient.Delete(ctx, obj)).Should(Succeed()) + Eventually(func(g Gomega) { + g.Expect(k8sClient.Get(ctx, key, obj)).Should(Satisfy(errors.IsNotFound)) + }, 10*time.Second).Should(Succeed()) + } + }) + It("get namespaced capabilities", func() { Context("found all capabilities", func() { capabilities, err := GetNamespacedCapabilitiesFromCluster(ctx, ns, c, nil) diff --git a/references/docgen/def-doc/workflowstep/suspend.eg.md b/references/docgen/def-doc/workflowstep/suspend.eg.md index 9ef055571..b87b33e4e 100644 --- a/references/docgen/def-doc/workflowstep/suspend.eg.md +++ b/references/docgen/def-doc/workflowstep/suspend.eg.md @@ -16,9 +16,11 @@ spec: workflow: steps: - name: slack-message - type: webhook-notification + type: notification properties: slack: + url: + value: # the Slack webhook address, please refer to: https://api.slack.com/messaging/webhooks message: text: Ready to apply the application, ask the administrator to approve and resume the workflow. @@ -27,5 +29,7 @@ spec: # properties: # duration: "30s" - name: express-server - type: apply-application + type: apply-component + properties: + component: express-server ``` \ No newline at end of file diff --git a/test/e2e-test/application_test.go b/test/e2e-test/application_test.go index 0082bbc81..467749ae8 100644 --- a/test/e2e-test/application_test.go +++ b/test/e2e-test/application_test.go @@ -39,208 +39,210 @@ import ( "github.com/oam-dev/kubevela/pkg/utils/common" ) +func createNamespace(ctx context.Context, namespaceName string) corev1.Namespace { + ns := corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespaceName, + }, + } + // delete the namespaceName with all its resources + Eventually( + func() error { + return k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground)) + }, + time.Second*120, time.Millisecond*500).Should(SatisfyAny(BeNil(), &util.NotFoundMatcher{})) + By("make sure all the resources are removed") + objectKey := client.ObjectKey{ + Name: namespaceName, + } + res := &corev1.Namespace{} + Eventually( + func() error { + return k8sClient.Get(ctx, objectKey, res) + }, + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + Eventually( + func() error { + return k8sClient.Create(ctx, &ns) + }, + time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + return ns +} + +func createServiceAccount(ctx context.Context, ns, name string) { + sa := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: name, + }, + } + Eventually( + func() error { + return k8sClient.Create(ctx, &sa) + }, + time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) +} + +func applyApp(ctx context.Context, namespaceName, source string, app *v1beta1.Application) { + By("Apply an application") + var newApp v1beta1.Application + Expect(common.ReadYamlToObject("testdata/app/"+source, &newApp)).Should(BeNil()) + newApp.Namespace = namespaceName + Eventually(func() error { + return k8sClient.Create(ctx, newApp.DeepCopy()) + }, 10*time.Second, 500*time.Millisecond).Should(Succeed()) + + By("Get Application latest status") + Eventually( + func() *oamcomm.Revision { + k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: newApp.Name}, app) + if app.Status.LatestRevision != nil { + return app.Status.LatestRevision + } + return nil + }, + time.Second*30, time.Millisecond*500).ShouldNot(BeNil()) +} + +func updateApp(ctx context.Context, namespaceName, target string, app *v1beta1.Application) { + By("Update the application to target spec during rolling") + var targetApp v1beta1.Application + Expect(common.ReadYamlToObject("testdata/app/"+target, &targetApp)).Should(BeNil()) + + Eventually( + func() error { + k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: app.Name}, app) + app.Spec = targetApp.Spec + return k8sClient.Update(ctx, app) + }, time.Second*5, time.Millisecond*500).Should(Succeed()) +} + +func verifyApplicationPhase(ctx context.Context, ns, appName string, expected oamcomm.ApplicationPhase) { + var testApp v1beta1.Application + Eventually(func() error { + err := k8sClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: appName}, &testApp) + if err != nil { + return err + } + if testApp.Status.Phase != expected { + return fmt.Errorf("application status wants %s, actually %s", expected, testApp.Status.Phase) + } + return nil + }, 120*time.Second, time.Second).Should(BeNil()) +} + +func verifyApplicationDelaySuspendExpected(ctx context.Context, ns, appName, suspendStep, nextStep, duration string) { + var testApp v1beta1.Application + Eventually(func() error { + waitDuration, err := time.ParseDuration(duration) + if err != nil { + return err + } + + err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: appName}, &testApp) + if err != nil { + return err + } + + if testApp.Status.Workflow == nil { + return fmt.Errorf("application wait to start workflow") + } + + if testApp.Status.Workflow.Finished { + var suspendStartTime, nextStepStartTime metav1.Time + var sFlag, nFlag bool + + for _, wfStatus := range testApp.Status.Workflow.Steps { + if wfStatus.Name == suspendStep { + suspendStartTime = wfStatus.FirstExecuteTime + sFlag = true + continue + } + + if wfStatus.Name == nextStep { + nextStepStartTime = wfStatus.FirstExecuteTime + nFlag = true + } + } + + if !sFlag { + return fmt.Errorf("application can not find suspend step: %s", suspendStep) + } + + if !nFlag { + return fmt.Errorf("application can not find next step: %s", nextStep) + } + + dd := nextStepStartTime.Sub(suspendStartTime.Time) + if waitDuration > dd { + return fmt.Errorf("application suspend wait duration wants more than %s, actually %s", duration, dd.String()) + } + + return nil + } + return fmt.Errorf("application status workflow finished wants true, actually false") + }, 120*time.Second, time.Second).Should(BeNil()) +} + +func verifyWorkloadRunningExpected(ctx context.Context, namespaceName, workloadName string, replicas int32, image string) { + var workload v1.Deployment + By("Verify Workload running as expected") + Eventually( + func() error { + if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: workloadName}, &workload); err != nil { + return err + } + if workload.Status.ReadyReplicas != replicas { + return fmt.Errorf("expect replicas %v != real %v", replicas, workload.Status.ReadyReplicas) + } + if workload.Spec.Template.Spec.Containers[0].Image != image { + return fmt.Errorf("expect replicas %v != real %v", image, workload.Spec.Template.Spec.Containers[0].Image) + } + return nil + }, + time.Second*60, time.Millisecond*500).Should(BeNil()) +} + var _ = Describe("Application Normal tests", func() { ctx := context.Background() var namespaceName string var ns corev1.Namespace - var app v1beta1.Application - - createNamespace := func() { - ns = corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: namespaceName, - }, - } - // delete the namespaceName with all its resources - Eventually( - func() error { - return k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground)) - }, - time.Second*120, time.Millisecond*500).Should(SatisfyAny(BeNil(), &util.NotFoundMatcher{})) - By("make sure all the resources are removed") - objectKey := client.ObjectKey{ - Name: namespaceName, - } - res := &corev1.Namespace{} - Eventually( - func() error { - return k8sClient.Get(ctx, objectKey, res) - }, - time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) - Eventually( - func() error { - return k8sClient.Create(ctx, &ns) - }, - time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - } - - createServiceAccount := func(ns, name string) { - sa := corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns, - Name: name, - }, - } - Eventually( - func() error { - return k8sClient.Create(ctx, &sa) - }, - time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - } - - applyApp := func(source string) { - By("Apply an application") - var newApp v1beta1.Application - Expect(common.ReadYamlToObject("testdata/app/"+source, &newApp)).Should(BeNil()) - newApp.Namespace = namespaceName - Eventually(func() error { - return k8sClient.Create(ctx, newApp.DeepCopy()) - }, 10*time.Second, 500*time.Millisecond).Should(Succeed()) - - By("Get Application latest status") - Eventually( - func() *oamcomm.Revision { - k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: newApp.Name}, &app) - if app.Status.LatestRevision != nil { - return app.Status.LatestRevision - } - return nil - }, - time.Second*30, time.Millisecond*500).ShouldNot(BeNil()) - } - - updateApp := func(target string) { - By("Update the application to target spec during rolling") - var targetApp v1beta1.Application - Expect(common.ReadYamlToObject("testdata/app/"+target, &targetApp)).Should(BeNil()) - - Eventually( - func() error { - k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: app.Name}, &app) - app.Spec = targetApp.Spec - return k8sClient.Update(ctx, &app) - }, time.Second*5, time.Millisecond*500).Should(Succeed()) - } - - verifyApplicationPhase := func(ns, appName string, expected oamcomm.ApplicationPhase) { - var testApp v1beta1.Application - Eventually(func() error { - err := k8sClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: appName}, &testApp) - if err != nil { - return err - } - if testApp.Status.Phase != expected { - return fmt.Errorf("application status wants %s, actually %s", expected, testApp.Status.Phase) - } - return nil - }, 120*time.Second, time.Second).Should(BeNil()) - } - - verifyApplicationDelaySuspendExpected := func(ns, appName, suspendStep, nextStep, duration string) { - var testApp v1beta1.Application - Eventually(func() error { - waitDuration, err := time.ParseDuration(duration) - if err != nil { - return err - } - - err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: appName}, &testApp) - if err != nil { - return err - } - - if testApp.Status.Workflow == nil { - return fmt.Errorf("application wait to start workflow") - } - - if testApp.Status.Workflow.Finished { - var suspendStartTime, nextStepStartTime metav1.Time - var sFlag, nFlag bool - - for _, wfStatus := range testApp.Status.Workflow.Steps { - if wfStatus.Name == suspendStep { - suspendStartTime = wfStatus.FirstExecuteTime - sFlag = true - continue - } - - if wfStatus.Name == nextStep { - nextStepStartTime = wfStatus.FirstExecuteTime - nFlag = true - } - } - - if !sFlag { - return fmt.Errorf("application can not find suspend step: %s", suspendStep) - } - - if !nFlag { - return fmt.Errorf("application can not find next step: %s", nextStep) - } - - dd := nextStepStartTime.Sub(suspendStartTime.Time) - if waitDuration > dd { - return fmt.Errorf("application suspend wait duration wants more than %s, actually %s", duration, dd.String()) - } - - return nil - } - return fmt.Errorf("application status workflow finished wants true, actually false") - }, 120*time.Second, time.Second).Should(BeNil()) - } - - verifyWorkloadRunningExpected := func(workloadName string, replicas int32, image string) { - var workload v1.Deployment - By("Verify Workload running as expected") - Eventually( - func() error { - if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: workloadName}, &workload); err != nil { - return err - } - if workload.Status.ReadyReplicas != replicas { - return fmt.Errorf("expect replicas %v != real %v", replicas, workload.Status.ReadyReplicas) - } - if workload.Spec.Template.Spec.Containers[0].Image != image { - return fmt.Errorf("expect replicas %v != real %v", image, workload.Spec.Template.Spec.Containers[0].Image) - } - return nil - }, - time.Second*60, time.Millisecond*500).Should(BeNil()) - } + var app *v1beta1.Application BeforeEach(func() { By("Start to run a test, clean up previous resources") namespaceName = "app-normal-e2e-test" + "-" + strconv.FormatInt(rand.Int63(), 16) - createNamespace() + ns = createNamespace(ctx, namespaceName) + app = &v1beta1.Application{} }) AfterEach(func() { By("Clean up resources after a test") - k8sClient.Delete(ctx, &app) + k8sClient.Delete(ctx, app) By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name)) // delete the namespaceName with all its resources Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil()) }) It("Test app created normally", func() { - applyApp("app1.yaml") + applyApp(ctx, namespaceName, "app1.yaml", app) By("Apply the application rollout go directly to the target") - verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:4.0.3") + verifyWorkloadRunningExpected(ctx, namespaceName, "myweb", 1, "stefanprodan/podinfo:4.0.3") By("Update app with trait") - updateApp("app2.yaml") + updateApp(ctx, namespaceName, "app2.yaml", app) By("Apply the application rollout go directly to the target") - verifyWorkloadRunningExpected("myweb", 2, "stefanprodan/podinfo:4.0.3") + verifyWorkloadRunningExpected(ctx, namespaceName, "myweb", 2, "stefanprodan/podinfo:4.0.3") By("Update app with trait updated") - updateApp("app3.yaml") + updateApp(ctx, namespaceName, "app3.yaml", app) By("Apply the application rollout go directly to the target") - verifyWorkloadRunningExpected("myweb", 3, "stefanprodan/podinfo:4.0.3") + verifyWorkloadRunningExpected(ctx, namespaceName, "myweb", 3, "stefanprodan/podinfo:4.0.3") By("Update app with trait and workload image updated") - updateApp("app4.yaml") + updateApp(ctx, namespaceName, "app4.yaml", app) By("Apply the application rollout go directly to the target") - verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:5.0.2") + verifyWorkloadRunningExpected(ctx, namespaceName, "myweb", 1, "stefanprodan/podinfo:5.0.2") }) It("Test app have component with multiple same type traits", func() { @@ -250,7 +252,7 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, traitDef)).Should(BeNil()) By("apply application") - applyApp("app7.yaml") + applyApp(ctx, namespaceName, "app7.yaml", app) appName := "test-worker" By("check application status") @@ -314,7 +316,7 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) By("check application status") - verifyApplicationPhase(newApp.Namespace, newApp.Name, oamcomm.ApplicationWorkflowFailed) + verifyApplicationPhase(ctx, newApp.Namespace, newApp.Name, oamcomm.ApplicationWorkflowFailed) }) It("Test app with notification and custom if", func() { @@ -325,7 +327,7 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) By("check application status") - verifyWorkloadRunningExpected("comp-custom-if", 1, "crccheck/hello-world") + verifyWorkloadRunningExpected(ctx, namespaceName, "comp-custom-if", 1, "crccheck/hello-world") }) It("Test wait suspend", func() { @@ -336,13 +338,13 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) By("check application suspend duration") - verifyApplicationDelaySuspendExpected(newApp.Namespace, newApp.Name, "suspend-test", "apply-wait-suspend-comp", "30s") + verifyApplicationDelaySuspendExpected(ctx, newApp.Namespace, newApp.Name, "suspend-test", "apply-wait-suspend-comp", "30s") }) It("Test app with ServiceAccount", func() { By("Creating a ServiceAccount") const saName = "app-service-account" - createServiceAccount(namespaceName, saName) + createServiceAccount(ctx, namespaceName, saName) By("Creating Role and RoleBinding") const roleName = "worker" @@ -391,7 +393,7 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) By("Checking an application status") - verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:4.0.3") + verifyWorkloadRunningExpected(ctx, namespaceName, "myweb", 1, "stefanprodan/podinfo:4.0.3") Expect(k8sClient.Delete(ctx, &newApp)).Should(Succeed()) Eventually(func(g Gomega) { @@ -402,7 +404,7 @@ var _ = Describe("Application Normal tests", func() { It("Test app with ServiceAccount which has no permission for the component", func() { By("Creating a ServiceAccount") const saName = "dummy-service-account" - createServiceAccount(namespaceName, saName) + createServiceAccount(ctx, namespaceName, saName) By("Creating an application") var newApp v1beta1.Application @@ -414,7 +416,7 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) By("Checking an application status") - verifyApplicationPhase(newApp.Namespace, newApp.Name, oamcomm.ApplicationWorkflowFailed) + verifyApplicationPhase(ctx, newApp.Namespace, newApp.Name, oamcomm.ApplicationWorkflowFailed) }) It("Test app with non-existence ServiceAccount", func() { @@ -442,7 +444,7 @@ var _ = Describe("Application Normal tests", func() { Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) By("Checking an application status") - verifyApplicationPhase(newApp.Namespace, newApp.Name, oamcomm.ApplicationWorkflowFailed) + verifyApplicationPhase(ctx, newApp.Namespace, newApp.Name, oamcomm.ApplicationWorkflowFailed) }) It("Test app with replication policy", func() { @@ -454,18 +456,18 @@ var _ = Describe("Application Normal tests", func() { }, 10*time.Second, 500*time.Millisecond).Should(SatisfyAny(util.AlreadyExistMatcher{}, BeNil())) By("Creating an application") - applyApp("app_replication.yaml") + applyApp(ctx, namespaceName, "app_replication.yaml", app) By("Checking the replication & application status") - verifyWorkloadRunningExpected("hello-rep-beijing", 1, "crccheck/hello-world") - verifyWorkloadRunningExpected("hello-rep-hangzhou", 1, "crccheck/hello-world") + verifyWorkloadRunningExpected(ctx, namespaceName, "hello-rep-beijing", 1, "crccheck/hello-world") + verifyWorkloadRunningExpected(ctx, namespaceName, "hello-rep-hangzhou", 1, "crccheck/hello-world") By("Checking the origin component are not be dispatched") var workload v1.Deployment err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "hello-rep"}, &workload) Expect(err).Should(SatisfyAny(&util.NotFoundMatcher{})) By("Checking the component not replicated & application status") - verifyWorkloadRunningExpected("hello-no-rep", 1, "crccheck/hello-world") + verifyWorkloadRunningExpected(ctx, namespaceName, "hello-no-rep", 1, "crccheck/hello-world") var svc corev1.Service By("Verify Service running as expected") @@ -480,7 +482,7 @@ var _ = Describe("Application Normal tests", func() { verifySeriveDispatched("hello-rep-hangzhou") By("Checking the services not replicated & application status") - verifyWorkloadRunningExpected("hello-no-rep", 1, "crccheck/hello-world") + verifyWorkloadRunningExpected(ctx, namespaceName, "hello-no-rep", 1, "crccheck/hello-world") }) }) diff --git a/test/e2e-test/definition_test.go b/test/e2e-test/definition_test.go index ee0ac16b9..bd10b63d2 100644 --- a/test/e2e-test/definition_test.go +++ b/test/e2e-test/definition_test.go @@ -19,8 +19,12 @@ package controllers_test import ( "context" "fmt" + "path/filepath" + "runtime" + "strings" "time" + testdef "github.com/kubevela/pkg/util/test/definition" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -32,6 +36,7 @@ import ( "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" + utilcommon "github.com/oam-dev/kubevela/pkg/utils/common" ) var _ = Describe("ComponentDefinition Normal tests", func() { @@ -54,6 +59,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() { k8sClient.DeleteAllOf(ctx, &v1beta1.ComponentDefinition{}, client.InNamespace(namespace)) k8sClient.DeleteAllOf(ctx, &v1beta1.WorkloadDefinition{}, client.InNamespace(namespace)) k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace)) + k8sClient.DeleteAllOf(ctx, &v1beta1.WorkflowStepDefinition{}, client.InNamespace(namespace)) k8sClient.DeleteAllOf(ctx, &v1beta1.DefinitionRevision{}, client.InNamespace(namespace)) By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name)) @@ -219,4 +225,27 @@ var _ = Describe("ComponentDefinition Normal tests", func() { Expect(k8sClient.Create(ctx, newTd)).Should(HaveOccurred()) }) }) + + It("Test notification step definition", func() { + _, file, _, _ := runtime.Caller(0) + Expect(testdef.InstallDefinitionFromYAML(ctx, k8sClient, filepath.Join(file, "../../../charts/vela-core/templates/defwithtemplate/notification.yaml"), func(s string) string { + return strings.ReplaceAll(s, `{{ include "systemDefinitionNamespace" . }}`, "vela-system") + })).Should(SatisfyAny(Succeed(), &util.AlreadyExistMatcher{})) + Expect(k8sClient.Create(ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-secret", + Namespace: "default", + }, + StringData: map[string]string{"url": "https://kubevela.io"}, + })).Should(SatisfyAny(Succeed(), &util.AlreadyExistMatcher{})) + var newApp v1beta1.Application + Expect(utilcommon.ReadYamlToObject("testdata/app/app_notification_secret.yaml", &newApp)).Should(BeNil()) + Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) + verifyApplicationPhase(context.TODO(), newApp.Namespace, newApp.Name, common.ApplicationRunning) + + newApp = v1beta1.Application{} + Expect(utilcommon.ReadYamlToObject("testdata/app/app_notification.yaml", &newApp)).Should(BeNil()) + Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) + verifyApplicationPhase(context.TODO(), newApp.Namespace, newApp.Name, common.ApplicationRunning) + }) }) diff --git a/test/e2e-test/testdata/app/app_notification.yaml b/test/e2e-test/testdata/app/app_notification.yaml new file mode 100644 index 000000000..37ce17d70 --- /dev/null +++ b/test/e2e-test/testdata/app/app_notification.yaml @@ -0,0 +1,17 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: noti + namespace: default +spec: + components: [] + workflow: + steps: + - name: notification + type: notification + properties: + slack: + url: + value: https://kubevela.io + message: + text: hello world \ No newline at end of file diff --git a/test/e2e-test/testdata/app/app_notification_secret.yaml b/test/e2e-test/testdata/app/app_notification_secret.yaml new file mode 100644 index 000000000..cd8e333bb --- /dev/null +++ b/test/e2e-test/testdata/app/app_notification_secret.yaml @@ -0,0 +1,19 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: noti-secret + namespace: default +spec: + components: [] + workflow: + steps: + - name: notification + type: notification + properties: + slack: + url: + secretRef: + name: my-secret + key: url + message: + text: hello world \ No newline at end of file diff --git a/vela-templates/definitions/deprecated/webhook-notification.cue b/vela-templates/definitions/deprecated/webhook-notification.cue deleted file mode 100644 index 2f7d0f185..000000000 --- a/vela-templates/definitions/deprecated/webhook-notification.cue +++ /dev/null @@ -1,264 +0,0 @@ -import ( - "vela/op" - "encoding/base64" -) - -"webhook-notification": { - type: "workflow-step" - annotations: {} - labels: { - "deprecated": "true" - } - description: "Send message to webhook. This definition is DEPRECATED, please use 'notification' instead." -} -template: { - - parameter: { - dingding?: { - url: value | secretRef - message: { - text?: *null | { - content: string - } - // +usage=msgType can be text, link, mardown, actionCard, feedCard - msgtype: string - link?: *null | { - text?: string - title?: string - messageUrl?: string - picUrl?: string - } - markdown?: *null | { - text: string - title: string - } - at?: *null | { - atMobiles?: *null | [...string] - isAtAll?: bool - } - actionCard?: *null | { - text: string - title: string - hideAvatar: string - btnOrientation: string - singleTitle: string - singleURL: string - btns: *null | [...*null | { - title: string - actionURL: string - }] - } - feedCard?: *null | { - links: *null | [...*null | { - text?: string - title?: string - messageUrl?: string - picUrl?: string - }] - } - } - } - - slack?: { - url: value | secretRef - message: { - text: string - blocks?: *null | [...block] - attachments?: *null | { - blocks?: *null | [...block] - color?: string - } - thread_ts?: string - mrkdwn?: *true | bool - } - } - - email?: { - from: { - address: string - alias?: string - password: value | secretRef - host: string - port: *587 | int - } - to: [...string] - content: { - subject: string - body: string - } - } - } - - block: { - type: string - block_id?: string - elements?: [...{ - type: string - action_id?: string - url?: string - value?: string - style?: string - text?: textType - confirm?: { - title: textType - text: textType - confirm: textType - deny: textType - style?: string - } - options?: [...option] - initial_options?: [...option] - placeholder?: textType - initial_date?: string - image_url?: string - alt_text?: string - option_groups?: [...option] - max_selected_items?: int - initial_value?: string - multiline?: bool - min_length?: int - max_length?: int - dispatch_action_config?: { - trigger_actions_on?: [...string] - } - initial_time?: string - }] - } - - textType: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - - option: { - text: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - value: string - description?: { - type: string - text: string - emoji?: bool - verbatim?: bool - } - url?: string - } - - secretRef: { - name: string - key: string - } - - value: string - - // send webhook notification - ding: op.#Steps & { - if parameter.dingding != _|_ { - if parameter.dingding.url.value != _|_ { - ding1: op.#DingTalk & { - message: parameter.dingding.message - dingUrl: parameter.dingding.url.value - } - } - if parameter.dingding.url.secretRef != _|_ && parameter.dingding.url.value == _|_ { - read: op.#Read & { - value: { - apiVersion: "v1" - kind: "Secret" - metadata: { - name: parameter.dingding.url.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - ding2: op.#DingTalk & { - message: parameter.dingding.message - dingUrl: stringValue.str - } - } - } - } - - slack: op.#Steps & { - if parameter.slack != _|_ { - if parameter.slack.url.value != _|_ { - slack1: op.#Slack & { - message: parameter.slack.message - slackUrl: parameter.slack.url.value - } - } - if parameter.slack.url.secretRef != _|_ && parameter.slack.url.value == _|_ { - read: op.#Read & { - value: { - kind: "Secret" - apiVersion: "v1" - metadata: { - name: parameter.slack.url.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - slack2: op.#Slack & { - message: parameter.slack.message - slackUrl: stringValue.str - } - } - } - } - - email: op.#Steps & { - if parameter.email != _|_ { - if parameter.email.from.password.value != _|_ { - email1: op.#SendEmail & { - from: { - address: parameter.email.from.value - alias: parameter.email.from.alias - password: parameter.email.from.password.value - host: parameter.email.from.host - port: parameter.email.from.port - } - to: parameter.email.to - content: parameter.email.content - } - } - - if parameter.email.from.password.secretRef != _|_ && parameter.email.from.password.value == _|_ { - read: op.#Read & { - value: { - kind: "Secret" - apiVersion: "v1" - metadata: { - name: parameter.email.from.password.secretRef.name - namespace: context.namespace - } - } - } - - decoded: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} - email2: op.#SendEmail & { - from: { - address: parameter.email.from.value - alias: parameter.email.from.alias - password: stringValue.str - host: parameter.email.from.host - port: parameter.email.from.port - } - to: parameter.email.to - content: parameter.email.content - } - } - } - } -} diff --git a/vela-templates/definitions/internal/workflowstep/notification.cue b/vela-templates/definitions/internal/workflowstep/notification.cue index 19f3cc18e..e616232ec 100644 --- a/vela-templates/definitions/internal/workflowstep/notification.cue +++ b/vela-templates/definitions/internal/workflowstep/notification.cue @@ -1,6 +1,7 @@ import ( "vela/op" "encoding/base64" + "encoding/json" ) "notification": { @@ -15,10 +16,10 @@ template: { // +usage=Please fulfill its url and message if you want to send Lark messages lark?: { // +usage=Specify the the lark url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -37,10 +38,10 @@ template: { // +usage=Please fulfill its url and message if you want to send DingTalk messages dingding?: { // +usage=Specify the the dingding url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -95,10 +96,10 @@ template: { // +usage=Please fulfill its url and message if you want to send Slack messages slack?: { // +usage=Specify the the slack url, you can either sepcify it in value or use secretRef - url: { + url: close({ // +usage=the url address content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -129,10 +130,10 @@ template: { // +usage=The alias is the email alias to show after sending the email alias?: string // +usage=Specify the password of the email, you can either sepcify it in value or use secretRef - password: { + password: close({ // +usage=the password content in string value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string @@ -238,8 +239,7 @@ template: { } } - decoded: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key])} ding2: op.#DingTalk & { message: parameter.dingding.message dingUrl: stringValue.str @@ -268,8 +268,7 @@ template: { } } - decoded: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key])} lark2: op.#Lark & { message: parameter.lark.message larkUrl: stringValue.str @@ -298,8 +297,7 @@ template: { } } - decoded: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key])} slack2: op.#Slack & { message: parameter.slack.message slackUrl: stringValue.str @@ -338,8 +336,7 @@ template: { } } - decoded: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key]) - stringValue: op.#ConvertString & {bt: decoded} + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key])} email2: op.#SendEmail & { from: { address: parameter.email.from.address diff --git a/vela-templates/definitions/internal/workflowstep/webhook.cue b/vela-templates/definitions/internal/workflowstep/webhook.cue index 4ee690fee..3599aa368 100644 --- a/vela-templates/definitions/internal/workflowstep/webhook.cue +++ b/vela-templates/definitions/internal/workflowstep/webhook.cue @@ -51,23 +51,22 @@ template: { } } @step(5) - decoded: base64.Decode(null, read.value.data[parameter.url.secretRef.key]) @step(6) - stringValue: op.#ConvertString & {bt: decoded} @step(7) + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} @step(6) http: op.#HTTPPost & { url: stringValue.str request: { body: data.value header: "Content-Type": "application/json" } - } @step(8) + } @step(7) } } parameter: { // +usage=Specify the webhook url - url: { + url: close({ value: string - } | close({ + }) | close({ secretRef: { // +usage=name is the name of the secret name: string