From 3c711cc5d9d54a6fc8d5e3c5e76ddd9191966cf4 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Fri, 3 Jul 2020 17:26:00 +0300 Subject: [PATCH] Initialise receivers --- api/v1alpha1/condition_types.go | 3 + api/v1alpha1/receiver_types.go | 29 +++++++++ .../samples/notification_v1alpha1_alert.yaml | 1 - .../notification_v1alpha1_provider.yaml | 8 ++- .../notification_v1alpha1_receiver.yaml | 20 +++++- controllers/receiver_controller.go | 62 +++++++++++++++---- 6 files changed, 106 insertions(+), 17 deletions(-) diff --git a/api/v1alpha1/condition_types.go b/api/v1alpha1/condition_types.go index bd18a9b..9890f8a 100644 --- a/api/v1alpha1/condition_types.go +++ b/api/v1alpha1/condition_types.go @@ -61,6 +61,9 @@ const ( // is underway. ProgressingReason string = "Progressing" + // TokenNotFound represents the fact that receiver token can't be found. + TokenNotFoundReason string = "TokenNotFound" + // SuspendedReason represents the fact that the resource reconciliation is suspended. SuspendedReason string = "Suspended" ) diff --git a/api/v1alpha1/receiver_types.go b/api/v1alpha1/receiver_types.go index ec0ddf3..29077c8 100644 --- a/api/v1alpha1/receiver_types.go +++ b/api/v1alpha1/receiver_types.go @@ -60,6 +60,35 @@ type ReceiverStatus struct { URL string `json:"url,omitempty"` } +func ReceiverReady(receiver Receiver, reason, message, url string) Receiver { + receiver.Status.Conditions = []Condition{ + { + Type: ReadyCondition, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + }, + } + receiver.Status.URL = url + + return receiver +} + +func ReceiverNotReady(receiver Receiver, reason, message string) Receiver { + receiver.Status.Conditions = []Condition{ + { + Type: ReadyCondition, + Status: corev1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + }, + } + + return receiver +} + // +genclient // +genclient:Namespaced // +kubebuilder:object:root=true diff --git a/config/samples/notification_v1alpha1_alert.yaml b/config/samples/notification_v1alpha1_alert.yaml index 2c3c32b..85c65cb 100644 --- a/config/samples/notification_v1alpha1_alert.yaml +++ b/config/samples/notification_v1alpha1_alert.yaml @@ -2,7 +2,6 @@ apiVersion: notification.fluxcd.io/v1alpha1 kind: Alert metadata: name: on-call-webapp - namespace: gitops-system spec: providerRef: name: slack diff --git a/config/samples/notification_v1alpha1_provider.yaml b/config/samples/notification_v1alpha1_provider.yaml index 6f98131..8a006f5 100644 --- a/config/samples/notification_v1alpha1_provider.yaml +++ b/config/samples/notification_v1alpha1_provider.yaml @@ -2,9 +2,15 @@ apiVersion: notification.fluxcd.io/v1alpha1 kind: Provider metadata: name: slack - namespace: gitops-system spec: type: slack channel: general secretRef: name: slack-url +--- +apiVersion: v1 +kind: Secret +metadata: + name: slack-url +data: + address: aHR0cHM6Ly9ob29rcy5zbGFjay5jb20vc2VydmljZXMv diff --git a/config/samples/notification_v1alpha1_receiver.yaml b/config/samples/notification_v1alpha1_receiver.yaml index 632053e..eecd9b3 100644 --- a/config/samples/notification_v1alpha1_receiver.yaml +++ b/config/samples/notification_v1alpha1_receiver.yaml @@ -1,7 +1,21 @@ apiVersion: notification.fluxcd.io/v1alpha1 kind: Receiver metadata: - name: receiver-sample + name: github-receiver spec: - # Add fields here - foo: bar + type: github + events: + - ping + - push + resources: + - kind: GitRepository + name: podinfo + secretRef: + name: github-token +--- +apiVersion: v1 +kind: Secret +metadata: + name: github-token +data: + token: YUhSMGNITTZMeTlvYjI5cmN5NXpiR0ZqYXk1amIyMHZjMlZ5ZG1salpYTXY= diff --git a/controllers/receiver_controller.go b/controllers/receiver_controller.go index 13eefbc..1dd3b88 100644 --- a/controllers/receiver_controller.go +++ b/controllers/receiver_controller.go @@ -18,12 +18,14 @@ package controllers import ( "context" + "crypto/sha256" + "fmt" "strings" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -57,23 +59,31 @@ func (r *ReceiverReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { break } } + if !init { + return ctrl.Result{}, nil + } - if init { - receiver.Status.Conditions = []v1alpha1.Condition{ - { - Type: v1alpha1.ReadyCondition, - Status: corev1.ConditionTrue, - LastTransitionTime: metav1.Now(), - Reason: v1alpha1.InitializedReason, - Message: v1alpha1.InitializedReason, - }, - } + token, err := r.token(ctx, receiver) + if err != nil { + receiver = v1alpha1.ReceiverNotReady(receiver, v1alpha1.TokenNotFoundReason, err.Error()) if err := r.Status().Update(ctx, &receiver); err != nil { + log.Error(err, "unable to update Receiver status") return ctrl.Result{Requeue: true}, err } - log.Info("Provider initialised") } + receiverURL := fmt.Sprintf("/hook/%s", sha256sum(token+receiver.Name+receiver.Namespace)) + receiver = v1alpha1.ReceiverReady(receiver, + v1alpha1.InitializedReason, + "Receiver initialised with URL: "+receiverURL, + receiverURL) + if err := r.Status().Update(ctx, &receiver); err != nil { + log.Error(err, "unable to update Receiver status") + return ctrl.Result{Requeue: true}, err + } + + log.Info("Receiver initialised") + return ctrl.Result{}, nil } @@ -82,3 +92,31 @@ func (r *ReceiverReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&v1alpha1.Receiver{}). Complete(r) } + +// token extract the token value from the secret object +func (r *ReceiverReconciler) token(ctx context.Context, receiver v1alpha1.Receiver) (string, error) { + token := "" + secretName := types.NamespacedName{ + Namespace: receiver.GetNamespace(), + Name: receiver.Spec.SecretRef.Name, + } + + var secret corev1.Secret + err := r.Client.Get(ctx, secretName, &secret) + if err != nil { + return "", fmt.Errorf("unable to read token from secret '%s' error: %w", secretName, err) + } + + if val, ok := secret.Data["token"]; ok { + token = string(val) + } else { + return "", fmt.Errorf("invalid '%s' secret data: required fields 'token'", secretName) + } + + return token, nil +} + +func sha256sum(val string) string { + digest := sha256.Sum256([]byte(val)) + return fmt.Sprintf("%x", digest) +}