Skip to content

Commit

Permalink
⚠️ Allow setting NewClientFunc w/o re-implementing ClientBuilder
Browse files Browse the repository at this point in the history
When introducing the ClientBuilder we lost the ability to easily
overwrite the NewClientFunc, this re-adds it.
  • Loading branch information
alvaroaleman committed Mar 3, 2021
1 parent e388e1e commit ded66c7
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
27 changes: 24 additions & 3 deletions pkg/cluster/client_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type ClientBuilder interface {
// for this client. This function can be called multiple times, it should append to an internal slice.
WithUncached(objs ...client.Object) ClientBuilder

// WithNewClientFunc can be used to override the default NewClientFunc.
WithNewClientFunc(NewClientFunc) ClientBuilder

// Build returns a new client.
Build(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error)
}
Expand All @@ -39,16 +42,34 @@ func NewClientBuilder() ClientBuilder {
}

type newClientBuilder struct {
uncached []client.Object
uncached []client.Object
newClientFunc NewClientFunc
}

func (n *newClientBuilder) WithUncached(objs ...client.Object) ClientBuilder {
n.uncached = append(n.uncached, objs...)
return n
}

func (n *newClientBuilder) WithNewClientFunc(f NewClientFunc) ClientBuilder {
n.newClientFunc = f
return n
}

func (n *newClientBuilder) Build(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
// Create the Client for Write operations.
if n.newClientFunc == nil {
n.newClientFunc = DefaultNewClientFunc
}

return n.newClientFunc(cache, config, options, n.uncached...)
}

// NewClientFunc is the signature of the func that is called to construct a new client.
type NewClientFunc func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error)

// DefaultNewClientFunc is the default NewClientFunc for the Builder. It's Reader interface
// is cache-backed.
func DefaultNewClientFunc(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) {
c, err := client.New(config, options)
if err != nil {
return nil, err
Expand All @@ -57,6 +78,6 @@ func (n *newClientBuilder) Build(cache cache.Cache, config *rest.Config, options
return client.NewDelegatingClient(client.NewDelegatingClientInput{
CacheReader: cache,
Client: c,
UncachedObjects: n.uncached,
UncachedObjects: uncachedObjects,
})
}
56 changes: 56 additions & 0 deletions pkg/cluster/client_builder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2021 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 cluster

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"

"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type recordingNewClientFunc struct {
uncachedObjects []client.Object
hasBeenCalled bool
}

func (r *recordingNewClientFunc) Func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) {
r.uncachedObjects = uncachedObjects
r.hasBeenCalled = true
return nil, nil
}

var _ = Describe("cluster.ClientBuilder", func() {
It("should set new client func", func() {
recorder := &recordingNewClientFunc{}
_, err := NewClientBuilder().WithNewClientFunc(recorder.Func).Build(nil, nil, client.Options{})
Expect(err).NotTo(HaveOccurred())
Expect(recorder.hasBeenCalled).To(BeTrue())
})

It("should set uncached objects", func() {
recorder := &recordingNewClientFunc{}
_, err := NewClientBuilder().WithUncached(&corev1.Pod{}).WithNewClientFunc(recorder.Func).Build(nil, nil, client.Options{})
Expect(err).NotTo(HaveOccurred())
Expect(recorder.hasBeenCalled).To(BeTrue())
Expect(recorder.uncachedObjects).To(Equal([]client.Object{&corev1.Pod{}}))
})
})
4 changes: 4 additions & 0 deletions pkg/cluster/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func (e *fakeClientBuilder) WithUncached(objs ...client.Object) ClientBuilder {
return e
}

func (e *fakeClientBuilder) WithNewClientFunc(f NewClientFunc) ClientBuilder {
return e
}

func (e *fakeClientBuilder) Build(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
return nil, e.err
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ func (e *fakeClientBuilder) WithUncached(objs ...client.Object) ClientBuilder {
return e
}

func (e *fakeClientBuilder) WithNewClientFunc(f cluster.NewClientFunc) ClientBuilder {
return e
}

func (e *fakeClientBuilder) Build(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
return nil, e.err
}
Expand Down

0 comments on commit ded66c7

Please sign in to comment.