github.com/oam-dev/kubevela@v1.9.11/vela-templates/definitions/internal/component/webservice.cue (about)

     1  import (
     2  	"strconv"
     3  	"strings"
     4  )
     5  
     6  webservice: {
     7  	type: "component"
     8  	annotations: {}
     9  	labels: {}
    10  	description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers."
    11  	attributes: {
    12  		workload: {
    13  			definition: {
    14  				apiVersion: "apps/v1"
    15  				kind:       "Deployment"
    16  			}
    17  			type: "deployments.apps"
    18  		}
    19  		status: {
    20  			customStatus: #"""
    21  				ready: {
    22  					readyReplicas: *0 | int
    23  				} & {
    24  					if context.output.status.readyReplicas != _|_ {
    25  						readyReplicas: context.output.status.readyReplicas
    26  					}
    27  				}
    28  				message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
    29  				"""#
    30  			healthPolicy: #"""
    31  				ready: {
    32  					updatedReplicas:    *0 | int
    33  					readyReplicas:      *0 | int
    34  					replicas:           *0 | int
    35  					observedGeneration: *0 | int
    36  				} & {
    37  					if context.output.status.updatedReplicas != _|_ {
    38  						updatedReplicas: context.output.status.updatedReplicas
    39  					}
    40  					if context.output.status.readyReplicas != _|_ {
    41  						readyReplicas: context.output.status.readyReplicas
    42  					}
    43  					if context.output.status.replicas != _|_ {
    44  						replicas: context.output.status.replicas
    45  					}
    46  					if context.output.status.observedGeneration != _|_ {
    47  						observedGeneration: context.output.status.observedGeneration
    48  					}
    49  				}
    50  				_isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
    51  				isHealth: *_isHealth | bool
    52  				if context.output.metadata.annotations != _|_ {
    53  					if context.output.metadata.annotations["app.oam.dev/disable-health-check"] != _|_ {
    54  						isHealth: true
    55  					}
    56  				}
    57  				"""#
    58  		}
    59  	}
    60  }
    61  template: {
    62  	mountsArray: [
    63  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
    64  			{
    65  				mountPath: v.mountPath
    66  				if v.subPath != _|_ {
    67  					subPath: v.subPath
    68  				}
    69  				name: v.name
    70  			}
    71  		},
    72  
    73  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.configMap != _|_ for v in parameter.volumeMounts.configMap {
    74  			{
    75  				mountPath: v.mountPath
    76  				if v.subPath != _|_ {
    77  					subPath: v.subPath
    78  				}
    79  				name: v.name
    80  			}
    81  		},
    82  
    83  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.secret != _|_ for v in parameter.volumeMounts.secret {
    84  			{
    85  				mountPath: v.mountPath
    86  				if v.subPath != _|_ {
    87  					subPath: v.subPath
    88  				}
    89  				name: v.name
    90  			}
    91  		},
    92  
    93  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.emptyDir != _|_ for v in parameter.volumeMounts.emptyDir {
    94  			{
    95  				mountPath: v.mountPath
    96  				if v.subPath != _|_ {
    97  					subPath: v.subPath
    98  				}
    99  				name: v.name
   100  			}
   101  		},
   102  
   103  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.hostPath != _|_ for v in parameter.volumeMounts.hostPath {
   104  			{
   105  				mountPath: v.mountPath
   106  				if v.subPath != _|_ {
   107  					subPath: v.subPath
   108  				}
   109  				name: v.name
   110  			}
   111  		},
   112  	]
   113  
   114  	volumesList: [
   115  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.pvc != _|_ for v in parameter.volumeMounts.pvc {
   116  			{
   117  				name: v.name
   118  				persistentVolumeClaim: claimName: v.claimName
   119  			}
   120  		},
   121  
   122  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.configMap != _|_ for v in parameter.volumeMounts.configMap {
   123  			{
   124  				name: v.name
   125  				configMap: {
   126  					defaultMode: v.defaultMode
   127  					name:        v.cmName
   128  					if v.items != _|_ {
   129  						items: v.items
   130  					}
   131  				}
   132  			}
   133  		},
   134  
   135  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.secret != _|_ for v in parameter.volumeMounts.secret {
   136  			{
   137  				name: v.name
   138  				secret: {
   139  					defaultMode: v.defaultMode
   140  					secretName:  v.secretName
   141  					if v.items != _|_ {
   142  						items: v.items
   143  					}
   144  				}
   145  			}
   146  		},
   147  
   148  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.emptyDir != _|_ for v in parameter.volumeMounts.emptyDir {
   149  			{
   150  				name: v.name
   151  				emptyDir: medium: v.medium
   152  			}
   153  		},
   154  
   155  		if parameter.volumeMounts != _|_ && parameter.volumeMounts.hostPath != _|_ for v in parameter.volumeMounts.hostPath {
   156  			{
   157  				name: v.name
   158  				hostPath: {
   159  					path: v.path
   160  				}
   161  			}
   162  		},
   163  	]
   164  
   165  	deDupVolumesArray: [
   166  		for val in [
   167  			for i, vi in volumesList {
   168  				for j, vj in volumesList if j < i && vi.name == vj.name {
   169  					_ignore: true
   170  				}
   171  				vi
   172  			},
   173  		] if val._ignore == _|_ {
   174  			val
   175  		},
   176  	]
   177  
   178  	output: {
   179  		apiVersion: "apps/v1"
   180  		kind:       "Deployment"
   181  		spec: {
   182  			selector: matchLabels: {
   183  				"app.oam.dev/component": context.name
   184  			}
   185  
   186  			template: {
   187  				metadata: {
   188  					labels: {
   189  						if parameter.labels != _|_ {
   190  							parameter.labels
   191  						}
   192  						if parameter.addRevisionLabel {
   193  							"app.oam.dev/revision": context.revision
   194  						}
   195  						"app.oam.dev/name":      context.appName
   196  						"app.oam.dev/component": context.name
   197  					}
   198  					if parameter.annotations != _|_ {
   199  						annotations: parameter.annotations
   200  					}
   201  				}
   202  
   203  				spec: {
   204  					containers: [{
   205  						name:  context.name
   206  						image: parameter.image
   207  						if parameter["port"] != _|_ && parameter["ports"] == _|_ {
   208  							ports: [{
   209  								containerPort: parameter.port
   210  							}]
   211  						}
   212  						if parameter["ports"] != _|_ {
   213  							ports: [ for v in parameter.ports {
   214  								{
   215  									containerPort: {
   216  										if v.containerPort != _|_ {v.containerPort}
   217  										if v.containerPort == _|_ {v.port}
   218  									}
   219  									protocol: v.protocol
   220  									if v.name != _|_ {
   221  										name: v.name
   222  									}
   223  									if v.name == _|_ {
   224  										_name: {
   225  											if v.containerPort != _|_ {"port-" + strconv.FormatInt(v.containerPort, 10)}
   226  											if v.containerPort == _|_ {"port-" + strconv.FormatInt(v.port, 10)}
   227  										}
   228  										name: *_name | string
   229  										if v.protocol != "TCP" {
   230  											name: _name + "-" + strings.ToLower(v.protocol)
   231  										}
   232  									}
   233  								}}]
   234  						}
   235  
   236  						if parameter["imagePullPolicy"] != _|_ {
   237  							imagePullPolicy: parameter.imagePullPolicy
   238  						}
   239  
   240  						if parameter["cmd"] != _|_ {
   241  							command: parameter.cmd
   242  						}
   243  
   244  						if parameter["args"] != _|_ {
   245  							args: parameter.args
   246  						}
   247  
   248  						if parameter["env"] != _|_ {
   249  							env: parameter.env
   250  						}
   251  
   252  						if context["config"] != _|_ {
   253  							env: context.config
   254  						}
   255  
   256  						if parameter["cpu"] != _|_ {
   257  							resources: {
   258  								limits: cpu:   parameter.cpu
   259  								requests: cpu: parameter.cpu
   260  							}
   261  						}
   262  
   263  						if parameter["memory"] != _|_ {
   264  							resources: {
   265  								limits: memory:   parameter.memory
   266  								requests: memory: parameter.memory
   267  							}
   268  						}
   269  
   270  						if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ {
   271  							volumeMounts: [ for v in parameter.volumes {
   272  								{
   273  									mountPath: v.mountPath
   274  									name:      v.name
   275  								}}]
   276  						}
   277  
   278  						if parameter["volumeMounts"] != _|_ {
   279  							volumeMounts: mountsArray
   280  						}
   281  
   282  						if parameter["livenessProbe"] != _|_ {
   283  							livenessProbe: parameter.livenessProbe
   284  						}
   285  
   286  						if parameter["readinessProbe"] != _|_ {
   287  							readinessProbe: parameter.readinessProbe
   288  						}
   289  
   290  					}]
   291  
   292  					if parameter["hostAliases"] != _|_ {
   293  						// +patchKey=ip
   294  						hostAliases: parameter.hostAliases
   295  					}
   296  
   297  					if parameter["imagePullSecrets"] != _|_ {
   298  						imagePullSecrets: [ for v in parameter.imagePullSecrets {
   299  							name: v
   300  						},
   301  						]
   302  					}
   303  
   304  					if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ {
   305  						volumes: [ for v in parameter.volumes {
   306  							{
   307  								name: v.name
   308  								if v.type == "pvc" {
   309  									persistentVolumeClaim: claimName: v.claimName
   310  								}
   311  								if v.type == "configMap" {
   312  									configMap: {
   313  										defaultMode: v.defaultMode
   314  										name:        v.cmName
   315  										if v.items != _|_ {
   316  											items: v.items
   317  										}
   318  									}
   319  								}
   320  								if v.type == "secret" {
   321  									secret: {
   322  										defaultMode: v.defaultMode
   323  										secretName:  v.secretName
   324  										if v.items != _|_ {
   325  											items: v.items
   326  										}
   327  									}
   328  								}
   329  								if v.type == "emptyDir" {
   330  									emptyDir: medium: v.medium
   331  								}
   332  							}
   333  						}]
   334  					}
   335  
   336  					if parameter["volumeMounts"] != _|_ {
   337  						volumes: deDupVolumesArray
   338  					}
   339  				}
   340  			}
   341  		}
   342  	}
   343  
   344  	exposePorts: [
   345  		if parameter.ports != _|_ for v in parameter.ports if v.expose == true {
   346  			port: v.port
   347  			if v.containerPort != _|_ {targetPort: v.containerPort}
   348  			if v.containerPort == _|_ {targetPort: v.port}
   349  			if v.name != _|_ {name: v.name}
   350  			if v.name == _|_ {
   351  				_name: {
   352  					if v.containerPort != _|_ {
   353  						"port-" + strconv.FormatInt(v.containerPort, 10)
   354  					}
   355  					if v.containerPort == _|_ {
   356  						"port-" + strconv.FormatInt(v.port, 10)
   357  					}
   358  				}
   359  				name: *_name | string
   360  				if v.protocol != "TCP" {
   361  					name: _name + "-" + strings.ToLower(v.protocol)
   362  				}
   363  			}
   364  			if v.nodePort != _|_ && parameter.exposeType == "NodePort" {
   365  				nodePort: v.nodePort
   366  			}
   367  			if v.protocol != _|_ {
   368  				protocol: v.protocol
   369  			}
   370  		},
   371  	]
   372  
   373  	outputs: {
   374  		if len(exposePorts) != 0 {
   375  			webserviceExpose: {
   376  				apiVersion: "v1"
   377  				kind:       "Service"
   378  				metadata: name: context.name
   379  				spec: {
   380  					selector: "app.oam.dev/component": context.name
   381  					ports: exposePorts
   382  					type:  parameter.exposeType
   383  				}
   384  			}
   385  		}
   386  	}
   387  
   388  	parameter: {
   389  		// +usage=Specify the labels in the workload
   390  		labels?: [string]: string
   391  
   392  		// +usage=Specify the annotations in the workload
   393  		annotations?: [string]: string
   394  
   395  		// +usage=Which image would you like to use for your service
   396  		// +short=i
   397  		image: string
   398  
   399  		// +usage=Specify image pull policy for your service
   400  		imagePullPolicy?: "Always" | "Never" | "IfNotPresent"
   401  
   402  		// +usage=Specify image pull secrets for your service
   403  		imagePullSecrets?: [...string]
   404  
   405  		// +ignore
   406  		// +usage=Deprecated field, please use ports instead
   407  		// +short=p
   408  		port?: int
   409  
   410  		// +usage=Which ports do you want customer traffic sent to, defaults to 80
   411  		ports?: [...{
   412  			// +usage=Number of port to expose on the pod's IP address
   413  			port: int
   414  			// +usage=Number of container port to connect to, defaults to port
   415  			containerPort?: int
   416  			// +usage=Name of the port
   417  			name?: string
   418  			// +usage=Protocol for port. Must be UDP, TCP, or SCTP
   419  			protocol: *"TCP" | "UDP" | "SCTP"
   420  			// +usage=Specify if the port should be exposed
   421  			expose: *false | bool
   422  			// +usage=exposed node port. Only Valid when exposeType is NodePort
   423  			nodePort?: int
   424  		}]
   425  
   426  		// +ignore
   427  		// +usage=Specify what kind of Service you want. options: "ClusterIP", "NodePort", "LoadBalancer"
   428  		exposeType: *"ClusterIP" | "NodePort" | "LoadBalancer"
   429  
   430  		// +ignore
   431  		// +usage=If addRevisionLabel is true, the revision label will be added to the underlying pods
   432  		addRevisionLabel: *false | bool
   433  
   434  		// +usage=Commands to run in the container
   435  		cmd?: [...string]
   436  
   437  		// +usage=Arguments to the entrypoint
   438  		args?: [...string]
   439  
   440  		// +usage=Define arguments by using environment variables
   441  		env?: [...{
   442  			// +usage=Environment variable name
   443  			name: string
   444  			// +usage=The value of the environment variable
   445  			value?: string
   446  			// +usage=Specifies a source the value of this var should come from
   447  			valueFrom?: {
   448  				// +usage=Selects a key of a secret in the pod's namespace
   449  				secretKeyRef?: {
   450  					// +usage=The name of the secret in the pod's namespace to select from
   451  					name: string
   452  					// +usage=The key of the secret to select from. Must be a valid secret key
   453  					key: string
   454  				}
   455  				// +usage=Selects a key of a config map in the pod's namespace
   456  				configMapKeyRef?: {
   457  					// +usage=The name of the config map in the pod's namespace to select from
   458  					name: string
   459  					// +usage=The key of the config map to select from. Must be a valid secret key
   460  					key: string
   461  				}
   462  			}
   463  		}]
   464  
   465  		// +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)
   466  		cpu?: string
   467  
   468  		// +usage=Specifies the attributes of the memory resource required for the container.
   469  		memory?: string
   470  
   471  		volumeMounts?: {
   472  			// +usage=Mount PVC type volume
   473  			pvc?: [...{
   474  				name:      string
   475  				mountPath: string
   476  				subPath?:  string
   477  				// +usage=The name of the PVC
   478  				claimName: string
   479  			}]
   480  			// +usage=Mount ConfigMap type volume
   481  			configMap?: [...{
   482  				name:        string
   483  				mountPath:   string
   484  				subPath?:    string
   485  				defaultMode: *420 | int
   486  				cmName:      string
   487  				items?: [...{
   488  					key:  string
   489  					path: string
   490  					mode: *511 | int
   491  				}]
   492  			}]
   493  			// +usage=Mount Secret type volume
   494  			secret?: [...{
   495  				name:        string
   496  				mountPath:   string
   497  				subPath?:    string
   498  				defaultMode: *420 | int
   499  				secretName:  string
   500  				items?: [...{
   501  					key:  string
   502  					path: string
   503  					mode: *511 | int
   504  				}]
   505  			}]
   506  			// +usage=Mount EmptyDir type volume
   507  			emptyDir?: [...{
   508  				name:      string
   509  				mountPath: string
   510  				subPath?:  string
   511  				medium:    *"" | "Memory"
   512  			}]
   513  			// +usage=Mount HostPath type volume
   514  			hostPath?: [...{
   515  				name:      string
   516  				mountPath: string
   517  				subPath?:  string
   518  				path:      string
   519  			}]
   520  		}
   521  
   522  		// +usage=Deprecated field, use volumeMounts instead.
   523  		volumes?: [...{
   524  			name:      string
   525  			mountPath: string
   526  			// +usage=Specify volume type, options: "pvc","configMap","secret","emptyDir", default to emptyDir
   527  			type: *"emptyDir" | "pvc" | "configMap" | "secret"
   528  			if type == "pvc" {
   529  				claimName: string
   530  			}
   531  			if type == "configMap" {
   532  				defaultMode: *420 | int
   533  				cmName:      string
   534  				items?: [...{
   535  					key:  string
   536  					path: string
   537  					mode: *511 | int
   538  				}]
   539  			}
   540  			if type == "secret" {
   541  				defaultMode: *420 | int
   542  				secretName:  string
   543  				items?: [...{
   544  					key:  string
   545  					path: string
   546  					mode: *511 | int
   547  				}]
   548  			}
   549  			if type == "emptyDir" {
   550  				medium: *"" | "Memory"
   551  			}
   552  		}]
   553  
   554  		// +usage=Instructions for assessing whether the container is alive.
   555  		livenessProbe?: #HealthProbe
   556  
   557  		// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
   558  		readinessProbe?: #HealthProbe
   559  
   560  		// +usage=Specify the hostAliases to add
   561  		hostAliases?: [...{
   562  			ip: string
   563  			hostnames: [...string]
   564  		}]
   565  	}
   566  
   567  	#HealthProbe: {
   568  
   569  		// +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.
   570  		exec?: {
   571  			// +usage=A command to be executed inside the container to assess its health. Each space delimited token of the command is a separate array element. Commands exiting 0 are considered to be successful probes, whilst all other exit codes are considered failures.
   572  			command: [...string]
   573  		}
   574  
   575  		// +usage=Instructions for assessing container health by executing an HTTP GET request. Either this attribute or the exec attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the exec attribute and the tcpSocket attribute.
   576  		httpGet?: {
   577  			// +usage=The endpoint, relative to the port, to which the HTTP GET request should be directed.
   578  			path: string
   579  			// +usage=The TCP socket within the container to which the HTTP GET request should be directed.
   580  			port:    int
   581  			host?:   string
   582  			scheme?: *"HTTP" | string
   583  			httpHeaders?: [...{
   584  				name:  string
   585  				value: string
   586  			}]
   587  		}
   588  
   589  		// +usage=Instructions for assessing container health by probing a TCP socket. Either this attribute or the exec attribute or the httpGet attribute MUST be specified. This attribute is mutually exclusive with both the exec attribute and the httpGet attribute.
   590  		tcpSocket?: {
   591  			// +usage=The TCP socket within the container that should be probed to assess container health.
   592  			port: int
   593  		}
   594  
   595  		// +usage=Number of seconds after the container is started before the first probe is initiated.
   596  		initialDelaySeconds: *0 | int
   597  
   598  		// +usage=How often, in seconds, to execute the probe.
   599  		periodSeconds: *10 | int
   600  
   601  		// +usage=Number of seconds after which the probe times out.
   602  		timeoutSeconds: *1 | int
   603  
   604  		// +usage=Minimum consecutive successes for the probe to be considered successful after having failed.
   605  		successThreshold: *1 | int
   606  
   607  		// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
   608  		failureThreshold: *3 | int
   609  	}
   610  }