github.com/operator-framework/operator-lifecycle-manager@v0.30.0/pkg/controller/operators/openshift/options.go (about)

     1  package openshift
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/go-logr/logr"
    10  	configv1 "github.com/openshift/api/config/v1"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  	"k8s.io/apimachinery/pkg/runtime"
    13  	"k8s.io/apimachinery/pkg/types"
    14  	ctrl "sigs.k8s.io/controller-runtime"
    15  	"sigs.k8s.io/controller-runtime/pkg/builder"
    16  	"sigs.k8s.io/controller-runtime/pkg/client"
    17  	"sigs.k8s.io/controller-runtime/pkg/handler"
    18  	"sigs.k8s.io/controller-runtime/pkg/predicate"
    19  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    20  
    21  	operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
    22  	olmversion "github.com/operator-framework/operator-lifecycle-manager/pkg/version"
    23  )
    24  
    25  type NowFunc func() metav1.Time
    26  
    27  type ReconcilerConfig struct {
    28  	Client       client.Client
    29  	Scheme       *runtime.Scheme
    30  	Log          logr.Logger
    31  	RequeueDelay time.Duration
    32  	TweakBuilder func(*builder.Builder) *builder.Builder
    33  	Now          NowFunc
    34  
    35  	Name           string
    36  	Namespace      string
    37  	SyncCh         <-chan error
    38  	TargetVersions []configv1.OperandVersion
    39  
    40  	Mutator Mutator
    41  }
    42  
    43  type ReconcilerOption func(*ReconcilerConfig)
    44  
    45  func (c *ReconcilerConfig) apply(opts []ReconcilerOption) {
    46  	for _, opt := range opts {
    47  		opt(c)
    48  	}
    49  }
    50  
    51  func (c *ReconcilerConfig) complete() error {
    52  	if c.Client == nil {
    53  		return fmt.Errorf("no client specified")
    54  	}
    55  	if c.Name == "" {
    56  		return fmt.Errorf("no ClusterOperator name specified")
    57  	}
    58  	if c.Log.GetSink() == nil {
    59  		c.Log = ctrl.Log.WithName(c.Name)
    60  	}
    61  	if c.Now == nil {
    62  		c.Now = NowFunc(metav1.Now)
    63  	}
    64  	if c.Scheme == nil {
    65  		c.Scheme = runtime.NewScheme()
    66  	}
    67  	if c.RequeueDelay == 0 {
    68  		c.RequeueDelay = time.Second * 5
    69  	}
    70  	if err := AddToScheme(c.Scheme); err != nil {
    71  		return err
    72  	}
    73  
    74  	if len(c.TargetVersions) < 1 {
    75  		c.TargetVersions = []configv1.OperandVersion{
    76  			{
    77  				Name:    "operator",
    78  				Version: os.Getenv("RELEASE_VERSION"),
    79  			},
    80  			{
    81  				Name:    c.Name,
    82  				Version: olmversion.OLMVersion,
    83  			},
    84  		}
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  func (c *ReconcilerConfig) mapClusterOperator(_ context.Context, _ client.Object) []reconcile.Request {
    91  	// Enqueue the cluster operator
    92  	return []reconcile.Request{
    93  		{NamespacedName: types.NamespacedName{Name: c.Name}},
    94  	}
    95  }
    96  
    97  func WithClient(cli client.Client) ReconcilerOption {
    98  	return func(config *ReconcilerConfig) {
    99  		config.Client = cli
   100  	}
   101  }
   102  
   103  func WithScheme(scheme *runtime.Scheme) ReconcilerOption {
   104  	return func(config *ReconcilerConfig) {
   105  		config.Scheme = scheme
   106  	}
   107  }
   108  
   109  func WithName(name string) ReconcilerOption {
   110  	return func(config *ReconcilerConfig) {
   111  		config.Name = name
   112  	}
   113  }
   114  
   115  func WithNamespace(namespace string) ReconcilerOption {
   116  	return func(config *ReconcilerConfig) {
   117  		config.Namespace = namespace
   118  	}
   119  }
   120  
   121  func WithSyncChannel(syncCh <-chan error) ReconcilerOption {
   122  	return func(config *ReconcilerConfig) {
   123  		config.SyncCh = syncCh
   124  	}
   125  }
   126  
   127  func WithNow(now NowFunc) ReconcilerOption {
   128  	return func(config *ReconcilerConfig) {
   129  		config.Now = now
   130  	}
   131  }
   132  
   133  func WithLog(log logr.Logger) ReconcilerOption {
   134  	return func(config *ReconcilerConfig) {
   135  		config.Log = log
   136  	}
   137  }
   138  
   139  func WithTargetVersions(targetVersions ...configv1.OperandVersion) ReconcilerOption {
   140  	return func(config *ReconcilerConfig) {
   141  		config.TargetVersions = targetVersions
   142  	}
   143  }
   144  
   145  func WithOLMOperator() ReconcilerOption {
   146  	return func(config *ReconcilerConfig) {
   147  		var mutations SerialMutations
   148  		if config.Mutator != nil {
   149  			mutations = append(mutations, config.Mutator)
   150  		}
   151  
   152  		mutations = append(mutations, MutateFunc(func(ctx context.Context, co *ClusterOperator) error {
   153  			refs, err := olmOperatorRelatedObjects(ctx, config.Client, config.Namespace)
   154  			if len(refs) > 0 {
   155  				// Set any refs we found, regardless of any errors encountered (best effort)
   156  				co.Status.RelatedObjects = refs
   157  			}
   158  
   159  			return err
   160  		}))
   161  		config.Mutator = mutations
   162  
   163  		enqueue := handler.EnqueueRequestsFromMapFunc(config.mapClusterOperator)
   164  
   165  		originalCSV := predicate.NewPredicateFuncs(func(obj client.Object) bool {
   166  			csv, ok := obj.(*operatorsv1alpha1.ClusterServiceVersion)
   167  			if !ok {
   168  				// Not a CSV, throw out
   169  				return false
   170  			}
   171  
   172  			return !csv.IsCopied() // Keep original CSVs only
   173  		})
   174  		config.TweakBuilder = func(bldr *builder.Builder) *builder.Builder {
   175  			return bldr.Watches(&operatorsv1alpha1.ClusterServiceVersion{}, enqueue, builder.WithPredicates(originalCSV))
   176  		}
   177  	}
   178  }