Chore: update cue version to attr and notification (#4734)

* Chore: update cue version to attr and notification

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

* Fix: docgen test

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
Co-authored-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
Tianxin Dong
2022-09-16 16:28:35 +08:00
committed by GitHub
co-authored by Somefive
parent b898cecf2f
commit cd9ac72531
21 changed files with 356 additions and 1052 deletions
@@ -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
@@ -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
}
}
}
}
@@ -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
@@ -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
@@ -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
}
}
}
}
@@ -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
+5 -5
View File
@@ -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
+11 -12
View File
@@ -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=
+1
View File
@@ -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 {
+2 -1
View File
@@ -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"
-1
View File
@@ -317,7 +317,6 @@ func TestGenAllDef(t *testing.T) {
"export2config.cue",
"webhook.cue",
"notification.cue",
"webhook-notification.cue",
"env.cue",
"command.cue",
+1
View File
@@ -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 {
+24 -8
View File
@@ -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)
@@ -16,9 +16,11 @@ spec:
workflow:
steps:
- name: slack-message
type: webhook-notification
type: notification
properties:
slack:
url:
value: <your-slack-url>
# 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
```
+190 -188
View File
@@ -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")
})
})
+29
View File
@@ -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)
})
})
+17
View File
@@ -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
+19
View File
@@ -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
@@ -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
}
}
}
}
}
@@ -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
@@ -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