Skip to content

Commit a326d83

Browse files
Merge pull request #2147 from benluddy/simpler-deployment-status
Simplify deployment status check to reduce flapping.
2 parents 1999e5e + 165e960 commit a326d83

File tree

2 files changed

+65
-114
lines changed

2 files changed

+65
-114
lines changed

pkg/controller/install/status_viewer.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package install
22

3-
// See kubernetes/pkg/kubectl/rollout_status.go
4-
53
import (
64
"fmt"
75

@@ -15,29 +13,26 @@ const TimedOutReason = "ProgressDeadlineExceeded"
1513
func DeploymentStatus(deployment *appsv1.Deployment) (string, bool, error) {
1614
if deployment.Generation <= deployment.Status.ObservedGeneration {
1715
// check if deployment has timed out
18-
cond := getDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)
19-
if cond != nil && cond.Reason == TimedOutReason {
16+
progressing := getDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)
17+
if progressing != nil && progressing.Reason == TimedOutReason {
2018
return "", false, fmt.Errorf("deployment %q exceeded its progress deadline", deployment.Name)
2119
}
22-
// not all replicas are up yet
23-
if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {
24-
return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new replicas have been updated...\n", deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false, nil
25-
}
26-
// waiting for old replicas to be cleaned up
20+
2721
if deployment.Status.Replicas > deployment.Status.UpdatedReplicas {
28-
return fmt.Sprintf("Waiting for rollout to finish: %d old replicas are pending termination...\n", deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil
22+
return fmt.Sprintf("deployment %q waiting for %d outdated replica(s) to be terminated", deployment.Name, deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil
2923
}
30-
if c := getDeploymentCondition(deployment.Status, appsv1.DeploymentAvailable); c == nil || c.Status != corev1.ConditionTrue {
31-
msg := fmt.Sprintf("deployment %q missing condition %q", deployment.Name, appsv1.DeploymentAvailable)
32-
if c != nil {
33-
msg = fmt.Sprintf("deployment %q not available: %s", deployment.Name, c.Message)
24+
25+
if available := getDeploymentCondition(deployment.Status, appsv1.DeploymentAvailable); available == nil || available.Status != corev1.ConditionTrue {
26+
msg := fmt.Sprintf("missing condition %q", appsv1.DeploymentAvailable)
27+
if available != nil {
28+
msg = available.Message
3429
}
35-
return fmt.Sprintf("Waiting for rollout to finish: %s\n", msg), false, nil
30+
return fmt.Sprintf("deployment %q not available: %s", deployment.Name, msg), false, nil
3631
}
37-
// deployment is finished
38-
return fmt.Sprintf("deployment %q successfully rolled out\n", deployment.Name), true, nil
32+
33+
return fmt.Sprintf("deployment %q is up-to-date and available", deployment.Name), true, nil
3934
}
40-
return fmt.Sprintf("Waiting for deployment spec update to be observed...\n"), false, nil
35+
return fmt.Sprintf("waiting for spec update of deployment %q to be observed...", deployment.Name), false, nil
4136
}
4237

4338
func getDeploymentCondition(status appsv1.DeploymentStatus, condType appsv1.DeploymentConditionType) *appsv1.DeploymentCondition {

pkg/controller/install/status_viewer_test.go

Lines changed: 52 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -4,140 +4,106 @@ import (
44
"fmt"
55
"testing"
66

7+
"github.com/stretchr/testify/assert"
78
apps "k8s.io/api/apps/v1"
89
core "k8s.io/api/core/v1"
910
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1011
)
1112

1213
func TestDeploymentStatusViewerStatus(t *testing.T) {
1314
tests := []struct {
14-
generation int64
15-
specReplicas int32
16-
status apps.DeploymentStatus
17-
msg string
18-
done bool
15+
generation int64
16+
status apps.DeploymentStatus
17+
err error
18+
msg string
19+
done bool
1920
}{
2021
{
21-
generation: 0,
22-
specReplicas: 1,
2322
status: apps.DeploymentStatus{
24-
ObservedGeneration: 1,
25-
Replicas: 1,
26-
UpdatedReplicas: 0,
27-
AvailableReplicas: 1,
28-
UnavailableReplicas: 0,
2923
Conditions: []apps.DeploymentCondition{
3024
{
3125
Type: apps.DeploymentProgressing,
32-
Reason: "NotTimedOut",
26+
Reason: TimedOutReason,
3327
},
3428
},
3529
},
36-
37-
msg: "Waiting for rollout to finish: 0 out of 1 new replicas have been updated...\n",
30+
err: fmt.Errorf("deployment \"foo\" exceeded its progress deadline"),
3831
done: false,
3932
},
4033
{
41-
generation: 0,
42-
specReplicas: 1,
4334
status: apps.DeploymentStatus{
44-
ObservedGeneration: 1,
45-
Replicas: 1,
46-
UpdatedReplicas: 0,
47-
AvailableReplicas: 1,
48-
UnavailableReplicas: 0,
35+
Conditions: []apps.DeploymentCondition{
36+
{
37+
Type: apps.DeploymentProgressing,
38+
Reason: "NotTimedOut",
39+
},
40+
{
41+
Type: apps.DeploymentAvailable,
42+
Status: core.ConditionTrue,
43+
},
44+
},
45+
},
46+
msg: "deployment \"foo\" is up-to-date and available",
47+
done: true,
48+
},
49+
{
50+
generation: 1,
51+
status: apps.DeploymentStatus{
52+
ObservedGeneration: 0,
4953
},
50-
51-
msg: "Waiting for rollout to finish: 0 out of 1 new replicas have been updated...\n",
54+
msg: "waiting for spec update of deployment \"foo\" to be observed...",
5255
done: false,
5356
},
5457
{
55-
generation: 1,
56-
specReplicas: 1,
5758
status: apps.DeploymentStatus{
58-
ObservedGeneration: 1,
59-
Replicas: 2,
60-
UpdatedReplicas: 1,
61-
AvailableReplicas: 2,
62-
UnavailableReplicas: 0,
59+
Replicas: 5,
60+
UpdatedReplicas: 3,
6361
},
64-
65-
msg: "Waiting for rollout to finish: 1 old replicas are pending termination...\n",
62+
msg: "deployment \"foo\" waiting for 2 outdated replica(s) to be terminated",
6663
done: false,
6764
},
6865
{
69-
generation: 1,
70-
specReplicas: 2,
66+
status: apps.DeploymentStatus{},
67+
msg: fmt.Sprintf("deployment \"foo\" not available: missing condition %q", apps.DeploymentAvailable),
68+
done: false,
69+
},
70+
{
7171
status: apps.DeploymentStatus{
72-
ObservedGeneration: 1,
73-
Replicas: 2,
74-
UpdatedReplicas: 2,
75-
AvailableReplicas: 1,
76-
UnavailableReplicas: 1,
7772
Conditions: []apps.DeploymentCondition{
7873
{
7974
Type: apps.DeploymentAvailable,
8075
Status: core.ConditionFalse,
81-
Message: "Deployment does not have minimum availability.",
76+
Message: "test message",
8277
},
8378
},
8479
},
85-
86-
msg: "Waiting for rollout to finish: deployment \"foo\" not available: Deployment does not have minimum availability.\n",
80+
msg: "deployment \"foo\" not available: test message",
8781
done: false,
8882
},
8983
{
90-
generation: 1,
91-
specReplicas: 2,
9284
status: apps.DeploymentStatus{
93-
ObservedGeneration: 1,
94-
Replicas: 2,
95-
UpdatedReplicas: 2,
96-
AvailableReplicas: 1,
97-
UnavailableReplicas: 1,
9885
Conditions: []apps.DeploymentCondition{
9986
{
100-
Type: apps.DeploymentAvailable,
101-
Status: core.ConditionTrue,
87+
Type: apps.DeploymentAvailable,
88+
Status: core.ConditionUnknown,
89+
Message: "test message",
10290
},
10391
},
10492
},
105-
106-
msg: "deployment \"foo\" successfully rolled out\n",
107-
done: true,
93+
msg: "deployment \"foo\" not available: test message",
94+
done: false,
10895
},
10996
{
110-
generation: 1,
111-
specReplicas: 2,
11297
status: apps.DeploymentStatus{
113-
ObservedGeneration: 1,
114-
Replicas: 2,
115-
UpdatedReplicas: 2,
116-
AvailableReplicas: 1,
117-
UnavailableReplicas: 1,
11898
Conditions: []apps.DeploymentCondition{
11999
{
120-
Type: "Fooing",
100+
Type: apps.DeploymentAvailable,
121101
Status: core.ConditionTrue,
122102
},
123103
},
124104
},
125-
msg: "Waiting for rollout to finish: deployment \"foo\" missing condition \"Available\"\n",
126-
done: false,
127-
},
128-
{
129-
generation: 2,
130-
specReplicas: 2,
131-
status: apps.DeploymentStatus{
132-
ObservedGeneration: 1,
133-
Replicas: 2,
134-
UpdatedReplicas: 2,
135-
AvailableReplicas: 2,
136-
UnavailableReplicas: 0,
137-
},
138-
139-
msg: "Waiting for deployment spec update to be observed...\n",
140-
done: false,
105+
msg: "deployment \"foo\" is up-to-date and available",
106+
done: true,
141107
},
142108
}
143109

@@ -147,29 +113,19 @@ func TestDeploymentStatusViewerStatus(t *testing.T) {
147113
ObjectMeta: metav1.ObjectMeta{
148114
Namespace: "bar",
149115
Name: "foo",
150-
UID: "8764ae47-9092-11e4-8393-42010af018ff",
151116
Generation: test.generation,
152117
},
153-
Spec: apps.DeploymentSpec{
154-
Replicas: &test.specReplicas,
155-
},
156118
Status: test.status,
157119
}
158120
msg, done, err := DeploymentStatus(d)
159-
if err != nil {
160-
t.Fatalf("DeploymentStatusViewer.Status(): %v", err)
161-
}
162-
if done != test.done || msg != test.msg {
163-
t.Errorf("DeploymentStatusViewer.Status() for deployment with generation %d, %d replicas specified, and status %+v returned %q, %t, want %q, %t",
164-
test.generation,
165-
test.specReplicas,
166-
test.status,
167-
msg,
168-
done,
169-
test.msg,
170-
test.done,
171-
)
121+
assert := assert.New(t)
122+
if test.err == nil {
123+
assert.NoError(err)
124+
} else {
125+
assert.EqualError(err, test.err.Error())
172126
}
127+
assert.Equal(test.done, done)
128+
assert.Equal(test.msg, msg)
173129
})
174130
}
175131
}

0 commit comments

Comments
 (0)