controller/

directory
v0.90.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2024 License: Apache-2.0

README

Controllers

The controllers folder contains several packages related to writing kubernetes operators/controllers and their lifecycle management.

Packages:

  • client
  • conditions
  • errors
  • filter
  • lifecycle

Package 'lifecycle'

Class Diagram
classDiagram
    class LifecycleManager {
        + Reconcile(ctx context.Context, req ctrl.Request, instance RuntimeObject) (ctrl.Result, error)
        + SetupWithManager(mgr ctrl.Manager, maxReconciles int, reconcilerName string, instance RuntimeObject, debugLabelValue string, r reconcile.Reconciler, log *logger.Logger, eventPredicates ...predicate.Predicate) error
        + NewLifecycleManager(log *logger.Logger, operatorName string, controllerName string, client client.Client, subroutines []Subroutine) *LifecycleManager
    }

    class Subroutine {
        <<interface>>
        + Process(ctx context.Context, instance RuntimeObject) (ctrl.Result, errors.OperatorError)
        + Finalize(ctx context.Context, instance RuntimeObject) (ctrl.Result, errors.OperatorError)
        + GetName() string
        + Finalizers() []string
    }

    class RuntimeObject {
        <<interface>>
        + runtime.Object
        + v1.Object
    }

    LifecycleManager "1" --> "0..*" Subroutine : uses
    LifecycleManager "1" --> "1" RuntimeObject : interacts with
Usage

The purpose of this library is to simplify the process of writing an operator. This is done in the user code by creating a subroutine and implementing the Subroutine interface:

const (
    ExtensionClassSubroutineName      = "ExtensionclassDeletionSubroutine"
    ExtensionClassSubroutineCondition = "ExtensionClassReadyForDeletion"
)

// interface to implement
type Subroutine interface {
	Process(ctx context.Context, instance RuntimeObject) (ctrl.Result, errors.OperatorError)
	Finalize(ctx context.Context, instance RuntimeObject) (ctrl.Result, errors.OperatorError)
	GetName() string
	Finalizers() []string
}

type NewSubroutine struct {
	client client.Client
}

func (r *NewSubroutine) GetName() string {
	return ExtensionClassSubroutineName
}

func (r *NewSubroutine) Finalize(ctx context.Context, runtimeObj lifecycle.RuntimeObject) (ctrl.Result, errors.OperatorError) {
	return ctrl.Result{}, nil
}

func (r *NewSubroutine) Finalizers() []string {
	return []string{config.ExtensionClassCleanupFinalizer}
}

func (r *NewSubroutine) Process(ctx context.Context, runtimeObj lifecycle.RuntimeObject) (ctrl.Result, errors.OperatorError) {
	extensionClass := runtimeObj.(*extensionsV1alpha1.ExtensionClass)
    if extensionClass.Spec.Type == nil {
        return ctrl.Result{}, errors.NewOperatorError(errors.New("ExtensionClass type is not set"), true, false)
    }
    // do something
	
    return ctrl.Result{}, nil
}

Then the user implements a Reconciler class which calls the Reconcile and SetupWithManager functions in the lifecycle package instead those in the controller runtime. The subroutines are registered and passed as parameter to the lifecycle.NewLifecycleManager call:

type NewReconciler struct {
	lifecycle *lifecycle.LifecycleManager
}

func NewNewReconciler(log *logger.Logger, mgr ctrl.Manager, cfg config.Config) *NewReconciler {
	subs := []lifecycle.Subroutine{}
	subs = append(subs, subroutines.NewSubroutine(mgr.GetClient()))
	return &NewReconciler{
		lifecycle: lifecycle.NewLifecycleManager(log,
			"manager-name",
			"reconciler-name",
			mgr.GetClient(),
			subs),
	}
}

func (r *NewReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	return r.lifecycle.Reconcile(ctx, req, &v1alpha.CustomResource{})
}

func (r *NewReconciler) SetupWithManager(mgr ctrl.Manager, cfg config.Config, log *logger.Logger, eventPredicates ...predicate.Predicate) error {
	return r.lifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "reconciler-name", &v1alpha.CustomResource{}, cfg.DebugLabelValue, r, log, eventPredicates...)
}

Features of the lifecycle package:

  • timestamp management
  • spread reconciles
  • condition management
  • finalization and subroutine processing
  • status update
  • tracing
  • logger management
Configuration
// SetupWithManager
func (l *LifecycleManager) SetupWithManager(mgr ctrl.Manager, maxReconciles int, reconcilerName string, instance RuntimeObject, debugLabelValue string, r reconcile.Reconciler, log *logger.Logger, eventPredicates ...predicate.Predicate) error

The debugLabelValue parameter enables filtering of the resources based on a debug.openmfp.io label. If the label has the value passed in debugLabelValue, the resource will be reconciled in the Process function of the subroutine and all other resources will be skipped. If the value is empty string, all resources will be reconciled. This could be useful in debuging situations.

apiVersion: myorg.com/v1alpha1
kind: CustomResource
metadata:
  name: resource1
  namespace: mynamespace
  labels:
    debug.openmfp.io: test

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL