§ C4 · Track A · Companions
eval and validate
What pravo eval and pravo validate check, what they print, and what the flags -c, -e and -O change.
On this page
Two commands read a specification without running it. pravo eval evaluates it and prints the result. pravo validate evaluates it and checks every resource against its provider's schema.
pravo has no vet command. To ask whether every value is final, use pravo eval -c.
Work in an empty directory. Neither command needs a provider for a file that declares none.
Quick reference
| Command | Use it to | Exit status on failure |
|---|---|---|
pravo eval |
Print the evaluated specification. | 6 |
pravo eval -e EXPR |
Print one path or one expression. | 6, or 1 when the path does not exist |
pravo eval -c |
Fail unless every value is concrete. | 1 for a value that is not concrete, 6 otherwise |
pravo eval -O |
Also print optional fields. | 6 |
pravo eval -t key=value |
Give an @tag field its value. |
6 |
pravo validate |
Check the specification against the provider schemas. | 6 |
pravo validate --json |
The same, as one JSON document. | 6 |
Status 6 means the specification does not load, evaluate or validate. Status 1 means a value is missing or not final.
The flags -t and -e combine with -c and -O. -t also works with validate.
What eval prints
pravo eval prints the value of the whole package: references resolved, comprehensions expanded, constraints unified and defaults selected. It prints CUE, in the order the fields were written.
package estate
#Bucket: {
name!: string
versioning: *false | bool
size?: int
}
let prefix = "estate"
_zones: ["a", "b"]
class: *"standard" | "ia"
names: [for z in _zones {"\(prefix)-\(z)"}]
logs: #Bucket & {name: names[0]}
class: "standard"
names: ["estate-a", "estate-b"]
logs: {
name: "estate-a"
versioning: false
}
The output holds the result of each step.
classshows its default,"standard".namesshows the comprehension expanded, withprefixand_zonesalready used.logsshows the fields of the definition, with the defaultfalseselected.
What it leaves out: the definition #Bucket, the let and the hidden field _zones. A definition, a let and a hidden field are not data. Name a definition with -e to see it.
name!: string
versioning: false
pravo eval reads the state of the directory so that it can show recorded values. A directory without one is read as an empty state, and eval creates nothing.
no state directory
Concrete values with -c
A value is concrete when it is one final value: "logs", 3, true. A type such as string, a range such as >=1 and a choice such as "standard" | "ia" are not concrete.
pravo eval prints a value that is not concrete as it is written. The flag -c makes the same value an error. It does not change what is printed. It changes which input fails.
package estate
#Bucket: {
name: string
class: "standard" | "ia"
versioning: *false | bool
size?: int
owner!: string
}
bucket: #Bucket
bucket: {
name: string
class: "standard" | "ia"
versioning: false
owner!: string
}
Error: the value is not concrete:
bucket.class: incomplete value "standard" | "ia":
./estate.cue:11:9
bucket.name: incomplete value string:
./estate.cue:4:14
./estate.cue:11:9
bucket.owner: field is required but not present:
./estate.cue:8:2
./estate.cue:11:9
Each error names a path and a reason.
incomplete value stringmeans the field is still a type. Write a value.incomplete value "standard" | "ia"means no choice is selected and no default marks one. Write a value or mark a default.field is required but not presentmeans a field declared with!has no value.
The optional field size? and the defaulted field versioning do not appear. An optional field may stay unset. A default is a value.
Write the missing values and run -c again.
package estate
#Bucket: {
name: string
class: "standard" | "ia"
versioning: *false | bool
size?: int
owner!: string
}
bucket: #Bucket & {name: "logs", class: "ia", owner: "platform"}
bucket: {
name: "logs"
class: "ia"
versioning: false
owner: "platform"
}
The exit status is 0, and the output is the value. C2 lists every cause of an incomplete value.
One expression with -e
-e evaluates one path or one CUE expression in the scope of the specification and prints only that.
"ia"
4
"platform/logs"
"LOGS"
- A path prints the value at that path.
- An expression may call functions of the standard library without an import.
-esees regular fields and definitions. A hidden field or aletis not visible to it. Copy the value into a regular field to look at it.- With
-c, only the selected value must be concrete.
A path that does not exist is an error.
Error: -e "bucket.colour": undefined field: colour:
1:8
Optional fields with -O
Without -O, pravo eval leaves out a field declared with ?. With -O it prints the field and its type. A field declared with ! is always printed.
name: "logs"
class: "ia"
versioning: false
size?: int
owner: "platform"
The flag shows what a definition offers. Combine it with -e to read the whole shape.
name: string
class: "standard" | "ia"
versioning: false
size?: int
owner!: string
Tags with -t and -T
A tag is a field marked @tag(name). The flag -t name=value gives it a value. A name that no field declares is refused.
package estate
env: *"dev" | "staging" | "prod" @tag(env)
env: "prod"
Error: loading .:
no tag for "stage"
The flag -T fills tags declared with var=, such as @tag(os,var=os), from the system. The names include os, arch and cwd.
What validate checks
pravo validate loads and evaluates the specification. It checks each resource, data source and call against the schema of its provider. It prints one line when everything holds.
Success! 0 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 0 providers.
For a file without providers, validate loads and evaluates the file as eval does. It prints a count instead of the value. It does not require concrete values.
The counts matter when providers are declared. Declare one and generate its schema with pravo init.
package estate
import rnd "pravo.dev/providers/hashicorp/random"
$random: rnd.#Provider & {$version: "~> 3.6"}
pet: $random.#Resource.random_pet & {
length: 3
separator: "-"
}
Configuration does not load yet; generating schemas for the declared providers first.
Created cue.mod/module.cue
Providers:
random = hashicorp/random v3.9.1
Up to date cue.mod/gen/pravo.dev/providers/hashicorp/random (10 resource types, 0 data sources, 2 ephemeral, 0 functions)
pravo has been initialised. Run "pravo plan" to see what it would do.
Success! 1 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 1 providers.
pravo validate accepts the resource. It checks the field names, the types and the constraints of the generated definition. Misspell a field.
package estate
import rnd "pravo.dev/providers/hashicorp/random"
$random: rnd.#Provider & {$version: "~> 3.6"}
pet: $random.#Resource.random_pet & {
lenght: 3
separator: "-"
}
Error: evaluating .:
pet.lenght: field not allowed:
./estate.cue:8:2
pravo validate exits with 6 when the specification does not evaluate or validate. pravo eval exits with 6 for the same file.
Error: evaluating .:
pet.lenght: field not allowed:
./estate.cue:8:2
Restore the field name. A resource has attributes that the provider computes, such as id. They are unknown before an apply, so -c over the whole file fails, and validate passes.
package estate
import rnd "pravo.dev/providers/hashicorp/random"
$random: rnd.#Provider & {$version: "~> 3.6"}
pet: $random.#Resource.random_pet & {
length: 3
separator: "-"
}
Success! 1 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 1 providers.
Error: the value is not concrete:
pet.id: incomplete value string | null
Select a value that is known, and -c passes.
3
After an apply
An apply records the computed attributes in the state. pravo eval fills them in, so -c passes for the whole file. B3 covers the apply.
"quiet-river-fox"
The id is random, so your output shows another name.
Which command, when
| Question | Command |
|---|---|
| What does my specification evaluate to? | pravo eval |
| What is this one value? | pravo eval -e path |
| Is every value final? | pravo eval -c, with -e for the part you care about |
| What fields can I still set? | pravo eval -O -e '#Shape' |
| Does each resource match its provider's schema? | pravo validate |
| Should a script stop? | The exit status: 6 for an error in the specification, 1 for a value that is missing or not final |
A short gate for a script runs both.
pravo validate && pravo eval -c -e buckets
Recap
pravo evalprints the evaluated value. It leaves out definitions,letand hidden fields.-cmakes a value that is not concrete an error.-eselects one expression.-Oadds optional fields.pravo validatechecks resources against provider schemas and does not require concrete values. It exits with 6.
The full list of flags is in the command reference.
Check yourself
A file contains size: int. Does pravo eval accept it? Does pravo eval -c?
pravo eval accepts it and prints size: int. pravo eval -c fails with incomplete value int.
Which command refuses a misspelt attribute of a resource, and with which exit status?
pravo validate, with exit status 6. It reports field not allowed.