mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 10:00:06 +00:00
Chore: fix definition parse logic and allow if/for comprehension & use op.#Suspend for deploy (#5743)
* Chore: fix definition parse logic and allow if/for comprehension & use op.#Suspend for deploy Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Fix: flaky mc test Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Fix: flaky mc test Signed-off-by: Somefive <yd219913@alibaba-inc.com> --------- Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
@@ -113,6 +113,7 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#labelSelector: {
|
||||
matchLabels?: [string]: string
|
||||
matchExpressions?: [...{
|
||||
@@ -121,21 +122,25 @@ spec:
|
||||
values?: [...string]
|
||||
}]
|
||||
}
|
||||
|
||||
#podAffinityTerm: {
|
||||
labelSelector?: #labelSelector
|
||||
namespaces?: [...string]
|
||||
topologyKey: string
|
||||
namespaceSelector?: #labelSelector
|
||||
}
|
||||
|
||||
#nodeSelecor: {
|
||||
key: string
|
||||
operator: *"In" | "NotIn" | "Exists" | "DoesNotExist" | "Gt" | "Lt"
|
||||
values?: [...string]
|
||||
}
|
||||
|
||||
#nodeSelectorTerm: {
|
||||
matchExpressions?: [...#nodeSelecor]
|
||||
matchFields?: [...#nodeSelecor]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the pod affinity scheduling rules
|
||||
podAffinity?: {
|
||||
|
||||
@@ -17,12 +17,14 @@ spec:
|
||||
// +usage=Specify the path of the resource that allow configuration drift
|
||||
path: [...string]
|
||||
}
|
||||
|
||||
#ApplyOncePolicyRule: {
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector?: #ResourcePolicyRuleSelector
|
||||
// +usage=Specify the strategy for configuring the resource level configuration drift behaviour
|
||||
strategy: #ApplyOnceStrategy
|
||||
}
|
||||
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -37,6 +39,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Whether to enable apply-once for the whole application
|
||||
enable: *false | bool
|
||||
|
||||
@@ -24,6 +24,7 @@ spec:
|
||||
apply: op.#ApplyRemaining & {
|
||||
parameter
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the name of the component
|
||||
exceptions?: [...string]
|
||||
|
||||
@@ -20,6 +20,7 @@ spec:
|
||||
labelselector?: {...}
|
||||
namespace: *context.namespace | string
|
||||
}
|
||||
|
||||
cleanJobs: op.#Delete & {
|
||||
value: {
|
||||
apiVersion: "batch/v1"
|
||||
@@ -39,6 +40,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanPods: op.#Delete & {
|
||||
value: {
|
||||
apiVersion: "v1"
|
||||
|
||||
@@ -35,6 +35,7 @@ spec:
|
||||
}
|
||||
}
|
||||
} @step(1)
|
||||
|
||||
outputs: {
|
||||
eps_port_name_filtered: *[] | [...]
|
||||
if parameter.portName == _|_ {
|
||||
@@ -69,9 +70,11 @@ spec:
|
||||
endpoints: eps_port_filtered
|
||||
}
|
||||
}
|
||||
|
||||
wait: op.#ConditionalWait & {
|
||||
continue: len(outputs.endpoints) > 0
|
||||
} @step(2)
|
||||
|
||||
value: {
|
||||
if len(outputs.endpoints) > 0 {
|
||||
endpoint: outputs.endpoints[0].endpoint
|
||||
@@ -79,6 +82,7 @@ spec:
|
||||
url: "\(parameter.protocal)://\(endpoint.host):\(_portStr)"
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the application
|
||||
name?: string
|
||||
|
||||
@@ -107,9 +107,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#PatchParams | close({
|
||||
// +usage=Specify the commands for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -72,9 +72,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: #PatchParams | close({
|
||||
// +usage=Specify the container image for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ spec:
|
||||
targetCPUUtilizationPercentage: parameter.cpuUtil
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the minimal number of replicas to which the autoscaler can scale down
|
||||
min: *1 | int
|
||||
|
||||
@@ -147,6 +147,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -276,6 +277,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -66,6 +66,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
|
||||
{
|
||||
@@ -114,6 +115,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -126,6 +128,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "DaemonSet"
|
||||
@@ -275,6 +278,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposePorts: [
|
||||
if parameter.ports != _|_ for v in parameter.ports if v.expose == true {
|
||||
port: v.port
|
||||
@@ -287,6 +291,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
outputs: {
|
||||
if len(exposePorts) != 0 {
|
||||
webserviceExpose: {
|
||||
@@ -301,6 +306,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -469,6 +475,7 @@ spec:
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -26,6 +26,7 @@ spec:
|
||||
// context.namespace indicates the name of the app
|
||||
name: context.name
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the name of the env-binding policy, if empty, the first env-binding policy will be used
|
||||
policy: *"" | string
|
||||
|
||||
@@ -18,6 +18,9 @@ spec:
|
||||
"vela/op"
|
||||
)
|
||||
|
||||
if parameter.auto == false {
|
||||
suspend: op.#Suspend & {message: "Waiting approval to the deploy step \"\(context.stepName)\""}
|
||||
}
|
||||
deploy: op.#Deploy & {
|
||||
policies: parameter.policies
|
||||
parallelism: parameter.parallelism
|
||||
|
||||
@@ -27,6 +27,7 @@ spec:
|
||||
// context.namespace indicates the namespace of the app
|
||||
namespace: context.namespace
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the name of the env-binding policy, if empty, the first env-binding policy will be used
|
||||
policy: *"" | string
|
||||
|
||||
@@ -41,6 +41,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the runtime clusters to apply, if empty, all runtime clusters will be used
|
||||
clusters?: [...string]
|
||||
|
||||
@@ -98,9 +98,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#PatchParams | close({
|
||||
// +usage=Specify the environment variables for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ spec:
|
||||
disable: *false | bool
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: envs: [...{
|
||||
name: string
|
||||
placement?: {
|
||||
|
||||
@@ -38,12 +38,14 @@ spec:
|
||||
stringData: parameter.data
|
||||
}
|
||||
} @step(1)
|
||||
|
||||
getPlacements: op.#GetPlacementsFromTopologyPolicies & {
|
||||
policies: *[] | [...string]
|
||||
if parameter.topology != _|_ {
|
||||
policies: [parameter.topology]
|
||||
}
|
||||
} @step(2)
|
||||
} @step(2)
|
||||
|
||||
apply: op.#Steps & {
|
||||
for p in getPlacements.placements {
|
||||
(p.cluster): op.#Apply & {
|
||||
@@ -52,6 +54,7 @@ spec:
|
||||
}
|
||||
}
|
||||
} @step(3)
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the export destination
|
||||
name?: string
|
||||
|
||||
@@ -49,12 +49,14 @@ spec:
|
||||
ports: [{port: parameter.targetPort}]
|
||||
}]
|
||||
}] @step(1)
|
||||
|
||||
getPlacements: op.#GetPlacementsFromTopologyPolicies & {
|
||||
policies: *[] | [...string]
|
||||
if parameter.topology != _|_ {
|
||||
policies: [parameter.topology]
|
||||
}
|
||||
} @step(2)
|
||||
} @step(2)
|
||||
|
||||
apply: op.#Steps & {
|
||||
for p in getPlacements.placements {
|
||||
for o in objects {
|
||||
@@ -65,6 +67,7 @@ spec:
|
||||
}
|
||||
}
|
||||
} @step(3)
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the export destination
|
||||
name?: string
|
||||
|
||||
@@ -17,6 +17,7 @@ spec:
|
||||
// +usage=Specify the strategy for target resource to recycle
|
||||
strategy: *"onAppUpdate" | "onAppDelete" | "never"
|
||||
}
|
||||
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -31,6 +32,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=If is set, outdated versioned resourcetracker will not be recycled automatically, outdated resources will be kept until resourcetracker be deleted manually
|
||||
keepLegacyResource: *false | bool
|
||||
|
||||
@@ -30,6 +30,7 @@ spec:
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
legacyAPI: context.clusterVersion.minor < 19
|
||||
outputs: ingress: {
|
||||
if legacyAPI {
|
||||
@@ -87,6 +88,7 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the domain you want to expose
|
||||
domain?: string
|
||||
@@ -126,7 +128,7 @@ spec:
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
|
||||
}
|
||||
if host != _|_ {
|
||||
if host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,13 @@ spec:
|
||||
dbName: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_NAME"])}
|
||||
username: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_USER"])}
|
||||
password: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PASSWORD"])}
|
||||
|
||||
env: [
|
||||
{name: "url", value: "jdbc://" + dbHost.str + ":" + dbPort.str + "/" + dbName.str + "?characterEncoding=utf8&useSSL=false"},
|
||||
{name: "username", value: username.str},
|
||||
{name: "password", value: password.str},
|
||||
]
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the secret generated by database component
|
||||
name: string
|
||||
|
||||
@@ -29,6 +29,7 @@ spec:
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
outputs: ingress: {
|
||||
apiVersion: "networking.k8s.io/v1"
|
||||
kind: "Ingress"
|
||||
@@ -50,6 +51,7 @@ spec:
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the domain you want to expose
|
||||
domain: string
|
||||
|
||||
@@ -29,6 +29,7 @@ spec:
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
outputs: ingress: {
|
||||
apiVersion: "networking.k8s.io/v1beta1"
|
||||
kind: "Ingress"
|
||||
@@ -46,6 +47,7 @@ spec:
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the domain you want to expose
|
||||
domain: string
|
||||
|
||||
@@ -12,6 +12,7 @@ spec:
|
||||
cue:
|
||||
template: |
|
||||
output: parameter.objects[0]
|
||||
|
||||
outputs: {
|
||||
for i, v in parameter.objects {
|
||||
if i > 0 {
|
||||
|
||||
@@ -38,6 +38,7 @@ spec:
|
||||
type: "ClusterIP"
|
||||
}
|
||||
}
|
||||
|
||||
patch: metadata: annotations: {
|
||||
"dev.nocalhost/application-name": context.appName
|
||||
"dev.nocalhost/application-namespace": context.namespace
|
||||
|
||||
@@ -159,6 +159,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
block: {
|
||||
type: string
|
||||
block_id?: string
|
||||
@@ -192,18 +193,21 @@ spec:
|
||||
initial_time?: string
|
||||
}]
|
||||
}
|
||||
|
||||
textType: {
|
||||
type: string
|
||||
text: string
|
||||
emoji?: bool
|
||||
verbatim?: bool
|
||||
}
|
||||
|
||||
option: {
|
||||
text: textType
|
||||
value: string
|
||||
description?: textType
|
||||
url?: string
|
||||
}
|
||||
|
||||
// send webhook notification
|
||||
ding: op.#Steps & {
|
||||
if parameter.dingding != _|_ {
|
||||
@@ -233,6 +237,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lark: op.#Steps & {
|
||||
if parameter.lark != _|_ {
|
||||
if parameter.lark.url.value != _|_ {
|
||||
@@ -261,6 +266,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slack: op.#Steps & {
|
||||
if parameter.slack != _|_ {
|
||||
if parameter.slack.url.value != _|_ {
|
||||
@@ -289,6 +295,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
email: op.#Steps & {
|
||||
if parameter.email != _|_ {
|
||||
if parameter.email.from.password.value != _|_ {
|
||||
|
||||
@@ -28,6 +28,7 @@ spec:
|
||||
disable: *false | bool
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the overridden component configuration.
|
||||
components: [...#PatchParams]
|
||||
|
||||
@@ -17,6 +17,7 @@ spec:
|
||||
)
|
||||
|
||||
parameter: message: string
|
||||
|
||||
msg: op.#Message & {
|
||||
message: parameter.message
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ spec:
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: #RuleSelector
|
||||
}
|
||||
|
||||
#RuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -29,6 +30,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control read only strategy at resource level.
|
||||
// The selected resource will be read-only to the current application. If the target resource does
|
||||
|
||||
@@ -28,12 +28,14 @@ spec:
|
||||
labelSelector?: [string]: string
|
||||
...
|
||||
}
|
||||
|
||||
output: {
|
||||
if len(parameter.objects) > 0 {
|
||||
parameter.objects[0]
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
outputs: {
|
||||
for i, v in parameter.objects {
|
||||
if i > 0 {
|
||||
|
||||
@@ -51,6 +51,7 @@ spec:
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the amount of cpu for requests and limits
|
||||
cpu?: *1 | number | string
|
||||
|
||||
@@ -41,6 +41,7 @@ spec:
|
||||
}
|
||||
// +patchStrategy=retainKeys
|
||||
patch: spec: template: spec: serviceAccountName: parameter.name
|
||||
|
||||
_clusterPrivileges: [ if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "cluster" {p}]
|
||||
_namespacePrivileges: [ if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "namespace" {p}]
|
||||
outputs: {
|
||||
|
||||
@@ -39,6 +39,7 @@ spec:
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=The mapping of environment variables to secret
|
||||
envMappings: [string]: #KeySecret
|
||||
|
||||
@@ -27,6 +27,7 @@ spec:
|
||||
// context.namespace indicates the name of the app
|
||||
name: context.name
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the location to bind
|
||||
placements: [...{
|
||||
|
||||
@@ -15,6 +15,7 @@ spec:
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#ResourcePolicyRuleSelector]
|
||||
}
|
||||
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -29,6 +30,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control shared-resource strategy at resource level.
|
||||
// The selected resource will be sharable across applications. (That means multiple applications
|
||||
|
||||
@@ -103,6 +103,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -116,6 +116,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patch: spec: template: spec: {
|
||||
if parameter.probes == _|_ {
|
||||
// +patchKey=name
|
||||
@@ -160,9 +161,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#StartupProbeParams | close({
|
||||
// +usage=Specify the startup probe for multiple containers
|
||||
probes: [...#StartupProbeParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumeMountsList: [
|
||||
if parameter.pvc != _|_ for v in parameter.pvc {
|
||||
if v.volumeMode == "Filesystem" {
|
||||
@@ -107,6 +108,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
envList: [
|
||||
if parameter.configMap != _|_ for v in parameter.configMap if v.mountToEnv != _|_ {
|
||||
{
|
||||
@@ -145,6 +147,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumeDevicesList: *[
|
||||
for v in parameter.pvc if v.volumeMode == "Block" {
|
||||
{
|
||||
@@ -156,6 +159,7 @@ spec:
|
||||
}
|
||||
},
|
||||
] | []
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -168,6 +172,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
patch: spec: template: spec: {
|
||||
// +patchKey=name
|
||||
volumes: deDupVolumesArray
|
||||
@@ -182,6 +187,7 @@ spec:
|
||||
}, ...]
|
||||
|
||||
}
|
||||
|
||||
outputs: {
|
||||
for v in parameter.pvc {
|
||||
if v.mountOnly == false {
|
||||
@@ -252,6 +258,7 @@ spec:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare pvc type storage
|
||||
pvc?: [...{
|
||||
|
||||
@@ -24,6 +24,7 @@ spec:
|
||||
message: parameter.message
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the wait duration time to resume workflow such as "30s", "1min" or "2m15s"
|
||||
duration?: string
|
||||
|
||||
@@ -15,6 +15,7 @@ spec:
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#RuleSelector]
|
||||
}
|
||||
|
||||
#RuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -29,6 +30,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control take over strategy at resource level.
|
||||
// The selected resource will be able to be taken over by the current application when the resource belongs to no
|
||||
|
||||
@@ -113,6 +113,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -209,6 +210,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -33,6 +33,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.storage != _|_ && parameter.storage.secret != _|_ for v in parameter.storage.secret {
|
||||
{
|
||||
@@ -53,6 +54,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -65,6 +67,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
job: op.#Apply & {
|
||||
value: {
|
||||
apiVersion: "batch/v1"
|
||||
@@ -99,9 +102,11 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log: op.#Log & {
|
||||
source: resources: [{labelSelector: "workflow.oam.dev/step-name": "\(context.name)-\(context.stepName)"}]
|
||||
}
|
||||
|
||||
fail: op.#Steps & {
|
||||
if job.value.status.failed != _|_ {
|
||||
if job.value.status.failed > 2 {
|
||||
@@ -111,9 +116,11 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wait: op.#ConditionalWait & {
|
||||
continue: job.value.status.succeeded != _|_ && job.value.status.succeeded > 0
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the addon.
|
||||
addonName: string
|
||||
|
||||
@@ -50,6 +50,7 @@ spec:
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare volumes and volumeMounts
|
||||
volumes?: [...{
|
||||
|
||||
@@ -68,6 +68,7 @@ spec:
|
||||
} @step(7)
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the webhook url
|
||||
url: close({
|
||||
|
||||
@@ -67,6 +67,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
|
||||
{
|
||||
@@ -115,6 +116,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -127,6 +129,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
@@ -284,6 +287,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposePorts: [
|
||||
if parameter.ports != _|_ for v in parameter.ports if v.expose == true {
|
||||
port: v.port
|
||||
@@ -306,6 +310,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
outputs: {
|
||||
if len(exposePorts) != 0 {
|
||||
webserviceExpose: {
|
||||
@@ -320,6 +325,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -496,6 +502,7 @@ spec:
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -64,6 +64,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
|
||||
{
|
||||
@@ -112,6 +113,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -124,6 +126,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
@@ -234,6 +237,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Which image would you like to use for your service
|
||||
// +short=i
|
||||
@@ -363,6 +367,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -113,6 +113,7 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#labelSelector: {
|
||||
matchLabels?: [string]: string
|
||||
matchExpressions?: [...{
|
||||
@@ -121,21 +122,25 @@ spec:
|
||||
values?: [...string]
|
||||
}]
|
||||
}
|
||||
|
||||
#podAffinityTerm: {
|
||||
labelSelector?: #labelSelector
|
||||
namespaces?: [...string]
|
||||
topologyKey: string
|
||||
namespaceSelector?: #labelSelector
|
||||
}
|
||||
|
||||
#nodeSelecor: {
|
||||
key: string
|
||||
operator: *"In" | "NotIn" | "Exists" | "DoesNotExist" | "Gt" | "Lt"
|
||||
values?: [...string]
|
||||
}
|
||||
|
||||
#nodeSelectorTerm: {
|
||||
matchExpressions?: [...#nodeSelecor]
|
||||
matchFields?: [...#nodeSelecor]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the pod affinity scheduling rules
|
||||
podAffinity?: {
|
||||
|
||||
@@ -17,12 +17,14 @@ spec:
|
||||
// +usage=Specify the path of the resource that allow configuration drift
|
||||
path: [...string]
|
||||
}
|
||||
|
||||
#ApplyOncePolicyRule: {
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector?: #ResourcePolicyRuleSelector
|
||||
// +usage=Specify the strategy for configuring the resource level configuration drift behaviour
|
||||
strategy: #ApplyOnceStrategy
|
||||
}
|
||||
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -37,6 +39,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Whether to enable apply-once for the whole application
|
||||
enable: *false | bool
|
||||
|
||||
@@ -20,6 +20,7 @@ spec:
|
||||
labelselector?: {...}
|
||||
namespace: *context.namespace | string
|
||||
}
|
||||
|
||||
cleanJobs: op.#Delete & {
|
||||
value: {
|
||||
apiVersion: "batch/v1"
|
||||
@@ -39,6 +40,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanPods: op.#Delete & {
|
||||
value: {
|
||||
apiVersion: "v1"
|
||||
|
||||
@@ -35,6 +35,7 @@ spec:
|
||||
}
|
||||
}
|
||||
} @step(1)
|
||||
|
||||
outputs: {
|
||||
eps_port_name_filtered: *[] | [...]
|
||||
if parameter.portName == _|_ {
|
||||
@@ -69,9 +70,11 @@ spec:
|
||||
endpoints: eps_port_filtered
|
||||
}
|
||||
}
|
||||
|
||||
wait: op.#ConditionalWait & {
|
||||
continue: len(outputs.endpoints) > 0
|
||||
} @step(2)
|
||||
|
||||
value: {
|
||||
if len(outputs.endpoints) > 0 {
|
||||
endpoint: outputs.endpoints[0].endpoint
|
||||
@@ -79,6 +82,7 @@ spec:
|
||||
url: "\(parameter.protocal)://\(endpoint.host):\(_portStr)"
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the application
|
||||
name?: string
|
||||
|
||||
@@ -107,9 +107,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#PatchParams | close({
|
||||
// +usage=Specify the commands for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -72,9 +72,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: #PatchParams | close({
|
||||
// +usage=Specify the container image for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ spec:
|
||||
targetCPUUtilizationPercentage: parameter.cpuUtil
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the minimal number of replicas to which the autoscaler can scale down
|
||||
min: *1 | int
|
||||
|
||||
@@ -147,6 +147,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -276,6 +277,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -66,6 +66,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
|
||||
{
|
||||
@@ -114,6 +115,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -126,6 +128,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "DaemonSet"
|
||||
@@ -275,6 +278,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposePorts: [
|
||||
if parameter.ports != _|_ for v in parameter.ports if v.expose == true {
|
||||
port: v.port
|
||||
@@ -287,6 +291,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
outputs: {
|
||||
if len(exposePorts) != 0 {
|
||||
webserviceExpose: {
|
||||
@@ -301,6 +306,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -469,6 +475,7 @@ spec:
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -26,6 +26,7 @@ spec:
|
||||
// context.namespace indicates the name of the app
|
||||
name: context.name
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the name of the env-binding policy, if empty, the first env-binding policy will be used
|
||||
policy: *"" | string
|
||||
|
||||
@@ -18,6 +18,9 @@ spec:
|
||||
"vela/op"
|
||||
)
|
||||
|
||||
if parameter.auto == false {
|
||||
suspend: op.#Suspend & {message: "Waiting approval to the deploy step \"\(context.stepName)\""}
|
||||
}
|
||||
deploy: op.#Deploy & {
|
||||
policies: parameter.policies
|
||||
parallelism: parameter.parallelism
|
||||
|
||||
@@ -98,9 +98,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#PatchParams | close({
|
||||
// +usage=Specify the environment variables for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -38,12 +38,14 @@ spec:
|
||||
stringData: parameter.data
|
||||
}
|
||||
} @step(1)
|
||||
|
||||
getPlacements: op.#GetPlacementsFromTopologyPolicies & {
|
||||
policies: *[] | [...string]
|
||||
if parameter.topology != _|_ {
|
||||
policies: [parameter.topology]
|
||||
}
|
||||
} @step(2)
|
||||
} @step(2)
|
||||
|
||||
apply: op.#Steps & {
|
||||
for p in getPlacements.placements {
|
||||
(p.cluster): op.#Apply & {
|
||||
@@ -52,6 +54,7 @@ spec:
|
||||
}
|
||||
}
|
||||
} @step(3)
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the export destination
|
||||
name?: string
|
||||
|
||||
@@ -49,12 +49,14 @@ spec:
|
||||
ports: [{port: parameter.targetPort}]
|
||||
}]
|
||||
}] @step(1)
|
||||
|
||||
getPlacements: op.#GetPlacementsFromTopologyPolicies & {
|
||||
policies: *[] | [...string]
|
||||
if parameter.topology != _|_ {
|
||||
policies: [parameter.topology]
|
||||
}
|
||||
} @step(2)
|
||||
} @step(2)
|
||||
|
||||
apply: op.#Steps & {
|
||||
for p in getPlacements.placements {
|
||||
for o in objects {
|
||||
@@ -65,6 +67,7 @@ spec:
|
||||
}
|
||||
}
|
||||
} @step(3)
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the export destination
|
||||
name?: string
|
||||
|
||||
@@ -17,6 +17,7 @@ spec:
|
||||
// +usage=Specify the strategy for target resource to recycle
|
||||
strategy: *"onAppUpdate" | "onAppDelete" | "never"
|
||||
}
|
||||
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -31,6 +32,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=If is set, outdated versioned resourcetracker will not be recycled automatically, outdated resources will be kept until resourcetracker be deleted manually
|
||||
keepLegacyResource: *false | bool
|
||||
|
||||
@@ -30,6 +30,7 @@ spec:
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
legacyAPI: context.clusterVersion.minor < 19
|
||||
outputs: ingress: {
|
||||
if legacyAPI {
|
||||
@@ -87,6 +88,7 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the domain you want to expose
|
||||
domain?: string
|
||||
@@ -126,7 +128,7 @@ spec:
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
|
||||
}
|
||||
if host != _|_ {
|
||||
if host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,13 @@ spec:
|
||||
dbName: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_NAME"])}
|
||||
username: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_USER"])}
|
||||
password: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PASSWORD"])}
|
||||
|
||||
env: [
|
||||
{name: "url", value: "jdbc://" + dbHost.str + ":" + dbPort.str + "/" + dbName.str + "?characterEncoding=utf8&useSSL=false"},
|
||||
{name: "username", value: username.str},
|
||||
{name: "password", value: password.str},
|
||||
]
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the secret generated by database component
|
||||
name: string
|
||||
|
||||
@@ -12,6 +12,7 @@ spec:
|
||||
cue:
|
||||
template: |
|
||||
output: parameter.objects[0]
|
||||
|
||||
outputs: {
|
||||
for i, v in parameter.objects {
|
||||
if i > 0 {
|
||||
|
||||
@@ -38,6 +38,7 @@ spec:
|
||||
type: "ClusterIP"
|
||||
}
|
||||
}
|
||||
|
||||
patch: metadata: annotations: {
|
||||
"dev.nocalhost/application-name": context.appName
|
||||
"dev.nocalhost/application-namespace": context.namespace
|
||||
|
||||
@@ -159,6 +159,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
block: {
|
||||
type: string
|
||||
block_id?: string
|
||||
@@ -192,18 +193,21 @@ spec:
|
||||
initial_time?: string
|
||||
}]
|
||||
}
|
||||
|
||||
textType: {
|
||||
type: string
|
||||
text: string
|
||||
emoji?: bool
|
||||
verbatim?: bool
|
||||
}
|
||||
|
||||
option: {
|
||||
text: textType
|
||||
value: string
|
||||
description?: textType
|
||||
url?: string
|
||||
}
|
||||
|
||||
// send webhook notification
|
||||
ding: op.#Steps & {
|
||||
if parameter.dingding != _|_ {
|
||||
@@ -233,6 +237,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lark: op.#Steps & {
|
||||
if parameter.lark != _|_ {
|
||||
if parameter.lark.url.value != _|_ {
|
||||
@@ -261,6 +266,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slack: op.#Steps & {
|
||||
if parameter.slack != _|_ {
|
||||
if parameter.slack.url.value != _|_ {
|
||||
@@ -289,6 +295,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
email: op.#Steps & {
|
||||
if parameter.email != _|_ {
|
||||
if parameter.email.from.password.value != _|_ {
|
||||
|
||||
@@ -28,6 +28,7 @@ spec:
|
||||
disable: *false | bool
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the overridden component configuration.
|
||||
components: [...#PatchParams]
|
||||
|
||||
@@ -17,6 +17,7 @@ spec:
|
||||
)
|
||||
|
||||
parameter: message: string
|
||||
|
||||
msg: op.#Message & {
|
||||
message: parameter.message
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ spec:
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: #RuleSelector
|
||||
}
|
||||
|
||||
#RuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -29,6 +30,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control read only strategy at resource level.
|
||||
// The selected resource will be read-only to the current application. If the target resource does
|
||||
|
||||
@@ -28,12 +28,14 @@ spec:
|
||||
labelSelector?: [string]: string
|
||||
...
|
||||
}
|
||||
|
||||
output: {
|
||||
if len(parameter.objects) > 0 {
|
||||
parameter.objects[0]
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
outputs: {
|
||||
for i, v in parameter.objects {
|
||||
if i > 0 {
|
||||
|
||||
@@ -51,6 +51,7 @@ spec:
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the amount of cpu for requests and limits
|
||||
cpu?: *1 | number | string
|
||||
|
||||
@@ -41,6 +41,7 @@ spec:
|
||||
}
|
||||
// +patchStrategy=retainKeys
|
||||
patch: spec: template: spec: serviceAccountName: parameter.name
|
||||
|
||||
_clusterPrivileges: [ if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "cluster" {p}]
|
||||
_namespacePrivileges: [ if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "namespace" {p}]
|
||||
outputs: {
|
||||
|
||||
@@ -39,6 +39,7 @@ spec:
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=The mapping of environment variables to secret
|
||||
envMappings: [string]: #KeySecret
|
||||
|
||||
@@ -27,6 +27,7 @@ spec:
|
||||
// context.namespace indicates the name of the app
|
||||
name: context.name
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare the location to bind
|
||||
placements: [...{
|
||||
|
||||
@@ -15,6 +15,7 @@ spec:
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#ResourcePolicyRuleSelector]
|
||||
}
|
||||
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -29,6 +30,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control shared-resource strategy at resource level.
|
||||
// The selected resource will be sharable across applications. (That means multiple applications
|
||||
|
||||
@@ -103,6 +103,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -116,6 +116,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patch: spec: template: spec: {
|
||||
if parameter.probes == _|_ {
|
||||
// +patchKey=name
|
||||
@@ -160,9 +161,11 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#StartupProbeParams | close({
|
||||
// +usage=Specify the startup probe for multiple containers
|
||||
probes: [...#StartupProbeParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumeMountsList: [
|
||||
if parameter.pvc != _|_ for v in parameter.pvc {
|
||||
if v.volumeMode == "Filesystem" {
|
||||
@@ -107,6 +108,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
envList: [
|
||||
if parameter.configMap != _|_ for v in parameter.configMap if v.mountToEnv != _|_ {
|
||||
{
|
||||
@@ -145,6 +147,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumeDevicesList: *[
|
||||
for v in parameter.pvc if v.volumeMode == "Block" {
|
||||
{
|
||||
@@ -156,6 +159,7 @@ spec:
|
||||
}
|
||||
},
|
||||
] | []
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -168,6 +172,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
patch: spec: template: spec: {
|
||||
// +patchKey=name
|
||||
volumes: deDupVolumesArray
|
||||
@@ -182,6 +187,7 @@ spec:
|
||||
}, ...]
|
||||
|
||||
}
|
||||
|
||||
outputs: {
|
||||
for v in parameter.pvc {
|
||||
if v.mountOnly == false {
|
||||
@@ -252,6 +258,7 @@ spec:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Declare pvc type storage
|
||||
pvc?: [...{
|
||||
|
||||
@@ -24,6 +24,7 @@ spec:
|
||||
message: parameter.message
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the wait duration time to resume workflow such as "30s", "1min" or "2m15s"
|
||||
duration?: string
|
||||
|
||||
@@ -15,6 +15,7 @@ spec:
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#RuleSelector]
|
||||
}
|
||||
|
||||
#RuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
@@ -29,6 +30,7 @@ spec:
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control take over strategy at resource level.
|
||||
// The selected resource will be able to be taken over by the current application when the resource belongs to no
|
||||
|
||||
@@ -113,6 +113,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -209,6 +210,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -33,6 +33,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.storage != _|_ && parameter.storage.secret != _|_ for v in parameter.storage.secret {
|
||||
{
|
||||
@@ -53,6 +54,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -65,6 +67,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
job: op.#Apply & {
|
||||
value: {
|
||||
apiVersion: "batch/v1"
|
||||
@@ -99,9 +102,11 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log: op.#Log & {
|
||||
source: resources: [{labelSelector: "workflow.oam.dev/step-name": "\(context.name)-\(context.stepName)"}]
|
||||
}
|
||||
|
||||
fail: op.#Steps & {
|
||||
if job.value.status.failed != _|_ {
|
||||
if job.value.status.failed > 2 {
|
||||
@@ -111,9 +116,11 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wait: op.#ConditionalWait & {
|
||||
continue: job.value.status.succeeded != _|_ && job.value.status.succeeded > 0
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the name of the addon.
|
||||
addonName: string
|
||||
|
||||
@@ -68,6 +68,7 @@ spec:
|
||||
} @step(7)
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the webhook url
|
||||
url: close({
|
||||
|
||||
@@ -67,6 +67,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
|
||||
{
|
||||
@@ -115,6 +116,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -127,6 +129,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
@@ -284,6 +287,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposePorts: [
|
||||
if parameter.ports != _|_ for v in parameter.ports if v.expose == true {
|
||||
port: v.port
|
||||
@@ -306,6 +310,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
outputs: {
|
||||
if len(exposePorts) != 0 {
|
||||
webserviceExpose: {
|
||||
@@ -320,6 +325,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
@@ -496,6 +502,7 @@ spec:
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -64,6 +64,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
volumesList: [
|
||||
if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
|
||||
{
|
||||
@@ -112,6 +113,7 @@ spec:
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
deDupVolumesArray: [
|
||||
for val in [
|
||||
for i, vi in volumesList {
|
||||
@@ -124,6 +126,7 @@ spec:
|
||||
val
|
||||
},
|
||||
]
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
@@ -234,6 +237,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Which image would you like to use for your service
|
||||
// +short=i
|
||||
@@ -363,6 +367,7 @@ spec:
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
|
||||
@@ -482,7 +482,6 @@ func (p *Parser) loadWorkflowToAppfile(ctx context.Context, af *Appfile) error {
|
||||
&step.DeployWorkflowStepGenerator{},
|
||||
&step.Deploy2EnvWorkflowStepGenerator{},
|
||||
&step.ApplyComponentWorkflowStepGenerator{},
|
||||
&step.DeployPreApproveWorkflowStepGenerator{},
|
||||
).Generate(af.app, af.WorkflowSteps)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -336,15 +336,11 @@ func (def *Definition) FromCUE(val *cue.Value, templateString string) error {
|
||||
}
|
||||
|
||||
func encodeDeclsToString(decls []ast.Decl) (string, error) {
|
||||
s := ""
|
||||
for _, decl := range decls {
|
||||
bs, err := format.Node(decl, format.Simplify())
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to encode decl to string: %v", decl)
|
||||
}
|
||||
s += string(bs) + "\n"
|
||||
bs, err := format.Node(&ast.File{Decls: decls}, format.Simplify())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to encode cue: %w", err)
|
||||
}
|
||||
return s, nil
|
||||
return strings.TrimSpace(string(bs)) + "\n", nil
|
||||
}
|
||||
|
||||
// FromYAML converts yaml into Definition
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
)
|
||||
|
||||
// WorkflowStepGenerator generator generates workflow steps
|
||||
@@ -184,33 +183,6 @@ func (g *DeployWorkflowStepGenerator) Generate(app *v1beta1.Application, existin
|
||||
return steps, nil
|
||||
}
|
||||
|
||||
// DeployPreApproveWorkflowStepGenerator generate suspend workflow steps before all deploy steps
|
||||
type DeployPreApproveWorkflowStepGenerator struct{}
|
||||
|
||||
// Generate generate workflow steps
|
||||
func (g *DeployPreApproveWorkflowStepGenerator) Generate(app *v1beta1.Application, existingSteps []workflowv1alpha1.WorkflowStep) (steps []workflowv1alpha1.WorkflowStep, err error) {
|
||||
lastSuspend := false
|
||||
for _, step := range existingSteps {
|
||||
if step.Type == "deploy" && !lastSuspend {
|
||||
props := DeployWorkflowStepSpec{}
|
||||
if step.Properties != nil {
|
||||
_ = utils.StrictUnmarshal(step.Properties.Raw, &props)
|
||||
}
|
||||
if props.Auto != nil && !*props.Auto {
|
||||
steps = append(steps, workflowv1alpha1.WorkflowStep{
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "manual-approve-" + step.Name,
|
||||
Type: wftypes.WorkflowStepTypeSuspend,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
lastSuspend = step.Type == wftypes.WorkflowStepTypeSuspend
|
||||
steps = append(steps, step)
|
||||
}
|
||||
return steps, nil
|
||||
}
|
||||
|
||||
// IsBuiltinWorkflowStepType checks if workflow step type is builtin type
|
||||
func IsBuiltinWorkflowStepType(wfType string) bool {
|
||||
for _, _type := range []string{
|
||||
|
||||
@@ -208,46 +208,6 @@ func TestWorkflowStepGenerator(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
},
|
||||
"pre-approve-workflow": {
|
||||
input: []workflowv1alpha1.WorkflowStep{{
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "deploy-example-topology-policy-1",
|
||||
Type: "deploy",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"policies":["example-topology-policy-1"]}`)},
|
||||
},
|
||||
}, {
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "deploy-example-topology-policy-2",
|
||||
Type: "deploy",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"auto":false,"policies":["example-topology-policy-2"]}`)},
|
||||
},
|
||||
}},
|
||||
app: &v1beta1.Application{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []common.ApplicationComponent{{
|
||||
Name: "example-comp-1",
|
||||
}},
|
||||
},
|
||||
},
|
||||
output: []workflowv1alpha1.WorkflowStep{{
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "deploy-example-topology-policy-1",
|
||||
Type: "deploy",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"policies":["example-topology-policy-1"]}`)},
|
||||
},
|
||||
}, {
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "manual-approve-deploy-example-topology-policy-2",
|
||||
Type: "suspend",
|
||||
},
|
||||
}, {
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "deploy-example-topology-policy-2",
|
||||
Type: "deploy",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"auto":false,"policies":["example-topology-policy-2"]}`)},
|
||||
},
|
||||
}},
|
||||
},
|
||||
"ref-workflow": {
|
||||
input: nil,
|
||||
app: &v1beta1.Application{
|
||||
@@ -317,7 +277,6 @@ func TestWorkflowStepGenerator(t *testing.T) {
|
||||
&DeployWorkflowStepGenerator{},
|
||||
&Deploy2EnvWorkflowStepGenerator{},
|
||||
&ApplyComponentWorkflowStepGenerator{},
|
||||
&DeployPreApproveWorkflowStepGenerator{},
|
||||
)
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/workflow/operation"
|
||||
)
|
||||
|
||||
var _ = Describe("Test multicluster standalone scenario", func() {
|
||||
@@ -134,7 +135,9 @@ var _ = Describe("Test multicluster standalone scenario", func() {
|
||||
Expect(k8sClient.Create(hubCtx, policy)).Should(Succeed())
|
||||
waitObject(hubCtx, *policy)
|
||||
app := readFile("app-with-publish-version.yaml")
|
||||
Expect(k8sClient.Create(hubCtx, app)).Should(Succeed())
|
||||
Eventually(func(g Gomega) {
|
||||
g.Expect(k8sClient.Create(hubCtx, app)).Should(Succeed())
|
||||
}).WithTimeout(10 * time.Second).WithPolling(2 * time.Second).Should(Succeed())
|
||||
appKey := client.ObjectKeyFromObject(app)
|
||||
|
||||
Eventually(func(g Gomega) {
|
||||
@@ -149,13 +152,7 @@ var _ = Describe("Test multicluster standalone scenario", func() {
|
||||
Eventually(func(g Gomega) {
|
||||
_app := &v1beta1.Application{}
|
||||
g.Expect(k8sClient.Get(hubCtx, appKey, _app)).Should(Succeed())
|
||||
_app.Status.Workflow.Suspend = false
|
||||
for i, step := range _app.Status.Workflow.Steps {
|
||||
if step.Type == "suspend" {
|
||||
_app.Status.Workflow.Steps[i].Phase = workflowv1alpha1.WorkflowStepPhaseSucceeded
|
||||
}
|
||||
}
|
||||
g.Expect(k8sClient.Status().Update(hubCtx, _app)).Should(Succeed())
|
||||
g.Expect(operation.ResumeWorkflow(hubCtx, k8sClient, _app, "")).Should(Succeed())
|
||||
}, 15*time.Second).Should(Succeed())
|
||||
|
||||
// test application can run without external policies and workflow since they are recorded in the application revision
|
||||
@@ -302,7 +299,7 @@ var _ = Describe("Test multicluster standalone scenario", func() {
|
||||
revs, err := application.GetSortedAppRevisions(hubCtx, k8sClient, app.Name, namespace)
|
||||
g.Expect(err).Should(Succeed())
|
||||
g.Expect(len(revs)).Should(Equal(1))
|
||||
}).WithTimeout(30 * time.Second).WithPolling(2 * time.Second).Should(Succeed())
|
||||
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||
})
|
||||
|
||||
It("Test large application parallel apply and delete", func() {
|
||||
|
||||
@@ -160,7 +160,7 @@ var _ = Describe("HealthScope", func() {
|
||||
if len(compSts1.Traits) != 1 {
|
||||
return fmt.Errorf("expect 1 trait statuses, but got %d", len(compSts1.Traits))
|
||||
}
|
||||
if !strings.Contains(compSts1.Traits[0].Message, "visit the cluster or load balancer in front of the cluster") {
|
||||
if !strings.Contains(compSts1.Traits[0].Message, "Visiting URL") {
|
||||
return fmt.Errorf("trait message isn't right, now is %s", compSts1.Traits[0].Message)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ gateway: {
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
|
||||
}
|
||||
if host != _|_ {
|
||||
if host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import (
|
||||
description: "A powerful and unified deploy step for components multi-cluster delivery with policies."
|
||||
}
|
||||
template: {
|
||||
if parameter.auto == false {
|
||||
suspend: op.#Suspend & {message: "Waiting approval to the deploy step \"\(context.stepName)\""}
|
||||
}
|
||||
deploy: op.#Deploy & {
|
||||
policies: parameter.policies
|
||||
parallelism: parameter.parallelism
|
||||
|
||||
@@ -36,6 +36,7 @@ spec:
|
||||
validation: "client"
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
//+usage=The repository URL, can be a HTTP/S or SSH address.
|
||||
repoUrl: string
|
||||
|
||||
Reference in New Issue
Block a user