Skip to content

Commit 6de1184

Browse files
committed
fix: unsolicited rollout after upgrade from v0.10->v1.0 when pod was using service account (argoproj#1367)
Signed-off-by: Jesse Suen <[email protected]>
1 parent abf7bf0 commit 6de1184

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

utils/replicaset/replicaset.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,15 @@ func PodTemplateEqualIgnoreHash(live, desired *corev1.PodTemplateSpec) bool {
493493
}
494494
corev1defaults.SetObjectDefaults_PodTemplate(&podTemplate)
495495
desired = &podTemplate.Template
496+
497+
// Do not allow the deprecated spec.serviceAccount to factor into the equality check. In live
498+
// ReplicaSet pod template, this field will be populated, but in the desired pod template
499+
// it will be missing (even after defaulting), causing us to believe there is a diff
500+
// (when there really wasn't), and hence causing an unsolicited update to be triggered.
501+
// See: https://github.com/argoproj/argo-rollouts/issues/1356
502+
desired.Spec.DeprecatedServiceAccount = ""
503+
live.Spec.DeprecatedServiceAccount = ""
504+
496505
return apiequality.Semantic.DeepEqual(live, desired)
497506
}
498507

utils/replicaset/replicaset_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99
"time"
1010

11+
"github.com/ghodss/yaml"
1112
"github.com/stretchr/testify/assert"
1213
appsv1 "k8s.io/api/apps/v1"
1314
corev1 "k8s.io/api/core/v1"
@@ -1167,3 +1168,54 @@ func TestGetPodsOwnedByReplicaSet(t *testing.T) {
11671168
assert.Len(t, pods, 1)
11681169
assert.Equal(t, "guestbook-abc123", pods[0].Name)
11691170
}
1171+
1172+
// TestPodTemplateEqualIgnoreHashWithServiceAccount catches a corner case where the K8s ComputeHash
1173+
// function changed from underneath us, and we fell back to deep equality checking, which then
1174+
// incorrectly detected a diff because of a deprecated field being present in the live but not desired.
1175+
func TestPodTemplateEqualIgnoreHashWithServiceAccount(t *testing.T) {
1176+
var desired corev1.PodTemplateSpec
1177+
desiredTemplate := `
1178+
metadata:
1179+
labels:
1180+
app: serviceaccount-ro
1181+
spec:
1182+
containers:
1183+
- image: nginx:1.19-alpine
1184+
name: app
1185+
serviceAccountName: default
1186+
`
1187+
err := yaml.Unmarshal([]byte(desiredTemplate), &desired)
1188+
assert.NoError(t, err)
1189+
1190+
// liveTemplate was captured from a ReplicaSet generated from the above desired template using
1191+
// Argo Rollouts v0.10. The rollouts-pod-template-hash value will not match newer hashing
1192+
// versions, causing PodTemplateEqualIgnoreHash to fall back to a deep equality check and
1193+
// pod template defaulting.
1194+
liveTemplate := `
1195+
metadata:
1196+
creationTimestamp: null
1197+
labels:
1198+
app: serviceaccount-ro
1199+
rollouts-pod-template-hash: 8684587d99
1200+
spec:
1201+
containers:
1202+
- image: nginx:1.19-alpine
1203+
imagePullPolicy: IfNotPresent
1204+
name: app
1205+
resources: {}
1206+
terminationMessagePath: /dev/termination-log
1207+
terminationMessagePolicy: File
1208+
dnsPolicy: ClusterFirst
1209+
restartPolicy: Always
1210+
schedulerName: default-scheduler
1211+
securityContext: {}
1212+
serviceAccount: default
1213+
serviceAccountName: default
1214+
terminationGracePeriodSeconds: 30
1215+
`
1216+
var live corev1.PodTemplateSpec
1217+
err = yaml.Unmarshal([]byte(liveTemplate), &live)
1218+
assert.NoError(t, err)
1219+
1220+
assert.True(t, PodTemplateEqualIgnoreHash(&live, &desired))
1221+
}

0 commit comments

Comments
 (0)