Skip to content

Commit 0cd0a0c

Browse files
committed
encoding/jsonschema: support x-kubernetes-embedded-resource
This adds initial support for the "x-kubernetes-embedded-resource" keyword. See https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#rawextension Signed-off-by: Roger Peppe <[email protected]> Change-Id: Ifdf199380fe24bbd7fcf8df1b5bb87faab4d226a Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1211212 Reviewed-by: Daniel Martí <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 0dcaff5 commit 0cd0a0c

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

encoding/jsonschema/constraints.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ var constraints = []*constraint{
127127
p2("uniqueItems", constraintUniqueItems, allVersions|openAPI|k8sCRD),
128128
px("writeOnly", constraintTODO, vfrom(VersionDraft7)|openAPI),
129129
px("xml", constraintTODO, openAPI),
130-
px("x-kubernetes-embedded-resource", constraintTODO, k8sCRD),
130+
p1("x-kubernetes-embedded-resource", constraintEmbeddedResource, k8sCRD),
131131
p2("x-kubernetes-int-or-string", constraintIntOrString, k8sCRD),
132132
px("x-kubernetes-list-map-keys", constraintTODO, k8sCRD),
133133
px("x-kubernetes-list-type", constraintTODO, k8sCRD),

encoding/jsonschema/constraints_object.go

+31-1
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,43 @@ func constraintPatternProperties(key string, n cue.Value, s *state) {
139139
})
140140
}
141141

142+
func constraintEmbeddedResource(key string, n cue.Value, s *state) {
143+
// TODO:
144+
// - should fail if type has not been specified as "object"
145+
// - should fail if neither x-kubernetes-preserve-unknown-fields or properties have been specified
146+
147+
// Note: this runs in a phase before the properties keyword so
148+
// that the embedded expression always comes first in the struct
149+
// literal.
150+
resourceDefinitionPath := cue.MakePath(cue.Hid("_embeddedResource", "_"))
151+
obj := s.object(n)
152+
153+
// Generate a reference to a shared schema that all embedded resources
154+
// can share. If it already exists, that's fine.
155+
// TODO add an attribute to make it clear what's going on here
156+
// when encoding a CRD from CUE?
157+
s.builder.put(resourceDefinitionPath, ast.NewStruct(
158+
"apiVersion", token.NOT, ast.NewIdent("string"),
159+
"kind", token.NOT, ast.NewIdent("string"),
160+
"metadata", token.NOT, ast.NewStruct(&ast.Ellipsis{}),
161+
), nil)
162+
refExpr, err := s.builder.getRef(resourceDefinitionPath)
163+
if err != nil {
164+
s.errf(n, `cannot get reference to embedded resource definition: %v`, err)
165+
} else {
166+
obj.Elts = append(obj.Elts, &ast.EmbedDecl{
167+
Expr: refExpr,
168+
})
169+
}
170+
s.allowedTypes &= cue.StructKind
171+
}
172+
142173
func constraintProperties(key string, n cue.Value, s *state) {
143174
obj := s.object(n)
144175

145176
if n.Kind() != cue.StructKind {
146177
s.errf(n, `"properties" expected an object, found %v`, n.Kind())
147178
}
148-
149179
s.processMap(n, func(key string, n cue.Value) {
150180
// property?: value
151181
name := ast.NewString(key)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#version: crd
2+
3+
-- schema.json --
4+
{
5+
"apiVersion": "apiextensions.k8s.io/v1",
6+
"kind": "CustomResourceDefinition",
7+
"metadata": {
8+
"name": "myapps.example.com"
9+
},
10+
"spec": {
11+
"group": "example.com",
12+
"scope": "Namespaced",
13+
"names": {
14+
"kind": "MyApp",
15+
"singular": "myapp",
16+
"plural": "myapps"
17+
},
18+
"versions": [
19+
{
20+
"name": "v1",
21+
"served": true,
22+
"storage": true,
23+
"schema": {
24+
"openAPIV3Schema": {
25+
"type": "object",
26+
"properties": {
27+
"r1": {
28+
"type": "object",
29+
"x-kubernetes-embedded-resource": true,
30+
"x-kubernetes-preserve-unknown-fields": true
31+
},
32+
"r2": {
33+
"type": "object",
34+
"x-kubernetes-embedded-resource": true,
35+
"properties": {
36+
"foo": {
37+
"type": "string"
38+
}
39+
}
40+
}
41+
}
42+
}
43+
}
44+
}
45+
]
46+
}
47+
}
48+
-- out/decode/extract --
49+
close({
50+
r1?: {
51+
_embeddedResource
52+
...
53+
}
54+
r2?: close({
55+
_embeddedResource
56+
foo?: string
57+
})
58+
})
59+
60+
_embeddedResource: {
61+
apiVersion!: string
62+
kind!: string
63+
metadata!: {
64+
...
65+
}
66+
}

0 commit comments

Comments
 (0)