Skip to content

Commit a758028

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 a758028

File tree

2 files changed

+611
-0
lines changed

2 files changed

+611
-0
lines changed

pkg/client/namespaced_client.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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(ns string, c Client) 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 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 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 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+
opts = append(opts, InNamespace(n.namespace))
85+
return n.client.DeleteAllOf(ctx, obj, opts...)
86+
}
87+
88+
// Patch implements client.Client
89+
func (n *namespacedClient) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error {
90+
metaObj, err := meta.Accessor(obj)
91+
if err != nil {
92+
return err
93+
}
94+
95+
if metaObj.GetNamespace() != n.namespace {
96+
metaObj.SetNamespace(n.namespace)
97+
}
98+
return n.client.Patch(ctx, obj, patch, opts...)
99+
}
100+
101+
// Get implements client.Client
102+
func (n *namespacedClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error {
103+
key.Namespace = n.namespace
104+
return n.client.Get(ctx, key, obj)
105+
}
106+
107+
// List implements client.Client
108+
func (n *namespacedClient) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error {
109+
opts = append(opts, InNamespace(n.namespace))
110+
return n.client.List(ctx, obj, opts...)
111+
}
112+
113+
// Status implements client.StatusClient
114+
func (n *namespacedClient) Status() StatusWriter {
115+
return &namespacedClientStatusWriter{client: n.client.Status(), namespace: n.namespace}
116+
}
117+
118+
// ensure namespacedClientStatusWriter implements client.StatusWriter
119+
var _ StatusWriter = &namespacedClientStatusWriter{}
120+
121+
type namespacedClientStatusWriter struct {
122+
client StatusWriter
123+
namespace string
124+
}
125+
126+
// Update implements client.StatusWriter
127+
func (nsw *namespacedClientStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error {
128+
metaObj, err := meta.Accessor(obj)
129+
if err != nil {
130+
return err
131+
}
132+
133+
if metaObj.GetNamespace() != nsw.namespace {
134+
metaObj.SetNamespace(nsw.namespace)
135+
}
136+
return nsw.client.Update(ctx, obj, opts...)
137+
}
138+
139+
// Patch implements client.StatusWriter
140+
func (nsw *namespacedClientStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error {
141+
metaObj, err := meta.Accessor(obj)
142+
if err != nil {
143+
return err
144+
}
145+
146+
if metaObj.GetNamespace() != nsw.namespace {
147+
metaObj.SetNamespace(nsw.namespace)
148+
}
149+
return nsw.client.Patch(ctx, obj, patch, opts...)
150+
}

0 commit comments

Comments
 (0)