1
16
17 package client
18
19 import (
20 "context"
21 "fmt"
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 func NewNamespacedClient(c Client, ns string) Client {
31 return &namespacedClient{
32 client: c,
33 namespace: ns,
34 }
35 }
36
37 var _ Client = &namespacedClient{}
38
39
40 type namespacedClient struct {
41 namespace string
42 client Client
43 }
44
45
46 func (n *namespacedClient) Scheme() *runtime.Scheme {
47 return n.client.Scheme()
48 }
49
50
51 func (n *namespacedClient) RESTMapper() meta.RESTMapper {
52 return n.client.RESTMapper()
53 }
54
55
56 func (n *namespacedClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) {
57 return n.client.GroupVersionKindFor(obj)
58 }
59
60
61 func (n *namespacedClient) IsObjectNamespaced(obj runtime.Object) (bool, error) {
62 return n.client.IsObjectNamespaced(obj)
63 }
64
65
66 func (n *namespacedClient) Create(ctx context.Context, obj Object, opts ...CreateOption) error {
67 isNamespaceScoped, err := n.IsObjectNamespaced(obj)
68 if err != nil {
69 return fmt.Errorf("error finding the scope of the object: %w", err)
70 }
71
72 objectNamespace := obj.GetNamespace()
73 if objectNamespace != n.namespace && objectNamespace != "" {
74 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), n.namespace)
75 }
76
77 if isNamespaceScoped && objectNamespace == "" {
78 obj.SetNamespace(n.namespace)
79 }
80 return n.client.Create(ctx, obj, opts...)
81 }
82
83
84 func (n *namespacedClient) Update(ctx context.Context, obj Object, opts ...UpdateOption) error {
85 isNamespaceScoped, err := n.IsObjectNamespaced(obj)
86 if err != nil {
87 return fmt.Errorf("error finding the scope of the object: %w", err)
88 }
89
90 objectNamespace := obj.GetNamespace()
91 if objectNamespace != n.namespace && objectNamespace != "" {
92 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), n.namespace)
93 }
94
95 if isNamespaceScoped && objectNamespace == "" {
96 obj.SetNamespace(n.namespace)
97 }
98 return n.client.Update(ctx, obj, opts...)
99 }
100
101
102 func (n *namespacedClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error {
103 isNamespaceScoped, err := n.IsObjectNamespaced(obj)
104 if err != nil {
105 return fmt.Errorf("error finding the scope of the object: %w", err)
106 }
107
108 objectNamespace := obj.GetNamespace()
109 if objectNamespace != n.namespace && objectNamespace != "" {
110 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), n.namespace)
111 }
112
113 if isNamespaceScoped && objectNamespace == "" {
114 obj.SetNamespace(n.namespace)
115 }
116 return n.client.Delete(ctx, obj, opts...)
117 }
118
119
120 func (n *namespacedClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error {
121 isNamespaceScoped, err := n.IsObjectNamespaced(obj)
122 if err != nil {
123 return fmt.Errorf("error finding the scope of the object: %w", err)
124 }
125
126 if isNamespaceScoped {
127 opts = append(opts, InNamespace(n.namespace))
128 }
129 return n.client.DeleteAllOf(ctx, obj, opts...)
130 }
131
132
133 func (n *namespacedClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
134 isNamespaceScoped, err := n.IsObjectNamespaced(obj)
135 if err != nil {
136 return fmt.Errorf("error finding the scope of the object: %w", err)
137 }
138
139 objectNamespace := obj.GetNamespace()
140 if objectNamespace != n.namespace && objectNamespace != "" {
141 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), n.namespace)
142 }
143
144 if isNamespaceScoped && objectNamespace == "" {
145 obj.SetNamespace(n.namespace)
146 }
147 return n.client.Patch(ctx, obj, patch, opts...)
148 }
149
150
151 func (n *namespacedClient) Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error {
152 isNamespaceScoped, err := n.IsObjectNamespaced(obj)
153 if err != nil {
154 return fmt.Errorf("error finding the scope of the object: %w", err)
155 }
156 if isNamespaceScoped {
157 if key.Namespace != "" && key.Namespace != n.namespace {
158 return fmt.Errorf("namespace %s provided for the object %s does not match the namespace %s on the client", key.Namespace, obj.GetName(), n.namespace)
159 }
160 key.Namespace = n.namespace
161 }
162 return n.client.Get(ctx, key, obj, opts...)
163 }
164
165
166 func (n *namespacedClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error {
167 if n.namespace != "" {
168 opts = append(opts, InNamespace(n.namespace))
169 }
170 return n.client.List(ctx, obj, opts...)
171 }
172
173
174 func (n *namespacedClient) Status() SubResourceWriter {
175 return n.SubResource("status")
176 }
177
178
179 func (n *namespacedClient) SubResource(subResource string) SubResourceClient {
180 return &namespacedClientSubResourceClient{client: n.client.SubResource(subResource), namespace: n.namespace, namespacedclient: n}
181 }
182
183
184 var _ SubResourceClient = &namespacedClientSubResourceClient{}
185
186 type namespacedClientSubResourceClient struct {
187 client SubResourceClient
188 namespace string
189 namespacedclient Client
190 }
191
192 func (nsw *namespacedClientSubResourceClient) Get(ctx context.Context, obj, subResource Object, opts ...SubResourceGetOption) error {
193 isNamespaceScoped, err := nsw.namespacedclient.IsObjectNamespaced(obj)
194 if err != nil {
195 return fmt.Errorf("error finding the scope of the object: %w", err)
196 }
197
198 objectNamespace := obj.GetNamespace()
199 if objectNamespace != nsw.namespace && objectNamespace != "" {
200 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), nsw.namespace)
201 }
202
203 if isNamespaceScoped && objectNamespace == "" {
204 obj.SetNamespace(nsw.namespace)
205 }
206
207 return nsw.client.Get(ctx, obj, subResource, opts...)
208 }
209
210 func (nsw *namespacedClientSubResourceClient) Create(ctx context.Context, obj, subResource Object, opts ...SubResourceCreateOption) error {
211 isNamespaceScoped, err := nsw.namespacedclient.IsObjectNamespaced(obj)
212 if err != nil {
213 return fmt.Errorf("error finding the scope of the object: %w", err)
214 }
215
216 objectNamespace := obj.GetNamespace()
217 if objectNamespace != nsw.namespace && objectNamespace != "" {
218 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), nsw.namespace)
219 }
220
221 if isNamespaceScoped && objectNamespace == "" {
222 obj.SetNamespace(nsw.namespace)
223 }
224
225 return nsw.client.Create(ctx, obj, subResource, opts...)
226 }
227
228
229 func (nsw *namespacedClientSubResourceClient) Update(ctx context.Context, obj Object, opts ...SubResourceUpdateOption) error {
230 isNamespaceScoped, err := nsw.namespacedclient.IsObjectNamespaced(obj)
231 if err != nil {
232 return fmt.Errorf("error finding the scope of the object: %w", err)
233 }
234
235 objectNamespace := obj.GetNamespace()
236 if objectNamespace != nsw.namespace && objectNamespace != "" {
237 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), nsw.namespace)
238 }
239
240 if isNamespaceScoped && objectNamespace == "" {
241 obj.SetNamespace(nsw.namespace)
242 }
243 return nsw.client.Update(ctx, obj, opts...)
244 }
245
246
247 func (nsw *namespacedClientSubResourceClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...SubResourcePatchOption) error {
248 isNamespaceScoped, err := nsw.namespacedclient.IsObjectNamespaced(obj)
249 if err != nil {
250 return fmt.Errorf("error finding the scope of the object: %w", err)
251 }
252
253 objectNamespace := obj.GetNamespace()
254 if objectNamespace != nsw.namespace && objectNamespace != "" {
255 return fmt.Errorf("namespace %s of the object %s does not match the namespace %s on the client", objectNamespace, obj.GetName(), nsw.namespace)
256 }
257
258 if isNamespaceScoped && objectNamespace == "" {
259 obj.SetNamespace(nsw.namespace)
260 }
261 return nsw.client.Patch(ctx, obj, patch, opts...)
262 }
263
View as plain text