|
| 1 | +package config |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + |
| 6 | + authzv1 "k8s.io/api/authorization/v1" |
| 7 | + "k8s.io/apimachinery/pkg/api/meta" |
| 8 | + "k8s.io/apimachinery/pkg/runtime" |
| 9 | + "k8s.io/client-go/rest" |
| 10 | + "sigs.k8s.io/controller-runtime/pkg/cache" |
| 11 | + "sigs.k8s.io/controller-runtime/pkg/client" |
| 12 | + "sigs.k8s.io/controller-runtime/pkg/cluster" |
| 13 | +) |
| 14 | + |
| 15 | +// newCachingClient is an alternative implementation of controller-runtime's |
| 16 | +// default client for manager.Manager. |
| 17 | +// The only difference is that this implementation sets `CacheUnstructured` to `true` to |
| 18 | +// cache unstructured objects. |
| 19 | +func newCachingClient(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { |
| 20 | + c, err := client.New(config, options) |
| 21 | + if err != nil { |
| 22 | + return nil, err |
| 23 | + } |
| 24 | + |
| 25 | + return client.NewDelegatingClient(client.NewDelegatingClientInput{ |
| 26 | + CacheReader: cache, |
| 27 | + Client: c, |
| 28 | + UncachedObjects: uncachedObjects, |
| 29 | + CacheUnstructured: true, |
| 30 | + }) |
| 31 | +} |
| 32 | + |
| 33 | +func NewClient(readOnly bool) cluster.NewClientFunc { |
| 34 | + return func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { |
| 35 | + c, err := newCachingClient(cache, config, options, uncachedObjects...) |
| 36 | + if readOnly { |
| 37 | + c = &readOnlyClient{client: c} |
| 38 | + } |
| 39 | + return c, err |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +// readOnlyClient is a client decorator that ensures no write operations are possible. |
| 44 | +type readOnlyClient struct { |
| 45 | + client client.Client |
| 46 | +} |
| 47 | + |
| 48 | +func (c readOnlyClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error { |
| 49 | + return c.client.Get(ctx, key, obj) |
| 50 | +} |
| 51 | + |
| 52 | +func (c readOnlyClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { |
| 53 | + return c.client.List(ctx, list, opts...) |
| 54 | +} |
| 55 | + |
| 56 | +func (c readOnlyClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { |
| 57 | + // Allow callers to create subject access reviews - even in read-only mode. |
| 58 | + // Creating a SAR will not modify state in etcd. Used to perform RBAC checks. |
| 59 | + if _, ok := obj.(*authzv1.SubjectAccessReview); ok { |
| 60 | + return c.client.Create(ctx, obj, opts...) |
| 61 | + } |
| 62 | + return nil |
| 63 | +} |
| 64 | + |
| 65 | +func (c readOnlyClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { |
| 66 | + return nil |
| 67 | +} |
| 68 | + |
| 69 | +func (c readOnlyClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { |
| 70 | + return nil |
| 71 | +} |
| 72 | + |
| 73 | +func (c readOnlyClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { |
| 74 | + return nil |
| 75 | +} |
| 76 | + |
| 77 | +func (c readOnlyClient) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { |
| 78 | + return nil |
| 79 | +} |
| 80 | + |
| 81 | +func (c readOnlyClient) Status() client.StatusWriter { |
| 82 | + return nopStatusWriter{} |
| 83 | +} |
| 84 | + |
| 85 | +func (c readOnlyClient) Scheme() *runtime.Scheme { |
| 86 | + return c.client.Scheme() |
| 87 | +} |
| 88 | + |
| 89 | +func (c readOnlyClient) RESTMapper() meta.RESTMapper { |
| 90 | + return c.client.RESTMapper() |
| 91 | +} |
| 92 | + |
| 93 | +type nopStatusWriter struct{} |
| 94 | + |
| 95 | +func (w nopStatusWriter) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { |
| 96 | + return nil |
| 97 | +} |
| 98 | + |
| 99 | +func (w nopStatusWriter) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { |
| 100 | + return nil |
| 101 | +} |
0 commit comments