CUE is an open source data constraint language designed to handle configurations, structures, data and execute them. Most people start using CUE because they want to do data validation and generate configurations. Then they go on to use CUE for data templates, runtime input validation, code generation, scripting, plumbing, and more. First you need to understand that CUE is not a programming language in the usual sense, it is a Turing non-complete programming language.
CUE continues the JSON superset idea, and additionally provides rich types, expressions, import statements and other common capabilities. Unlike JSONNET, CUE does not support custom functions, and supports external schema based on the typed feature structure idea, and supports type and data fusion through explicit unification and separation operations, but such settings and external type derivation also increase the difficulty of understanding and writing complexity.
The CUE project is written entirely in Golang, and relies on Golang to allow the necessary capabilities provided by CUE to be introduced through “import” to assist users with common functions such as encoding, strings, math, and other configuration writing. We can say that CUE is both a JSON-based template language and also comes with a lot of Configuration Language thinking, providing a good sample of both its language design ideas and the engineering approach based on the introduction of capabilities of mature high-level programming languages are worth studying in depth.
Installation
Install CUE via official binary
The installer supports multiple operating systems, including Linux, Window, and macOS, and can be downloaded from the official CUE website at https://cuelang.org/releases.
IInstallation with homebrew
Alternatively, CUE is installed via brew on MacOS and Linux.
|
|
Installation via source code
First you need to ensure that Go 1.16 or higher is installed, then execute the following command to install it.
|
|
Once the installation is complete, you can execute the cue
command.
CUE Command Line
CUE is a superset of JSON, and we can use CUE as JSON with the following features.
- C-style comments
- field names can be enclosed in double quotes, but no special characters are allowed in field names
- Optional field endings with or without a comma
- Comma at the end of the last element in an array is allowed
- Outer curly brackets optional
Please first copy the following information and save it as a first.cue
file.
Next, let’s use this file above as an example to learn about the CUE command line commands.
-
How to format a CUE file. The following commands not only format the CUE file, but also prompt for the wrong model.
1
cue fmt first.cue
-
How to calibrate the model. In addition to
cue fmt
, you can also usecue vet
to calibrate the model.Hint: The variable e in this file has the data type
string
but is not assigned a value. -
How to calculate/render the result.
cue eval
computes the CUE file and renders the final result. We see that the final result does not containa: float
andb: int
, because these two variables have already been computed and populated. Thee: string
is not explicitly assigned, so it remains unchanged. -
How to specify the result of the rendering. For example, if we only want to know the rendering result of
b
in the file, we can use this parameter-e
. -
How to export the rendering result.
cue export
exports the final rendering results. If some variables are not defined executing this command will give an error.Let’s update the
first.cue
file and assign a value toe
.Then, the command works properly. By default, the rendered results are formatted as JSON.
-
How to export rendered results in YAML format.
-
How to export the result of the specified variable.
Above, you have learned all the common CUE command line commands.
Data Types
After familiarizing yourself with the common CUE command line instructions, let’s learn more about the CUE language.
Let’s start by understanding CUE’s data types. Here are its basic data types.
How do I customize the CUE type? Use the #
symbol to specify some variables that indicate the CUE type.
|
|
We save the above to a second.cue
file. Executing cue export
will not report that #abc
is an incomplete type value.
You can also define more complex custom structures, such as
CUE Templates
Next, let’s start trying to define the CUE template using what we just learned.
-
Define the structure variable
parameter
.Save the above variables to the file
deployment.cue
. -
Define more complex structural variables
template
and refer to the variableparameter
.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
template: { apiVersion: "apps/v1" kind: "Deployment" spec: { selector: matchLabels: { "app.oam.dev/component": parameter.name } template: { metadata: labels: { "app.oam.dev/component": parameter.name } spec: { containers: [{ name: parameter.name image: parameter.image }] }}} }
As you may already know if you are familiar with Kubernetes, this is the template for Kubernetes Deployment.
parameter
is the parameters section of the template.Add the above to the file
deployment.cue
. -
Then, we complete the variable assignment by updating the
-
Finally, the rendered results are exported in YAML format.
Above, you get a template for the Kubernetes Deployment type.
Other Uses
-
Design open structures and arrays. If
...
is used in an array or structure, the object is open.-
The array object
[... .string]
, indicating that the object can hold multiple string elements. If you do not add...
, the object[string]
indicates that the array can hold only one element of typestring
. -
The structure shown below illustrates that it can contain unknown fields.
-
-
Use the operator
|
to represent two types of values. As shown below, the variablea
indicates that the type can be either a string or an integer type.1
a: string | int
-
Use the symbol
*
to define the default value of a variable. It is usually used in conjunction with the symbol|
to represent the default value of a certain type. As shown below, the variablea
is of typeint
and has a default value of1
.1
a: *1 | int
-
Make some variables optional. In some cases, variables that are not necessarily used are optional variables, and we can use
? :
to define such variables. As shown below,a
is an optional variable,x
andz
are optional in the custom#my
object, andy
is a required field.Optional variables can be skipped, which is often used in conjunction with conditional judgment logic. Specifically, if some field does not exist, the CUE syntax is
if _variable_! = _ | _
, as follows. -
Use the operator
&
to operate on two variables.Save the above to the
third.cue
file.You can use
cue eval
to verify the results. -
Need to perform conditional judgments. Conditional judgments are very useful when you perform some cascading operations where different values affect different results. Therefore, you can execute
if..else
logic in your templates.Save the above to a
fourth.cue
file.You can use
cue eval
to verify the results.Another example is to include a boolean type as a parameter.
-
Use a For loop. We often use For loops to avoid duplicating code.
-
Mapping iterations.
-
Type iteration
-
Slicing iteration.
-
Alternatively, you can use "\( _my-statement_ )"
to perform internal string calculations, such as getting the length of a value in the type loop example above, and so on.
Importing packages
For example, use the strings.Join
method to stitch an array of strings into a string.
|
|
You can import kubernetes packages in the CUE template via kube/<apiVersion>
, just as you would with CUE internal packages.
For example, Deployment
can be used like this.
Service
can be used this way (no need to import packages with aliases).
Even installed CRDs can be imported and used.