1
16
17 package client
18
19 import (
20 "context"
21 "fmt"
22 "strings"
23
24 "k8s.io/apimachinery/pkg/api/meta"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/runtime/schema"
27 "k8s.io/client-go/metadata"
28 )
29
30
31
32
33
34
35
36 type metadataClient struct {
37 client metadata.Interface
38 restMapper meta.RESTMapper
39 }
40
41 func (mc *metadataClient) getResourceInterface(gvk schema.GroupVersionKind, ns string) (metadata.ResourceInterface, error) {
42 mapping, err := mc.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
43 if err != nil {
44 return nil, err
45 }
46 if mapping.Scope.Name() == meta.RESTScopeNameRoot {
47 return mc.client.Resource(mapping.Resource), nil
48 }
49 return mc.client.Resource(mapping.Resource).Namespace(ns), nil
50 }
51
52
53 func (mc *metadataClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error {
54 metadata, ok := obj.(*metav1.PartialObjectMetadata)
55 if !ok {
56 return fmt.Errorf("metadata client did not understand object: %T", obj)
57 }
58
59 resInt, err := mc.getResourceInterface(metadata.GroupVersionKind(), metadata.Namespace)
60 if err != nil {
61 return err
62 }
63
64 deleteOpts := DeleteOptions{}
65 deleteOpts.ApplyOptions(opts)
66
67 return resInt.Delete(ctx, metadata.Name, *deleteOpts.AsDeleteOptions())
68 }
69
70
71 func (mc *metadataClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error {
72 metadata, ok := obj.(*metav1.PartialObjectMetadata)
73 if !ok {
74 return fmt.Errorf("metadata client did not understand object: %T", obj)
75 }
76
77 deleteAllOfOpts := DeleteAllOfOptions{}
78 deleteAllOfOpts.ApplyOptions(opts)
79
80 resInt, err := mc.getResourceInterface(metadata.GroupVersionKind(), deleteAllOfOpts.ListOptions.Namespace)
81 if err != nil {
82 return err
83 }
84
85 return resInt.DeleteCollection(ctx, *deleteAllOfOpts.AsDeleteOptions(), *deleteAllOfOpts.AsListOptions())
86 }
87
88
89 func (mc *metadataClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
90 metadata, ok := obj.(*metav1.PartialObjectMetadata)
91 if !ok {
92 return fmt.Errorf("metadata client did not understand object: %T", obj)
93 }
94
95 gvk := metadata.GroupVersionKind()
96 resInt, err := mc.getResourceInterface(gvk, metadata.Namespace)
97 if err != nil {
98 return err
99 }
100
101 data, err := patch.Data(obj)
102 if err != nil {
103 return err
104 }
105
106 patchOpts := &PatchOptions{}
107 patchOpts.ApplyOptions(opts)
108
109 res, err := resInt.Patch(ctx, metadata.Name, patch.Type(), data, *patchOpts.AsPatchOptions())
110 if err != nil {
111 return err
112 }
113 *metadata = *res
114 metadata.SetGroupVersionKind(gvk)
115 return nil
116 }
117
118
119 func (mc *metadataClient) Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error {
120 metadata, ok := obj.(*metav1.PartialObjectMetadata)
121 if !ok {
122 return fmt.Errorf("metadata client did not understand object: %T", obj)
123 }
124
125 gvk := metadata.GroupVersionKind()
126
127 getOpts := GetOptions{}
128 getOpts.ApplyOptions(opts)
129
130 resInt, err := mc.getResourceInterface(gvk, key.Namespace)
131 if err != nil {
132 return err
133 }
134
135 res, err := resInt.Get(ctx, key.Name, *getOpts.AsGetOptions())
136 if err != nil {
137 return err
138 }
139 *metadata = *res
140 metadata.SetGroupVersionKind(gvk)
141 return nil
142 }
143
144
145 func (mc *metadataClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error {
146 metadata, ok := obj.(*metav1.PartialObjectMetadataList)
147 if !ok {
148 return fmt.Errorf("metadata client did not understand object: %T", obj)
149 }
150
151 gvk := metadata.GroupVersionKind()
152 gvk.Kind = strings.TrimSuffix(gvk.Kind, "List")
153
154 listOpts := ListOptions{}
155 listOpts.ApplyOptions(opts)
156
157 resInt, err := mc.getResourceInterface(gvk, listOpts.Namespace)
158 if err != nil {
159 return err
160 }
161
162 res, err := resInt.List(ctx, *listOpts.AsListOptions())
163 if err != nil {
164 return err
165 }
166 *metadata = *res
167 metadata.SetGroupVersionKind(gvk)
168 return nil
169 }
170
171 func (mc *metadataClient) PatchSubResource(ctx context.Context, obj Object, subResource string, patch Patch, opts ...SubResourcePatchOption) error {
172 metadata, ok := obj.(*metav1.PartialObjectMetadata)
173 if !ok {
174 return fmt.Errorf("metadata client did not understand object: %T", obj)
175 }
176
177 gvk := metadata.GroupVersionKind()
178 resInt, err := mc.getResourceInterface(gvk, metadata.Namespace)
179 if err != nil {
180 return err
181 }
182
183 patchOpts := &SubResourcePatchOptions{}
184 patchOpts.ApplyOptions(opts)
185
186 body := obj
187 if patchOpts.SubResourceBody != nil {
188 body = patchOpts.SubResourceBody
189 }
190
191 data, err := patch.Data(body)
192 if err != nil {
193 return err
194 }
195
196 res, err := resInt.Patch(ctx, metadata.Name, patch.Type(), data, *patchOpts.AsPatchOptions(), subResource)
197 if err != nil {
198 return err
199 }
200
201 *metadata = *res
202 metadata.SetGroupVersionKind(gvk)
203 return nil
204 }
205
View as plain text