I'd like to have additional constraints on certain struct fields in a cue schema that was generated from a Golang module.
schema.cue
below is generated from a corresponding Golang module
package app
#App: {
version: string @go(Version)
}
...
I have tried specifying cue annotations in the source Golang module (example below) but that wasn't yielding the right constraints in the generated schema.cue
.
type App struct {
Version string `cue:"'version: =~core.myapp.dev/v1'" yaml:"Version"`
}
Another approach I tried was using conjuctions to extend an instance of the schema.
package app
#App: {
version: string @go(Version)
}
...
#AppExtended: #App & {
version: =~ "core.myapp.dev/v1"
}
However, cue vet schema.cue tests/badVersionValue.yaml
, wasn't yielding any errors to stdout
, where badVersionValue.yaml
contained Version: badstring
.
I am able to have a working solution with the following manually written schema.cue
package app
version: =~"core.myapp.dev/v1"
such that cue vet schema.cue tests/badVersionValue.yaml
yields
Version: invalid value "badstring" (out of bound =~"core.myapp.dev/v1"):
...
The downside of this approach is I would then be writing cue schema files from scratch rather than using and iterating upon the generated ones from the Golang source code/source of truth.
I misunderstood how to properly vet with cue when definitions
are involved.
Based on this example from cuetorials.com you can specify -d "#Schema"
where
The extra -d "<path>" tells Cue the value we want to use to validate each Yaml entry against. We have to do this because Cue defaults to using top-level information.
I'm seeing success not only with the following where the yaml file contents are Version: 5
.
cue vet badVersionStr.yaml schema.cue -d '#App'
Version: conflicting values 5 and string (mismatched types int and string):
but also with appending constraints to existing fields, per the OP:
package app
#App: {
version: string @go(Version)
version: =~ "core.myapp.dev/v1"
}
...
which now yields the expected output
cue vet badVersionStr.yaml schema.cue -d '#App'
Version: invalid value "badString" (out of bound =~"core.myapp.dev/v1"):
EDIT: An even better approach for folks using a Golang module for everything. You can place constraints as struct field annotations in the Golang module.
# app.go
type App struct {
Version string `cue:"=~\"core.myapp.dev/v1\"" yaml:"Version"`
...
With cue get go app.go
you get a corresponding app_go_gen.cue
that should look like this
#App: {
Version: string & =~"core.myapp.dev/v1" @go(Version)
...
Which works when doing the cue vet ...
commands referenced above. This means you only need to specify the constraints in the Golang module and then generate the Cue schema which will interpret those annotations as constraints on the struct field.