Skip to content

Commit

Permalink
Add olm operator plug-in framework
Browse files Browse the repository at this point in the history
Signed-off-by: perdasilva <[email protected]>
  • Loading branch information
perdasilva committed Aug 25, 2022
1 parent 665c25b commit 5cbf02b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 13 deletions.
20 changes: 20 additions & 0 deletions pkg/controller/operators/olm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@ type operatorConfig struct {
configClient configv1client.Interface
}

func (o *operatorConfig) OperatorClient() operatorclient.ClientInterface {
return o.operatorClient
}

func (o *operatorConfig) ExternalClient() versioned.Interface {
return o.externalClient
}

func (o *operatorConfig) ResyncPeriod() func() time.Duration {
return o.resyncPeriod
}

func (o *operatorConfig) WatchedNamespaces() []string {
return o.watchedNamespaces
}

func (o *operatorConfig) Logger() *logrus.Logger {
return o.logger
}

func (o *operatorConfig) apply(options []OperatorOption) {
for _, option := range options {
option(o)
Expand Down
31 changes: 31 additions & 0 deletions pkg/controller/operators/olm/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"time"

"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/plugins"
"github.com/sirupsen/logrus"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -61,6 +62,10 @@ var (
ErrAPIServiceOwnerConflict = errors.New("unable to adopt APIService")
)

// this unexported operator plugin slice provides an entrypoint for
// downstream to inject its own plugins to augment the controller behavior
var operatorPlugInFactoryFuncs []plugins.OperatorPlugInFactoryFunc

type Operator struct {
queueinformer.Operator

Expand Down Expand Up @@ -91,6 +96,7 @@ type Operator struct {
clientAttenuator *scoped.ClientAttenuator
serviceAccountQuerier *scoped.UserDefinedServiceAccountQuerier
clientFactory clients.Factory
plugins []plugins.OperatorPlugin
}

func NewOperator(ctx context.Context, options ...OperatorOption) (*Operator, error) {
Expand Down Expand Up @@ -588,6 +594,31 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat
OverridesBuilderFunc: overridesBuilderFunc.GetDeploymentInitializer,
}

// initialize plugins
for _, makePlugIn := range operatorPlugInFactoryFuncs {
plugin, err := makePlugIn(ctx, config, op)
if err != nil {
return nil, fmt.Errorf("error creating plugin: %s", err)
}
op.plugins = append(op.plugins, plugin)
}

if len(operatorPlugInFactoryFuncs) > 0 {
go func() {
// block until operator is done
<-op.Done()

// shutdown plug-ins
for _, plugin := range op.plugins {
if err := plugin.Shutdown(); err != nil {
if op.logger != nil {
op.logger.Warnf("error shutting down plug-in: %s", err)
}
}
}
}()
}

return op, nil
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/controller/operators/olm/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func apiResourcesForObjects(objs []runtime.Object) []*metav1.APIResourceList {

// fakeOperatorConfig is the configuration for a fake operator.
type fakeOperatorConfig struct {
*operatorConfig
*OperatorConfig

recorder record.EventRecorder
namespaces []string
Expand Down Expand Up @@ -247,7 +247,7 @@ func withLogger(logger *logrus.Logger) fakeOperatorOption {
func NewFakeOperator(ctx context.Context, options ...fakeOperatorOption) (*Operator, error) {
// Apply options to default config
config := &fakeOperatorConfig{
operatorConfig: &operatorConfig{
OperatorConfig: &OperatorConfig{
resyncPeriod: queueinformer.ResyncWithJitter(5*time.Minute, 0.1),
operatorNamespace: "default",
watchedNamespaces: []string{metav1.NamespaceAll},
Expand Down Expand Up @@ -288,7 +288,7 @@ func NewFakeOperator(ctx context.Context, options ...fakeOperatorOption) (*Opera
}
}

op, err := newOperatorWithConfig(ctx, config.operatorConfig)
op, err := newOperatorWithConfig(ctx, config.OperatorConfig)
if err != nil {
return nil, err
}
Expand Down
37 changes: 37 additions & 0 deletions pkg/controller/operators/olm/plugins/operator_plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package plugins

import (
"context"
"time"

"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/queueinformer"
"github.com/sirupsen/logrus"
)

// HostOperator is an extensible and observable operator that hosts the plug-in, i.e. which the plug-in is extending
type HostOperator interface {
queueinformer.ObservableOperator
queueinformer.ExtensibleOperator
}

// OperatorConfig gives access to required configuration from the host operator
type OperatorConfig interface {
OperatorClient() operatorclient.ClientInterface
ExternalClient() versioned.Interface
ResyncPeriod() func() time.Duration
WatchedNamespaces() []string
Logger() *logrus.Logger
}

// OperatorPlugin provides a simple interface
// that can be used to extend the olm operator's functionality
type OperatorPlugin interface {
// Shutdown is called once the host operator is done
// to give the plug-in a change to clean up resources if necessary
Shutdown() error
}

// OperatorPlugInFactoryFunc factory function that returns a new instance of a plug-in
type OperatorPlugInFactoryFunc func(ctx context.Context, config OperatorConfig, hostOperator HostOperator) (OperatorPlugin, error)
28 changes: 18 additions & 10 deletions pkg/lib/queueinformer/queueinformer_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,19 @@ import (
"k8s.io/client-go/tools/cache"
)

// Operator describes a Reconciler that manages a set of QueueInformers.
type Operator interface {
// ExtensibleOperator describes a Reconciler that can be extended with additional informers and queue informers
type ExtensibleOperator interface {
// RegisterQueueInformer registers the given QueueInformer with the Operator.
// This method returns an error if the Operator has already been started.
RegisterQueueInformer(queueInformer *QueueInformer) error

// RegisterInformer registers an informer with the Operator.
// This method returns an error if the Operator has already been started.
RegisterInformer(cache.SharedIndexInformer) error
}

// ObservableOperator describes a Reconciler whose state can be queried
type ObservableOperator interface {
// Ready returns a channel that is closed when the Operator is ready to run.
Ready() <-chan struct{}

Expand All @@ -29,15 +40,12 @@ type Operator interface {

// HasSynced returns true if the Operator's Informers have synced, false otherwise.
HasSynced() bool
}

// RegisterQueueInformer registers the given QueueInformer with the Operator.
// This method returns an error if the Operator has already been started.
RegisterQueueInformer(queueInformer *QueueInformer) error

// RegisterInformer registers an informer with the Operator.
// This method returns an error if the Operator has already been started.
RegisterInformer(cache.SharedIndexInformer) error

// Operator describes a Reconciler that manages a set of QueueInformers.
type Operator interface {
ObservableOperator
ExtensibleOperator
// RunInformers starts the Operator's underlying Informers.
RunInformers(ctx context.Context)

Expand Down

0 comments on commit 5cbf02b

Please sign in to comment.