@@ -21,58 +21,73 @@ import (
2121 "fmt"
2222
2323 "k8s.io/apimachinery/pkg/api/meta"
24+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2425 "k8s.io/apimachinery/pkg/runtime"
26+ "k8s.io/apimachinery/pkg/runtime/schema"
2527 "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
2628)
2729
2830// NewNamespacedClient wraps an existing client enforcing the namespace value.
2931// 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 {
3133 return & namespacedClient {
32- client : c ,
33- namespace : ns ,
34- restmapper : rmp ,
35- scheme : * sch ,
34+ client : c ,
35+ namespace : ns ,
3636 }
3737}
3838
3939var _ Client = & namespacedClient {}
4040
4141// namespacedClient is a Client that wraps another Client in order to enforce the specified namespace value.
4242type namespacedClient struct {
43- namespace string
44- client Client
45- restmapper meta.RESTMapper
46- scheme runtime.Scheme
43+ namespace string
44+ client Client
4745}
4846
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+ }
5974 }
6075
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 )
6681 if err != nil {
67- return false , fmt .Errorf ("error here restmapping %v " , obj )
82+ return false , fmt .Errorf ("failed to get restmapping: %w " , err )
6883 }
6984 scope := restmapping .Scope .Name ()
7085
7186 if scope == "" {
72- return false , nil
87+ return false , fmt . Errorf ( "Scope cannot be identified. Empty scope returned" )
7388 }
7489
75- if scope != meta .RESTScopeNameNamespace {
90+ if scope != meta .RESTScopeNameRoot {
7691 return true , nil
7792 }
7893 return false , nil
@@ -85,9 +100,9 @@ func (n *namespacedClient) Create(ctx context.Context, obj runtime.Object, opts
85100 return err
86101 }
87102
88- isNamespaceScoped , err := getNamespace (n .restmapper , obj , & n . scheme )
103+ isNamespaceScoped , err := isNamespaced (n .client , obj )
89104 if err != nil {
90- return fmt .Errorf ("erroring Here, %v" , err )
105+ return fmt .Errorf ("error finding the scope of the object %v" , err )
91106 }
92107 if isNamespaceScoped {
93108 metaObj .SetNamespace (n .namespace )
@@ -102,7 +117,12 @@ func (n *namespacedClient) Update(ctx context.Context, obj runtime.Object, opts
102117 return err
103118 }
104119
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 {
106126 metaObj .SetNamespace (n .namespace )
107127 }
108128 return n .client .Update (ctx , obj , opts ... )
@@ -115,15 +135,25 @@ func (n *namespacedClient) Delete(ctx context.Context, obj runtime.Object, opts
115135 return err
116136 }
117137
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 {
119144 metaObj .SetNamespace (n .namespace )
120145 }
121146 return n .client .Delete (ctx , obj , opts ... )
122147}
123148
124149// DeleteAllOf implements client.Client
125150func (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 {
127157 opts = append (opts , InNamespace (n .namespace ))
128158 }
129159 return n .client .DeleteAllOf (ctx , obj , opts ... )
@@ -136,17 +166,22 @@ func (n *namespacedClient) Patch(ctx context.Context, obj runtime.Object, patch
136166 return err
137167 }
138168
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 {
140175 metaObj .SetNamespace (n .namespace )
141176 }
142177 return n .client .Patch (ctx , obj , patch , opts ... )
143178}
144179
145180// Get implements client.Client
146181func (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 )
148183 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 )
150185 }
151186 if isNamespaceScoped {
152187 key .Namespace = n .namespace
@@ -164,15 +199,16 @@ func (n *namespacedClient) List(ctx context.Context, obj runtime.Object, opts ..
164199
165200// Status implements client.StatusClient
166201func (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 }
168203}
169204
170205// ensure namespacedClientStatusWriter implements client.StatusWriter
171206var _ StatusWriter = & namespacedClientStatusWriter {}
172207
173208type namespacedClientStatusWriter struct {
174- client StatusWriter
175- namespace string
209+ StatusClient StatusWriter
210+ namespace string
211+ namespacedclient Client
176212}
177213
178214// Update implements client.StatusWriter
@@ -182,10 +218,15 @@ func (nsw *namespacedClientStatusWriter) Update(ctx context.Context, obj runtime
182218 return err
183219 }
184220
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 {
186227 metaObj .SetNamespace (nsw .namespace )
187228 }
188- return nsw .client .Update (ctx , obj , opts ... )
229+ return nsw .StatusClient .Update (ctx , obj , opts ... )
189230}
190231
191232// Patch implements client.StatusWriter
@@ -195,8 +236,13 @@ func (nsw *namespacedClientStatusWriter) Patch(ctx context.Context, obj runtime.
195236 return err
196237 }
197238
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 {
199245 metaObj .SetNamespace (nsw .namespace )
200246 }
201- return nsw .client .Patch (ctx , obj , patch , opts ... )
247+ return nsw .StatusClient .Patch (ctx , obj , patch , opts ... )
202248}
0 commit comments