mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
Deprecate spec.canaryAnalysis replaced by spec.analysis
- add analysis field to Canary spec - deprecate canaryAnalysis filed (to be removed in the next API version) - maintain backwards compatibility with v1alpha3 by using spec.canaryAnalysis if spec.analysis is nil - set analysis threshold default value to 1
This commit is contained in:
@@ -80,8 +80,11 @@ type CanarySpec struct {
|
||||
// Service defines how ClusterIP services, service mesh or ingress routing objects are generated
|
||||
Service CanaryService `json:"service"`
|
||||
|
||||
// CanaryAnalysis defines how the analysis should be performed
|
||||
CanaryAnalysis CanaryAnalysis `json:"canaryAnalysis"`
|
||||
// Analysis defines the validation process of a release
|
||||
Analysis *CanaryAnalysis `json:"analysis,omitempty"`
|
||||
|
||||
// Deprecated: replaced by Analysis
|
||||
CanaryAnalysis *CanaryAnalysis `json:"canaryAnalysis,omitempty"`
|
||||
|
||||
// ProgressDeadlineSeconds represents the maximum time in seconds for a
|
||||
// canary deployment to make progress before it is considered to be failed
|
||||
@@ -352,13 +355,22 @@ func (c *Canary) GetProgressDeadlineSeconds() int {
|
||||
return ProgressDeadlineSeconds
|
||||
}
|
||||
|
||||
// GetAnalysis returns the analysis v1beta1 or v1alpha3
|
||||
// to be removed along with spec.canaryAnalysis in v1
|
||||
func (c *Canary) GetAnalysis() *CanaryAnalysis {
|
||||
if c.Spec.Analysis != nil {
|
||||
return c.Spec.Analysis
|
||||
}
|
||||
return c.Spec.CanaryAnalysis
|
||||
}
|
||||
|
||||
// GetAnalysisInterval returns the canary analysis interval (default 60s)
|
||||
func (c *Canary) GetAnalysisInterval() time.Duration {
|
||||
if c.Spec.CanaryAnalysis.Interval == "" {
|
||||
if c.GetAnalysis().Interval == "" {
|
||||
return AnalysisInterval
|
||||
}
|
||||
|
||||
interval, err := time.ParseDuration(c.Spec.CanaryAnalysis.Interval)
|
||||
interval, err := time.ParseDuration(c.GetAnalysis().Interval)
|
||||
if err != nil {
|
||||
return AnalysisInterval
|
||||
}
|
||||
@@ -370,7 +382,24 @@ func (c *Canary) GetAnalysisInterval() time.Duration {
|
||||
return interval
|
||||
}
|
||||
|
||||
// GetAnalysisThreshold returns the canary threshold (default 1)
|
||||
func (c *Canary) GetAnalysisThreshold() int {
|
||||
if c.GetAnalysis().Threshold > 0 {
|
||||
return c.GetAnalysis().Threshold
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// GetMetricInterval returns the metric interval default value (1m)
|
||||
func (c *Canary) GetMetricInterval() string {
|
||||
return MetricInterval
|
||||
}
|
||||
|
||||
// SkipAnalysis returns true if the analysis is nil
|
||||
// or if spec.SkipAnalysis is true
|
||||
func (c *Canary) SkipAnalysis() bool {
|
||||
if c.Spec.Analysis == nil && c.Spec.CanaryAnalysis == nil {
|
||||
return true
|
||||
}
|
||||
return c.Spec.SkipAnalysis
|
||||
}
|
||||
|
||||
@@ -392,7 +392,16 @@ func (in *CanarySpec) DeepCopyInto(out *CanarySpec) {
|
||||
**out = **in
|
||||
}
|
||||
in.Service.DeepCopyInto(&out.Service)
|
||||
in.CanaryAnalysis.DeepCopyInto(&out.CanaryAnalysis)
|
||||
if in.Analysis != nil {
|
||||
in, out := &in.Analysis, &out.Analysis
|
||||
*out = new(CanaryAnalysis)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CanaryAnalysis != nil {
|
||||
in, out := &in.CanaryAnalysis, &out.CanaryAnalysis
|
||||
*out = new(CanaryAnalysis)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ProgressDeadlineSeconds != nil {
|
||||
in, out := &in.ProgressDeadlineSeconds, &out.ProgressDeadlineSeconds
|
||||
*out = new(int32)
|
||||
|
||||
@@ -91,7 +91,7 @@ func (c *DaemonSetController) Initialize(cd *flaggerv1.Canary, skipLivenessCheck
|
||||
}
|
||||
|
||||
if cd.Status.Phase == "" || cd.Status.Phase == flaggerv1.CanaryPhaseInitializing {
|
||||
if !skipLivenessChecks && !cd.Spec.SkipAnalysis {
|
||||
if !skipLivenessChecks && !cd.SkipAnalysis() {
|
||||
_, readyErr := c.IsPrimaryReady(cd)
|
||||
if readyErr != nil {
|
||||
return readyErr
|
||||
|
||||
@@ -37,7 +37,7 @@ func (c *DeploymentController) Initialize(cd *flaggerv1.Canary, skipLivenessChec
|
||||
}
|
||||
|
||||
if cd.Status.Phase == "" || cd.Status.Phase == flaggerv1.CanaryPhaseInitializing {
|
||||
if !skipLivenessChecks && !cd.Spec.SkipAnalysis {
|
||||
if !skipLivenessChecks && !cd.SkipAnalysis() {
|
||||
_, readyErr := c.IsPrimaryReady(cd)
|
||||
if readyErr != nil {
|
||||
return readyErr
|
||||
|
||||
@@ -207,7 +207,7 @@ func newDeploymentControllerTestCanary() *flaggerv1.Canary {
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
|
||||
+11
-11
@@ -30,8 +30,8 @@ func (c *Controller) recordEventWarningf(r *flaggerv1.Canary, template string, a
|
||||
|
||||
func (c *Controller) sendEventToWebhook(r *flaggerv1.Canary, eventType, template string, args []interface{}) {
|
||||
webhookOverride := false
|
||||
if len(r.Spec.CanaryAnalysis.Webhooks) > 0 {
|
||||
for _, canaryWebhook := range r.Spec.CanaryAnalysis.Webhooks {
|
||||
if len(r.GetAnalysis().Webhooks) > 0 {
|
||||
for _, canaryWebhook := range r.GetAnalysis().Webhooks {
|
||||
if canaryWebhook.Type == flaggerv1.EventHook {
|
||||
webhookOverride = true
|
||||
err := CallEventWebhook(r, canaryWebhook.URL, fmt.Sprintf(template, args...), eventType)
|
||||
@@ -51,7 +51,7 @@ func (c *Controller) sendEventToWebhook(r *flaggerv1.Canary, eventType, template
|
||||
}
|
||||
|
||||
func (c *Controller) alert(canary *flaggerv1.Canary, message string, metadata bool, severity flaggerv1.AlertSeverity) {
|
||||
if c.notifier == nil && len(canary.Spec.CanaryAnalysis.Alerts) == 0 {
|
||||
if c.notifier == nil && len(canary.GetAnalysis().Alerts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func (c *Controller) alert(canary *flaggerv1.Canary, message string, metadata bo
|
||||
}
|
||||
|
||||
// send alert with the global notifier
|
||||
if len(canary.Spec.CanaryAnalysis.Alerts) == 0 {
|
||||
if len(canary.GetAnalysis().Alerts) == 0 {
|
||||
err := c.notifier.Post(canary.Name, canary.Namespace, message, fields, string(severity))
|
||||
if err != nil {
|
||||
c.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
|
||||
@@ -72,7 +72,7 @@ func (c *Controller) alert(canary *flaggerv1.Canary, message string, metadata bo
|
||||
}
|
||||
|
||||
// send canary alerts
|
||||
for _, alert := range canary.Spec.CanaryAnalysis.Alerts {
|
||||
for _, alert := range canary.GetAnalysis().Alerts {
|
||||
// determine if alert should be sent based on severity level
|
||||
shouldAlert := false
|
||||
if alert.Severity == flaggerv1.SeverityInfo {
|
||||
@@ -161,7 +161,7 @@ func alertMetadata(canary *flaggerv1.Canary) []notifier.Field {
|
||||
},
|
||||
notifier.Field{
|
||||
Name: "Failed checks threshold",
|
||||
Value: fmt.Sprintf("%v", canary.Spec.CanaryAnalysis.Threshold),
|
||||
Value: fmt.Sprintf("%v", canary.GetAnalysisThreshold()),
|
||||
},
|
||||
notifier.Field{
|
||||
Name: "Progress deadline",
|
||||
@@ -169,19 +169,19 @@ func alertMetadata(canary *flaggerv1.Canary) []notifier.Field {
|
||||
},
|
||||
)
|
||||
|
||||
if canary.Spec.CanaryAnalysis.StepWeight > 0 {
|
||||
if canary.GetAnalysis().StepWeight > 0 {
|
||||
fields = append(fields, notifier.Field{
|
||||
Name: "Traffic routing",
|
||||
Value: fmt.Sprintf("Weight step: %v max: %v",
|
||||
canary.Spec.CanaryAnalysis.StepWeight,
|
||||
canary.Spec.CanaryAnalysis.MaxWeight),
|
||||
canary.GetAnalysis().StepWeight,
|
||||
canary.GetAnalysis().MaxWeight),
|
||||
})
|
||||
} else if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
} else if len(canary.GetAnalysis().Match) > 0 {
|
||||
fields = append(fields, notifier.Field{
|
||||
Name: "Traffic routing",
|
||||
Value: "A/B Testing",
|
||||
})
|
||||
} else if canary.Spec.CanaryAnalysis.Iterations > 0 {
|
||||
} else if canary.GetAnalysis().Iterations > 0 {
|
||||
fields = append(fields, notifier.Field{
|
||||
Name: "Traffic routing",
|
||||
Value: "Blue/Green",
|
||||
|
||||
+36
-36
@@ -157,12 +157,12 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
|
||||
// set max weight default value to 100%
|
||||
maxWeight := 100
|
||||
if cd.Spec.CanaryAnalysis.MaxWeight > 0 {
|
||||
maxWeight = cd.Spec.CanaryAnalysis.MaxWeight
|
||||
if cd.GetAnalysis().MaxWeight > 0 {
|
||||
maxWeight = cd.GetAnalysis().MaxWeight
|
||||
}
|
||||
|
||||
// check primary status
|
||||
if !skipLivenessChecks && !cd.Spec.SkipAnalysis {
|
||||
if !skipLivenessChecks && !cd.SkipAnalysis() {
|
||||
if _, err := canaryController.IsPrimaryReady(cd); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
@@ -278,7 +278,7 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
|
||||
// check if the number of failed checks reached the threshold
|
||||
if cd.Status.Phase == flaggerv1.CanaryPhaseProgressing &&
|
||||
(!retriable || cd.Status.FailedChecks >= cd.Spec.CanaryAnalysis.Threshold) {
|
||||
(!retriable || cd.Status.FailedChecks >= cd.GetAnalysisThreshold()) {
|
||||
if !retriable {
|
||||
c.recordEventWarningf(cd, "Rolling back %s.%s progress deadline exceeded %v",
|
||||
cd.Name, cd.Namespace, err)
|
||||
@@ -297,7 +297,7 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
// check if the canary success rate is above the threshold
|
||||
// skip check if no traffic is routed or mirrored to canary
|
||||
if canaryWeight == 0 && cd.Status.Iterations == 0 &&
|
||||
(cd.Spec.CanaryAnalysis.Mirror == false || mirrored == false) {
|
||||
(cd.GetAnalysis().Mirror == false || mirrored == false) {
|
||||
c.recordEventInfof(cd, "Starting canary analysis for %s.%s", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
|
||||
// run pre-rollout web hooks
|
||||
@@ -320,31 +320,31 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
|
||||
// use blue/green strategy for kubernetes provider
|
||||
if provider == "kubernetes" {
|
||||
if len(cd.Spec.CanaryAnalysis.Match) > 0 {
|
||||
if len(cd.GetAnalysis().Match) > 0 {
|
||||
c.recordEventWarningf(cd, "A/B testing is not supported when using the kubernetes provider")
|
||||
cd.Spec.CanaryAnalysis.Match = nil
|
||||
cd.GetAnalysis().Match = nil
|
||||
}
|
||||
if cd.Spec.CanaryAnalysis.Iterations < 1 {
|
||||
if cd.GetAnalysis().Iterations < 1 {
|
||||
c.recordEventWarningf(cd, "Progressive traffic is not supported when using the kubernetes provider")
|
||||
c.recordEventWarningf(cd, "Setting canaryAnalysis.iterations: 10")
|
||||
cd.Spec.CanaryAnalysis.Iterations = 10
|
||||
cd.GetAnalysis().Iterations = 10
|
||||
}
|
||||
}
|
||||
|
||||
// strategy: A/B testing
|
||||
if len(cd.Spec.CanaryAnalysis.Match) > 0 && cd.Spec.CanaryAnalysis.Iterations > 0 {
|
||||
if len(cd.GetAnalysis().Match) > 0 && cd.GetAnalysis().Iterations > 0 {
|
||||
c.runAB(cd, canaryController, meshRouter, provider)
|
||||
return
|
||||
}
|
||||
|
||||
// strategy: Blue/Green
|
||||
if cd.Spec.CanaryAnalysis.Iterations > 0 {
|
||||
if cd.GetAnalysis().Iterations > 0 {
|
||||
c.runBlueGreen(cd, canaryController, meshRouter, provider, mirrored)
|
||||
return
|
||||
}
|
||||
|
||||
// strategy: Canary progressive traffic increase
|
||||
if cd.Spec.CanaryAnalysis.StepWeight > 0 {
|
||||
if cd.GetAnalysis().StepWeight > 0 {
|
||||
c.runCanary(cd, canaryController, meshRouter, provider, mirrored, canaryWeight, primaryWeight, maxWeight)
|
||||
}
|
||||
|
||||
@@ -358,25 +358,25 @@ func (c *Controller) runCanary(canary *flaggerv1.Canary, canaryController canary
|
||||
// If in "mirror" mode, do one step of mirroring before shifting traffic to canary.
|
||||
// When mirroring, all requests go to primary and canary, but only responses from
|
||||
// primary go back to the user.
|
||||
if canary.Spec.CanaryAnalysis.Mirror && canaryWeight == 0 {
|
||||
if canary.GetAnalysis().Mirror && canaryWeight == 0 {
|
||||
if mirrored == false {
|
||||
mirrored = true
|
||||
primaryWeight = 100
|
||||
canaryWeight = 0
|
||||
} else {
|
||||
mirrored = false
|
||||
primaryWeight = 100 - canary.Spec.CanaryAnalysis.StepWeight
|
||||
canaryWeight = canary.Spec.CanaryAnalysis.StepWeight
|
||||
primaryWeight = 100 - canary.GetAnalysis().StepWeight
|
||||
canaryWeight = canary.GetAnalysis().StepWeight
|
||||
}
|
||||
c.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
|
||||
Infof("Running mirror step %d/%d/%t", primaryWeight, canaryWeight, mirrored)
|
||||
} else {
|
||||
|
||||
primaryWeight -= canary.Spec.CanaryAnalysis.StepWeight
|
||||
primaryWeight -= canary.GetAnalysis().StepWeight
|
||||
if primaryWeight < 0 {
|
||||
primaryWeight = 0
|
||||
}
|
||||
canaryWeight += canary.Spec.CanaryAnalysis.StepWeight
|
||||
canaryWeight += canary.GetAnalysis().StepWeight
|
||||
if canaryWeight > 100 {
|
||||
canaryWeight = 100
|
||||
}
|
||||
@@ -424,7 +424,7 @@ func (c *Controller) runAB(canary *flaggerv1.Canary, canaryController canary.Con
|
||||
primaryName := fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name)
|
||||
|
||||
// route traffic to canary and increment iterations
|
||||
if canary.Spec.CanaryAnalysis.Iterations > canary.Status.Iterations {
|
||||
if canary.GetAnalysis().Iterations > canary.Status.Iterations {
|
||||
if err := meshRouter.SetRoutes(canary, 0, 100, false); err != nil {
|
||||
c.recordEventWarningf(canary, "%v", err)
|
||||
return
|
||||
@@ -436,7 +436,7 @@ func (c *Controller) runAB(canary *flaggerv1.Canary, canaryController canary.Con
|
||||
return
|
||||
}
|
||||
c.recordEventInfof(canary, "Advance %s.%s canary iteration %v/%v",
|
||||
canary.Name, canary.Namespace, canary.Status.Iterations+1, canary.Spec.CanaryAnalysis.Iterations)
|
||||
canary.Name, canary.Namespace, canary.Status.Iterations+1, canary.GetAnalysis().Iterations)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ func (c *Controller) runAB(canary *flaggerv1.Canary, canaryController canary.Con
|
||||
}
|
||||
|
||||
// promote canary - max iterations reached
|
||||
if canary.Spec.CanaryAnalysis.Iterations == canary.Status.Iterations {
|
||||
if canary.GetAnalysis().Iterations == canary.Status.Iterations {
|
||||
c.recordEventInfof(canary, "Copying %s.%s template spec to %s.%s",
|
||||
canary.Spec.TargetRef.Name, canary.Namespace, primaryName, canary.Namespace)
|
||||
if err := canaryController.Promote(canary); err != nil {
|
||||
@@ -466,10 +466,10 @@ func (c *Controller) runBlueGreen(canary *flaggerv1.Canary, canaryController can
|
||||
primaryName := fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name)
|
||||
|
||||
// increment iterations
|
||||
if canary.Spec.CanaryAnalysis.Iterations > canary.Status.Iterations {
|
||||
if canary.GetAnalysis().Iterations > canary.Status.Iterations {
|
||||
// If in "mirror" mode, mirror requests during the entire B/G canary test
|
||||
if provider != "kubernetes" &&
|
||||
canary.Spec.CanaryAnalysis.Mirror == true && mirrored == false {
|
||||
canary.GetAnalysis().Mirror == true && mirrored == false {
|
||||
if err := meshRouter.SetRoutes(canary, 100, 0, true); err != nil {
|
||||
c.recordEventWarningf(canary, "%v", err)
|
||||
}
|
||||
@@ -481,7 +481,7 @@ func (c *Controller) runBlueGreen(canary *flaggerv1.Canary, canaryController can
|
||||
return
|
||||
}
|
||||
c.recordEventInfof(canary, "Advance %s.%s canary iteration %v/%v",
|
||||
canary.Name, canary.Namespace, canary.Status.Iterations+1, canary.Spec.CanaryAnalysis.Iterations)
|
||||
canary.Name, canary.Namespace, canary.Status.Iterations+1, canary.GetAnalysis().Iterations)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -491,9 +491,9 @@ func (c *Controller) runBlueGreen(canary *flaggerv1.Canary, canaryController can
|
||||
}
|
||||
|
||||
// route all traffic to canary - max iterations reached
|
||||
if canary.Spec.CanaryAnalysis.Iterations == canary.Status.Iterations {
|
||||
if canary.GetAnalysis().Iterations == canary.Status.Iterations {
|
||||
if provider != "kubernetes" {
|
||||
if canary.Spec.CanaryAnalysis.Mirror {
|
||||
if canary.GetAnalysis().Mirror {
|
||||
c.recordEventInfof(canary, "Stop traffic mirroring and route all traffic to canary")
|
||||
} else {
|
||||
c.recordEventInfof(canary, "Routing all traffic to canary")
|
||||
@@ -514,7 +514,7 @@ func (c *Controller) runBlueGreen(canary *flaggerv1.Canary, canaryController can
|
||||
}
|
||||
|
||||
// promote canary - max iterations reached
|
||||
if canary.Spec.CanaryAnalysis.Iterations < canary.Status.Iterations {
|
||||
if canary.GetAnalysis().Iterations < canary.Status.Iterations {
|
||||
c.recordEventInfof(canary, "Copying %s.%s template spec to %s.%s",
|
||||
canary.Spec.TargetRef.Name, canary.Namespace, primaryName, canary.Namespace)
|
||||
if err := canaryController.Promote(canary); err != nil {
|
||||
@@ -532,7 +532,7 @@ func (c *Controller) runBlueGreen(canary *flaggerv1.Canary, canaryController can
|
||||
}
|
||||
|
||||
func (c *Controller) shouldSkipAnalysis(canary *flaggerv1.Canary, canaryController canary.Controller, meshRouter router.Interface, primaryWeight int, canaryWeight int) bool {
|
||||
if !canary.Spec.SkipAnalysis {
|
||||
if !canary.SkipAnalysis() {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ func (c *Controller) hasCanaryRevisionChanged(canary *flaggerv1.Canary, canaryCo
|
||||
}
|
||||
|
||||
func (c *Controller) runConfirmRolloutHooks(canary *flaggerv1.Canary, canaryController canary.Controller) bool {
|
||||
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
|
||||
for _, webhook := range canary.GetAnalysis().Webhooks {
|
||||
if webhook.Type == flaggerv1.ConfirmRolloutHook {
|
||||
err := CallWebhook(canary.Name, canary.Namespace, flaggerv1.CanaryPhaseProgressing, webhook)
|
||||
if err != nil {
|
||||
@@ -685,7 +685,7 @@ func (c *Controller) runConfirmRolloutHooks(canary *flaggerv1.Canary, canaryCont
|
||||
}
|
||||
|
||||
func (c *Controller) runConfirmPromotionHooks(canary *flaggerv1.Canary) bool {
|
||||
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
|
||||
for _, webhook := range canary.GetAnalysis().Webhooks {
|
||||
if webhook.Type == flaggerv1.ConfirmPromotionHook {
|
||||
err := CallWebhook(canary.Name, canary.Namespace, flaggerv1.CanaryPhaseProgressing, webhook)
|
||||
if err != nil {
|
||||
@@ -702,7 +702,7 @@ func (c *Controller) runConfirmPromotionHooks(canary *flaggerv1.Canary) bool {
|
||||
}
|
||||
|
||||
func (c *Controller) runPreRolloutHooks(canary *flaggerv1.Canary) bool {
|
||||
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
|
||||
for _, webhook := range canary.GetAnalysis().Webhooks {
|
||||
if webhook.Type == flaggerv1.PreRolloutHook {
|
||||
err := CallWebhook(canary.Name, canary.Namespace, flaggerv1.CanaryPhaseProgressing, webhook)
|
||||
if err != nil {
|
||||
@@ -718,7 +718,7 @@ func (c *Controller) runPreRolloutHooks(canary *flaggerv1.Canary) bool {
|
||||
}
|
||||
|
||||
func (c *Controller) runPostRolloutHooks(canary *flaggerv1.Canary, phase flaggerv1.CanaryPhase) bool {
|
||||
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
|
||||
for _, webhook := range canary.GetAnalysis().Webhooks {
|
||||
if webhook.Type == flaggerv1.PostRolloutHook {
|
||||
err := CallWebhook(canary.Name, canary.Namespace, phase, webhook)
|
||||
if err != nil {
|
||||
@@ -733,7 +733,7 @@ func (c *Controller) runPostRolloutHooks(canary *flaggerv1.Canary, phase flagger
|
||||
}
|
||||
|
||||
func (c *Controller) runRollbackHooks(canary *flaggerv1.Canary, phase flaggerv1.CanaryPhase) bool {
|
||||
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
|
||||
for _, webhook := range canary.GetAnalysis().Webhooks {
|
||||
if webhook.Type == flaggerv1.RollbackHook {
|
||||
err := CallWebhook(canary.Name, canary.Namespace, phase, webhook)
|
||||
if err != nil {
|
||||
@@ -749,7 +749,7 @@ func (c *Controller) runRollbackHooks(canary *flaggerv1.Canary, phase flaggerv1.
|
||||
|
||||
func (c *Controller) runAnalysis(canary *flaggerv1.Canary) bool {
|
||||
// run external checks
|
||||
for _, webhook := range canary.Spec.CanaryAnalysis.Webhooks {
|
||||
for _, webhook := range canary.GetAnalysis().Webhooks {
|
||||
if webhook.Type == "" || webhook.Type == flaggerv1.RolloutHook {
|
||||
err := CallWebhook(canary.Name, canary.Namespace, flaggerv1.CanaryPhaseProgressing, webhook)
|
||||
if err != nil {
|
||||
@@ -812,7 +812,7 @@ func (c *Controller) runBuiltinMetricChecks(canary *flaggerv1.Canary) bool {
|
||||
observer := observerFactory.Observer(metricsProvider)
|
||||
|
||||
// run metrics checks
|
||||
for _, metric := range canary.Spec.CanaryAnalysis.Metrics {
|
||||
for _, metric := range canary.GetAnalysis().Metrics {
|
||||
if metric.Interval == "" {
|
||||
metric.Interval = canary.GetMetricInterval()
|
||||
}
|
||||
@@ -914,7 +914,7 @@ func (c *Controller) runBuiltinMetricChecks(canary *flaggerv1.Canary) bool {
|
||||
}
|
||||
|
||||
func (c *Controller) runMetricChecks(canary *flaggerv1.Canary) bool {
|
||||
for _, metric := range canary.Spec.CanaryAnalysis.Metrics {
|
||||
for _, metric := range canary.GetAnalysis().Metrics {
|
||||
if metric.TemplateRef != nil {
|
||||
namespace := canary.Namespace
|
||||
if metric.TemplateRef.Namespace != "" {
|
||||
@@ -1007,7 +1007,7 @@ func toMetricModel(r *flaggerv1.Canary, interval string) flaggerv1.MetricTemplat
|
||||
}
|
||||
|
||||
func (c *Controller) rollback(canary *flaggerv1.Canary, canaryController canary.Controller, meshRouter router.Interface) {
|
||||
if canary.Status.FailedChecks >= canary.Spec.CanaryAnalysis.Threshold {
|
||||
if canary.Status.FailedChecks >= canary.GetAnalysisThreshold() {
|
||||
c.recordEventWarningf(canary, "Rolling back %s.%s failed checks threshold reached %v",
|
||||
canary.Name, canary.Namespace, canary.Status.FailedChecks)
|
||||
c.alert(canary, fmt.Sprintf("Failed checks threshold reached %v", canary.Status.FailedChecks),
|
||||
|
||||
@@ -250,7 +250,7 @@ func newDaemonSetTestCanary() *flaggerv1.Canary {
|
||||
Kind: "DaemonSet",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
@@ -307,7 +307,7 @@ func newDaemonSetTestCanaryAB() *flaggerv1.Canary {
|
||||
Kind: "DaemonSet",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
Iterations: 10,
|
||||
Match: []istiov1alpha3.HTTPMatchRequest{
|
||||
|
||||
@@ -257,7 +257,7 @@ func newDeploymentTestCanary() *flaggerv1.Canary {
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
@@ -319,7 +319,7 @@ func newDeploymentTestCanaryAB() *flaggerv1.Canary {
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
Iterations: 10,
|
||||
Match: []istiov1alpha3.HTTPMatchRequest{
|
||||
|
||||
@@ -142,7 +142,7 @@ func newTestServiceCanary() *flaggerv1.Canary {
|
||||
Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
},
|
||||
CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
|
||||
@@ -203,7 +203,7 @@ func (ar *AppMeshRouter) reconcileVirtualService(canary *flaggerv1.Canary, name
|
||||
}
|
||||
|
||||
// A/B testing - header based routing
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 && canaryWeight == 0 {
|
||||
if len(canary.GetAnalysis().Match) > 0 && canaryWeight == 0 {
|
||||
routes = []appmeshv1.Route{
|
||||
{
|
||||
Name: fmt.Sprintf("%s-a", apexName),
|
||||
@@ -451,7 +451,7 @@ func makeRetryPolicy(canary *flaggerv1.Canary) *appmeshv1.HttpRetryPolicy {
|
||||
func (ar *AppMeshRouter) makeHeaders(canary *flaggerv1.Canary) []appmeshv1.HttpRouteHeader {
|
||||
headers := []appmeshv1.HttpRouteHeader{}
|
||||
|
||||
for _, m := range canary.Spec.CanaryAnalysis.Match {
|
||||
for _, m := range canary.GetAnalysis().Match {
|
||||
for key, value := range m.Headers {
|
||||
header := appmeshv1.HttpRouteHeader{
|
||||
Name: key,
|
||||
|
||||
@@ -64,7 +64,7 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error {
|
||||
},
|
||||
}
|
||||
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
newSpec = contourv1.HTTPProxySpec{
|
||||
Routes: []contourv1.Route{
|
||||
{
|
||||
@@ -277,7 +277,7 @@ func (cr *ContourRouter) SetRoutes(
|
||||
},
|
||||
}
|
||||
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
proxy.Spec = contourv1.HTTPProxySpec{
|
||||
Routes: []contourv1.Route{
|
||||
{
|
||||
@@ -364,8 +364,8 @@ func (cr *ContourRouter) makePrefix(canary *flaggerv1.Canary) string {
|
||||
func (cr *ContourRouter) makeConditions(canary *flaggerv1.Canary) []contourv1.Condition {
|
||||
list := []contourv1.Condition{}
|
||||
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
for _, match := range canary.Spec.CanaryAnalysis.Match {
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
for _, match := range canary.GetAnalysis().Match {
|
||||
for s, stringMatch := range match.Headers {
|
||||
h := &contourv1.HeaderCondition{
|
||||
Name: s,
|
||||
|
||||
@@ -117,7 +117,7 @@ func (i *IngressRouter) GetRoutes(canary *flaggerv1.Canary) (
|
||||
}
|
||||
|
||||
// A/B testing
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
for k := range canaryIngress.Annotations {
|
||||
if k == i.GetAnnotationWithPrefix("canary-by-cookie") || k == i.GetAnnotationWithPrefix("canary-by-header") {
|
||||
return 0, 100, false, nil
|
||||
@@ -158,11 +158,11 @@ func (i *IngressRouter) SetRoutes(
|
||||
iClone := canaryIngress.DeepCopy()
|
||||
|
||||
// A/B testing
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
cookie := ""
|
||||
header := ""
|
||||
headerValue := ""
|
||||
for _, m := range canary.Spec.CanaryAnalysis.Match {
|
||||
for _, m := range canary.GetAnalysis().Match {
|
||||
for k, v := range m.Headers {
|
||||
if k == "cookie" {
|
||||
cookie = v.Exact
|
||||
|
||||
+4
-4
@@ -152,8 +152,8 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
|
||||
},
|
||||
}
|
||||
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
canaryMatch := mergeMatchConditions(canary.Spec.CanaryAnalysis.Match, canary.Spec.Service.Match)
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
canaryMatch := mergeMatchConditions(canary.GetAnalysis().Match, canary.Spec.Service.Match)
|
||||
newSpec.Http = []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Match: canaryMatch,
|
||||
@@ -323,9 +323,9 @@ func (ir *IstioRouter) SetRoutes(
|
||||
}
|
||||
|
||||
// fix routing (A/B testing)
|
||||
if len(canary.Spec.CanaryAnalysis.Match) > 0 {
|
||||
if len(canary.GetAnalysis().Match) > 0 {
|
||||
// merge the common routes with the canary ones
|
||||
canaryMatch := mergeMatchConditions(canary.Spec.CanaryAnalysis.Match, canary.Spec.Service.Match)
|
||||
canaryMatch := mergeMatchConditions(canary.GetAnalysis().Match, canary.Spec.Service.Match)
|
||||
vsCopy.Spec.Http = []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Match: canaryMatch,
|
||||
|
||||
@@ -112,7 +112,7 @@ func newTestCanary() *flaggerv1.Canary {
|
||||
"public-gateway.istio",
|
||||
"mesh",
|
||||
},
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
@@ -158,7 +158,7 @@ func newTestCanaryAppMesh() *flaggerv1.Canary {
|
||||
PerTryTimeout: "gateway-error",
|
||||
RetryOn: "5s",
|
||||
},
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
@@ -203,7 +203,7 @@ func newTestSMICanary() *flaggerv1.Canary {
|
||||
},
|
||||
PortDiscovery: true,
|
||||
},
|
||||
CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
@@ -227,7 +227,7 @@ func newTestSMICanary() *flaggerv1.Canary {
|
||||
|
||||
func newTestMirror() *flaggerv1.Canary {
|
||||
cd := newTestCanary()
|
||||
cd.Spec.CanaryAnalysis.Mirror = true
|
||||
cd.GetAnalysis().Mirror = true
|
||||
return cd
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ func newTestABTest() *flaggerv1.Canary {
|
||||
Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
MeshName: "global",
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
Iterations: 2,
|
||||
Match: []istiov1alpha3.HTTPMatchRequest{
|
||||
@@ -397,7 +397,7 @@ func newTestCanaryIngress() *flaggerv1.Canary {
|
||||
},
|
||||
Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
}, CanaryAnalysis: &flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
|
||||
Reference in New Issue
Block a user