kubevela.github.io/docs/platform-engineers/workflow/cue-actions.md

758 lines
13 KiB
Markdown

---
title: Built-in Workflow Operations
---
This document introduces the CUE operations that can be used in the workflow step definitions. You need to import the `vela/op` package to use these operations.
:::tip
Before reading this section, make sure you understand how to [customize workflow](./workflow.md) and learn the basics of [CUE](../cue/basic.md)
:::
## Process Control
### ConditionalWait
Makes the workflow step wait until the condition is met.
**Parameters**
```
#ConditionalWait: {
// +usage=If continue is false, the step will wait for continue to be true.
continue: bool
// +usage=Optional message that will be shown in workflow step status, note that the message might be override by other actions.
message?: string
}
```
**Example**
```
import "vela/op"
myRead: op.#Read & {
value: {
kind: "Deployment"
apiVersion: "apps/v1"
metadata: name: "test-app"
}
}
wait: op.#ConditionalWait & {
continue: myRead.value.status.phase == "running"
}
```
### Fail
Make the workflow step failed.
**Parameters**
```
#Fail: {
// +usage=Optional message that will be shown in workflow step status, note that the message might be override by other actions.
message?: string
}
```
**Example**
```
import "vela/op"
fail: op.#Fail & {
message: "error in the step"
}
```
## Data Control
### Log
Output the log or configure the log source for this step. If `op.#Log` is used in a step definition, then you can use `vela workflow logs <name>` to view the log for that step.
**Parameters**
```
#Log: {
// +usage=The data to print in the controller logs
data?: {...} | string
// +usage=The log level of the data
level: *3 | int
// +usage=The log source of this step. You can specify it from a url or resources. Note that if you set source in multiple op.#Log, only the latest one will work
source?: close({
// +usage=Specify the log source url of this step
url: string
}) | close({
// +usage=Specify the log resources of this step
resources?: [...{
// +usage=Specify the name of the resource
name?: string
// +usage=Specify the cluster of the resource
cluster?: string
// +usage=Specify the namespace of the resource
namespace?: string
// +usage=Specify the label selector of the resource
labelSelector?: {...}
}]
})
}
```
**Example**
```
import "vela/op"
myLog: op.#Log & {
data: "my custom log"
resources: [{
labelsSelector: {"test-key": "test-value"}
}]
}
```
### Message
Write message to the workflow step status.
**Parameters**
```
#Message: {
// +usage=Optional message that will be shown in workflow step status, note that the message might be override by other actions.
message?: string
}
```
**Example**
```
import "vela/op"
msg: op.#Message & {
message: "custom message"
}
```
### DoVar
Used to save or read user-defined data in the context of workflow.
**Parameters**
```
#DoVar: {
// +usage=The method to call on the variable
method: *"Get" | "Put"
// +usage=The path to the variable
path: string
// +usage=The value of the variable
value?: _
}
```
**Example**
```
put: op.ws.#DoVar & {
method: "Put"
path: "foo.score"
value: 100
}
// The user can get the data saved above through get.value (100)
get: op.ws.#DoVar & {
method: "Get"
path: "foo.score"
}
```
## Requests
### HTTPDo
Send HTTP request to the specified URL.
**Parameters**
```
#HTTPDo: {
// +usage=The method of HTTP request
method: *"GET" | "POST" | "PUT" | "DELETE"
// +usage=The url to request
url: string
// +usage=The request config
request?: {
// +usage=The timeout of this request
timeout?: string
// +usage=The request body
body?: string
// +usage=The header of the request
header?: [string]: string
// +usage=The trailer of the request
trailer?: [string]: string
// +usage=The rate limiter of the request
ratelimiter?: {
limit: int
period: string
}
}
// +usgae=The tls config of the request
tls_config?: secret: string
// +usage=The response of the request will be filled in this field after the action is executed
response: {
// +usage=The body of the response
body: string
// +usage=The header of the response
header?: [string]: [...string]
// +usage=The trailer of the response
trailer?: [string]: [...string]
// +usage=The status code of the response
statusCode: int
}
}
```
**Example**
```
import "vela/op"
myRequest: op.#HTTPDo & {
method: "POST"
url: "http://my-url.com"
request: {
body: {
"hello": "body"
}
}
}
```
### HTTPGet
Send HTTP GET request to the specified URL.
**Parameters**
Same as HTTPDo, but `method` has been specified as GET.
**Example**
Please refer the example in HTTPDo.
### HTTPPost
Send HTTP POST request to the specified URL.
**Parameters**
Same as HTTPDo, but `method` has been specified as POST.
**Example**
Please refer the example in HTTPDo.
### HTTPPut
Send HTTP PUT request to the specified URL.
**Parameters**
Same as HTTPDo, but `method` has been specified as PUT.
**Example**
Please refer the example in HTTPDo.
### HTTPDelete
Send HTTP DELETE request to the specified URL.
**Parameters**
Same as HTTPDo, but `method` has been specified as DELETE.
**Example**
Please refer the example in HTTPDo.
### SendEmail
Send emails.
**Parameters**
```
#SendEmail {
// +usage=The info of the sender
from: {
// +usage=The address of the sender
address: string
// +usage=The alias of the sender
alias?: string
// +usage=The password of the sender
password: string
// +usage=The host of the sender server
host: string
// +usage=The port of the sender server
port: int
}
// +usgae=The email address list of the recievers
to: [...string]
// +usage=The content of the email
content: {
// +usage=The subject of the email
subject: string
// +usage=The body of the email
body: string
}
}
```
**Example**
```
import "vela/op"
myEmail: op.#SendEmail & {
from: {
address: "hello@mail.com"
password: "password"
host: "myhost"
port: 465
}
to: ["world@mail.com", "next@workflow.com"]
content: {
subject: "Hello Vela"
body: "Hello Vela, this is a test email"
}
}
```
## Resource Management
### Apply
Apply resources in the Kubernetes cluster.
**Parameters**
```
#Apply: {
// +usage=The cluster to use
cluster: *"" | string
// +usage=The resource to apply
value: {...}
}
```
**Example**
```
import "vela/op"
myApply: op.#Apply & {
value: {
kind: "Deployment"
apiVersion: "apps/v1"
metadata: name: "test-app"
spec: {
replicas: 2
...
}
}
}
```
### ApplyInParallel
Apply resources in parallel in the Kubernetes cluster.
**Parameters**
```
#ApplyInParallel: {
// +usage=The cluster to use
cluster: *"" | string
// +usage=The resources to apply in parallel
value: [...{...}]
}
```
**Example**
```
import "vela/op"
myApply: op.#ApplyInParallel & {
value: [{
kind: "Deployment"
apiVersion: "apps/v1"
metadata: name: "test-app"
spec: {
replicas: 2
...
}
}, {
kind: "Deployment"
apiVersion: "apps/v1"
metadata: name: "test-app2"
spec: {
replicas: 2
...
}
}]
}
```
### Read
Read resources in the Kubernetes cluster.
**Parameters**
```
#Read: {
// +usage=The cluster to use
cluster: *"" | string
// +usage=The resource to read, this field will be filled with the resource read from the cluster after the action is executed
value?: {...}
...
}
```
**Example**
```
import "vela/op"
myRead: op.#Read & {
value: {
kind: "Deployment"
apiVersion: "apps/v1"
metadata: name: "test-app"
}
}
```
### List
List resources in the Kubernetes cluster.
**Parameters**
```
#List: {
// +usage=The cluster to use
cluster: *"" | string
// +usage=The resource to list
resource: {
// +usage=The api version of the resource
apiVersion: string
// +usage=The kind of the resource
kind: string
}
// +usage=The filter to list the resources
filter?: {
// +usage=The namespace to list the resources
namespace?: *"" | string
// +usage=The label selector to filter the resources
matchingLabels?: {...}
}
// +usage=The listed resources will be filled in this field after the action is executed
list?: {...}
...
}
```
**Example**
```
import "vela/op"
myList: op.#List & {
resource: {
kind: "Deployment"
apiVersion: "apps/v1"
}
filter: {
matchingLabels: {
"mylabel": "myvalue"
}
}
}
```
### Delete
Delete resources in the Kubernetes cluster.
**Parameters**
```
#Delete: {
// +usage=The cluster to use
cluster: *"" | string
// +usage=The resource to delete
value: {
// +usage=The api version of the resource
apiVersion: string
// +usage=The kind of the resource
kind: string
// +usage=The metadata of the resource
metadata: {
// +usage=The name of the resource
name?: string
// +usage=The namespace of the resource
namespace: *"default" | string
}
}
// +usage=The filter to delete the resources
filter?: {
// +usage=The namespace to list the resources
namespace?: string
// +usage=The label selector to filter the resources
matchingLabels?: {...}
}
}
```
**Example**
```
import "vela/op"
myDelete: op.#Delete & {
resource: {
kind: "Deployment"
apiVersion: "apps/v1"
metadata: name: "my-app"
}
}
```
## Application Operations
### Load
Load all the components and its traits in the application.
**Parameters**
```
#Load: {
// +usage=If specify `app`, use specified application to load its component resources otherwise use current application
app?: string
// +usage=The value of the components will be filled in this field after the action is executed, you can use value[componentName] to refer a specified component
value?: {...}
}
```
**Example**
```
import "vela/op"
// You can use `load.value.[componentName] to refer the component.
load: op.#Load & {}
mycomp: load.value["my-comp"]
```
### ApplyComponent
Create or update resources corresponding to the component in Kubernetes cluster. Note that need to use `Load` first to apply the resources.
**Parameters**
```
#ApplyComponent: {
// +usage=The cluster to use
cluster: *"" | string
// +usage=The env to use
env: *"" | string
// +usage=The namespace to apply
namespace: *"" | string
// +usage=Whether to wait healthy of the applied component
waitHealthy: *true | bool
// +usage=The value of the component resource
value: {...}
// +usage=The patcher that will be applied to the resource, you can define the strategy of list merge through comments. Reference doc here: https://kubevela.io/docs/platform-engineers/traits/patch-trait#patch-in-workflow-step
patch?: {...}
}
```
**Example**
```
import "vela/op"
load: op.#Load & {}
apply: op.#ApplyComponent & {
value: load.value["my-comp"]
}
```
### ApplyApplication
Create or update resources corresponding to the application in Kubernetes cluster.
**Parameters**
```
#ApplyApplication: {}
```
**Example**
```
import "vela/op"
apply: op.#ApplyApplication & {}
```
## Special Operations
### Steps
A combination of a set of operations that can be used to implement complex operation logic.
**Parameters**
```
#Steps: {}
```
**Example**
```
import "vela/op"
env: "prod"
app: op.#Steps & {
if env == "prod" {
load: op.#Load & {
component: "component-name"
}
apply: op.#Apply & {
value: load.value.workload
}
}
if env != "prod" {
request: op.#HTTPGet & {
url: "http://my-url.com"
}
}
}
```
## Deprecated Operations
### Slack
Send a request to the specified Slack URL. `#Slack` is actually a secondary wrapper for `#HTTPPost`, we will deprecate this operation in the next version. You can use `#HTTPPost` instead, like:
```
import (
"vela/op"
"encoding/json"
)
message: {
"hello": "world"
}
mySlack: op.#HTTPPost & {
url: "slackURL"
request: {
body: json.Marshal(message)
header: "Content-Type": "application/json"
}
}
```
**Parameters**
```
#Slack: {
message: {...}
slackUrl: string
}
```
**Example**
```
import "vela/op"
myMessage: {
"hello": "world"
}
myRequest: op.#Slack & {
message: myMessage
slackUrl: "slackURL"
}
```
### DingTalk
Send a request to the specified DingTalk URL. `#DingTalk` is actually a secondary wrapper of `#HTTPPost`, we will deprecate this operation in the next version. You can use `#HTTPPost` instead, please refer to the example in Slack action.
**Parameters**
```
#DingTalk: {
message: {...}
dingUrl: string
}
```
**Example**
```
import "vela/op"
myMessage: {
"hello": "world"
}
myRequest: op.#DingTalk & {
message: myMessage
dingUrl: "dingURL"
}
```
### Lark
Send a request to the specified Lark URL. `#Lark` is actually a secondary wrapper of `#HTTPPost`, we will deprecate this operation in the next version. You can use `#HTTPPost` instead, please refer to the example in Slack action.
**Parameters**
```
#Lark: {
message: {...}
larkUrl: string
}
```
**Example**
```
import "vela/op"
myMessage: {
"hello": "world"
}
myRequest: op.#Lark & {
message: myMessage
larkUrl: "larkURL"
}
```