From 0598e4b51e617aa9f517ae374b0014f3553bfea8 Mon Sep 17 00:00:00 2001 From: Tanner Altares Date: Tue, 18 Feb 2020 12:33:52 -0600 Subject: [PATCH 1/2] add support for rollback gating for loadtester --- pkg/loadtester/server.go | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/pkg/loadtester/server.go b/pkg/loadtester/server.go index b91af4945..d37d65ea4 100644 --- a/pkg/loadtester/server.go +++ b/pkg/loadtester/server.go @@ -109,6 +109,85 @@ func ListenAndServe(port string, timeout time.Duration, logger *zap.SugaredLogge logger.Infof("%s gate closed", canaryName) }) + mux.HandleFunc("/rollback/check", func(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + logger.Error("reading the request body failed", zap.Error(err)) + w.WriteHeader(http.StatusBadRequest) + return + } + defer r.Body.Close() + + canary := &flaggerv1.CanaryWebhookPayload{} + err = json.Unmarshal(body, canary) + if err != nil { + logger.Error("decoding the request body failed", zap.Error(err)) + w.WriteHeader(http.StatusBadRequest) + return + } + + canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace) + approved := gate.isOpen(canaryName) + if approved { + w.WriteHeader(http.StatusOK) + w.Write([]byte("Approved")) + } else { + w.WriteHeader(http.StatusForbidden) + w.Write([]byte("Forbidden")) + } + + logger.Infof("%s rollback check: approved %v", canaryName, approved) + }) + mux.HandleFunc("/rollback/open", func(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + logger.Error("reading the request body failed", zap.Error(err)) + w.WriteHeader(http.StatusBadRequest) + return + } + defer r.Body.Close() + + canary := &flaggerv1.CanaryWebhookPayload{} + err = json.Unmarshal(body, canary) + if err != nil { + logger.Error("decoding the request body failed", zap.Error(err)) + w.WriteHeader(http.StatusBadRequest) + return + } + + canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace) + gate.open(canaryName) + + w.WriteHeader(http.StatusAccepted) + + logger.Infof("%s rollback opened", canaryName) + }) + mux.HandleFunc("/rollback/close", func(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + logger.Error("reading the request body failed", zap.Error(err)) + w.WriteHeader(http.StatusBadRequest) + return + } + defer r.Body.Close() + + canary := &flaggerv1.CanaryWebhookPayload{} + err = json.Unmarshal(body, canary) + if err != nil { + logger.Error("decoding the request body failed", zap.Error(err)) + w.WriteHeader(http.StatusBadRequest) + return + } + + + canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace) + gate.close(canaryName) + + w.WriteHeader(http.StatusAccepted) + + logger.Infof("%s rollback closed", canaryName) + }) + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { From 34ed69041601781014e86cce46a84928bd39562e Mon Sep 17 00:00:00 2001 From: Tanner Altares Date: Tue, 18 Feb 2020 15:00:03 -0600 Subject: [PATCH 2/2] update the docs --- docs/gitbook/how-it-works.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/gitbook/how-it-works.md b/docs/gitbook/how-it-works.md index 9cdd28f44..5e1e0ecdb 100644 --- a/docs/gitbook/how-it-works.md +++ b/docs/gitbook/how-it-works.md @@ -589,7 +589,7 @@ Spec: some: "message" - name: "rollback gate" type: rollback - url: http://flagger-loadtester.test/gate/halt + url: http://flagger-loadtester.test/rollback/check - name: "send to Slack" type: event url: http://event-recevier.notifications/slack @@ -908,14 +908,29 @@ While the promotion is paused, Flagger will continue to run the metrics checks a url: http://flagger-loadtester.test/gate/halt ``` -The `rollback` hook type can be used to manually rollback the canary promotion. +The `rollback` hook type can be used to manually rollback the canary promotion. As with gating, rollbacks can be driven +with Flagger's tester API by setting the rollback URL to `/rollback/check` ```yaml canaryAnalysis: webhooks: - name: "rollback" type: rollback - url: http://flagger-loadtester.test/gate/halt + url: http://flagger-loadtester.test/rollback/check ``` +By default rollback is closed, you can rollback a canary rollout with: + +```bash +kubectl -n test exec -it flagger-loadtester-xxxx-xxxx sh + +curl -d '{"name": "podinfo","namespace":"test"}' http://localhost:8080/rollback/open +``` + +You can close the rollback with: + +```bash +curl -d '{"name": "podinfo","namespace":"test"}' http://localhost:8080/rollback/close +`` + If you have notifications enabled, Flagger will post a message to Slack or MS Teams if a canary promotion is waiting for approval.