From 658fafa8b4f9b7bd5bcd1d90fdcf40d2b56c0de4 Mon Sep 17 00:00:00 2001 From: Venkat Ramaraju Date: Fri, 18 Jun 2021 10:40:56 -0700 Subject: [PATCH] predicate for helm Signed-off-by: Venkat Ramaraju --- changelog/fragments/helm-labelselector.yaml | 7 +++++++ internal/cmd/helm-operator/run/cmd.go | 1 + internal/helm/controller/controller.go | 18 +++++++++++++++++- internal/helm/watches/watches.go | 8 +++++--- .../helm/reference/watches.md | 7 ++++++- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 changelog/fragments/helm-labelselector.yaml diff --git a/changelog/fragments/helm-labelselector.yaml b/changelog/fragments/helm-labelselector.yaml new file mode 100644 index 00000000000..ff356a3e491 --- /dev/null +++ b/changelog/fragments/helm-labelselector.yaml @@ -0,0 +1,7 @@ +entries: + - description: > + Added a filter predicate for labels based on selectors specified in watches.yaml. + Only the resources that contain the labels specified by selectors will be reconciled. + + kind: addition + breaking: false \ No newline at end of file diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index 3eecfd48898..f72f121b13a 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -184,6 +184,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { WatchDependentResources: *w.WatchDependentResources, OverrideValues: w.OverrideValues, MaxConcurrentReconciles: f.MaxConcurrentReconciles, + Selector: w.Selector, }) if err != nil { log.Error(err, "Failed to add manager factory to controller.") diff --git a/internal/helm/controller/controller.go b/internal/helm/controller/controller.go index a3f5a5d0467..c1c978ce27e 100644 --- a/internal/helm/controller/controller.go +++ b/internal/helm/controller/controller.go @@ -16,6 +16,7 @@ package controller import ( "fmt" + "reflect" "strings" "sync" "time" @@ -30,6 +31,7 @@ import ( crthandler "sigs.k8s.io/controller-runtime/pkg/handler" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" + ctrlpredicate "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/source" "sigs.k8s.io/yaml" @@ -51,6 +53,7 @@ type WatchOptions struct { WatchDependentResources bool OverrideValues map[string]string MaxConcurrentReconciles int + Selector metav1.LabelSelector } // Add creates a new helm operator controller and adds it to the manager @@ -80,7 +83,20 @@ func Add(mgr manager.Manager, options WatchOptions) error { o := &unstructured.Unstructured{} o.SetGroupVersionKind(options.GVK) - if err := c.Watch(&source.Kind{Type: o}, &libhandler.InstrumentedEnqueueRequestForObject{}); err != nil { + + var preds []ctrlpredicate.Predicate + + // If a selector has been specified in watches.yaml, add it to the watch's predicates. + if !reflect.ValueOf(options.Selector).IsZero() { + p, err := ctrlpredicate.LabelSelectorPredicate(options.Selector) + if err != nil { + log.Error(err, "Unable to create predicate from selector.") + return err + } + preds = append(preds, p) + } + + if err := c.Watch(&source.Kind{Type: o}, &libhandler.InstrumentedEnqueueRequestForObject{}, preds...); err != nil { return err } diff --git a/internal/helm/watches/watches.go b/internal/helm/watches/watches.go index c02413abb32..8aa0e650832 100644 --- a/internal/helm/watches/watches.go +++ b/internal/helm/watches/watches.go @@ -22,6 +22,7 @@ import ( "os" "helm.sh/helm/v3/pkg/chartutil" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/yaml" ) @@ -32,9 +33,10 @@ const WatchesFile = "watches.yaml" // custom resource. type Watch struct { schema.GroupVersionKind `json:",inline"` - ChartDir string `json:"chart"` - WatchDependentResources *bool `json:"watchDependentResources,omitempty"` - OverrideValues map[string]string `json:"overrideValues,omitempty"` + ChartDir string `json:"chart"` + WatchDependentResources *bool `json:"watchDependentResources,omitempty"` + OverrideValues map[string]string `json:"overrideValues,omitempty"` + Selector metav1.LabelSelector `json:"selector"` } // UnmarshalYAML unmarshals an individual watch from the Helm watches.yaml file diff --git a/website/content/en/docs/building-operators/helm/reference/watches.md b/website/content/en/docs/building-operators/helm/reference/watches.md index de423dfd50d..f8447b684b3 100644 --- a/website/content/en/docs/building-operators/helm/reference/watches.md +++ b/website/content/en/docs/building-operators/helm/reference/watches.md @@ -19,6 +19,7 @@ The follow tables describes the fields in an entry in `watches.yaml`: | chart | The path to the helm chart to use when reconciling this GVK. | | watchDependentResources | Enable watching resources that are created by helm (default: `true`). | | overrideValues | Values to be used for overriding Helm chart's defaults. For additional information see the [reference doc][override-values]. | +| selector | The conditions that a resource's labels must satsify in order to get reconciled. For additional information see [labels and selectors documentation][label-selector-doc]. | For reference, here is an example of a simple `watches.yaml` file: @@ -31,7 +32,11 @@ For reference, here is an example of a simple `watches.yaml` file: chart: helm-charts/foo overrideValues: image.repository: quay.io/mycustomrepo - watchDependentResources: false + watchDependentResources: false + selector: + matchExpressions: + - {key: testLabel, operator: Exists, values: []} ``` [override-values]: /docs/building-operators/helm/reference/advanced_features/override_values/ +[label-selector-doc]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/