@@ -21,58 +21,73 @@ import (
21
21
"fmt"
22
22
23
23
"k8s.io/apimachinery/pkg/api/meta"
24
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
24
25
"k8s.io/apimachinery/pkg/runtime"
26
+ "k8s.io/apimachinery/pkg/runtime/schema"
25
27
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
26
28
)
27
29
28
30
// NewNamespacedClient wraps an existing client enforcing the namespace value.
29
31
// All functions using this client will have the same namespace declared here.
30
- func NewNamespacedClient (c Client , ns string , rmp meta. RESTMapper , sch * runtime. Scheme ) Client {
32
+ func NewNamespacedClient (c Client , ns string ) Client {
31
33
return & namespacedClient {
32
- client : c ,
33
- namespace : ns ,
34
- restmapper : rmp ,
35
- scheme : * sch ,
34
+ client : c ,
35
+ namespace : ns ,
36
36
}
37
37
}
38
38
39
39
var _ Client = & namespacedClient {}
40
40
41
41
// namespacedClient is a Client that wraps another Client in order to enforce the specified namespace value.
42
42
type namespacedClient struct {
43
- namespace string
44
- client Client
45
- restmapper meta.RESTMapper
46
- scheme runtime.Scheme
43
+ namespace string
44
+ client Client
47
45
}
48
46
49
- func getNamespace (restmapper meta.RESTMapper , obj runtime.Object , sch * runtime.Scheme ) (bool , error ) {
50
- // var sch = runtime.NewScheme()
51
- // // appsv1.AddToScheme(sch)
52
- // rbacv1.AddToScheme(sch)
53
- gvk , err := apiutil .GVKForObject (obj , sch )
54
- if err != nil {
55
- return false , err
56
- }
57
- if restmapper == nil {
58
- return false , err
47
+ // Scheme returns the scheme this client is using.
48
+ func (n * namespacedClient ) Scheme () * runtime.Scheme {
49
+ return n .client .Scheme ()
50
+ }
51
+
52
+ // RESTMapper returns the scheme this client is using.
53
+ func (n * namespacedClient ) RESTMapper () meta.RESTMapper {
54
+ return n .client .RESTMapper ()
55
+ }
56
+
57
+ // isNamespaced returns true if the object is namespace scoped.
58
+ // For unstructured objects the gvk is found from the object itself.
59
+ func isNamespaced (c Client , obj runtime.Object ) (bool , error ) {
60
+ var gvk schema.GroupVersionKind
61
+ var err error
62
+
63
+ _ , isUnstructured := obj .(* unstructured.Unstructured )
64
+ _ , isUnstructuredList := obj .(* unstructured.UnstructuredList )
65
+
66
+ isUnstructured = isUnstructured || isUnstructuredList
67
+ if isUnstructured {
68
+ gvk = obj .GetObjectKind ().GroupVersionKind ()
69
+ } else {
70
+ gvk , err = apiutil .GVKForObject (obj , c .Scheme ())
71
+ if err != nil {
72
+ return false , err
73
+ }
59
74
}
60
75
61
- // gvk := schema.GroupKind{
62
- // Group: obj.GetObjectKind().GroupVersionKind() .Group,
63
- // Kind: obj.GetObjectKind().GroupVersionKind() .Kind,
64
- // }
65
- restmapping , err := restmapper . RESTMapping ( gvk . GroupKind () )
76
+ gk := schema.GroupKind {
77
+ Group : gvk .Group ,
78
+ Kind : gvk .Kind ,
79
+ }
80
+ restmapping , err := c . RESTMapper (). RESTMapping ( gk )
66
81
if err != nil {
67
- return false , fmt .Errorf ("error here restmapping %v " , obj )
82
+ return false , fmt .Errorf ("failed to get restmapping: %w " , err )
68
83
}
69
84
scope := restmapping .Scope .Name ()
70
85
71
86
if scope == "" {
72
- return false , nil
87
+ return false , fmt . Errorf ( "Scope cannot be identified. Empty scope returned" )
73
88
}
74
89
75
- if scope != meta .RESTScopeNameNamespace {
90
+ if scope != meta .RESTScopeNameRoot {
76
91
return true , nil
77
92
}
78
93
return false , nil
@@ -85,9 +100,9 @@ func (n *namespacedClient) Create(ctx context.Context, obj runtime.Object, opts
85
100
return err
86
101
}
87
102
88
- isNamespaceScoped , err := getNamespace (n .restmapper , obj , & n . scheme )
103
+ isNamespaceScoped , err := isNamespaced (n .client , obj )
89
104
if err != nil {
90
- return fmt .Errorf ("erroring Here, %v" , err )
105
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
91
106
}
92
107
if isNamespaceScoped {
93
108
metaObj .SetNamespace (n .namespace )
@@ -102,7 +117,12 @@ func (n *namespacedClient) Update(ctx context.Context, obj runtime.Object, opts
102
117
return err
103
118
}
104
119
105
- if n .namespace != "" && metaObj .GetNamespace () != n .namespace {
120
+ isNamespaceScoped , err := isNamespaced (n .client , obj )
121
+ if err != nil {
122
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
123
+ }
124
+
125
+ if isNamespaceScoped && metaObj .GetNamespace () != n .namespace {
106
126
metaObj .SetNamespace (n .namespace )
107
127
}
108
128
return n .client .Update (ctx , obj , opts ... )
@@ -115,15 +135,25 @@ func (n *namespacedClient) Delete(ctx context.Context, obj runtime.Object, opts
115
135
return err
116
136
}
117
137
118
- if n .namespace != "" && metaObj .GetNamespace () != n .namespace {
138
+ isNamespaceScoped , err := isNamespaced (n .client , obj )
139
+ if err != nil {
140
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
141
+ }
142
+
143
+ if isNamespaceScoped && metaObj .GetNamespace () != n .namespace {
119
144
metaObj .SetNamespace (n .namespace )
120
145
}
121
146
return n .client .Delete (ctx , obj , opts ... )
122
147
}
123
148
124
149
// DeleteAllOf implements client.Client
125
150
func (n * namespacedClient ) DeleteAllOf (ctx context.Context , obj runtime.Object , opts ... DeleteAllOfOption ) error {
126
- if n .namespace != "" {
151
+ isNamespaceScoped , err := isNamespaced (n .client , obj )
152
+ if err != nil {
153
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
154
+ }
155
+
156
+ if isNamespaceScoped {
127
157
opts = append (opts , InNamespace (n .namespace ))
128
158
}
129
159
return n .client .DeleteAllOf (ctx , obj , opts ... )
@@ -136,17 +166,22 @@ func (n *namespacedClient) Patch(ctx context.Context, obj runtime.Object, patch
136
166
return err
137
167
}
138
168
139
- if n .namespace != "" && metaObj .GetNamespace () != n .namespace {
169
+ isNamespaceScoped , err := isNamespaced (n .client , obj )
170
+ if err != nil {
171
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
172
+ }
173
+
174
+ if isNamespaceScoped && metaObj .GetNamespace () != n .namespace {
140
175
metaObj .SetNamespace (n .namespace )
141
176
}
142
177
return n .client .Patch (ctx , obj , patch , opts ... )
143
178
}
144
179
145
180
// Get implements client.Client
146
181
func (n * namespacedClient ) Get (ctx context.Context , key ObjectKey , obj runtime.Object ) error {
147
- isNamespaceScoped , err := getNamespace (n .restmapper , obj , & n . scheme )
182
+ isNamespaceScoped , err := isNamespaced (n .client , obj )
148
183
if err != nil {
149
- return fmt .Errorf ("erroring Here, %v %v" , err , obj . GetObjectKind () )
184
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
150
185
}
151
186
if isNamespaceScoped {
152
187
key .Namespace = n .namespace
@@ -164,15 +199,16 @@ func (n *namespacedClient) List(ctx context.Context, obj runtime.Object, opts ..
164
199
165
200
// Status implements client.StatusClient
166
201
func (n * namespacedClient ) Status () StatusWriter {
167
- return & namespacedClientStatusWriter {client : n .client .Status (), namespace : n .namespace }
202
+ return & namespacedClientStatusWriter {StatusClient : n .client .Status (), namespace : n .namespace , namespacedclient : n }
168
203
}
169
204
170
205
// ensure namespacedClientStatusWriter implements client.StatusWriter
171
206
var _ StatusWriter = & namespacedClientStatusWriter {}
172
207
173
208
type namespacedClientStatusWriter struct {
174
- client StatusWriter
175
- namespace string
209
+ StatusClient StatusWriter
210
+ namespace string
211
+ namespacedclient Client
176
212
}
177
213
178
214
// Update implements client.StatusWriter
@@ -182,10 +218,15 @@ func (nsw *namespacedClientStatusWriter) Update(ctx context.Context, obj runtime
182
218
return err
183
219
}
184
220
185
- if nsw .namespace != "" && metaObj .GetNamespace () != nsw .namespace {
221
+ isNamespaceScoped , err := isNamespaced (nsw .namespacedclient , obj )
222
+ if err != nil {
223
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
224
+ }
225
+
226
+ if isNamespaceScoped && metaObj .GetNamespace () != nsw .namespace {
186
227
metaObj .SetNamespace (nsw .namespace )
187
228
}
188
- return nsw .client .Update (ctx , obj , opts ... )
229
+ return nsw .StatusClient .Update (ctx , obj , opts ... )
189
230
}
190
231
191
232
// Patch implements client.StatusWriter
@@ -195,8 +236,13 @@ func (nsw *namespacedClientStatusWriter) Patch(ctx context.Context, obj runtime.
195
236
return err
196
237
}
197
238
198
- if nsw .namespace != "" && metaObj .GetNamespace () != nsw .namespace {
239
+ isNamespaceScoped , err := isNamespaced (nsw .namespacedclient , obj )
240
+ if err != nil {
241
+ return fmt .Errorf ("error finding the scope of the object %v" , err )
242
+ }
243
+
244
+ if isNamespaceScoped && metaObj .GetNamespace () != nsw .namespace {
199
245
metaObj .SetNamespace (nsw .namespace )
200
246
}
201
- return nsw .client .Patch (ctx , obj , patch , opts ... )
247
+ return nsw .StatusClient .Patch (ctx , obj , patch , opts ... )
202
248
}
0 commit comments