1
16
17 package resource
18
19 import (
20 "fmt"
21 "reflect"
22
23 "k8s.io/apimachinery/pkg/api/meta"
24 "k8s.io/apimachinery/pkg/runtime"
25 "k8s.io/apimachinery/pkg/runtime/schema"
26 )
27
28
29
30 type mapper struct {
31
32 localFn func() bool
33
34 restMapperFn RESTMapperFunc
35 clientFn func(version schema.GroupVersion) (RESTClient, error)
36 decoder runtime.Decoder
37 }
38
39
40
41
42 func (m *mapper) infoForData(data []byte, source string) (*Info, error) {
43 obj, gvk, err := m.decoder.Decode(data, nil, nil)
44 if err != nil {
45 return nil, fmt.Errorf("unable to decode %q: %v", source, err)
46 }
47
48 name, _ := metadataAccessor.Name(obj)
49 namespace, _ := metadataAccessor.Namespace(obj)
50 resourceVersion, _ := metadataAccessor.ResourceVersion(obj)
51
52 ret := &Info{
53 Source: source,
54 Namespace: namespace,
55 Name: name,
56 ResourceVersion: resourceVersion,
57
58 Object: obj,
59 }
60
61 if m.localFn == nil || !m.localFn() {
62 restMapper, err := m.restMapperFn()
63 if err != nil {
64 return nil, err
65 }
66 mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
67 if err != nil {
68 if _, ok := err.(*meta.NoKindMatchError); ok {
69 return nil, fmt.Errorf("resource mapping not found for name: %q namespace: %q from %q: %w\nensure CRDs are installed first",
70 name, namespace, source, err)
71 }
72 return nil, fmt.Errorf("unable to recognize %q: %v", source, err)
73 }
74 ret.Mapping = mapping
75
76 client, err := m.clientFn(gvk.GroupVersion())
77 if err != nil {
78 return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
79 }
80 ret.Client = client
81 }
82
83 return ret, nil
84 }
85
86
87
88
89 func (m *mapper) infoForObject(obj runtime.Object, typer runtime.ObjectTyper, preferredGVKs []schema.GroupVersionKind) (*Info, error) {
90 groupVersionKinds, _, err := typer.ObjectKinds(obj)
91 if err != nil {
92 return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err)
93 }
94
95 gvk := groupVersionKinds[0]
96 if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 {
97 gvk = preferredObjectKind(groupVersionKinds, preferredGVKs)
98 }
99
100 name, _ := metadataAccessor.Name(obj)
101 namespace, _ := metadataAccessor.Namespace(obj)
102 resourceVersion, _ := metadataAccessor.ResourceVersion(obj)
103 ret := &Info{
104 Namespace: namespace,
105 Name: name,
106 ResourceVersion: resourceVersion,
107
108 Object: obj,
109 }
110
111 if m.localFn == nil || !m.localFn() {
112 restMapper, err := m.restMapperFn()
113 if err != nil {
114 return nil, err
115 }
116 mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
117 if err != nil {
118 return nil, fmt.Errorf("unable to recognize %v", err)
119 }
120 ret.Mapping = mapping
121
122 client, err := m.clientFn(gvk.GroupVersion())
123 if err != nil {
124 return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
125 }
126 ret.Client = client
127 }
128
129 return ret, nil
130 }
131
132
133
134
135
136 func preferredObjectKind(possibilities []schema.GroupVersionKind, preferences []schema.GroupVersionKind) schema.GroupVersionKind {
137
138 for _, priority := range preferences {
139 for _, possibility := range possibilities {
140 if possibility == priority {
141 return possibility
142 }
143 }
144 }
145
146
147 for _, priority := range preferences {
148 for _, possibility := range possibilities {
149 if possibility.GroupKind() == priority.GroupKind() {
150 return possibility
151 }
152 }
153 }
154
155
156 for _, priority := range preferences {
157 for _, possibility := range possibilities {
158 if possibility.Group == priority.Group {
159 return possibility
160 }
161 }
162 }
163
164
165 return possibilities[0]
166 }
167
View as plain text