Skip to content

Commit

Permalink
✨ Allow user to define how create managed objects
Browse files Browse the repository at this point in the history
* Allow the user to specify in the options how to create the client,
cache, and how to construct the delegating client.

fixes #226
  • Loading branch information
Shawn Hurley committed Dec 6, 2018
1 parent 8991a78 commit 8fba660
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 20 deletions.
61 changes: 43 additions & 18 deletions pkg/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,30 @@ type Options struct {
// for serving prometheus metrics
MetricsBindAddress string

// Functions to all for a user to customize the values that will be injected.

// NewCache is the function that will create the cache to be used
// by the manager. If not set this will use the default new cache function.
NewCache NewCacheFunc

// NewClient will create 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 NewClientFunc

// Dependency injection for testing
newCache func(config *rest.Config, opts cache.Options) (cache.Cache, error)
newClient func(config *rest.Config, options client.Options) (client.Client, error)
newRecorderProvider func(config *rest.Config, scheme *runtime.Scheme, logger logr.Logger) (recorder.Provider, error)
newResourceLock func(config *rest.Config, recorderProvider recorder.Provider, options leaderelection.Options) (resourcelock.Interface, error)
newAdmissionDecoder func(scheme *runtime.Scheme) (types.Decoder, error)
newMetricsListener func(addr string) (net.Listener, error)
}

// NewCacheFunc allows a user to define how to create a cache
type NewCacheFunc func(config *rest.Config, opts cache.Options) (cache.Cache, error)

// NewClientFunc allows a user to define how to create a client
type NewClientFunc func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error)

// Runnable allows a component to be started.
type Runnable interface {
// Start starts running the component. The component will stop running when the channel is closed.
Expand Down Expand Up @@ -159,14 +174,13 @@ func New(config *rest.Config, options Options) (Manager, error) {
return nil, err
}

// Create the Client for Write operations.
writeObj, err := options.newClient(config, client.Options{Scheme: options.Scheme, Mapper: mapper})
// Create the cache for the cached read client and registering informers
cache, err := options.NewCache(config, cache.Options{Scheme: options.Scheme, Mapper: mapper, Resync: options.SyncPeriod, Namespace: options.Namespace})
if err != nil {
return nil, err
}

// Create the cache for the cached read client and registering informers
cache, err := options.newCache(config, cache.Options{Scheme: options.Scheme, Mapper: mapper, Resync: options.SyncPeriod, Namespace: options.Namespace})
writeObj, err := options.NewClient(cache, config, client.Options{Scheme: options.Scheme, Mapper: mapper})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -209,14 +223,7 @@ func New(config *rest.Config, options Options) (Manager, error) {
errChan: make(chan error),
cache: cache,
fieldIndexes: cache,
client: client.DelegatingClient{
Reader: &client.DelegatingReader{
CacheReader: cache,
ClientReader: writeObj,
},
Writer: writeObj,
StatusClient: writeObj,
},
client: writeObj,
recorderProvider: recorderProvider,
resourceLock: resourceLock,
mapper: mapper,
Expand All @@ -226,6 +233,24 @@ func New(config *rest.Config, options Options) (Manager, error) {
}, nil
}

// defaultNewClient creates the default caching client
func defaultNewClient(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
// Create the Client for Write operations.
c, err := client.New(config, options)
if err != nil {
return nil, err
}

return &client.DelegatingClient{
Reader: &client.DelegatingReader{
CacheReader: cache,
ClientReader: c,
},
Writer: c,
StatusClient: c,
}, nil
}

// setOptionsDefaults set default values for Options fields
func setOptionsDefaults(options Options) Options {
// Use the Kubernetes client-go scheme if none is specified
Expand All @@ -238,13 +263,13 @@ func setOptionsDefaults(options Options) Options {
}

// Allow newClient to be mocked
if options.newClient == nil {
options.newClient = client.New
if options.NewClient == nil {
options.NewClient = defaultNewClient
}

// Allow newCache to be mocked
if options.newCache == nil {
options.newCache = cache.New
if options.NewCache == nil {
options.NewCache = cache.New
}

// Allow newRecorderProvider to be mocked
Expand Down
18 changes: 16 additions & 2 deletions pkg/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ var _ = Describe("manger.Manager", func() {

It("should return an error it can't create a client.Client", func(done Done) {
m, err := New(cfg, Options{
newClient: func(config *rest.Config, options client.Options) (client.Client, error) {
NewClient: func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
return nil, fmt.Errorf("expected error")
},
})
Expand All @@ -85,7 +85,7 @@ var _ = Describe("manger.Manager", func() {

It("should return an error it can't create a cache.Cache", func(done Done) {
m, err := New(cfg, Options{
newCache: func(config *rest.Config, opts cache.Options) (cache.Cache, error) {
NewCache: func(config *rest.Config, opts cache.Options) (cache.Cache, error) {
return nil, fmt.Errorf("expected error")
},
})
Expand All @@ -95,6 +95,20 @@ var _ = Describe("manger.Manager", func() {

close(done)
})

It("should create a client defined in by the new client function", func(done Done) {
m, err := New(cfg, Options{
NewClient: func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
return nil, nil
},
})
Expect(m).ToNot(BeNil())
Expect(err).ToNot(HaveOccurred())
Expect(m.GetClient()).To(BeNil())

close(done)
})

It("should return an error it can't create a recorder.Provider", func(done Done) {
m, err := New(cfg, Options{
newRecorderProvider: func(config *rest.Config, scheme *runtime.Scheme, logger logr.Logger) (recorder.Provider, error) {
Expand Down

0 comments on commit 8fba660

Please sign in to comment.