Skip to content

Commit

Permalink
nginx canary weight support headers
Browse files Browse the repository at this point in the history
Signed-off-by: bin.hu <[email protected]>
  • Loading branch information
bin.hu committed Sep 15, 2023
1 parent 5ca1ade commit 051809f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
9 changes: 5 additions & 4 deletions pkg/router/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (i *IngressRouter) GetRoutes(canary *flaggerv1.Canary) (
}

// A/B testing
if len(canary.GetAnalysis().Match) > 0 {
if len(canary.GetAnalysis().Match) > 0 && canary.GetAnalysis().Iterations > 0 {
for k := range canaryIngress.Annotations {
if k == i.GetAnnotationWithPrefix("canary-by-cookie") || k == i.GetAnnotationWithPrefix("canary-by-header") {
return 0, 100, false, nil
Expand All @@ -156,7 +156,6 @@ func (i *IngressRouter) GetRoutes(canary *flaggerv1.Canary) (
break
}
}

primaryWeight = 100 - canaryWeight
mirrored = false
return
Expand All @@ -176,7 +175,8 @@ func (i *IngressRouter) SetRoutes(

iClone := canaryIngress.DeepCopy()

// A/B testing
// if iterations > 0 ,it's A/B testing.
// else it's a weight canary with match header
if len(canary.GetAnalysis().Match) > 0 {
var cookie, header, headerValue, headerRegex string
for _, m := range canary.GetAnalysis().Match {
Expand All @@ -192,7 +192,8 @@ func (i *IngressRouter) SetRoutes(
}

iClone.Annotations = i.makeHeaderAnnotations(iClone.Annotations, header, headerValue, headerRegex, cookie)
} else {
}
if canary.GetAnalysis().Iterations == 0 {
// canary
iClone.Annotations[i.GetAnnotationWithPrefix("canary-weight")] = fmt.Sprintf("%v", canaryWeight)
}
Expand Down
59 changes: 59 additions & 0 deletions pkg/router/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,65 @@ func TestIngressRouter_GetSetRoutes(t *testing.T) {
assert.Equal(t, "0", inCanary.Annotations[canaryWeightAn])
}

func TestIngressRouter_GetSetRoutes_WithMatch(t *testing.T) {
mocks := newFixture(nil)
router := &IngressRouter{
logger: mocks.logger,
kubeClient: mocks.kubeClient,
annotationsPrefix: "prefix1.nginx.ingress.kubernetes.io",
}
mocks.ingressCanary.Spec.Analysis.Match = []istiov1alpha3.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-canary": {
Exact: "always",
},
},
},
}
err := router.Reconcile(mocks.ingressCanary)
require.NoError(t, err)

p, c, m, err := router.GetRoutes(mocks.ingressCanary)
require.NoError(t, err)

p = 50
c = 50
m = false

err = router.SetRoutes(mocks.ingressCanary, p, c, m)
require.NoError(t, err)

canaryAn := "prefix1.nginx.ingress.kubernetes.io/canary"
canaryWeightAn := "prefix1.nginx.ingress.kubernetes.io/canary-weight"
canaryByHeaderAn := "prefix1.nginx.ingress.kubernetes.io/canary-by-header"
canaryByHeaderValueAn := "prefix1.nginx.ingress.kubernetes.io/canary-by-header-value"

canaryName := fmt.Sprintf("%s-canary", mocks.ingressCanary.Spec.IngressRef.Name)
inCanary, err := router.kubeClient.NetworkingV1().Ingresses("default").Get(context.TODO(), canaryName, metav1.GetOptions{})
require.NoError(t, err)

// test rollout
assert.Equal(t, "true", inCanary.Annotations[canaryAn])
assert.Equal(t, "50", inCanary.Annotations[canaryWeightAn])
assert.Equal(t, "x-canary", inCanary.Annotations[canaryByHeaderAn])
assert.Equal(t, "always", inCanary.Annotations[canaryByHeaderValueAn])

p = 100
c = 0
m = false

err = router.SetRoutes(mocks.ingressCanary, p, c, m)
require.NoError(t, err)

inCanary, err = router.kubeClient.NetworkingV1().Ingresses("default").Get(context.TODO(), canaryName, metav1.GetOptions{})
require.NoError(t, err)

// test promotion
assert.Equal(t, "true", inCanary.Annotations[canaryAn])
assert.Equal(t, "0", inCanary.Annotations[canaryWeightAn])
}

func TestIngressRouter_ABTest(t *testing.T) {
mocks := newFixture(nil)
router := &IngressRouter{
Expand Down

0 comments on commit 051809f

Please sign in to comment.