§ Reference · Language

Generated packages

The CUE packages that pravo init writes under cue.mod/gen, one per provider and one for pravo itself.

View as Markdown

On this page

pravo init writes no file into the root. It writes CUE packages under cue.mod/gen/, and the root imports them.

Import path Contents
pravo.dev/pravo #Settings, #Output, #Env, #SecretEnv, #RemoteOutputs, #Movable and the types of the state setting.
pravo.dev/providers/<namespace>/<type> One provider: #Provider, with #Resource, #Data, #Ephemeral and #Function as members, and #Lifecycle.
pravo.dev/providers/<host>/<namespace>/<type> A provider from a registry other than the default one.

Work in an empty directory.

main.cue
package demo

import (
	rnd "pravo.dev/providers/hashicorp/random"
	nul "pravo.dev/providers/hashicorp/null:null_"
)

$random: rnd.#Provider
$null:   nul.#Provider

pet:    $random.#Resource.random_pet & {length: 2}
marker: $null.#Resource.null_resource & {triggers: build: "1"}
terminal
$pravo init
$find cue.mod -type f | sort
Configuration does not load yet; generating schemas for the declared providers first.
Created cue.mod/module.cue
Providers:
  null = hashicorp/null v3.3.2
  random = hashicorp/random v3.9.1
Up to date cue.mod/gen/pravo.dev/providers/hashicorp/null (1 resource types, 1 data sources, 0 ephemeral, 0 functions)
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.
cue.mod/gen/pravo.dev/pravo/settings_gen.cue
cue.mod/gen/pravo.dev/providers/hashicorp/null/null__gen.cue
cue.mod/gen/pravo.dev/providers/hashicorp/random/random_gen.cue
cue.mod/module.cue

Each provider package holds every type the provider offers. The first line records the provider version it was made from:

terminal
$head -n 4 cue.mod/gen/pravo.dev/providers/hashicorp/random/random_gen.cue
// Provider registry.opentofu.org/hashicorp/random v3.9.1
// Code generated by pravo. DO NOT EDIT.

package random

Run pravo init before the first plan. Commit cue.mod/gen and pravo.lock.cue, or run pravo init in CI, so that a clean checkout behaves the same.

The pravo package

Definition Used as
#Settings $settings: pravo.#Settings & {...}. See Settings.
#StateSettings, #LocalState, #S3State, #StateFields The types of the state key.
#Output name: pravo.#Output & {value: ...}. See Outputs.
#Env, #SecretEnv Environment variables. See Environment and remote outputs.
#RemoteOutputs The outputs of another root.
#Movable Embedded in a definition so that its instances accept $from. See Moves and imports.
terminal
$grep -E '^#[A-Za-z0-9]+:' cue.mod/gen/pravo.dev/pravo/settings_gen.cue
#Movable: {
#Output: {
#Env: {
#SecretEnv: {
#RemoteOutputs: {
#Settings: {
#StateSettings: #StateFields & (#LocalState | #S3State)
#StateFields: {
#LocalState: {
#S3State: {

The provider package

A provider package declares:

Definition Contents
#Provider The provider's configuration, the $ fields and the four members below.
#Provider.#Resource.<type> One definition per managed resource type.
#Provider.#Data.<type> One per data source.
#Provider.#Ephemeral.<type> One per ephemeral resource.
#Provider.#Function.<name> One per provider-defined function: args and result.
#Lifecycle The shape of $lifecycle. A specification does not use it directly.

Every definition carries $kind, $type and $source, which is how pravo recognises a resource, and the meta fields. pravo schema <type> prints one definition with the provider's documentation. With --required it keeps only the attributes that must be set. The end of the definition of random_pet:

terminal
$pravo schema random_pet | tail -n 14
	// Additional dependencies, as references to other resources.
	$depends_on?: [..._]
	$lifecycle?: #Lifecycle
	// The random pet name.
	id: __string | null
	// Arbitrary map of values that, when changed, will trigger recreation of resource. See [the main provider documentation](../index.html) for more information.
	keepers?: {[string]: __string}
	// The length (in words) of the pet name. Defaults to 2
	length: __number | null
	// A string to prefix the name with.
	prefix?: __string
	// The character to separate words in the pet name. Defaults to "-"
	separator: __string | null
}

Schema mapping

Provider attribute CUE
required name: T
optional name?: T
computed name: T | null
optional and computed name: T | null
string, number, bool string, number, bool
list(T), set(T) [...T]
map(T) {[string]: T}
object({a=T}) {a?: T}
tuple([T1,T2]) [T1, T2]
dynamic _
nested block, single or group name?: {...}
nested block, list or set name?: [...{...}]
nested block, map name?: {[string]: {...}}
nested attribute (protocol 6) as a block, following its mode

The generated files write the predeclared types as __string, __number and __bool. CUE reads them as string, number and bool.

A computed attribute such as id is a regular field, id: string | null, so another resource can refer to it before it is known. After the apply the concrete value fills in. If you set an attribute that is optional and computed, the value is sent. If you leave it out, it is sent as null and the provider picks the default.

sensitive, deprecated and write_only attributes carry a @pravo(...) attribute on the field. A sensitive value prints as (sensitive) in plans. A write-only attribute may take an ephemeral value.

Package names

The package name is the provider type with - and . replaced by _. A name that is a CUE keyword gets a trailing underscore: null, true, false, package, import, for, in, if and let. A name that begins with a digit gets a p in front. Whenever the package name differs from the last element of the path, the import names it after a colon, and you choose the alias.

Provider type Package name Import
random random "pravo.dev/providers/hashicorp/random"
null null_ "pravo.dev/providers/hashicorp/null:null_"
my-cloud my_cloud "pravo.dev/providers/acme/my-cloud:my_cloud"

Without the colon, the import cannot be resolved:

main.cue
package demo

import nul "pravo.dev/providers/hashicorp/null"

$null: nul.#Provider
terminalexit 6
$pravo validate
Error: loading .:
pravo.local/ws@v0: import failed: cannot find package "pravo.dev/providers/hashicorp/null": no files in package directory with package name "null":
    ./main.cue:3:8


hint: a provider schema package is missing. Run "pravo init" to generate it

Choose an alias that differs from the provider's local name and from every field name in scope. A top-level field with the name of an import is an error, random redeclared as imported package name. Provider structs are named with a leading $ for this reason. The examples use rnd for random, loc for local, awsp for aws, tlsp for tls and k8s for kubernetes.

Regenerating

pravo init and pravo gen rewrite the packages from the provider schemas. A package that already has the right content is left alone.

main.cue
package demo

import rnd "pravo.dev/providers/hashicorp/random"

$random: rnd.#Provider
terminal
$pravo gen
Up to date cue.mod/gen/pravo.dev/providers/hashicorp/random (10 resource types, 0 data sources, 2 ephemeral, 0 functions)

When the version in the lock file or on disk differs from the version a package was made from, plan, apply, validate and the other commands warn and carry on. init and gen write the package again and do not warn. An attribute that the new version added is rejected until the package is regenerated. Change the version on the first line of the package to see the warning:

terminal
$sed -i.bak '1s/v[0-9.]*$/v3.0.0/' cue.mod/gen/pravo.dev/providers/hashicorp/random/random_gen.cue
$pravo validate
$pravo gen
$pravo validate
Warning: the generated schema for provider random was made from a different version than the selected v3.9.1; run "pravo init" to refresh it
Success! 0 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 1 providers.
Generated cue.mod/gen/pravo.dev/providers/hashicorp/random (10 resource types, 0 data sources, 2 ephemeral, 0 functions)
Success! 0 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 1 providers.

See also