Skip to content

Commit

Permalink
Use Set-based requirement to simplify the support of labelSelectors d…
Browse files Browse the repository at this point in the history
…efinition

Signed-off-by: Wilfried Roset <[email protected]>
  • Loading branch information
wilfriedroset committed Jan 21, 2025
1 parent c10e665 commit b06e4da
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 28 deletions.
2 changes: 1 addition & 1 deletion deploy/helm/grafana-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,6 @@ It's easier to just manage this configuration outside of the operator.
| serviceMonitor.targetLabels | list | `[]` | Set of labels to transfer from the Kubernetes Service onto the target |
| serviceMonitor.telemetryPath | string | `"/metrics"` | Set path to metrics path |
| tolerations | list | `[]` | pod tolerations |
| watchLabelSelectors | object | `{}` | Sets the `WATCH_LABEL_SELECTORS` environment variable, if defines which CRs are watched according to thei labels. By default, the operator watches all CRs. To make it watch only a subset of CRs, set the value to a map of key/value |
| watchLabelSelectors | string | `""` | Sets the `WATCH_LABEL_SELECTORS` environment variable, if defines which CRs are watched according to thei labels. By default, the operator watches all CRs. To make it watch only a subset of CRs, define the variable as a *Set-based requirement* See also: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ |
| watchNamespaceSelector | string | `""` | Sets the `WATCH_NAMESPACE_SELECTOR` environment variable, it defines which namespaces the operator should be listening for based on a namespace label (e.g. `"environment: dev"`). By default, the operator watches all namespaces. To make it watch only its own namespace, check out `namespaceScope` option instead. |
| watchNamespaces | string | `""` | Sets the `WATCH_NAMESPACE` environment variable, it defines which namespaces the operator should be listening for (e.g. `"grafana, foo"`). By default, the operator watches all namespaces. To make it watch only its own namespace, check out `namespaceScope` option instead. |
2 changes: 1 addition & 1 deletion deploy/helm/grafana-operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ spec:
{{- if and .Values.watchLabelSelectors (eq .Values.watchLabelSelectors "") }}
value: ""
{{ else }}
value: {{quote .Values.watchLabelSelectors | toJson }}
value: {{quote .Values.watchLabelSelectors }}
{{- end }}
{{- with .Values.env }}
{{- toYaml . | nindent 12 }}
Expand Down
9 changes: 5 additions & 4 deletions deploy/helm/grafana-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ watchNamespaces: ""
watchNamespaceSelector: ""

# -- Sets the `WATCH_LABEL_SELECTORS` environment variable,
# if defines which CRs are watched according to thei labels.
# By default, the operator watches all CRs. To make it watch only a subset of CRs, set the value to a map of key/value
watchLabelSelectors: {}
# labelKey: labelValue
# it defines which CRs are watched according to their labels.
# By default, the operator watches all CRs. To make it watch only a subset of CRs, define the variable as a *stringified label selector*.
# See also: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
watchLabelSelectors: ""
# watchLabelSelectors: "partition in (customerA, customerB),environment!=qa"

# -- Determines if the target cluster is OpenShift. Additional rbac permissions for routes will be added on OpenShift
isOpenShift: false
Expand Down
39 changes: 17 additions & 22 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package main

import (
"context"
"encoding/json"
"flag"
"fmt"
"os"
"os/signal"
"strings"
Expand Down Expand Up @@ -49,7 +49,6 @@ import (
"github.com/grafana/grafana-operator/v5/controllers/autodetect"
"github.com/grafana/grafana-operator/v5/embeds"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/selection"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -68,7 +67,7 @@ const (
// If empty or undefined, the operator will run in cluster scope.
watchNamespaceEnvSelector = "WATCH_NAMESPACE_SELECTOR"
// watchLabelSelectorsEnvVar is the constant for env variable WATCH_LABEL_SELECTORS which specifies the resources to watch according to their labels.
// eg: '{"labelKey": "labelValue"}'
// eg: 'partition in (customerA, customerB),environment!=qa'
// If empty of undefined, the operator will watch all CRs.
watchLabelSelectorsEnvVar = "WATCH_LABEL_SELECTORS"
)
Expand Down Expand Up @@ -127,6 +126,18 @@ func main() {
PprofBindAddress: pprofAddr,
}

var labelSelectors labels.Selector
var err error
if watchLabelSelectors != "" {
labelSelectors, err = labels.Parse(watchLabelSelectors)
if err != nil {
setupLog.Error(err, fmt.Sprintf("unable to parse %s", watchLabelSelectorsEnvVar))
os.Exit(1) //nolint
}
} else {
labelSelectors = labels.Everything() // Match any labels
}

getNamespaceConfig := func(namespaces string) map[string]cache.Config {
defaultNamespaces := map[string]cache.Config{}
for _, v := range strings.Split(namespaces, ",") {
Expand All @@ -135,7 +146,7 @@ func main() {
// this is the default behavior of the operator on v5, if you require finer grained control over this
// please file an issue in the grafana-operator/grafana-operator GH project
defaultNamespaces[v] = cache.Config{
LabelSelector: labels.Everything(), // Match any labels
LabelSelector: labelSelectors,
FieldSelector: fields.Everything(), // Match any fields
Transform: nil,
UnsafeDisableDeepCopy: nil,
Expand Down Expand Up @@ -163,7 +174,7 @@ func main() {
// this is the default behavior of the operator on v5, if you require finer grained control over this
// please file an issue in the grafana-operator/grafana-operator GH project
defaultNamespaces[v.Name] = cache.Config{
LabelSelector: labels.Everything(), // Match any labels
LabelSelector: labelSelectors,
FieldSelector: fields.Everything(), // Match any fields
Transform: nil,
UnsafeDisableDeepCopy: nil,
Expand All @@ -187,26 +198,10 @@ func main() {

case watchNamespace == "" && watchNamespaceSelector == "":
// cluster scoped
controllerOptions.Cache.DefaultLabelSelector = labelSelectors
setupLog.Info("operator running in cluster scoped mode")
}

if watchLabelSelectors != "" {
labelSelectors := map[string]string{}
err := json.Unmarshal([]byte(watchLabelSelectors), &labelSelectors)
if err != nil {
setupLog.Error(err, "unable to Unmarshal labelSelectors")
os.Exit(1) //nolint
}
for k, v := range labelSelectors {
req, err := labels.NewRequirement(k, selection.Equals, []string{v}, nil)
if err != nil {
setupLog.Error(err, "unable to create labels selector")
os.Exit(1) //nolint
}
controllerOptions.Cache.DefaultLabelSelector.Add(*req)
}
}

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGPIPE)
defer stop()

Expand Down

0 comments on commit b06e4da

Please sign in to comment.