From 6dc37baf876ae877a47c4e5ec46afdc4fbca456c Mon Sep 17 00:00:00 2001 From: Utibeabasi Umanah Date: Tue, 19 Sep 2023 21:51:42 +0100 Subject: [PATCH] feat: trigger webhook on reload Signed-off-by: Utibeabasi Umanah --- go.sum | 8 -------- internal/pkg/cmd/reloader.go | 5 +++++ internal/pkg/handler/create.go | 5 +++++ internal/pkg/handler/update.go | 5 +++++ internal/pkg/handler/upgrade.go | 33 +++++++++++++++++++++++++++++++++ internal/pkg/options/flags.go | 2 ++ 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/go.sum b/go.sum index 20adc22..46dcade 100644 --- a/go.sum +++ b/go.sum @@ -192,24 +192,16 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.28.0 h1:3j3VPWmN9tTDI68NETBWlDiA9qOiGJ7sdKeufehBYsM= -k8s.io/api v0.28.0/go.mod h1:0l8NZJzB0i/etuWnIXcwfIv+xnDOhL3lLW919AWYDuY= k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= -k8s.io/apimachinery v0.28.0 h1:ScHS2AG16UlYWk63r46oU3D5y54T53cVI5mMJwwqFNA= -k8s.io/apimachinery v0.28.0/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= -k8s.io/client-go v0.28.0 h1:ebcPRDZsCjpj62+cMk1eGNX1QkMdRmQ6lmz5BLoFWeM= -k8s.io/client-go v0.28.0/go.mod h1:0Asy9Xt3U98RypWJmU1ZrRAGKhP6NqDPmptlAzK2kMc= k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/kubectl v0.28.0 h1:qhfju0OaU+JGeBlToPeeIg2UJUWP++QwTkpio6nlPKg= -k8s.io/kubectl v0.28.0/go.mod h1:1We+E5nSX3/TVoSQ6y5Bzld5OhTBHZHlKEYl7g/NaTk= k8s.io/kubectl v0.28.1 h1:jAq4yKEqQL+fwkWcEsUWxhJ7uIRcOYQraJxx4SyAMTY= k8s.io/kubectl v0.28.1/go.mod h1:a0nk/lMMeKBulp0lMTJAKbkjZg1ykqfLfz/d6dnv1ak= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= diff --git a/internal/pkg/cmd/reloader.go b/internal/pkg/cmd/reloader.go index 4e1e844..5d5dd73 100644 --- a/internal/pkg/cmd/reloader.go +++ b/internal/pkg/cmd/reloader.go @@ -39,6 +39,7 @@ func NewReloaderCommand() *cobra.Command { cmd.PersistentFlags().StringVar(&options.AutoSearchAnnotation, "auto-search-annotation", "reloader.stakater.com/search", "annotation to detect changes in configmaps or secrets tagged with special match annotation") cmd.PersistentFlags().StringVar(&options.SearchMatchAnnotation, "search-match-annotation", "reloader.stakater.com/match", "annotation to mark secrets or configmaps to match the search") cmd.PersistentFlags().StringVar(&options.LogFormat, "log-format", "", "Log format to use (empty string for text, or JSON") + cmd.PersistentFlags().StringVar(&options.WebhookUrl, "webhook-url", "", "webhook to trigger instead of performing a reload") cmd.PersistentFlags().StringSlice("resources-to-ignore", []string{}, "list of resources to ignore (valid options 'configMaps' or 'secrets')") cmd.PersistentFlags().StringSlice("namespaces-to-ignore", []string{}, "list of namespaces to ignore") cmd.PersistentFlags().StringSlice("namespace-selector", []string{}, "list of key:value labels to filter on for namespaces") @@ -156,6 +157,10 @@ func startReloader(cmd *cobra.Command, args []string) { logrus.Warnf("resource-label-selector is set, will only detect changes on resources with these labels: %s.", resourceLabelSelector) } + if options.WebhookUrl != "" { + logrus.Warnf("webhook-url is set, will only send webhook, no resources will be reloaded") + } + collectors := metrics.SetupPrometheusEndpoint() var controllers []*controller.Controller diff --git a/internal/pkg/handler/create.go b/internal/pkg/handler/create.go index 1bd6222..6c869c3 100644 --- a/internal/pkg/handler/create.go +++ b/internal/pkg/handler/create.go @@ -3,6 +3,7 @@ package handler import ( "github.com/sirupsen/logrus" "github.com/stakater/Reloader/internal/pkg/metrics" + "github.com/stakater/Reloader/internal/pkg/options" "github.com/stakater/Reloader/internal/pkg/util" v1 "k8s.io/api/core/v1" "k8s.io/client-go/tools/record" @@ -21,6 +22,10 @@ func (r ResourceCreatedHandler) Handle() error { logrus.Errorf("Resource creation handler received nil resource") } else { config, _ := r.GetConfig() + // Send webhook + if options.WebhookUrl != "" { + return sendUpgradeWebhook(config, options.WebhookUrl) + } // process resource based on its type return doRollingUpgrade(config, r.Collectors, r.Recorder) } diff --git a/internal/pkg/handler/update.go b/internal/pkg/handler/update.go index ff20d7f..edb2556 100644 --- a/internal/pkg/handler/update.go +++ b/internal/pkg/handler/update.go @@ -3,6 +3,7 @@ package handler import ( "github.com/sirupsen/logrus" "github.com/stakater/Reloader/internal/pkg/metrics" + "github.com/stakater/Reloader/internal/pkg/options" "github.com/stakater/Reloader/internal/pkg/util" v1 "k8s.io/api/core/v1" "k8s.io/client-go/tools/record" @@ -23,6 +24,10 @@ func (r ResourceUpdatedHandler) Handle() error { } else { config, oldSHAData := r.GetConfig() if config.SHAValue != oldSHAData { + // Send a webhook if update + if options.WebhookUrl != "" { + return sendUpgradeWebhook(config, options.WebhookUrl) + } // process resource based on its type return doRollingUpgrade(config, r.Collectors, r.Recorder) } diff --git a/internal/pkg/handler/upgrade.go b/internal/pkg/handler/upgrade.go index bc2a04a..b8cb311 100644 --- a/internal/pkg/handler/upgrade.go +++ b/internal/pkg/handler/upgrade.go @@ -1,14 +1,17 @@ package handler import ( + "bytes" "encoding/json" "errors" "fmt" + "io" "os" "regexp" "strconv" "strings" + "github.com/parnurzeal/gorequest" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" alert "github.com/stakater/Reloader/internal/pkg/alerts" @@ -94,6 +97,36 @@ func GetArgoRolloutRollingUpgradeFuncs() callbacks.RollingUpgradeFuncs { } } +func sendUpgradeWebhook(config util.Config, webhookUrl string) error { + message := fmt.Sprintf("Changes detected in '%s' of type '%s' in namespace '%s'", config.ResourceName, config.Type, config.Namespace) + message += fmt.Sprintf(", Sending webhook to '%s'", webhookUrl) + logrus.Infof(message) + body, errs := sendWebhook(webhookUrl) + if errs != nil { + // return the first error + return errs[0] + } else { + logrus.Info(body) + } + + return nil +} + +func sendWebhook(url string) (string, []error) { + request := gorequest.New() + resp, _, err := request.Post(url).Send(`{"webhook":"update successful"}`).End() + if err != nil { + // the reloader seems to retry automatically so no retry logic added + return "", err + } + var buffer bytes.Buffer + _, bufferErr := io.Copy(&buffer, resp.Body) + if bufferErr != nil { + logrus.Error(bufferErr) + } + return buffer.String(), nil +} + func doRollingUpgrade(config util.Config, collectors metrics.Collectors, recorder record.EventRecorder) error { clients := kube.GetClients() diff --git a/internal/pkg/options/flags.go b/internal/pkg/options/flags.go index 0faa6d2..bf16b92 100644 --- a/internal/pkg/options/flags.go +++ b/internal/pkg/options/flags.go @@ -30,4 +30,6 @@ var ( SyncAfterRestart = false // EnableHA adds support for running multiple replicas via leadership election EnableHA = false + // Url to send a request to instead of triggering a reload + WebhookUrl = "" )