Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.

Commit ff8d2f5

Browse files
authored
Merge commit from fork
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
1 parent f70cbd1 commit ff8d2f5

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

pkg/diff/diff.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,11 @@ func serverSideDiff(config, live *unstructured.Unstructured, opts ...Option) (*D
188188

189189
Normalize(predictedLive, opts...)
190190
unstructured.RemoveNestedField(predictedLive.Object, "metadata", "managedFields")
191+
unstructured.RemoveNestedField(predictedLive.Object, "metadata", "annotations", AnnotationLastAppliedConfig)
191192

192193
Normalize(live, opts...)
193194
unstructured.RemoveNestedField(live.Object, "metadata", "managedFields")
195+
unstructured.RemoveNestedField(live.Object, "metadata", "annotations", AnnotationLastAppliedConfig)
194196

195197
if isCoreSecret(config) {
196198
// Mask Secret data symmetrically before comparison.

pkg/diff/diff_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"os/exec"
99
"path/filepath"
10+
"strconv"
1011
"strings"
1112
"testing"
1213

@@ -1167,6 +1168,74 @@ func TestServerSideDiff(t *testing.T) {
11671168
assert.Empty(t, liveDeploy.Annotations[AnnotationLastAppliedConfig])
11681169
})
11691170

1171+
t.Run("will strip kubectl.kubernetes.io/last-applied-configuration from both sides", func(t *testing.T) {
1172+
t.Parallel()
1173+
1174+
const lastAppliedRaw = `{"apiVersion":"v1","kind":"Secret","metadata":{"name":"secret","namespace":"default","annotations":{"app":"test"}},"data":{"password":"U0VDUkVUVkFM"},"stringData":{"username":"SECRETVAL"}}`
1175+
1176+
liveState := StrToUnstructured(`{
1177+
"apiVersion": "v1",
1178+
"kind": "Secret",
1179+
"metadata": {
1180+
"name": "secret",
1181+
"namespace": "default",
1182+
"annotations": {
1183+
"app": "test",
1184+
"kubectl.kubernetes.io/last-applied-configuration": ` + strconv.Quote(lastAppliedRaw) + `
1185+
}
1186+
},
1187+
"type": "Opaque",
1188+
"data": {
1189+
"password": "U0VDUkVUVkFM"
1190+
}
1191+
}`)
1192+
desiredState := StrToUnstructured(`{
1193+
"apiVersion": "v1",
1194+
"kind": "Secret",
1195+
"metadata": {
1196+
"name": "secret",
1197+
"namespace": "default",
1198+
"annotations": {
1199+
"app": "test"
1200+
}
1201+
},
1202+
"type": "Opaque",
1203+
"data": {
1204+
"password": "U0VDUkVUVkFM"
1205+
}
1206+
}`)
1207+
predictedLiveJSON := `{
1208+
"apiVersion": "v1",
1209+
"kind": "Secret",
1210+
"metadata": {
1211+
"name": "secret",
1212+
"namespace": "default",
1213+
"annotations": {
1214+
"app": "test",
1215+
"kubectl.kubernetes.io/last-applied-configuration": ` + strconv.Quote(lastAppliedRaw) + `
1216+
}
1217+
},
1218+
"type": "Opaque",
1219+
"data": {
1220+
"password": "U0VDUkVUVkFM"
1221+
}
1222+
}`
1223+
opts := buildOpts(predictedLiveJSON)
1224+
opts = append(opts, WithIgnoreMutationWebhook(false))
1225+
1226+
// when
1227+
result, err := serverSideDiff(desiredState, liveState, opts...)
1228+
1229+
// then
1230+
require.NoError(t, err)
1231+
require.NotNil(t, result)
1232+
assert.NotContains(t, string(result.PredictedLive), "kubectl.kubernetes.io/last-applied-configuration",
1233+
"PredictedLive must not contain the last-applied-configuration annotation")
1234+
assert.NotContains(t, string(result.NormalizedLive), "kubectl.kubernetes.io/last-applied-configuration",
1235+
"NormalizedLive must not contain the last-applied-configuration annotation")
1236+
assert.NotContains(t, string(result.PredictedLive), "SECRETVAL",
1237+
"PredictedLive must not contain raw secret values from last-applied-configuration")
1238+
})
11701239
t.Run("will mask Secret data symmetrically so identical values do not produce a spurious diff", func(t *testing.T) {
11711240
t.Parallel()
11721241

0 commit comments

Comments
 (0)