...
1
16
17 package managedfields
18
19 import (
20 "fmt"
21
22 "k8s.io/apimachinery/pkg/runtime/schema"
23 "k8s.io/kube-openapi/pkg/schemaconv"
24 "k8s.io/kube-openapi/pkg/util/proto"
25 smdschema "sigs.k8s.io/structured-merge-diff/v4/schema"
26 "sigs.k8s.io/structured-merge-diff/v4/typed"
27 )
28
29
30
31
32 const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind"
33
34
35 type GvkParser struct {
36 gvks map[schema.GroupVersionKind]string
37 parser typed.Parser
38 }
39
40
41
42 func (p *GvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
43 typeName, ok := p.gvks[gvk]
44 if !ok {
45 return nil
46 }
47 t := p.parser.Type(typeName)
48 return &t
49 }
50
51
52
53
54 func NewGVKParser(models proto.Models, preserveUnknownFields bool) (*GvkParser, error) {
55 typeSchema, err := schemaconv.ToSchemaWithPreserveUnknownFields(models, preserveUnknownFields)
56 if err != nil {
57 return nil, fmt.Errorf("failed to convert models to schema: %v", err)
58 }
59 parser := GvkParser{
60 gvks: map[schema.GroupVersionKind]string{},
61 }
62 parser.parser = typed.Parser{Schema: smdschema.Schema{Types: typeSchema.Types}}
63 for _, modelName := range models.ListModels() {
64 model := models.LookupModel(modelName)
65 if model == nil {
66 panic(fmt.Sprintf("ListModels returns a model that can't be looked-up for: %v", modelName))
67 }
68 gvkList := parseGroupVersionKind(model)
69 for _, gvk := range gvkList {
70 if len(gvk.Kind) > 0 {
71 _, ok := parser.gvks[gvk]
72 if ok {
73 return nil, fmt.Errorf("duplicate entry for %v", gvk)
74 }
75 parser.gvks[gvk] = modelName
76 }
77 }
78 }
79 return &parser, nil
80 }
81
82
83 func parseGroupVersionKind(s proto.Schema) []schema.GroupVersionKind {
84 extensions := s.GetExtensions()
85
86 gvkListResult := []schema.GroupVersionKind{}
87
88
89 gvkExtension, ok := extensions[groupVersionKindExtensionKey]
90 if !ok {
91 return []schema.GroupVersionKind{}
92 }
93
94
95 gvkList, ok := gvkExtension.([]interface{})
96 if !ok {
97 return []schema.GroupVersionKind{}
98 }
99
100 for _, gvk := range gvkList {
101
102
103 gvkMap, ok := gvk.(map[interface{}]interface{})
104 if !ok {
105 continue
106 }
107 group, ok := gvkMap["group"].(string)
108 if !ok {
109 continue
110 }
111 version, ok := gvkMap["version"].(string)
112 if !ok {
113 continue
114 }
115 kind, ok := gvkMap["kind"].(string)
116 if !ok {
117 continue
118 }
119
120 gvkListResult = append(gvkListResult, schema.GroupVersionKind{
121 Group: group,
122 Version: version,
123 Kind: kind,
124 })
125 }
126
127 return gvkListResult
128 }
129
View as plain text