Skip to content

Commit 91ef812

Browse files
authored
Merge pull request #449 from ta924/loadtesterRollbackSupport
Add support for rollback gating in tester API
2 parents 7f9cc30 + 34ed690 commit 91ef812

File tree

2 files changed

+97
-3
lines changed

2 files changed

+97
-3
lines changed

docs/gitbook/how-it-works.md

+18-3
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ Spec:
589589
some: "message"
590590
- name: "rollback gate"
591591
type: rollback
592-
url: http://flagger-loadtester.test/gate/halt
592+
url: http://flagger-loadtester.test/rollback/check
593593
- name: "send to Slack"
594594
type: event
595595
url: http://event-recevier.notifications/slack
@@ -908,14 +908,29 @@ While the promotion is paused, Flagger will continue to run the metrics checks a
908908
url: http://flagger-loadtester.test/gate/halt
909909
```
910910

911-
The `rollback` hook type can be used to manually rollback the canary promotion.
911+
The `rollback` hook type can be used to manually rollback the canary promotion. As with gating, rollbacks can be driven
912+
with Flagger's tester API by setting the rollback URL to `/rollback/check`
912913

913914
```yaml
914915
canaryAnalysis:
915916
webhooks:
916917
- name: "rollback"
917918
type: rollback
918-
url: http://flagger-loadtester.test/gate/halt
919+
url: http://flagger-loadtester.test/rollback/check
919920
```
920921

922+
By default rollback is closed, you can rollback a canary rollout with:
923+
924+
```bash
925+
kubectl -n test exec -it flagger-loadtester-xxxx-xxxx sh
926+
927+
curl -d '{"name": "podinfo","namespace":"test"}' http://localhost:8080/rollback/open
928+
```
929+
930+
You can close the rollback with:
931+
932+
```bash
933+
curl -d '{"name": "podinfo","namespace":"test"}' http://localhost:8080/rollback/close
934+
``
935+
921936
If you have notifications enabled, Flagger will post a message to Slack or MS Teams if a canary promotion is waiting for approval.

pkg/loadtester/server.go

+79
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,85 @@ func ListenAndServe(port string, timeout time.Duration, logger *zap.SugaredLogge
109109
logger.Infof("%s gate closed", canaryName)
110110
})
111111

112+
mux.HandleFunc("/rollback/check", func(w http.ResponseWriter, r *http.Request) {
113+
body, err := ioutil.ReadAll(r.Body)
114+
if err != nil {
115+
logger.Error("reading the request body failed", zap.Error(err))
116+
w.WriteHeader(http.StatusBadRequest)
117+
return
118+
}
119+
defer r.Body.Close()
120+
121+
canary := &flaggerv1.CanaryWebhookPayload{}
122+
err = json.Unmarshal(body, canary)
123+
if err != nil {
124+
logger.Error("decoding the request body failed", zap.Error(err))
125+
w.WriteHeader(http.StatusBadRequest)
126+
return
127+
}
128+
129+
canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace)
130+
approved := gate.isOpen(canaryName)
131+
if approved {
132+
w.WriteHeader(http.StatusOK)
133+
w.Write([]byte("Approved"))
134+
} else {
135+
w.WriteHeader(http.StatusForbidden)
136+
w.Write([]byte("Forbidden"))
137+
}
138+
139+
logger.Infof("%s rollback check: approved %v", canaryName, approved)
140+
})
141+
mux.HandleFunc("/rollback/open", func(w http.ResponseWriter, r *http.Request) {
142+
body, err := ioutil.ReadAll(r.Body)
143+
if err != nil {
144+
logger.Error("reading the request body failed", zap.Error(err))
145+
w.WriteHeader(http.StatusBadRequest)
146+
return
147+
}
148+
defer r.Body.Close()
149+
150+
canary := &flaggerv1.CanaryWebhookPayload{}
151+
err = json.Unmarshal(body, canary)
152+
if err != nil {
153+
logger.Error("decoding the request body failed", zap.Error(err))
154+
w.WriteHeader(http.StatusBadRequest)
155+
return
156+
}
157+
158+
canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace)
159+
gate.open(canaryName)
160+
161+
w.WriteHeader(http.StatusAccepted)
162+
163+
logger.Infof("%s rollback opened", canaryName)
164+
})
165+
mux.HandleFunc("/rollback/close", func(w http.ResponseWriter, r *http.Request) {
166+
body, err := ioutil.ReadAll(r.Body)
167+
if err != nil {
168+
logger.Error("reading the request body failed", zap.Error(err))
169+
w.WriteHeader(http.StatusBadRequest)
170+
return
171+
}
172+
defer r.Body.Close()
173+
174+
canary := &flaggerv1.CanaryWebhookPayload{}
175+
err = json.Unmarshal(body, canary)
176+
if err != nil {
177+
logger.Error("decoding the request body failed", zap.Error(err))
178+
w.WriteHeader(http.StatusBadRequest)
179+
return
180+
}
181+
182+
183+
canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace)
184+
gate.close(canaryName)
185+
186+
w.WriteHeader(http.StatusAccepted)
187+
188+
logger.Infof("%s rollback closed", canaryName)
189+
})
190+
112191
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
113192
body, err := ioutil.ReadAll(r.Body)
114193
if err != nil {

0 commit comments

Comments
 (0)