Original thread
#### David Desmarais-Michaud
Hi, I am a newer comer to Cue, long time lurker, but first time user. One of the things that is stumping me is that I want to use cue to do strict validation for a helm chart values spec we are working on.
I want to describe my spec in cue:
```cue
app: {
name: string
}
```
And validate the values.yaml
```yaml
name: true # error when validating with cue
```
However when running cue vet I want to be able to detect unknown properties. Such that if the user makes a spelling error in a property name, that property would be raised as unknown. I haven't found the write keyword search to figure this out yet...
Thanks in advance!!! Happy to be here!
27 replies
#### cwp
You could use the close function on your app definition. That would make fields that are not explicitly defined generate an error.
#### cwp
```cue
app: close({
name: string
})
```
#### David Desmarais-Michaud
Awesome! That's what I want. Can I close the definition of the entire cue file?
And can close be recursive?
#### cwp
AFAIK, no and no.
#### David Desmarais-Michaud
I suppose the former is simply:
```cue
close({
app: close({...})
})
```
but its would have been great to close everything below it
#### eloip
Hum, this seems to be the typical use for [Definitions](https://cuelang.org/docs/references/spec/#definitions-and-hidden-fields): with `#app: { name: string }` , any further reference of #app can only refine its fields but not create new ones, thus catching typos. note that the `#app:` object itself is not closed (you can, `#app: { foo: int }` to add valid fields)
Also, if the reference is an embedding, `{ #app, bar: string }`, it is considered as an extension of `#app:` so it's for schema definition, use `values: #app & config` to validate. AFAIK... (edited)
#### cwp
Indeed. With a definition, it’d be something like this:
```cue
package example
#App: {
name: string
}
_yamlData: _
app: #App & _yamlData
```
Then you’d have to export with something like `cue export :example -l _yamlData: yaml: app.yaml`
That’s pretty finicky though, might take some trial and error.
Using close is probably easier. :smile:
#### eloip
yes! it will depend on "how" values are unified in the end. I'm not so familiar with the `-l` flags and path syntax in the CLI, is that a heritage from Go ?
#### cwp
:shrug:
#### David Desmarais-Michaud
It seems to me, that if I want to do closed schema validation my best bet is to define all my types as `#Definitions` and and close my top level:
```cue
#app: { ... }
#database: { ... }
close({
app: #app
database: #database
})
```
Any thoughts on this approach? (edited)
Also if anybody can help me understand the value in having package declarations as if it was a Go package that would be great but unrelated :slightly_smiling_face:
#### cwp
That looks good!
The package declaration groups together all the files with that declaration, so you can do eg `cue vet :examplePackge`.
You can also import other packages, so it’s a good way to organize and structure your code.
#### myitcv
This is a good thread for a concept guide/tutorial to my mind!
Just following up on a few points here with an example using cue vet
```
exec cue vet -d '#schema' x.cue ok.yaml
! exec cue vet -d '#schema' x.cue bad.yaml
cmp stderr stderr.golden
-- bad.yaml --
app:
name: test
database:
name: test
other:
name: test
-- ok.yaml --
app:
name: test
database:
name: test
-- x.cue --
#schema: {
app: #app
database: #database
}
#app: {
name?: string
}
#database: {
name?: string
}
-- stderr.golden --
other: field not allowed:
./bad.yaml:7:1
./x.cue:1:10
```
Whilst `close()` is not recursive, referring to a definition does recursively close the everything "contained" within the value, unless it is explicitly left open via `...`
The use of the -d flag to cue vet allows me to refer to the schema that I want to use for validation
And if that is reference to a definition, the result will be recursively closed
#### David Desmarais-Michaud
Yeah I didn't get that definitions were recursively closed at first, but I figured it out along the way. I love it, and love the `...` syntax to open the definitions. Closed first is a great model.
Content
A concept guide that explains the different results achieved when using a definition versus explicit close() calls.
From Slack: https://cuelang.slack.com/archives/CLT4FD7KP/p1708102852448829
Original thread
#### David Desmarais-Michaud Hi, I am a newer comer to Cue, long time lurker, but first time user. One of the things that is stumping me is that I want to use cue to do strict validation for a helm chart values spec we are working on. I want to describe my spec in cue: ```cue app: { name: string } ``` And validate the values.yaml ```yaml name: true # error when validating with cue ``` However when running cue vet I want to be able to detect unknown properties. Such that if the user makes a spelling error in a property name, that property would be raised as unknown. I haven't found the write keyword search to figure this out yet... Thanks in advance!!! Happy to be here! 27 replies #### cwp You could use the close function on your app definition. That would make fields that are not explicitly defined generate an error. #### cwp ```cue app: close({ name: string }) ``` #### David Desmarais-Michaud Awesome! That's what I want. Can I close the definition of the entire cue file? And can close be recursive? #### cwp AFAIK, no and no. #### David Desmarais-Michaud I suppose the former is simply: ```cue close({ app: close({...}) }) ``` but its would have been great to close everything below it #### eloip Hum, this seems to be the typical use for [Definitions](https://cuelang.org/docs/references/spec/#definitions-and-hidden-fields): with `#app: { name: string }` , any further reference of #app can only refine its fields but not create new ones, thus catching typos. note that the `#app:` object itself is not closed (you can, `#app: { foo: int }` to add valid fields) Also, if the reference is an embedding, `{ #app, bar: string }`, it is considered as an extension of `#app:` so it's for schema definition, use `values: #app & config` to validate. AFAIK... (edited) #### cwp Indeed. With a definition, it’d be something like this: ```cue package example #App: { name: string } _yamlData: _ app: #App & _yamlData ``` Then you’d have to export with something like `cue export :example -l _yamlData: yaml: app.yaml` That’s pretty finicky though, might take some trial and error. Using close is probably easier. :smile: #### eloip yes! it will depend on "how" values are unified in the end. I'm not so familiar with the `-l` flags and path syntax in the CLI, is that a heritage from Go ? #### cwp :shrug: #### David Desmarais-Michaud It seems to me, that if I want to do closed schema validation my best bet is to define all my types as `#Definitions` and and close my top level: ```cue #app: { ... } #database: { ... } close({ app: #app database: #database }) ``` Any thoughts on this approach? (edited) Also if anybody can help me understand the value in having package declarations as if it was a Go package that would be great but unrelated :slightly_smiling_face: #### cwp That looks good! The package declaration groups together all the files with that declaration, so you can do eg `cue vet :examplePackge`. You can also import other packages, so it’s a good way to organize and structure your code. #### myitcv This is a good thread for a concept guide/tutorial to my mind! Just following up on a few points here with an example using cue vet ``` exec cue vet -d '#schema' x.cue ok.yaml ! exec cue vet -d '#schema' x.cue bad.yaml cmp stderr stderr.golden -- bad.yaml -- app: name: test database: name: test other: name: test -- ok.yaml -- app: name: test database: name: test -- x.cue -- #schema: { app: #app database: #database } #app: { name?: string } #database: { name?: string } -- stderr.golden -- other: field not allowed: ./bad.yaml:7:1 ./x.cue:1:10 ``` Whilst `close()` is not recursive, referring to a definition does recursively close the everything "contained" within the value, unless it is explicitly left open via `...` The use of the -d flag to cue vet allows me to refer to the schema that I want to use for validation And if that is reference to a definition, the result will be recursively closed #### David Desmarais-Michaud Yeah I didn't get that definitions were recursively closed at first, but I figured it out along the way. I love it, and love the `...` syntax to open the definitions. Closed first is a great model.Content
A concept guide that explains the different results achieved when using a definition versus explicit
close()
calls.Audience
A CUE-aware beginner.