Introduction
Dagger is a devkit used in CICD using BuildKit and CUE for platform independent pipeline creation. The language CUE stands for Configure,Unify and Execute. It is a logical configuration language. This means it can create template with scripting as well. We have explore Dagger in this blog.
We will see various feature that are useful for Dagger environment in CUE. We will using CUE Playground for the code used. You can also install CUE on local system after installing GoLang.
Prerequisites
- If using CUE Playground, all required is the Internet.
- If Locally then, Go and CUE installed on System.
Features of CUE for Dagger
CUE is a superset of JSON
This means whatever that is written in JSON can be written in CUE. The following line is written in same way in JSON and CUE.
{
"Vaibhav": {
"Name": "Vaibhav Kumar",
"Age": 22
}
}
But CUE has some more power, like define the template as we will be seeing in Definations. One other power is writing the expression in a single line
Vaibhav: Name: "Vaibhav Kumar"
It is similar to JSON in following way:
{
"Vaibhav": {
"Name": "Vaibhav Kumar"
}
}

Types as the Values
When we give an input or expression in CUE it should obey some restrictions. As Dagger will be used for CICD process, it expects values to be defined or constraints. So we give the type of it in CUE as following:
Vaibhav: {
Name: string // type
Age: int
}
Vaibhav: {
Name: "Vaibhav kumar"
Age: 22
}
Since the type string and int do not require quotes, we say types as values.



Now if we miss or change any value other than type defined, it gives error. as following:



Concrete values
This is for fixed values which are not definitions or rules. It is actual data for workflow. This is exported in CICD . In last example, if we miss any value it shows error in following way:
Vaibhav: {
Name: string
Age: int
}
Vaibhav: {
Name: "Vaibhav Kumar"
//Age: 22 we have commented this line
}



Definitions
Till now we were defining for one Person, but in CICD we need rules for multiple persons. We can create a template or blueprint in CUE called Definations. they have the symbol ‘#’ for this. We will be doing in following way:
#Person: {
Name: string
Email: string
Age?: int
}
Vaibhav: #Person & {
Name: "Vaibhav Kumar"
Email: "vaibhav.kumar@knoldus.com"
}
Shivam: #Person & {
Name: "Shivam Pateriya"
Email: "shivam.pateriya@knoldus.com"
Age: 23
}
To use Defination Person we need to abstact it using symbol ‘&‘ . Note: There a symbol ‘?’ after ‘Age’. This makes it optional to define when used. And we do not get an error using above code as following:



Unification
It is the speciality of CUE which allows to use constraints and concrete values in a single file. This was seen in last example as well. We can add more constraints as in following code:
import (
"strings"
)
#Person: {
// further constrain to a min and max length
Name: string & strings.MinRunes(3) & strings.MaxRunes(22)
// we don't need string because the regex handles that
Email: =~"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
// constrain to age
Age?: int & >0 & <140
}
Vaibhav: #Person & {
Name: "Vaibhav Kumar"
Email: "vaibhav.kumar@knoldus.com"
Age: 22
}
We have defined import in later part.



Inheritance
CUE does not allow overrides. An this is due to reason that it leads to unwanted and difficult to debug side effects. While other languages like Python, you define classes where an Inherited class values are not permanent. You cannot override them in CUE. In following example, if uncomment the Job line it give conflict value error.
#Person: {
Name: string
Email: string
Age?: int
Job?: string
}
#Engineer: #Person & {
Job: "Engineer" // Job is further constrained to required and exactly this value
}
Vaibhav: #Engineer & {
Name: "Vaibhav Kumar"
Email: "vaibhav.kumar@knoldus.com"
Age: 22
//Job: "Pilot"
}



Since it is only for concrete values, we can add options and a default value to allow changes.As done below:
#Person: {
Name: string
Email: string
Age?: int
Job?: string
}
#Engineer: #Person & {
Job: string | *"Engineer"
}
Vaibhav: #Engineer & {
Name: "Vaibhav Kumar"
Email: "vaibhav.kumar@knoldus.com"
Age: 22
Job: "Pilot"
}
Here default value is Engineer but if provided it would allow input as different Job.



Embedding
CUE allows embedding of one definition in another. As seen in last example. We can also extend the definition as following:
#Person: {
Name: string
Email: string
Age?: int
Job?: string
}
#Engineer: {
Domain: "Backend" | "Frontend" | "DevOps"
#Person & {
Job: "Engineer"
}
}
Vaibhav: #Engineer & {
Name: "Vaibhav Kumar"
Email: "vaibhav.kumar@knoldus.com"
Age: 22
Domain: "DevOps"
}



Packages
Like programming languages Python, Java etc. , CUE also import packages. The are reusable, predefined code or scripts. One example has used “strings” package. When you explore Dagger, it has used this feature to use the predefined binaries, created in Dagger Universe. This overcomes the docker problem of various repositories to use for a project.Dagger team create and verifies these packages.
Conclusion
These features have enabled CUE as the scripting partner to dagger. You do not need to master CUE to move to dagger. We can start with this much understanding only.
References


