Merge pull request #463 from weaveworks/analysis-v1beta1

Rename spec.canaryAnalysis to spec.analysis
This commit is contained in:
Stefan Prodan
2020-02-28 13:18:48 +02:00
committed by GitHub
42 changed files with 335 additions and 147 deletions
+2 -2
View File
@@ -14,8 +14,8 @@ jobs:
name: Run go mod download
command: go mod download
- run:
name: Run go fmt
command: make test-fmt
name: Check code formatting
command: go install golang.org/x/tools/cmd/goimports && make test-fmt
- run:
name: Build Flagger
command: |
+4 -3
View File
@@ -2,7 +2,6 @@ TAG?=latest
VERSION?=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"')
VERSION_MINOR:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"' | rev | cut -d'.' -f2- | rev)
PATCH:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"' | awk -F. '{print $$NF}')
SOURCE_DIRS = cmd pkg/apis pkg/controller pkg/server pkg/canary pkg/metrics pkg/router pkg/notifier
LT_VERSION?=$(shell grep 'VERSION' cmd/loadtester/main.go | awk '{ print $$4 }' | tr -d '"' | head -n1)
TS=$(shell date +%Y-%m-%d_%H-%M-%S)
@@ -43,10 +42,12 @@ push:
docker push weaveworks/flagger:$(VERSION)
fmt:
gofmt -l -s -w $(SOURCE_DIRS)
gofmt -l -s -w ./
goimports -l -w ./
test-fmt:
gofmt -l -s $(SOURCE_DIRS) | grep ".*\.go"; if [ "$$?" = "0" ]; then exit 1; fi
gofmt -l -s ./ | grep ".*\.go"; if [ "$$?" = "0" ]; then exit 1; fi
goimports -l ./ | grep ".*\.go"; if [ "$$?" = "0" ]; then exit 1; fi
test-codegen:
./hack/verify-codegen.sh
+10 -7
View File
@@ -42,19 +42,19 @@ spec:
priority: 1
- name: Interval
type: string
JSONPath: .spec.canaryAnalysis.interval
JSONPath: .spec.analysis.interval
priority: 1
- name: Mirror
type: boolean
JSONPath: .spec.canaryAnalysis.mirror
JSONPath: .spec.analysis.mirror
priority: 1
- name: StepWeight
type: string
JSONPath: .spec.canaryAnalysis.stepWeight
JSONPath: .spec.analysis.stepWeight
priority: 1
- name: MaxWeight
type: string
JSONPath: .spec.canaryAnalysis.maxWeight
JSONPath: .spec.analysis.maxWeight
priority: 1
- name: LastTransitionTime
type: string
@@ -66,7 +66,7 @@ spec:
required:
- targetRef
- service
- canaryAnalysis
- analysis
properties:
provider:
description: Traffic managent provider
@@ -502,9 +502,12 @@ spec:
skipAnalysis:
description: Skip analysis and promote canary
type: boolean
canaryAnalysis:
analysis:
description: Canary analysis for this canary
type: object
oneOf:
- required: ["interval", "threshold", "iterations"]
- required: ["interval", "threshold", "stepWeight"]
properties:
interval:
description: Schedule interval for this canary
@@ -523,7 +526,7 @@ spec:
description: Incremental traffic percentage step
type: number
mirror:
description: Mirror traffic to canary before shifting
description: Mirror traffic to canary
type: boolean
match:
description: A/B testing match conditions
+10 -7
View File
@@ -42,19 +42,19 @@ spec:
priority: 1
- name: Interval
type: string
JSONPath: .spec.canaryAnalysis.interval
JSONPath: .spec.analysis.interval
priority: 1
- name: Mirror
type: boolean
JSONPath: .spec.canaryAnalysis.mirror
JSONPath: .spec.analysis.mirror
priority: 1
- name: StepWeight
type: string
JSONPath: .spec.canaryAnalysis.stepWeight
JSONPath: .spec.analysis.stepWeight
priority: 1
- name: MaxWeight
type: string
JSONPath: .spec.canaryAnalysis.maxWeight
JSONPath: .spec.analysis.maxWeight
priority: 1
- name: LastTransitionTime
type: string
@@ -66,7 +66,7 @@ spec:
required:
- targetRef
- service
- canaryAnalysis
- analysis
properties:
provider:
description: Traffic managent provider
@@ -502,9 +502,12 @@ spec:
skipAnalysis:
description: Skip analysis and promote canary
type: boolean
canaryAnalysis:
analysis:
description: Canary analysis for this canary
type: object
oneOf:
- required: ["interval", "threshold", "iterations"]
- required: ["interval", "threshold", "stepWeight"]
properties:
interval:
description: Schedule interval for this canary
@@ -523,7 +526,7 @@ spec:
description: Incremental traffic percentage step
type: number
mirror:
description: Mirror traffic to canary before shifting
description: Mirror traffic to canary
type: boolean
match:
description: A/B testing match conditions
+3 -2
View File
@@ -2,12 +2,13 @@ package main
import (
"flag"
"log"
"time"
"github.com/weaveworks/flagger/pkg/loadtester"
"github.com/weaveworks/flagger/pkg/logger"
"github.com/weaveworks/flagger/pkg/signals"
"go.uber.org/zap"
"log"
"time"
)
var VERSION = "0.12.1"
+10 -7
View File
@@ -42,19 +42,19 @@ spec:
priority: 1
- name: Interval
type: string
JSONPath: .spec.canaryAnalysis.interval
JSONPath: .spec.analysis.interval
priority: 1
- name: Mirror
type: boolean
JSONPath: .spec.canaryAnalysis.mirror
JSONPath: .spec.analysis.mirror
priority: 1
- name: StepWeight
type: string
JSONPath: .spec.canaryAnalysis.stepWeight
JSONPath: .spec.analysis.stepWeight
priority: 1
- name: MaxWeight
type: string
JSONPath: .spec.canaryAnalysis.maxWeight
JSONPath: .spec.analysis.maxWeight
priority: 1
- name: LastTransitionTime
type: string
@@ -66,7 +66,7 @@ spec:
required:
- targetRef
- service
- canaryAnalysis
- analysis
properties:
provider:
description: Traffic managent provider
@@ -502,9 +502,12 @@ spec:
skipAnalysis:
description: Skip analysis and promote canary
type: boolean
canaryAnalysis:
analysis:
description: Canary analysis for this canary
type: object
oneOf:
- required: ["interval", "threshold", "iterations"]
- required: ["interval", "threshold", "stepWeight"]
properties:
interval:
description: Schedule interval for this canary
@@ -523,7 +526,7 @@ spec:
description: Incremental traffic percentage step
type: number
mirror:
description: Mirror traffic to canary before shifting
description: Mirror traffic to canary
type: boolean
match:
description: A/B testing match conditions
+33 -4
View File
@@ -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)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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,
+12 -11
View File
@@ -2,6 +2,7 @@ package controller
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
@@ -30,8 +31,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 +52,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 +62,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 +73,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 +162,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 +170,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
View File
@@ -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),
+21
View File
@@ -1,5 +1,26 @@
package controller
import (
"fmt"
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
clientset "github.com/weaveworks/flagger/pkg/client/clientset/versioned"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func assertPhase(flaggerClient clientset.Interface, canary string, phase flaggerv1.CanaryPhase) error {
c, err := flaggerClient.FlaggerV1beta1().Canaries("default").Get(canary, metav1.GetOptions{})
if err != nil {
return err
}
if c.Status.Phase != phase {
return fmt.Errorf("Got canary state %v wanted %v", c.Status.Phase, phase)
}
return nil
}
func alwaysReady() bool {
return true
}
@@ -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{
+110
View File
@@ -144,6 +144,116 @@ func TestScheduler_DeploymentSkipAnalysis(t *testing.T) {
}
}
func TestScheduler_DeploymentAnalysisPhases(t *testing.T) {
cd := newDeploymentTestCanary()
cd.Spec.Analysis = &flaggerv1.CanaryAnalysis{
Interval: "1m",
StepWeight: 100,
}
mocks := newDeploymentFixture(cd)
// init
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseInitialized); err != nil {
t.Fatal(err.Error())
}
// update
dep2 := newDeploymentTestDeploymentV2()
_, err := mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
if err != nil {
t.Fatal(err.Error())
}
// detect changes
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseProgressing); err != nil {
t.Fatal(err.Error())
}
// progressing
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseProgressing); err != nil {
t.Fatal(err.Error())
}
// promoting
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhasePromoting); err != nil {
t.Fatal(err.Error())
}
// finalising
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseFinalising); err != nil {
t.Fatal(err.Error())
}
// succeeded
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseSucceeded); err != nil {
t.Fatal(err.Error())
}
}
func TestScheduler_DeploymentBlueGreenAnalysisPhases(t *testing.T) {
cd := newDeploymentTestCanary()
cd.Spec.Analysis = &flaggerv1.CanaryAnalysis{
Interval: "1m",
Iterations: 1,
}
mocks := newDeploymentFixture(cd)
// init
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseInitialized); err != nil {
t.Fatal(err.Error())
}
// update
dep2 := newDeploymentTestDeploymentV2()
_, err := mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
if err != nil {
t.Fatal(err.Error())
}
// detect changes (progressing)
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseProgressing); err != nil {
t.Fatal(err.Error())
}
// advance (progressing)
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseProgressing); err != nil {
t.Fatal(err.Error())
}
// route traffic to primary (progressing)
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseProgressing); err != nil {
t.Fatal(err.Error())
}
// promoting
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhasePromoting); err != nil {
t.Fatal(err.Error())
}
// finalising
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseFinalising); err != nil {
t.Fatal(err.Error())
}
// succeeded
mocks.ctrl.advanceCanary("podinfo", "default", true)
if err := assertPhase(mocks.flaggerClient, "podinfo", flaggerv1.CanaryPhaseSucceeded); err != nil {
t.Fatal(err.Error())
}
}
func TestScheduler_DeploymentNewRevisionReset(t *testing.T) {
mocks := newDeploymentFixture(nil)
// init
+1 -1
View File
@@ -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,
+2 -1
View File
@@ -7,12 +7,13 @@ import (
"errors"
"fmt"
"io/ioutil"
"k8s.io/utils/clock"
"net/http"
"net/url"
"strconv"
"time"
"k8s.io/utils/clock"
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
)
+2 -1
View File
@@ -2,10 +2,11 @@ package loadtester
import (
"context"
"go.uber.org/zap"
"sync"
"sync/atomic"
"time"
"go.uber.org/zap"
)
type TaskRunner struct {
+2 -1
View File
@@ -1,9 +1,10 @@
package loadtester
import (
"github.com/weaveworks/flagger/pkg/logger"
"testing"
"time"
"github.com/weaveworks/flagger/pkg/logger"
)
func TestTaskRunner_Start(t *testing.T) {
-1
View File
@@ -179,7 +179,6 @@ func ListenAndServe(port string, timeout time.Duration, logger *zap.SugaredLogge
return
}
canaryName := fmt.Sprintf("rollback.%s.%s", canary.Name, canary.Namespace)
gate.close(canaryName)
+2 -1
View File
@@ -3,9 +3,10 @@ package loadtester
import (
"context"
"encoding/hex"
"go.uber.org/zap"
"hash/fnv"
"sync"
"go.uber.org/zap"
)
// Modeling a loadtester task
+2 -1
View File
@@ -6,12 +6,13 @@ import (
"encoding/json"
"errors"
"fmt"
"go.uber.org/zap"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"time"
"go.uber.org/zap"
)
const TaskTypeNGrinder = "ngrinder"
+3 -2
View File
@@ -3,10 +3,11 @@ package loadtester
import (
"context"
"fmt"
"github.com/weaveworks/flagger/pkg/logger"
"gopkg.in/h2non/gock.v1"
"testing"
"time"
"github.com/weaveworks/flagger/pkg/logger"
"gopkg.in/h2non/gock.v1"
)
func TestTaskNGrinder(t *testing.T) {
+2 -1
View File
@@ -4,9 +4,10 @@ import (
"context"
"errors"
"fmt"
"go.uber.org/zap"
"os/exec"
"strconv"
"go.uber.org/zap"
)
const TaskTypeShell = "cmd"
+2 -1
View File
@@ -1,8 +1,9 @@
package observers
import (
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
"time"
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
)
type Interface interface {
+2 -2
View File
@@ -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,
+4 -4
View File
@@ -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,
+3 -3
View File
@@ -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
View File
@@ -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,
+6 -6
View File
@@ -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,
+6 -6
View File
@@ -34,7 +34,7 @@ spec:
EOF
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -49,7 +49,7 @@ spec:
service:
port: 80
targetPort: 9898
canaryAnalysis:
analysis:
interval: 15s
threshold: 15
maxWeight: 50
@@ -145,7 +145,7 @@ echo '✔ Canary promotion test passed'
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -160,7 +160,7 @@ spec:
service:
port: 80
targetPort: 9898
canaryAnalysis:
analysis:
interval: 15s
threshold: 15
maxWeight: 50
@@ -218,7 +218,7 @@ done
echo '✔ Canary rollback test passed'
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -233,7 +233,7 @@ spec:
service:
port: 80
targetPort: 9898
canaryAnalysis:
analysis:
interval: 10s
threshold: 5
iterations: 5
+2 -2
View File
@@ -37,7 +37,7 @@ spec:
EOF
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -52,7 +52,7 @@ spec:
service:
port: 80
targetPort: 9898
canaryAnalysis:
analysis:
interval: 15s
threshold: 15
maxWeight: 50
+1 -1
View File
@@ -2,7 +2,7 @@
set -o errexit
ISTIO_VER="1.4.4"
ISTIO_VER="1.4.5"
REPO_ROOT=$(git rev-parse --show-toplevel)
echo ">>> Installing Istio ${ISTIO_VER}"
+2 -2
View File
@@ -18,7 +18,7 @@ echo '>>> Initialising canary'
kubectl apply -f ${REPO_ROOT}/test/e2e-daemonset.yaml
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -35,7 +35,7 @@ spec:
targetPort: 9898
name: podinfo-svc
portDiscovery: true
canaryAnalysis:
analysis:
interval: 15s
threshold: 10
iterations: 5
+2 -2
View File
@@ -18,7 +18,7 @@ echo '>>> Initialising canary'
kubectl apply -f ${REPO_ROOT}/test/e2e-workload.yaml
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -35,7 +35,7 @@ spec:
targetPort: 9898
name: podinfo-svc
portDiscovery: true
canaryAnalysis:
analysis:
interval: 15s
threshold: 10
iterations: 5
+2 -2
View File
@@ -34,7 +34,7 @@ spec:
EOS
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -48,7 +48,7 @@ spec:
progressDeadlineSeconds: 60
service:
port: 9898
canaryAnalysis:
analysis:
interval: 15s
threshold: 10
iterations: 5
+4 -4
View File
@@ -43,7 +43,7 @@ spec:
EOF
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -58,7 +58,7 @@ spec:
port: 80
targetPort: http
portDiscovery: true
canaryAnalysis:
analysis:
interval: 15s
threshold: 15
maxWeight: 50
@@ -154,7 +154,7 @@ done
echo '✔ Canary promotion test passed'
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -168,7 +168,7 @@ spec:
service:
port: 80
targetPort: 9898
canaryAnalysis:
analysis:
interval: 15s
threshold: 3
maxWeight: 50
+4 -4
View File
@@ -19,7 +19,7 @@ kubectl apply -f ${REPO_ROOT}/test/e2e-workload.yaml
kubectl apply -f ${REPO_ROOT}/test/e2e-ingress.yaml
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -37,7 +37,7 @@ spec:
service:
port: 80
targetPort: http
canaryAnalysis:
analysis:
interval: 15s
threshold: 15
maxWeight: 30
@@ -156,7 +156,7 @@ done
echo '✔ Canary promotion test passed'
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -174,7 +174,7 @@ spec:
service:
port: 80
targetPort: 9898
canaryAnalysis:
analysis:
interval: 10s
threshold: 5
iterations: 5
+1 -1
View File
@@ -3,7 +3,7 @@
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
NGINX_VERSION=1.26.0
NGINX_VERSION=1.33.0
echo '>>> Installing NGINX Ingress'
kubectl create ns ingress-nginx
+6 -6
View File
@@ -19,7 +19,7 @@ echo '>>> Initialising canary'
kubectl apply -f ${REPO_ROOT}/test/e2e-workload.yaml
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -39,7 +39,7 @@ spec:
x-envoy-upstream-rq-timeout-ms: "15000"
x-envoy-max-retries: "10"
x-envoy-retry-on: "gateway-error,connect-failure,refused-stream"
canaryAnalysis:
analysis:
interval: 15s
threshold: 15
maxWeight: 30
@@ -145,7 +145,7 @@ if [[ "$1" = "canary" ]]; then
fi
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -161,7 +161,7 @@ spec:
port: 80
targetPort: 9898
portName: http-podinfo
canaryAnalysis:
analysis:
interval: 10s
threshold: 5
iterations: 5
@@ -234,7 +234,7 @@ done
echo '✔ B/G promotion test passed'
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
@@ -250,7 +250,7 @@ spec:
port: 80
portName: http-podinfo
targetPort: http
canaryAnalysis:
analysis:
interval: 10s
threshold: 5
iterations: 5