Skip to content

Commit fca0592

Browse files
Modify namespaced client to use RestMapper for finding the scope of object.
1 parent 9260be6 commit fca0592

File tree

2 files changed

+547
-416
lines changed

2 files changed

+547
-416
lines changed

pkg/client/namespaced_client.go

Lines changed: 88 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -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

3939
var _ Client = &namespacedClient{}
4040

4141
// namespacedClient is a Client that wraps another Client in order to enforce the specified namespace value.
4242
type 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
125150
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 {
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
146181
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)
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
166201
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}
168203
}
169204

170205
// ensure namespacedClientStatusWriter implements client.StatusWriter
171206
var _ StatusWriter = &namespacedClientStatusWriter{}
172207

173208
type 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

Comments
 (0)