Define, Validate, Generate with CUE language
In this article, I'll briefly explain how to use the CUE
configuration language and how it might help you to keep consistent the YAML
/JSON
files by validating against the schema, reducing repetition, and many more.
Arguably, validation should be the foremost task of any configuration language. Most configuration languages, however, focus on boilerplate removal. CUE is different in that it takes the validation first stance. cuelang.org
Lets start from a simple example:
// Schema
[string]: {
name: *"buddy" | string
count: >=0 & <=100 | number
}
In the file example.cue
we define the schema and the validation rules of our data.
The schema states:
[string]
- is an any arbitrary key.name
- default value is"buddy"
or the type isstring
.count
- default value in between0
and100
or the type isnumber
.
That's good, we've the schema of our data, let's check arbitrary YAML
against the defined schema.
Here is an example of YAML
, this example contains a bunch of errors related to the wrong value type:
item:
name: []
count: "110"
Let's use the cue vet
command:
cue vet example.yaml example.cue
item.count: 2 errors in empty disjunction:
item.count: conflicting values "110" and >=0 (mismatched types string and number):
./example.cue:4:17
./example.cue:6:12
./example.yaml:3:11
item.count: conflicting values "110" and number (mismatched types string and number):
./example.cue:4:17
./example.cue:6:26
./example.yaml:3:11
item.name: 2 errors in empty disjunction:
item.name: conflicting values "buddy" and [] (mismatched types string and list):
./example.cue:5:13
./example.yaml:2:10
item.name: conflicting values string and [] (mismatched types string and list):
./example.cue:5:23
./example.yaml:2:10
As you can see there are many errors, is about conflicting values, the name
value must be string
, and "buddy"
is not equal []
and so on.
Lets fix our example.yaml
item:
name: "teammate"
count: 110
We've changed our example.yaml
, run cue vet example.yaml example.cue
and there are no errors, but what about the schema state >=0 & <=100 | number
?
The schema state is right, it denotes the value of the count
key must be more or equal 0
and less or equal 100
or the number
type,
and in our last changes 110
is a number
type.
Lets adjunct the schema a little to meet our requirements:
// Schema
[string]: {
name: *"buddy" | string
count: >=0 & <=100 & number // instead of '>=0 & <=100 | number'
}
Run cue vet
again:
cue vet example.yaml example.cue
item.count: invalid value 110 (out of bound <=100):
./example.cue:6:18
./example.yaml:3:11
That's right.
Another things we can do is to move our data closer to schema and generate valid YAML
/JSON
.
Let's change example.cue
a little:
// Schema
[string]: {
name: *"buddy" | string
count: >=0 & <=100 & number
}
// Data
example: {
name: "somebody"
count: 12
}
Now we able to generate a valid YAML
/JSON
from out data:
cue export example.cue --out yaml
example:
name: somebody
count: 12
cue export example.cue --out json
{
"example": {
"name": "somebody",
"count": 12
}
}
One of the cool things about CUE
here is that it can infer default values for our data from the schema:
// Schema
[string]: {
name: *"buddy" | string
count: >=0 & <=100 & number
}
// Data
example: {
count: 12
}
The code above generate next output:
cue export example.cue --out yaml
example:
name: buddy
count: 12
We're working a lot with different types of configurations, and on many occasions,
that particular area is a mess, in most cases, the mess happens because of humans,
somewhere you chose the wrong type of particular field or just forgot some key, it takes the time from us.
There is no more precious thing in the world than time. In my opinion, the CUE
can help here.
In this small article, I've scratched the surface of how CUE
works and presented a small example with schema definition and data validation.
Happy coding!