Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
### Improvements

- Add support for environment-level schema validation with top-level `schema` key.
[#625](https://github.com/pulumi/esc/pull/625)

- Surface warnings when editing environments with the CLI
[#631](https://github.com/pulumi/esc/pull/631)

Expand Down
1 change: 1 addition & 0 deletions ast/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ type EnvironmentDecl struct {
Description *StringExpr
Imports ImportListDecl
Values PropertyMapDecl
Schema Expr
}

func (d *EnvironmentDecl) Syntax() syntax.Node {
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/duplicate-top-level-keys/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/invalid-interpolations/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/invalid-invocation/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/invalid-invocation2/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/invalid-join/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/invalid-open/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
3 changes: 2 additions & 1 deletion ast/testdata/parse/invalid-plaintext/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
}
}
]
}
},
"Schema": null
},
"diags": [
{
Expand Down
26 changes: 25 additions & 1 deletion eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ func declare[Expr exprNode](e *evalContext, path string, x Expr, base *value) *e

func (e *evalContext) isReserveTopLevelKey(k string) bool {
switch k {
case "imports", "context", "environments":
case "imports", "context", "environments", "schema":
return true
default:
return false
Expand Down Expand Up @@ -471,6 +471,30 @@ func (e *evalContext) evaluate() (*value, syntax.Diagnostics) {

// Evaluate the root value and return.
v := e.evaluateExpr(e.root, schema.Always())

// If a top-level schema is defined, validate the root value against it.
if e.env.Schema != nil {
schemaDef := declare(e, "*schema*", e.env.Schema, nil)
schemaVal := e.evaluateExpr(schemaDef, schema.JSONSchemaSchema())
if schemaVal.containsUnknowns() {
e.errorf(e.env.Schema, "schema must not contain unknowns")
} else {
vv := validator{}
schemaOk := vv.validateValue(schemaVal, schema.JSONSchemaSchema(), validationLoc{x: schemaDef})
e.diags.Extend(vv.diags...)
if schemaOk {
validationSchema, err := e.valueToSchema(schemaVal)
if err != nil {
e.errorf(e.env.Schema, "invalid schema: %v", err)
} else if err := validationSchema.Compile(); err != nil {
e.errorf(e.env.Schema, "invalid schema: %v", err)
} else {
v, _ = e.evaluateTypedExpr(e.root, validationSchema)
}
}
}
}

return v, e.diags
}

Expand Down
9 changes: 9 additions & 0 deletions eval/testdata/eval/schema-top-level-error/env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
schema:
type: object
properties:
foo:
type: string
required:
- foo
values:
bar: baz
Loading
Loading