From 755770297b56b1b19179443d5bddecdf894d52f2 Mon Sep 17 00:00:00 2001 From: Vince Prignano Date: Fri, 27 Jan 2023 15:06:44 -0800 Subject: [PATCH] Remove DelegatedClient, move Options in client.New Signed-off-by: Vince Prignano --- pkg/client/client.go | 109 +++++++++++++++++++---- pkg/client/client_test.go | 72 +++++++-------- pkg/client/dryrun.go | 4 +- pkg/client/fake/client.go | 4 +- pkg/client/interfaces.go | 4 +- pkg/client/namespaced_client.go | 4 +- pkg/client/split.go | 153 -------------------------------- pkg/cluster/cluster.go | 60 ++++--------- pkg/cluster/cluster_test.go | 4 +- pkg/manager/manager.go | 2 +- pkg/manager/manager_test.go | 4 +- 11 files changed, 156 insertions(+), 264 deletions(-) delete mode 100644 pkg/client/split.go diff --git a/pkg/client/client.go b/pkg/client/client.go index c87a8a8707..1d6e1d83c5 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -36,6 +36,21 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" ) +// Options are creation options for a Client. +type Options struct { + // Scheme, if provided, will be used to map go structs to GroupVersionKinds + Scheme *runtime.Scheme + + // Mapper, if provided, will be used to map GroupVersionKinds to Resources + Mapper meta.RESTMapper + + Cache *CacheOptions + + // WarningHandler is used to configure the warning handler responsible for + // surfacing and handling warnings messages sent by the API server. + WarningHandler WarningHandlerOptions +} + // WarningHandlerOptions are options for configuring a // warning handler for the client which is responsible // for surfacing API Server warnings. @@ -50,19 +65,21 @@ type WarningHandlerOptions struct { AllowDuplicateLogs bool } -// Options are creation options for a Client. -type Options struct { - // Scheme, if provided, will be used to map go structs to GroupVersionKinds - Scheme *runtime.Scheme - - // Mapper, if provided, will be used to map GroupVersionKinds to Resources - Mapper meta.RESTMapper - - // Opts is used to configure the warning handler responsible for - // surfacing and handling warnings messages sent by the API server. - Opts WarningHandlerOptions +// CacheOptions are options for creating a cache-backed client. +type CacheOptions struct { + // Reader is a cache-backed reader that will be used to read objects from the cache. + // +required + Reader Reader + // DisableFor is a list of objects that should not be read from the cache. + DisableFor []Object + // Unstructured is a flag that indicates whether the cache-backed client should + // read unstructured objects or lists from the cache. + Unstructured bool } +// NewClientFunc allows a user to define how to create a client. +type NewClientFunc func(config *rest.Config, options Options) (Client, error) + // New returns a new Client using the provided config and Options. // The returned client reads *and* writes directly from the server // (it doesn't use object caches). It understands how to work with @@ -82,7 +99,7 @@ func newClient(config *rest.Config, options Options) (*client, error) { return nil, fmt.Errorf("must provide non-nil rest.Config to client.New") } - if !options.Opts.SuppressWarnings { + if !options.WarningHandler.SuppressWarnings { // surface warnings logger := log.Log.WithName("KubeAPIWarningLogger") // Set a WarningHandler, the default WarningHandler @@ -93,7 +110,7 @@ func newClient(config *rest.Config, options Options) (*client, error) { config.WarningHandler = log.NewKubeAPIWarningLogger( logger, log.KubeAPIWarningLoggerOptions{ - Deduplicate: !options.Opts.AllowDuplicateLogs, + Deduplicate: !options.WarningHandler.AllowDuplicateLogs, }, ) } @@ -143,7 +160,28 @@ func newClient(config *rest.Config, options Options) (*client, error) { scheme: options.Scheme, mapper: options.Mapper, } + if options.Cache == nil { + return c, nil + } + + // We want a cache if we're here. + if options.Cache.Reader == nil { + return nil, fmt.Errorf("must provide a Options.Cache.Reader when using a cache") + } + // Set the cache. + c.cache = options.Cache.Reader + + // Load uncached GVKs. + c.cacheUnstructured = options.Cache.Unstructured + uncachedGVKs := map[schema.GroupVersionKind]struct{}{} + for _, obj := range options.Cache.DisableFor { + gvk, err := c.GroupVersionKindFor(obj) + if err != nil { + return nil, err + } + uncachedGVKs[gvk] = struct{}{} + } return c, nil } @@ -157,6 +195,35 @@ type client struct { metadataClient metadataClient scheme *runtime.Scheme mapper meta.RESTMapper + + cache Reader + uncachedGVKs map[schema.GroupVersionKind]struct{} + cacheUnstructured bool +} + +func (c *client) shouldBypassCache(obj runtime.Object) (bool, error) { + if c.cache == nil { + return true, nil + } + + gvk, err := c.GroupVersionKindFor(obj) + if err != nil { + return false, err + } + // TODO: this is producing unsafe guesses that don't actually work, + // but it matches ~99% of the cases out there. + if meta.IsListType(obj) { + gvk.Kind = strings.TrimSuffix(gvk.Kind, "List") + } + if _, isUncached := c.uncachedGVKs[gvk]; isUncached { + return true, nil + } + if !c.cacheUnstructured { + _, isUnstructured := obj.(*unstructured.Unstructured) + _, isUnstructuredList := obj.(*unstructured.UnstructuredList) + return isUnstructured || isUnstructuredList, nil + } + return false, nil } // resetGroupVersionKind is a helper function to restore and preserve GroupVersionKind on an object. @@ -169,12 +236,12 @@ func (c *client) resetGroupVersionKind(obj runtime.Object, gvk schema.GroupVersi } // GroupVersionKindFor returns the GroupVersionKind for the given object. -func (c *client) GroupVersionKindFor(obj Object) (schema.GroupVersionKind, error) { +func (c *client) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { return apiutil.GVKForObject(obj, c.scheme) } // IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. -func (c *client) IsObjectNamespaced(obj Object) (bool, error) { +func (c *client) IsObjectNamespaced(obj runtime.Object) (bool, error) { return apiutil.IsObjectNamespaced(obj, c.scheme, c.mapper) } @@ -252,6 +319,12 @@ func (c *client) Patch(ctx context.Context, obj Object, patch Patch, opts ...Pat // Get implements client.Client. func (c *client) Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error { + if isUncached, err := c.shouldBypassCache(obj); err != nil { + return err + } else if !isUncached { + return c.cache.Get(ctx, key, obj, opts...) + } + switch obj.(type) { case *unstructured.Unstructured: return c.unstructuredClient.Get(ctx, key, obj, opts...) @@ -266,6 +339,12 @@ func (c *client) Get(ctx context.Context, key ObjectKey, obj Object, opts ...Get // List implements client.Client. func (c *client) List(ctx context.Context, obj ObjectList, opts ...ListOption) error { + if isUncached, err := c.shouldBypassCache(obj); err != nil { + return err + } else if !isUncached { + return c.cache.List(ctx, obj, opts...) + } + switch x := obj.(type) { case *unstructured.UnstructuredList: return c.unstructuredClient.List(ctx, obj, opts...) diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 856aaa067e..3e96a9da3a 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -3541,20 +3541,19 @@ U5wwSivyi7vmegHKmblOzNVKA5qPO8zWzqBC }) }) -var _ = Describe("DelegatingClient", func() { +var _ = Describe("ClientWithCache", func() { Describe("Get", func() { It("should call cache reader when structured object", func() { cachedReader := &fakeReader{} - cl, err := client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - dReader, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cachedReader, - Client: cl, + cl, err := client.New(cfg, client.Options{ + Cache: &client.CacheOptions{ + Reader: cachedReader, + }, }) Expect(err).NotTo(HaveOccurred()) var actual appsv1.Deployment key := client.ObjectKey{Namespace: "ns", Name: "name"} - Expect(dReader.Get(context.TODO(), key, &actual)).To(Succeed()) + Expect(cl.Get(context.TODO(), key, &actual)).To(Succeed()) Expect(1).To(Equal(cachedReader.Called)) }) @@ -3590,11 +3589,10 @@ var _ = Describe("DelegatingClient", func() { }) It("should call client reader when not cached", func() { cachedReader := &fakeReader{} - cl, err := client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - dReader, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cachedReader, - Client: cl, + cl, err := client.New(cfg, client.Options{ + Cache: &client.CacheOptions{ + Reader: cachedReader, + }, }) Expect(err).NotTo(HaveOccurred()) @@ -3606,17 +3604,16 @@ var _ = Describe("DelegatingClient", func() { }) actual.SetName(dep.Name) key := client.ObjectKey{Namespace: dep.Namespace, Name: dep.Name} - Expect(dReader.Get(context.TODO(), key, actual)).To(Succeed()) + Expect(cl.Get(context.TODO(), key, actual)).To(Succeed()) Expect(0).To(Equal(cachedReader.Called)) }) It("should call cache reader when cached", func() { cachedReader := &fakeReader{} - cl, err := client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - dReader, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cachedReader, - Client: cl, - CacheUnstructured: true, + cl, err := client.New(cfg, client.Options{ + Cache: &client.CacheOptions{ + Reader: cachedReader, + Unstructured: true, + }, }) Expect(err).NotTo(HaveOccurred()) @@ -3628,7 +3625,7 @@ var _ = Describe("DelegatingClient", func() { }) actual.SetName(dep.Name) key := client.ObjectKey{Namespace: dep.Namespace, Name: dep.Name} - Expect(dReader.Get(context.TODO(), key, actual)).To(Succeed()) + Expect(cl.Get(context.TODO(), key, actual)).To(Succeed()) Expect(1).To(Equal(cachedReader.Called)) }) }) @@ -3636,26 +3633,24 @@ var _ = Describe("DelegatingClient", func() { Describe("List", func() { It("should call cache reader when structured object", func() { cachedReader := &fakeReader{} - cl, err := client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - dReader, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cachedReader, - Client: cl, + cl, err := client.New(cfg, client.Options{ + Cache: &client.CacheOptions{ + Reader: cachedReader, + }, }) Expect(err).NotTo(HaveOccurred()) var actual appsv1.DeploymentList - Expect(dReader.List(context.Background(), &actual)).To(Succeed()) + Expect(cl.List(context.Background(), &actual)).To(Succeed()) Expect(1).To(Equal(cachedReader.Called)) }) When("listing unstructured objects", func() { It("should call client reader when not cached", func() { cachedReader := &fakeReader{} - cl, err := client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - dReader, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cachedReader, - Client: cl, + cl, err := client.New(cfg, client.Options{ + Cache: &client.CacheOptions{ + Reader: cachedReader, + }, }) Expect(err).NotTo(HaveOccurred()) @@ -3665,17 +3660,16 @@ var _ = Describe("DelegatingClient", func() { Kind: "DeploymentList", Version: "v1", }) - Expect(dReader.List(context.Background(), actual)).To(Succeed()) + Expect(cl.List(context.Background(), actual)).To(Succeed()) Expect(0).To(Equal(cachedReader.Called)) }) It("should call cache reader when cached", func() { cachedReader := &fakeReader{} - cl, err := client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - dReader, err := client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cachedReader, - Client: cl, - CacheUnstructured: true, + cl, err := client.New(cfg, client.Options{ + Cache: &client.CacheOptions{ + Reader: cachedReader, + Unstructured: true, + }, }) Expect(err).NotTo(HaveOccurred()) @@ -3685,7 +3679,7 @@ var _ = Describe("DelegatingClient", func() { Kind: "DeploymentList", Version: "v1", }) - Expect(dReader.List(context.Background(), actual)).To(Succeed()) + Expect(cl.List(context.Background(), actual)).To(Succeed()) Expect(1).To(Equal(cachedReader.Called)) }) }) diff --git a/pkg/client/dryrun.go b/pkg/client/dryrun.go index 328a38103a..bbcdd38321 100644 --- a/pkg/client/dryrun.go +++ b/pkg/client/dryrun.go @@ -48,12 +48,12 @@ func (c *dryRunClient) RESTMapper() meta.RESTMapper { } // GroupVersionKindFor returns the GroupVersionKind for the given object. -func (c *dryRunClient) GroupVersionKindFor(obj Object) (schema.GroupVersionKind, error) { +func (c *dryRunClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { return c.client.GroupVersionKindFor(obj) } // IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. -func (c *dryRunClient) IsObjectNamespaced(obj Object) (bool, error) { +func (c *dryRunClient) IsObjectNamespaced(obj runtime.Object) (bool, error) { return c.client.IsObjectNamespaced(obj) } diff --git a/pkg/client/fake/client.go b/pkg/client/fake/client.go index db8d8e6df3..2199927428 100644 --- a/pkg/client/fake/client.go +++ b/pkg/client/fake/client.go @@ -564,12 +564,12 @@ func (c *fakeClient) RESTMapper() meta.RESTMapper { } // GroupVersionKindFor returns the GroupVersionKind for the given object. -func (c *fakeClient) GroupVersionKindFor(obj client.Object) (schema.GroupVersionKind, error) { +func (c *fakeClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { return apiutil.GVKForObject(obj, c.scheme) } // IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. -func (c *fakeClient) IsObjectNamespaced(obj client.Object) (bool, error) { +func (c *fakeClient) IsObjectNamespaced(obj runtime.Object) (bool, error) { return apiutil.IsObjectNamespaced(obj, c.scheme, c.restMapper) } diff --git a/pkg/client/interfaces.go b/pkg/client/interfaces.go index 7ec7e6d486..0ddda3163d 100644 --- a/pkg/client/interfaces.go +++ b/pkg/client/interfaces.go @@ -171,9 +171,9 @@ type Client interface { // RESTMapper returns the rest this client is using. RESTMapper() meta.RESTMapper // GroupVersionKindFor returns the GroupVersionKind for the given object. - GroupVersionKindFor(obj Object) (schema.GroupVersionKind, error) + GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) // IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. - IsObjectNamespaced(obj Object) (bool, error) + IsObjectNamespaced(obj runtime.Object) (bool, error) } // WithWatch supports Watch on top of the CRUD operations supported by diff --git a/pkg/client/namespaced_client.go b/pkg/client/namespaced_client.go index e7f2b2bac7..222dc79579 100644 --- a/pkg/client/namespaced_client.go +++ b/pkg/client/namespaced_client.go @@ -53,12 +53,12 @@ func (n *namespacedClient) RESTMapper() meta.RESTMapper { } // GroupVersionKindFor returns the GroupVersionKind for the given object. -func (n *namespacedClient) GroupVersionKindFor(obj Object) (schema.GroupVersionKind, error) { +func (n *namespacedClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { return n.client.GroupVersionKindFor(obj) } // IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. -func (n *namespacedClient) IsObjectNamespaced(obj Object) (bool, error) { +func (n *namespacedClient) IsObjectNamespaced(obj runtime.Object) (bool, error) { return n.client.IsObjectNamespaced(obj) } diff --git a/pkg/client/split.go b/pkg/client/split.go deleted file mode 100644 index cf46f79043..0000000000 --- a/pkg/client/split.go +++ /dev/null @@ -1,153 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package client - -import ( - "context" - "strings" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" -) - -// NewDelegatingClientInput encapsulates the input parameters to create a new delegating client. -type NewDelegatingClientInput struct { - CacheReader Reader - Client Client - UncachedObjects []Object - CacheUnstructured bool -} - -// NewDelegatingClient creates a new delegating client. -// -// A delegating client forms a Client by composing separate reader, writer and -// statusclient interfaces. This way, you can have an Client that reads from a -// cache and writes to the API server. -func NewDelegatingClient(in NewDelegatingClientInput) (Client, error) { - uncachedGVKs := map[schema.GroupVersionKind]struct{}{} - for _, obj := range in.UncachedObjects { - gvk, err := apiutil.GVKForObject(obj, in.Client.Scheme()) - if err != nil { - return nil, err - } - uncachedGVKs[gvk] = struct{}{} - } - - return &delegatingClient{ - scheme: in.Client.Scheme(), - mapper: in.Client.RESTMapper(), - Reader: &delegatingReader{ - CacheReader: in.CacheReader, - ClientReader: in.Client, - scheme: in.Client.Scheme(), - uncachedGVKs: uncachedGVKs, - cacheUnstructured: in.CacheUnstructured, - }, - Writer: in.Client, - StatusClient: in.Client, - SubResourceClientConstructor: in.Client, - }, nil -} - -type delegatingClient struct { - Reader - Writer - StatusClient - SubResourceClientConstructor - - scheme *runtime.Scheme - mapper meta.RESTMapper -} - -// Scheme returns the scheme this client is using. -func (d *delegatingClient) Scheme() *runtime.Scheme { - return d.scheme -} - -// RESTMapper returns the rest mapper this client is using. -func (d *delegatingClient) RESTMapper() meta.RESTMapper { - return d.mapper -} - -// GroupVersionKindFor returns the GroupVersionKind for the given object. -func (d *delegatingClient) GroupVersionKindFor(obj Object) (schema.GroupVersionKind, error) { - return apiutil.GVKForObject(obj, d.scheme) -} - -// IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. -func (d *delegatingClient) IsObjectNamespaced(obj Object) (bool, error) { - return apiutil.IsObjectNamespaced(obj, d.scheme, d.mapper) -} - -// delegatingReader forms a Reader that will cause Get and List requests for -// unstructured types to use the ClientReader while requests for any other type -// of object with use the CacheReader. This avoids accidentally caching the -// entire cluster in the common case of loading arbitrary unstructured objects -// (e.g. from OwnerReferences). -type delegatingReader struct { - CacheReader Reader - ClientReader Reader - - uncachedGVKs map[schema.GroupVersionKind]struct{} - scheme *runtime.Scheme - cacheUnstructured bool -} - -func (d *delegatingReader) shouldBypassCache(obj runtime.Object) (bool, error) { - gvk, err := apiutil.GVKForObject(obj, d.scheme) - if err != nil { - return false, err - } - // TODO: this is producing unsafe guesses that don't actually work, - // but it matches ~99% of the cases out there. - if meta.IsListType(obj) { - gvk.Kind = strings.TrimSuffix(gvk.Kind, "List") - } - if _, isUncached := d.uncachedGVKs[gvk]; isUncached { - return true, nil - } - if !d.cacheUnstructured { - _, isUnstructured := obj.(*unstructured.Unstructured) - _, isUnstructuredList := obj.(*unstructured.UnstructuredList) - return isUnstructured || isUnstructuredList, nil - } - return false, nil -} - -// Get retrieves an obj for a given object key from the Kubernetes Cluster. -func (d *delegatingReader) Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error { - if isUncached, err := d.shouldBypassCache(obj); err != nil { - return err - } else if isUncached { - return d.ClientReader.Get(ctx, key, obj, opts...) - } - return d.CacheReader.Get(ctx, key, obj, opts...) -} - -// List retrieves list of objects for a given namespace and list options. -func (d *delegatingReader) List(ctx context.Context, list ObjectList, opts ...ListOption) error { - if isUncached, err := d.shouldBypassCache(list); err != nil { - return err - } else if isUncached { - return d.ClientReader.List(ctx, list, opts...) - } - return d.CacheReader.List(ctx, list, opts...) -} diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index eb0e68a095..efcf1545b4 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -108,7 +108,7 @@ type Options struct { // If not set this will create the default DelegatingClient that will // use the cache for reads and the client for writes. // NOTE: The default client will not cache Unstructured. - NewClient NewClientFunc + NewClient client.NewClientFunc // ClientDisableCacheFor tells the client that, if any cache is used, to bypass it // for the given objects. @@ -163,14 +163,14 @@ func New(config *rest.Config, opts ...Option) (Cluster, error) { return nil, err } - clientOptions := client.Options{Scheme: options.Scheme, Mapper: mapper} - - apiReader, err := client.New(config, clientOptions) - if err != nil { - return nil, err - } - - writeObj, err := options.NewClient(cache, config, clientOptions, options.ClientDisableCacheFor...) + writeObj, err := options.NewClient(config, client.Options{ + Scheme: options.Scheme, + Mapper: mapper, + Cache: &client.CacheOptions{ + Reader: cache, + DisableFor: options.ClientDisableCacheFor, + }, + }) if err != nil { return nil, err } @@ -179,6 +179,12 @@ func New(config *rest.Config, opts ...Option) (Cluster, error) { writeObj = client.NewDryRunClient(writeObj) } + // Create the API Reader, a client with no cache. + apiReader, err := client.New(config, client.Options{Scheme: options.Scheme, Mapper: mapper}) + if err != nil { + return nil, err + } + // Create the recorder provider to inject event recorders for the components. // TODO(directxman12): the log for the event provider should have a context (name, tags, etc) specific // to the particular controller that it's being injected into, rather than a generic one like is here. @@ -215,7 +221,7 @@ func setOptionsDefaults(options Options) Options { // Allow users to define how to create a new client if options.NewClient == nil { - options.NewClient = DefaultNewClient + options.NewClient = client.New } // Allow newCache to be mocked @@ -247,37 +253,3 @@ func setOptionsDefaults(options Options) Options { return options } - -// NewClientFunc allows a user to define how to create a client. -type NewClientFunc func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) - -// ClientOptions are the optional arguments for tuning the caching client. -type ClientOptions struct { - UncachedObjects []client.Object - CacheUnstructured bool -} - -// DefaultNewClient creates the default caching client, that will never cache Unstructured. -func DefaultNewClient(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { - return ClientBuilderWithOptions(ClientOptions{})(cache, config, options, uncachedObjects...) -} - -// ClientBuilderWithOptions returns a Client constructor that will build a client -// honoring the options argument -func ClientBuilderWithOptions(options ClientOptions) NewClientFunc { - return func(cache cache.Cache, config *rest.Config, clientOpts client.Options, uncachedObjects ...client.Object) (client.Client, error) { - options.UncachedObjects = append(options.UncachedObjects, uncachedObjects...) - - c, err := client.New(config, clientOpts) - if err != nil { - return nil, err - } - - return client.NewDelegatingClient(client.NewDelegatingClientInput{ - CacheReader: cache, - Client: c, - UncachedObjects: options.UncachedObjects, - CacheUnstructured: options.CacheUnstructured, - }) - } -} diff --git a/pkg/cluster/cluster_test.go b/pkg/cluster/cluster_test.go index ba127d8fe9..8efec2459a 100644 --- a/pkg/cluster/cluster_test.go +++ b/pkg/cluster/cluster_test.go @@ -54,7 +54,7 @@ var _ = Describe("cluster.Cluster", func() { It("should return an error it can't create a client.Client", func() { c, err := New(cfg, func(o *Options) { - o.NewClient = func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { + o.NewClient = func(config *rest.Config, options client.Options) (client.Client, error) { return nil, errors.New("expected error") } }) @@ -76,7 +76,7 @@ var _ = Describe("cluster.Cluster", func() { It("should create a client defined in by the new client function", func() { c, err := New(cfg, func(o *Options) { - o.NewClient = func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { + o.NewClient = func(config *rest.Config, options client.Options) (client.Client, error) { return nil, nil } }) diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go index dd4cb4055a..f0257bcfdd 100644 --- a/pkg/manager/manager.go +++ b/pkg/manager/manager.go @@ -264,7 +264,7 @@ type Options struct { // NewClient is the func that creates the client to be used by the manager. // If not set this will create the default DelegatingClient that will // use the cache for reads and the client for writes. - NewClient cluster.NewClientFunc + NewClient client.NewClientFunc // BaseContext is the function that provides Context values to Runnables // managed by the Manager. If a BaseContext function isn't provided, Runnables diff --git a/pkg/manager/manager_test.go b/pkg/manager/manager_test.go index a430664509..9d600c925c 100644 --- a/pkg/manager/manager_test.go +++ b/pkg/manager/manager_test.go @@ -77,7 +77,7 @@ var _ = Describe("manger.Manager", func() { It("should return an error it can't create a client.Client", func() { m, err := New(cfg, Options{ - NewClient: func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { + NewClient: func(config *rest.Config, options client.Options) (client.Client, error) { return nil, errors.New("expected error") }, }) @@ -99,7 +99,7 @@ var _ = Describe("manger.Manager", func() { It("should create a client defined in by the new client function", func() { m, err := New(cfg, Options{ - NewClient: func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) { + NewClient: func(config *rest.Config, options client.Options) (client.Client, error) { return nil, nil }, })