mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 03:56:36 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -317,7 +317,6 @@ func TestGenAllDef(t *testing.T) {
|
||||
"export2config.cue",
|
||||
"webhook.cue",
|
||||
"notification.cue",
|
||||
"webhook-notification.cue",
|
||||
"env.cue",
|
||||
"command.cue",
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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")
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user