Skip to content

Commit d0dc121

Browse files
This commit adds a namespace enforcing wrapper for client.Client.
This helps while dealing with namespace-scoped objects, where the namespace value need not be specified in every operation.
1 parent cea989b commit d0dc121

File tree

2 files changed

+617
-0
lines changed

2 files changed

+617
-0
lines changed

pkg/client/namespaced_client.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"context"
21+
22+
"k8s.io/apimachinery/pkg/api/meta"
23+
"k8s.io/apimachinery/pkg/runtime"
24+
)
25+
26+
// NewNamespacedClient wraps an existing client enforcing the namespace value.
27+
// All functions using this client will have the same namespace declared here.
28+
func NewNamespacedClient(c Client, ns string) Client {
29+
return &namespacedClient{
30+
client: c,
31+
namespace: ns,
32+
}
33+
}
34+
35+
var _ Client = &namespacedClient{}
36+
37+
// namespacedClient is a Client that wraps another Client in order to enforce the specified namespace value.
38+
type namespacedClient struct {
39+
namespace string
40+
client Client
41+
}
42+
43+
// Create implements clinet.Client
44+
func (n *namespacedClient) Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error {
45+
metaObj, err := meta.Accessor(obj)
46+
if err != nil {
47+
return err
48+
}
49+
50+
if n.namespace != "" && metaObj.GetNamespace() != n.namespace {
51+
metaObj.SetNamespace(n.namespace)
52+
}
53+
return n.client.Create(ctx, obj, opts...)
54+
}
55+
56+
// Update implements client.Client
57+
func (n *namespacedClient) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error {
58+
metaObj, err := meta.Accessor(obj)
59+
if err != nil {
60+
return err
61+
}
62+
63+
if n.namespace != "" && metaObj.GetNamespace() != n.namespace {
64+
metaObj.SetNamespace(n.namespace)
65+
}
66+
return n.client.Update(ctx, obj, opts...)
67+
}
68+
69+
// Delete implements client.Client
70+
func (n *namespacedClient) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error {
71+
metaObj, err := meta.Accessor(obj)
72+
if err != nil {
73+
return err
74+
}
75+
76+
if n.namespace != "" && metaObj.GetNamespace() != n.namespace {
77+
metaObj.SetNamespace(n.namespace)
78+
}
79+
return n.client.Delete(ctx, obj, opts...)
80+
}
81+
82+
// DeleteAllOf implements client.Client
83+
func (n *namespacedClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error {
84+
if n.namespace != "" {
85+
opts = append(opts, InNamespace(n.namespace))
86+
}
87+
return n.client.DeleteAllOf(ctx, obj, opts...)
88+
}
89+
90+
// Patch implements client.Client
91+
func (n *namespacedClient) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error {
92+
metaObj, err := meta.Accessor(obj)
93+
if err != nil {
94+
return err
95+
}
96+
97+
if n.namespace != "" && metaObj.GetNamespace() != n.namespace {
98+
metaObj.SetNamespace(n.namespace)
99+
}
100+
return n.client.Patch(ctx, obj, patch, opts...)
101+
}
102+
103+
// Get implements client.Client
104+
func (n *namespacedClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error {
105+
if n.namespace != "" {
106+
key.Namespace = n.namespace
107+
}
108+
return n.client.Get(ctx, key, obj)
109+
}
110+
111+
// List implements client.Client
112+
func (n *namespacedClient) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error {
113+
if n.namespace != "" {
114+
opts = append(opts, InNamespace(n.namespace))
115+
}
116+
return n.client.List(ctx, obj, opts...)
117+
}
118+
119+
// Status implements client.StatusClient
120+
func (n *namespacedClient) Status() StatusWriter {
121+
return &namespacedClientStatusWriter{client: n.client.Status(), namespace: n.namespace}
122+
}
123+
124+
// ensure namespacedClientStatusWriter implements client.StatusWriter
125+
var _ StatusWriter = &namespacedClientStatusWriter{}
126+
127+
type namespacedClientStatusWriter struct {
128+
client StatusWriter
129+
namespace string
130+
}
131+
132+
// Update implements client.StatusWriter
133+
func (nsw *namespacedClientStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error {
134+
metaObj, err := meta.Accessor(obj)
135+
if err != nil {
136+
return err
137+
}
138+
139+
if nsw.namespace != "" && metaObj.GetNamespace() != nsw.namespace {
140+
metaObj.SetNamespace(nsw.namespace)
141+
}
142+
return nsw.client.Update(ctx, obj, opts...)
143+
}
144+
145+
// Patch implements client.StatusWriter
146+
func (nsw *namespacedClientStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error {
147+
metaObj, err := meta.Accessor(obj)
148+
if err != nil {
149+
return err
150+
}
151+
152+
if nsw.namespace != "" && metaObj.GetNamespace() != nsw.namespace {
153+
metaObj.SetNamespace(nsw.namespace)
154+
}
155+
return nsw.client.Patch(ctx, obj, patch, opts...)
156+
}

0 commit comments

Comments
 (0)