Documentation ¶
Index ¶
- Constants
- func NewPause[T client.Object](key string) (handler.TypedEventHandler[T, reconcile.Request], error)
- func SetOwnerAnnotations(owner, object client.Object) error
- type EnqueueRequestForAnnotation
- func (e *EnqueueRequestForAnnotation[T]) Create(_ context.Context, evt event.TypedCreateEvent[T], ...)
- func (e *EnqueueRequestForAnnotation[T]) Delete(_ context.Context, evt event.TypedDeleteEvent[T], ...)
- func (e *EnqueueRequestForAnnotation[T]) Generic(_ context.Context, evt event.TypedGenericEvent[T], ...)
- func (e *EnqueueRequestForAnnotation[T]) Update(_ context.Context, evt event.TypedUpdateEvent[T], ...)
- type InstrumentedEnqueueRequestForObject
- func (h InstrumentedEnqueueRequestForObject[T]) Create(ctx context.Context, e event.TypedCreateEvent[T], ...)
- func (h InstrumentedEnqueueRequestForObject[T]) Delete(ctx context.Context, e event.TypedDeleteEvent[T], ...)
- func (h InstrumentedEnqueueRequestForObject[T]) Update(ctx context.Context, e event.TypedUpdateEvent[T], ...)
Examples ¶
Constants ¶
const ( // NamespacedNameAnnotation is an annotation whose value encodes the name and namespace of a resource to // reconcile when a resource containing this annotation changes. Valid values are of the form // `<namespace>/<name>` for namespace-scoped owners and `<name>` for cluster-scoped owners. NamespacedNameAnnotation = "operator-sdk/primary-resource" // TypeAnnotation is an annotation whose value encodes the group and kind of a resource to reconcil when a // resource containing this annotation changes. Valid values are of the form `<Kind>` for resource in the // core group, and `<Kind>.<group>` for all other resources. TypeAnnotation = "operator-sdk/primary-resource-type" )
Variables ¶
This section is empty.
Functions ¶
func NewPause ¶ added in v0.6.0
NewPause returns an event handler that filters out objects with a truthy "paused" annotation. When an annotation with key string key is present on an object and has a truthy value, ex. "true", the watch constructed with this event handler will not add events for that object to the queue. Key string key must be a valid annotation key.
A note on security: since users that can CRUD a particular API can apply or remove annotations with default cluster admission controllers, this same set of users can therefore start or stop reconciliation of objects via this pause mechanism. If this is a concern, configure an admission webhook to enforce a stricter annotation modification policy. See AdmissionReview configuration for user info available to a webhook: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#request
Example ¶
This example applies the Pause handler to all incoming Pod events on a Pod controller.
package main import ( "context" "os" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager/signals" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" "github.com/operator-framework/operator-lib/handler" ) func main() { cfg, err := config.GetConfig() if err != nil { os.Exit(1) } mgr, err := manager.New(cfg, manager.Options{}) if err != nil { os.Exit(1) } c, err := controller.NewUnmanaged("pod", mgr, controller.Options{ Reconciler: reconcile.Func(func(context.Context, reconcile.Request) (reconcile.Result, error) { return reconcile.Result{}, nil }), }) if err != nil { os.Exit(1) } // Filter out Pods with the "my.app/paused: true" annotation. pause, err := handler.NewPause[*corev1.Pod]("my.app/paused") if err != nil { os.Exit(1) } if err := c.Watch(source.Kind(mgr.GetCache(), &corev1.Pod{}, pause)); err != nil { os.Exit(1) } <-mgr.Elected() if err := c.Start(signals.SetupSignalHandler()); err != nil { os.Exit(1) } }
Output:
func SetOwnerAnnotations ¶
SetOwnerAnnotations helps in adding 'NamespacedNameAnnotation' and 'TypeAnnotation' to object based on the values obtained from owner. The object gets the annotations from owner's namespace, name, group and kind. In other terms, object can be said to be the dependent having annotations from the owner. When a watch is set on the object, the annotations help to identify the owner and trigger reconciliation. Annotations are ALWAYS overwritten.
Types ¶
type EnqueueRequestForAnnotation ¶
EnqueueRequestForAnnotation enqueues Request containing the Name and Namespace specified in the annotations of the object that is the source of the Event. The source of the event triggers reconciliation of the parent resource which is identified by annotations. `NamespacedNameAnnotation` and `TypeAnnotation` together uniquely identify an owner resource to reconcile.
handler.EnqueueRequestForAnnotation can be used to trigger reconciliation of resources which are cross-referenced. This allows a namespace-scoped dependent to trigger reconciliation of an owner which is in a different namespace, and a cluster-scoped dependent can trigger the reconciliation of a namespace(scoped)-owner.
As an example, consider the case where we would like to watch clusterroles based on which we reconcile namespace-scoped replicasets. With native owner references, this would not be possible since the cluster-scoped dependent (clusterroles) is trying to specify a namespace-scoped owner (replicasets). Whereas in case of annotations-based handlers, we could implement the following:
if err := c.Watch(&source.Kind{ // Watch clusterroles Type: &rbacv1.ClusterRole{}}, // Enqueue ReplicaSet reconcile requests using the namespacedName annotation value in the request. &handler.EnqueueRequestForAnnotation{schema.GroupKind{Group:"apps", Kind:"ReplicaSet"}}); err != nil { entryLog.Error(err, "unable to watch ClusterRole") os.Exit(1) } }
With this watch, the ReplicaSet reconciler would receive a request to reconcile "my-namespace/my-replicaset" based on a change to a ClusterRole that has the following annotations:
annotations: operator-sdk/primary-resource:"my-namespace/my-replicaset" operator-sdk/primary-resource-type:"ReplicaSet.apps"
Though an annotation-based watch handler removes the boundaries set by native owner reference implementation, the garbage collector still respects the scope restrictions. For example, if a parent creates a child resource across scopes not supported by owner references, it becomes the responsibility of the reconciler to clean up the child resource. Hence, the resource utilizing this handler SHOULD ALWAYS BE IMPLEMENTED WITH A FINALIZER.
func (*EnqueueRequestForAnnotation[T]) Create ¶
func (e *EnqueueRequestForAnnotation[T]) Create(_ context.Context, evt event.TypedCreateEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Create implements EventHandler
func (*EnqueueRequestForAnnotation[T]) Delete ¶
func (e *EnqueueRequestForAnnotation[T]) Delete(_ context.Context, evt event.TypedDeleteEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Delete implements EventHandler
func (*EnqueueRequestForAnnotation[T]) Generic ¶
func (e *EnqueueRequestForAnnotation[T]) Generic(_ context.Context, evt event.TypedGenericEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Generic implements EventHandler
func (*EnqueueRequestForAnnotation[T]) Update ¶
func (e *EnqueueRequestForAnnotation[T]) Update(_ context.Context, evt event.TypedUpdateEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Update implements EventHandler
type InstrumentedEnqueueRequestForObject ¶
type InstrumentedEnqueueRequestForObject[T client.Object] struct { handler.TypedEnqueueRequestForObject[T] }
InstrumentedEnqueueRequestForObject wraps controller-runtime handler for "EnqueueRequestForObject", and sets up primary resource metrics on event handlers. The main objective of this handler is to set prometheus metrics when create/update/delete events occur. These metrics contain the following information on resource.
resource_created_at_seconds{"name", "namespace", "group", "version", "kind"}
To call the handler use:
&handler.InstrumentedEnqueueRequestForObject{}
func (InstrumentedEnqueueRequestForObject[T]) Create ¶
func (h InstrumentedEnqueueRequestForObject[T]) Create(ctx context.Context, e event.TypedCreateEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Create implements EventHandler, and creates the metrics.
func (InstrumentedEnqueueRequestForObject[T]) Delete ¶
func (h InstrumentedEnqueueRequestForObject[T]) Delete(ctx context.Context, e event.TypedDeleteEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Delete implements EventHandler, and deletes metrics.
func (InstrumentedEnqueueRequestForObject[T]) Update ¶
func (h InstrumentedEnqueueRequestForObject[T]) Update(ctx context.Context, e event.TypedUpdateEvent[T], q workqueue.TypedRateLimitingInterface[reconcile.Request])
Update implements EventHandler, and updates the metrics.