Skip to content

Commit d2753c2

Browse files
authored
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 0c559a0 commit d2753c2

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

utils/replicaset/replicaset.go

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

utils/replicaset/replicaset_test.go

Lines changed: 51 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"
@@ -1186,5 +1187,55 @@ func TestGetTimeRemainingBeforeScaleDownDeadline(t *testing.T) {
11861187
assert.Nil(t, err)
11871188
assert.NotNil(t, remainingTime)
11881189
}
1190+
}
1191+
1192+
// TestPodTemplateEqualIgnoreHashWithServiceAccount catches a corner case where the K8s ComputeHash
1193+
// function changed from underneath us, and we fell back to deep equality checking, which then
1194+
// incorrectly detected a diff because of a deprecated field being present in the live but not desired.
1195+
func TestPodTemplateEqualIgnoreHashWithServiceAccount(t *testing.T) {
1196+
var desired corev1.PodTemplateSpec
1197+
desiredTemplate := `
1198+
metadata:
1199+
labels:
1200+
app: serviceaccount-ro
1201+
spec:
1202+
containers:
1203+
- image: nginx:1.19-alpine
1204+
name: app
1205+
serviceAccountName: default
1206+
`
1207+
err := yaml.Unmarshal([]byte(desiredTemplate), &desired)
1208+
assert.NoError(t, err)
1209+
1210+
// liveTemplate was captured from a ReplicaSet generated from the above desired template using
1211+
// Argo Rollouts v0.10. The rollouts-pod-template-hash value will not match newer hashing
1212+
// versions, causing PodTemplateEqualIgnoreHash to fall back to a deep equality check and
1213+
// pod template defaulting.
1214+
liveTemplate := `
1215+
metadata:
1216+
creationTimestamp: null
1217+
labels:
1218+
app: serviceaccount-ro
1219+
rollouts-pod-template-hash: 8684587d99
1220+
spec:
1221+
containers:
1222+
- image: nginx:1.19-alpine
1223+
imagePullPolicy: IfNotPresent
1224+
name: app
1225+
resources: {}
1226+
terminationMessagePath: /dev/termination-log
1227+
terminationMessagePolicy: File
1228+
dnsPolicy: ClusterFirst
1229+
restartPolicy: Always
1230+
schedulerName: default-scheduler
1231+
securityContext: {}
1232+
serviceAccount: default
1233+
serviceAccountName: default
1234+
terminationGracePeriodSeconds: 30
1235+
`
1236+
var live corev1.PodTemplateSpec
1237+
err = yaml.Unmarshal([]byte(liveTemplate), &live)
1238+
assert.NoError(t, err)
11891239

1240+
assert.True(t, PodTemplateEqualIgnoreHash(&live, &desired))
11901241
}

0 commit comments

Comments
 (0)