-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
rollout_test.go
127 lines (107 loc) · 4.25 KB
/
rollout_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//go:build e2e
// +build e2e
/*
Copyright 2021 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e
import (
"fmt"
"testing"
"time"
pkgtest "knative.dev/pkg/test"
"knative.dev/serving/pkg/apis/serving"
v1 "knative.dev/serving/pkg/apis/serving/v1"
testingv1 "knative.dev/serving/pkg/testing/v1"
"knative.dev/serving/test"
v1test "knative.dev/serving/test/v1"
)
// TestGradualRollout ensures the traffic is rolled out gradually.
func TestGradualRollout(t *testing.T) {
t.Parallel()
clients := test.Setup(t)
const rolloutDuration = time.Minute
names := test.ResourceNames{
Service: test.ObjectNameForTest(t),
Image: test.PizzaPlanet1,
}
// Clean up on test failure or interrupt
test.EnsureTearDown(t, clients, &names)
// Setup Service
t.Log("Creating a new Service", names.Service)
robjs, err := v1test.CreateServiceReady(t, clients, &names,
testingv1.WithServiceAnnotation(serving.RolloutDurationKey, rolloutDuration.String()))
if err != nil {
t.Fatal("Create Ready Service:", err)
}
if _, err := v1test.PatchService(t, clients, robjs.Service, testingv1.WithServiceImage(pkgtest.ImagePath(test.Autoscale))); err != nil {
t.Fatalf("Patch update for Service %s with image %s failed: %v", names.Service, test.Autoscale, err)
}
// This will cover all the status checks:
// - Status is in Rollout
// - Traffic is splitting
if err := v1test.WaitForServiceState(clients.ServingClient, names.Service,
func(s *v1.Service) (bool, error) {
// New revision not yet created.
return s.Status.LatestCreatedRevisionName != robjs.Revision.Name, nil
}, "SecondRevision"); err != nil {
t.Fatal("Second revision never got created")
}
if err := v1test.WaitForServiceState(clients.ServingClient, names.Service,
func(s *v1.Service) (bool, error) {
return s.Status.GetCondition(v1.ServiceConditionRoutesReady).GetReason() == "RolloutInProgress", nil
}, "RolloutStarted"); err != nil {
t.Fatal("Rollout never started")
}
t.Log("Rollout started to the second revision")
if err := v1test.WaitForServiceState(clients.ServingClient, names.Service,
func(s *v1.Service) (bool, error) {
traffic := s.Status.Traffic
return len(traffic) == 2, nil
}, "TrafficSplit"); err != nil {
t.Fatal("Never got split traffic")
}
t.Log("Saw two traffic targets")
if err := v1test.WaitForServiceState(clients.ServingClient, names.Service,
func(s *v1.Service) (bool, error) {
// Here we saw rollout and split traffic So two things can happen:
// 1. Rollout finished
// 2. Rollout in progress.
// We must see two traffic targets at least once (60s to rollout, so more than once in reality).
traffic := s.Status.Traffic
if s.IsReady() {
t.Log("Saw the status ready!")
// Rollout finished! Verify single target.
if len(traffic) != 1 {
return false, fmt.Errorf("expected one item in traffic stanza but got: %#v", traffic)
}
// Verify we reconciled on the second revision.
if traffic[0].RevisionName != s.Status.LatestCreatedRevisionName {
return false, fmt.Errorf("expected %s as final targtet revision but got %s", s.Status.LatestCreatedRevisionName, traffic[0].RevisionName)
}
// All good, we're done.
return true, nil
}
// Verify traffic shape. During the rollout there should be exactly 2 items or rollout just finished
// and the new target has 100%, but service is not yet ready.
if tl := len(traffic); tl != 2 {
if tl == 1 &&
traffic[0].RevisionName == s.Status.LatestCreatedRevisionName &&
*traffic[0].Percent == 100 {
return false, nil
}
return false, fmt.Errorf("Expected two items in traffic stanza but got: %#v", s.Status.Traffic)
}
return false, nil
}, "RolloutFinished"); err != nil {
t.Fatalf("Failed waiting for Rollout %q to complete: %+v", names.Service, err)
}
}