...
1
16
17 package schemaconv
18
19 import (
20 "errors"
21 "path"
22 "strings"
23
24 "k8s.io/kube-openapi/pkg/util/proto"
25 "sigs.k8s.io/structured-merge-diff/v4/schema"
26 )
27
28
29
30 func ToSchema(models proto.Models) (*schema.Schema, error) {
31 return ToSchemaWithPreserveUnknownFields(models, false)
32 }
33
34
35
36 func ToSchemaWithPreserveUnknownFields(models proto.Models, preserveUnknownFields bool) (*schema.Schema, error) {
37 c := convert{
38 preserveUnknownFields: preserveUnknownFields,
39 output: &schema.Schema{},
40 }
41 for _, name := range models.ListModels() {
42 model := models.LookupModel(name)
43
44 var a schema.Atom
45 c2 := c.push(name, &a)
46 model.Accept(c2)
47 c.pop(c2)
48
49 c.insertTypeDef(name, a)
50 }
51
52 if len(c.errorMessages) > 0 {
53 return nil, errors.New(strings.Join(c.errorMessages, "\n"))
54 }
55
56 c.addCommonTypes()
57 return c.output, nil
58 }
59
60 func (c *convert) makeRef(model proto.Schema, preserveUnknownFields bool) schema.TypeRef {
61 var tr schema.TypeRef
62 if r, ok := model.(*proto.Ref); ok {
63 if r.Reference() == "io.k8s.apimachinery.pkg.runtime.RawExtension" {
64 return schema.TypeRef{
65 NamedType: &untypedName,
66 }
67 }
68
69 _, n := path.Split(r.Reference())
70 tr.NamedType = &n
71
72 mapRelationship, err := getMapElementRelationship(model.GetExtensions())
73
74 if err != nil {
75 c.reportError(err.Error())
76 }
77
78
79 if len(mapRelationship) > 0 {
80 tr.ElementRelationship = &mapRelationship
81 }
82 } else {
83
84 c2 := c.push("inlined in "+c.currentName, &tr.Inlined)
85 c2.preserveUnknownFields = preserveUnknownFields
86 model.Accept(c2)
87 c.pop(c2)
88
89 if tr == (schema.TypeRef{}) {
90
91 tr.NamedType = &untypedName
92 }
93 }
94 return tr
95 }
96
97 func (c *convert) VisitKind(k *proto.Kind) {
98 preserveUnknownFields := c.preserveUnknownFields
99 if p, ok := k.GetExtensions()["x-kubernetes-preserve-unknown-fields"]; ok && p == true {
100 preserveUnknownFields = true
101 }
102
103 a := c.top()
104 a.Map = &schema.Map{}
105 for _, name := range k.FieldOrder {
106 member := k.Fields[name]
107 tr := c.makeRef(member, preserveUnknownFields)
108 a.Map.Fields = append(a.Map.Fields, schema.StructField{
109 Name: name,
110 Type: tr,
111 Default: member.GetDefault(),
112 })
113 }
114
115 unions, err := makeUnions(k.GetExtensions())
116 if err != nil {
117 c.reportError(err.Error())
118 return
119 }
120
121
122 a.Map.Unions = unions
123
124 if preserveUnknownFields {
125 a.Map.ElementType = schema.TypeRef{
126 NamedType: &deducedName,
127 }
128 }
129
130 a.Map.ElementRelationship, err = getMapElementRelationship(k.GetExtensions())
131 if err != nil {
132 c.reportError(err.Error())
133 }
134 }
135
136 func (c *convert) VisitArray(a *proto.Array) {
137 relationship, mapKeys, err := getListElementRelationship(a.GetExtensions())
138 if err != nil {
139 c.reportError(err.Error())
140 }
141
142 atom := c.top()
143 atom.List = &schema.List{
144 ElementType: c.makeRef(a.SubType, c.preserveUnknownFields),
145 ElementRelationship: relationship,
146 Keys: mapKeys,
147 }
148 }
149
150 func (c *convert) VisitMap(m *proto.Map) {
151 relationship, err := getMapElementRelationship(m.GetExtensions())
152 if err != nil {
153 c.reportError(err.Error())
154 }
155
156 a := c.top()
157 a.Map = &schema.Map{
158 ElementType: c.makeRef(m.SubType, c.preserveUnknownFields),
159 ElementRelationship: relationship,
160 }
161 }
162
163 func (c *convert) VisitPrimitive(p *proto.Primitive) {
164 a := c.top()
165 if c.currentName == quantityResource {
166 a.Scalar = ptr(schema.Scalar("untyped"))
167 } else {
168 *a = convertPrimitive(p.Type, p.Format)
169 }
170 }
171
172 func (c *convert) VisitArbitrary(a *proto.Arbitrary) {
173 *c.top() = deducedDef.Atom
174 }
175
176 func (c *convert) VisitReference(proto.Reference) {
177
178 }
179
View as plain text