Skip to main content
Version: v1.7

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 and learn the basics of CUE

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"
}