Implement confirm-promotion hook

The confirm promotion hooks are executed right before the promotion step. The canary promotion is paused until the hooks return HTTP 200. While the promotion is paused, Flagger will continue to run the metrics checks and load tests.
This commit is contained in:
stefanprodan
2019-09-22 13:23:19 +03:00
parent 2b6966d8e3
commit 8282f86d9c
2 changed files with 36 additions and 0 deletions
+2
View File
@@ -139,6 +139,8 @@ const (
PostRolloutHook HookType = "post-rollout"
// ConfirmRolloutHook halt canary analysis until webhook returns HTTP 200
ConfirmRolloutHook HookType = "confirm-rollout"
// ConfirmPromotionHook halt canary promotion until webhook returns HTTP 200
ConfirmPromotionHook HookType = "confirm-promotion"
)
// CanaryWebhook holds the reference to external checks used for canary analysis
+34
View File
@@ -323,6 +323,11 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
return
}
// check promotion gate
if promote := c.runConfirmPromotionHooks(cd); !promote {
return
}
// promote canary - max iterations reached
if cd.Spec.CanaryAnalysis.Iterations == cd.Status.Iterations {
c.recordEventInfof(cd, "Copying %s.%s template spec to %s.%s",
@@ -375,6 +380,11 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
return
}
// check promotion gate
if promote := c.runConfirmPromotionHooks(cd); !promote {
return
}
// route all traffic to canary - max iterations reached
if cd.Spec.CanaryAnalysis.Iterations == cd.Status.Iterations {
if provider != "kubernetes" {
@@ -445,6 +455,13 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
primaryWeight = 100
}
// check promotion gate
if canaryWeight >= maxWeight {
if promote := c.runConfirmPromotionHooks(cd); !promote {
return
}
}
if err := meshRouter.SetRoutes(cd, primaryWeight, canaryWeight); err != nil {
c.recordEventWarningf(cd, "%v", err)
return
@@ -637,6 +654,23 @@ func (c *Controller) runConfirmRolloutHooks(canary *flaggerv1.Canary) bool {
return true
}
func (c *Controller) runConfirmPromotionHooks(canary *flaggerv1.Canary) bool {
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
if webhook.Type == flaggerv1.ConfirmPromotionHook {
err := CallWebhook(canary.Name, canary.Namespace, flaggerv1.CanaryPhaseProgressing, webhook)
if err != nil {
c.recordEventWarningf(canary, "Halt %s.%s advancement waiting for promotion approval %s",
canary.Name, canary.Namespace, webhook.Name)
c.sendNotification(canary, "Canary promotion is waiting for approval.", false, false)
return false
} else {
c.recordEventInfof(canary, "Confirm-promotion check %s passed", webhook.Name)
}
}
}
return true
}
func (c *Controller) runPreRolloutHooks(canary *flaggerv1.Canary) bool {
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
if webhook.Type == flaggerv1.PreRolloutHook {