Skip to content

Commit

Permalink
feat: contact point overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
theSuess committed Sep 10, 2024
1 parent e4dd317 commit 60199a8
Show file tree
Hide file tree
Showing 11 changed files with 493 additions and 90 deletions.
17 changes: 17 additions & 0 deletions api/v1beta1/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package v1beta1

import v1 "k8s.io/api/core/v1"

type ValueFrom struct {
TargetPath string `json:"targetPath"`
ValueFrom ValueFromSource `json:"valueFrom"`
}

type ValueFromSource struct {
// Selects a key of a ConfigMap.
// +optional
ConfigMapKeyRef *v1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
// Selects a key of a Secret.
// +optional
SecretKeyRef *v1.SecretKeySelector `json:"secretKeyRef,omitempty"`
}
2 changes: 2 additions & 0 deletions api/v1beta1/grafanacontactpoint_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type GrafanaContactPointSpec struct {

Settings *apiextensions.JSON `json:"settings"`

ValuesFrom []ValueFrom `json:"valuesFrom,omitempty"`

// +kubebuilder:validation:Enum=alertmanager;prometheus-alertmanager;dingding;discord;email;googlechat;kafka;line;opsgenie;pagerduty;pushover;sensugo;sensu;slack;teams;telegram;threema;victorops;webhook;wecom;hipchat;oncall
Type string `json:"type,omitempty"`

Expand Down
18 changes: 1 addition & 17 deletions api/v1beta1/grafanadatasource_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"fmt"
"time"

v1 "k8s.io/api/core/v1"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -72,7 +70,7 @@ type GrafanaDatasourceSpec struct {

// environments variables from secrets or config maps
// +optional
ValuesFrom []GrafanaDatasourceValueFrom `json:"valuesFrom,omitempty"`
ValuesFrom []ValueFrom `json:"valuesFrom,omitempty"`

// how often the datasource is refreshed, defaults to 5m if not set
// +optional
Expand All @@ -87,20 +85,6 @@ type GrafanaDatasourceSpec struct {
AllowCrossNamespaceImport *bool `json:"allowCrossNamespaceImport,omitempty"`
}

type GrafanaDatasourceValueFrom struct {
TargetPath string `json:"targetPath"`
ValueFrom GrafanaDatasourceValueFromSource `json:"valueFrom"`
}

type GrafanaDatasourceValueFromSource struct {
// Selects a key of a ConfigMap.
// +optional
ConfigMapKeyRef *v1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
// Selects a key of a Secret.
// +optional
SecretKeyRef *v1.SecretKeySelector `json:"secretKeyRef,omitempty"`
}

// GrafanaDatasourceStatus defines the observed state of GrafanaDatasource
type GrafanaDatasourceStatus struct {
Hash string `json:"hash,omitempty"`
Expand Down
91 changes: 49 additions & 42 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 64 additions & 0 deletions config/crd/bases/grafana.integreatly.org_grafanacontactpoints.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,70 @@ spec:
- hipchat
- oncall
type: string
valuesFrom:
items:
properties:
targetPath:
type: string
valueFrom:
properties:
configMapKeyRef:
description: Selects a key of a ConfigMap.
properties:
key:
description: The key to select.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
TODO: Add other useful fields. apiVersion, kind, uid?
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
type: string
optional:
description: Specify whether the ConfigMap or its key
must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
secretKeyRef:
description: Selects a key of a Secret.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
TODO: Add other useful fields. apiVersion, kind, uid?
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
type: object
required:
- targetPath
- valueFrom
type: object
type: array
required:
- instanceSelector
- name
Expand Down
28 changes: 28 additions & 0 deletions controllers/controller_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana-operator/v5/api/v1beta1"
grafanav1beta1 "github.com/grafana/grafana-operator/v5/api/v1beta1"
"github.com/grafana/grafana-operator/v5/controllers/model"
corev1 "k8s.io/api/core/v1"
kuberr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -230,3 +231,30 @@ func buildSynchronizedCondition(resource string, syncType string, generation int
}
return condition
}

func getReferencedValue(ctx context.Context, cl client.Client, cr metav1.ObjectMetaAccessor, source v1beta1.ValueFromSource) (string, string, error) {
objMeta := cr.GetObjectMeta()
if source.SecretKeyRef != nil {
s := &corev1.Secret{}
err := cl.Get(ctx, client.ObjectKey{Namespace: objMeta.GetNamespace(), Name: source.SecretKeyRef.Name}, s)
if err != nil {
return "", "", err
}
if val, ok := s.Data[source.SecretKeyRef.Key]; ok {
return string(val), source.SecretKeyRef.Key, nil
} else {
return "", "", fmt.Errorf("missing key %s in secret %s", source.SecretKeyRef.Key, source.SecretKeyRef.Name)
}
} else {
s := &corev1.ConfigMap{}
err := cl.Get(ctx, client.ObjectKey{Namespace: objMeta.GetNamespace(), Name: source.ConfigMapKeyRef.Name}, s)
if err != nil {
return "", "", err
}
if val, ok := s.Data[source.ConfigMapKeyRef.Key]; ok {
return val, source.ConfigMapKeyRef.Key, nil
} else {
return "", "", fmt.Errorf("missing key %s in configmap %s", source.ConfigMapKeyRef.Key, source.ConfigMapKeyRef.Name)
}
}
}
30 changes: 1 addition & 29 deletions controllers/datasource_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import (
"strings"
"time"

v1 "k8s.io/api/core/v1"

simplejson "github.com/bitly/go-simplejson"
"github.com/grafana/grafana-openapi-client-go/client/datasources"
"github.com/grafana/grafana-openapi-client-go/models"
Expand Down Expand Up @@ -453,7 +451,7 @@ func (r *GrafanaDatasourceReconciler) getDatasourceContent(ctx context.Context,

for _, ref := range cr.Spec.ValuesFrom {
ref := ref
val, key, err := r.getReferencedValue(ctx, cr, &ref.ValueFrom)
val, key, err := getReferencedValue(ctx, r.Client, cr, ref.ValueFrom)
if err != nil {
return nil, "", err
}
Expand Down Expand Up @@ -485,29 +483,3 @@ func (r *GrafanaDatasourceReconciler) getDatasourceContent(ctx context.Context,

return &res, fmt.Sprintf("%x", hash.Sum(nil)), nil
}

func (r *GrafanaDatasourceReconciler) getReferencedValue(ctx context.Context, cr *v1beta1.GrafanaDatasource, source *v1beta1.GrafanaDatasourceValueFromSource) (string, string, error) {
if source.SecretKeyRef != nil {
s := &v1.Secret{}
err := r.Client.Get(ctx, client.ObjectKey{Namespace: cr.Namespace, Name: source.SecretKeyRef.Name}, s)
if err != nil {
return "", "", err
}
if val, ok := s.Data[source.SecretKeyRef.Key]; ok {
return string(val), source.SecretKeyRef.Key, nil
} else {
return "", "", fmt.Errorf("missing key %s in secret %s", source.SecretKeyRef.Key, source.SecretKeyRef.Name)
}
} else {
s := &v1.ConfigMap{}
err := r.Client.Get(ctx, client.ObjectKey{Namespace: cr.Namespace, Name: source.ConfigMapKeyRef.Name}, s)
if err != nil {
return "", "", err
}
if val, ok := s.Data[source.ConfigMapKeyRef.Key]; ok {
return val, source.ConfigMapKeyRef.Key, nil
} else {
return "", "", fmt.Errorf("missing key %s in configmap %s", source.ConfigMapKeyRef.Key, source.ConfigMapKeyRef.Name)
}
}
}
Loading

0 comments on commit 60199a8

Please sign in to comment.