@@ -1086,3 +1086,200 @@ func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
1086
1086
return true
1087
1087
}
1088
1088
}
1089
+
1090
+ func TestRemoveUnstructuredKeys (t * testing.T ) {
1091
+ t .Run ("remove single key" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1092
+ givenPath : []string {"metadata" , "annotations" },
1093
+ givenExclude : []string {"^key1$" },
1094
+ givenObj : map [string ]interface {}{
1095
+ "metadata" : map [string ]interface {}{
1096
+ "name" : "foo" ,
1097
+ "annotations" : map [string ]interface {}{
1098
+ "key1" : "value1" ,
1099
+ "key2" : "value2" ,
1100
+ },
1101
+ },
1102
+ },
1103
+ expectObj : map [string ]interface {}{
1104
+ "metadata" : map [string ]interface {}{
1105
+ "name" : "foo" ,
1106
+ },
1107
+ },
1108
+ }))
1109
+
1110
+ t .Run ("remove keys using multiple regexes" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1111
+ givenPath : []string {"metadata" , "annotations" },
1112
+ givenExclude : []string {"^key1$" , "^key2$" },
1113
+ givenObj : map [string ]interface {}{
1114
+ "metadata" : map [string ]interface {}{
1115
+ "name" : "foo" ,
1116
+ "annotations" : map [string ]interface {}{
1117
+ "key1" : "value1" ,
1118
+ "key2" : "value2" ,
1119
+ },
1120
+ },
1121
+ },
1122
+ expectObj : map [string ]interface {}{
1123
+ "metadata" : map [string ]interface {}{
1124
+ "name" : "foo" ,
1125
+ },
1126
+ },
1127
+ }))
1128
+
1129
+ t .Run ("remove multiple keys with a single regex" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1130
+ givenPath : []string {"metadata" , "annotations" },
1131
+ givenExclude : []string {"key.*" },
1132
+ givenObj : map [string ]interface {}{
1133
+ "metadata" : map [string ]interface {}{
1134
+ "name" : "foo" ,
1135
+ "annotations" : map [string ]interface {}{
1136
+ "key1" : "value1" ,
1137
+ "key2" : "value2" ,
1138
+ },
1139
+ },
1140
+ },
1141
+ expectObj : map [string ]interface {}{
1142
+ "metadata" : map [string ]interface {}{
1143
+ "name" : "foo" ,
1144
+ },
1145
+ },
1146
+ }))
1147
+
1148
+ t .Run ("with no regex, the object is untouched" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1149
+ givenPath : []string {"metadata" , "annotations" },
1150
+ givenExclude : []string {},
1151
+ givenObj : map [string ]interface {}{
1152
+ "metadata" : map [string ]interface {}{
1153
+ "name" : "foo" ,
1154
+ "annotations" : map [string ]interface {}{
1155
+ "key1" : "value1" ,
1156
+ "key2" : "value2" ,
1157
+ },
1158
+ },
1159
+ },
1160
+ expectObj : map [string ]interface {}{
1161
+ "metadata" : map [string ]interface {}{
1162
+ "name" : "foo" ,
1163
+ "annotations" : map [string ]interface {}{
1164
+ "key1" : "value1" ,
1165
+ "key2" : "value2" ,
1166
+ },
1167
+ },
1168
+ },
1169
+ }))
1170
+
1171
+ // The "leaf" field is the field that is at the end of the path. For
1172
+ // example, "annotations" is the leaf field in metadata.annotations.
1173
+ t .Run ("works when the leaf field is not found" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1174
+ givenPath : []string {"metadata" , "annotations" },
1175
+ givenExclude : []string {},
1176
+
1177
+ givenObj : map [string ]interface {}{"metadata" : map [string ]interface {}{}},
1178
+ expectObj : map [string ]interface {}{"metadata" : map [string ]interface {}{}},
1179
+ }))
1180
+
1181
+ t .Run ("works when the leaf field is nil" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1182
+ givenPath : []string {"metadata" , "annotations" },
1183
+ givenExclude : []string {},
1184
+ givenObj : map [string ]interface {}{
1185
+ "metadata" : map [string ]interface {}{
1186
+ "name" : "foo" ,
1187
+ "annotations" : nil ,
1188
+ },
1189
+ },
1190
+ expectObj : map [string ]interface {}{"metadata" : map [string ]interface {}{"name" : "foo" }},
1191
+ }))
1192
+
1193
+ t .Run ("works when leaf field is unexpectedly not nil and not a known map" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1194
+ givenPath : []string {"metadata" , "annotations" },
1195
+ givenObj : map [string ]interface {}{"metadata" : map [string ]interface {}{"annotations" : 42 }},
1196
+ expectObj : map [string ]interface {}{"metadata" : map [string ]interface {}{"annotations" : 42 }},
1197
+ }))
1198
+
1199
+ // The "intermediate" field is the field that is not at the end of the path.
1200
+ // For example, "metadata" is the intermediate field in
1201
+ // metadata.annotations.
1202
+ t .Run ("works when the intermediate field doesn't exist" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1203
+ givenPath : []string {"metadata" , "annotations" },
1204
+ givenObj : map [string ]interface {}{},
1205
+ expectObj : map [string ]interface {}{},
1206
+ }))
1207
+
1208
+ t .Run ("works when the intermediate field is nil" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1209
+ givenPath : []string {"metadata" , "annotations" },
1210
+ givenObj : map [string ]interface {}{"metadata" : nil },
1211
+ }))
1212
+
1213
+ t .Run ("works when the intermediate field is unexpectedly not nil and not a map" , run_TestRemoveUnstructuredKeys (tc_RemoveUnstructuredKeys {
1214
+ givenPath : []string {"metadata" , "annotations" },
1215
+ givenObj : map [string ]interface {}{"metadata" : 42 },
1216
+ expectObj : map [string ]interface {}{"metadata" : 42 },
1217
+ }))
1218
+ }
1219
+
1220
+ type tc_RemoveUnstructuredKeys struct {
1221
+ givenExclude []string
1222
+ givenObj map [string ]interface {}
1223
+ givenPath []string
1224
+ expectObj map [string ]interface {}
1225
+ }
1226
+
1227
+ func run_TestRemoveUnstructuredKeys (tc tc_RemoveUnstructuredKeys ) func (* testing.T ) {
1228
+ return func (t * testing.T ) {
1229
+ t .Helper ()
1230
+ RemoveUnstructuredKeys (toRegexps (tc .givenExclude ), & unstructured.Unstructured {Object : tc .givenObj }, tc .givenPath ... )
1231
+ }
1232
+ }
1233
+
1234
+ func TestRemoveTypedKeys (t * testing.T ) {
1235
+ t .Run ("remove single key" , run_TestRemoveTypedKeys (tc_TestRemoveTypedKeys {
1236
+ givenExclude : []string {"^key1$" },
1237
+ given : map [string ]string {"key1" : "value1" , "key2" : "value2" },
1238
+ expected : map [string ]string {"key2" : "value2" },
1239
+ }))
1240
+
1241
+ t .Run ("remove keys using multiple regexes" , run_TestRemoveTypedKeys (tc_TestRemoveTypedKeys {
1242
+ givenExclude : []string {"^key1$" , "^key2$" },
1243
+ given : map [string ]string {"key1" : "value1" , "key2" : "value2" },
1244
+ expected : map [string ]string {},
1245
+ }))
1246
+
1247
+ t .Run ("remove multiple keys with a single regex" , run_TestRemoveTypedKeys (tc_TestRemoveTypedKeys {
1248
+ givenExclude : []string {"key.*" },
1249
+ given : map [string ]string {"key1" : "value1" , "key2" : "value2" },
1250
+ expected : map [string ]string {},
1251
+ }))
1252
+
1253
+ t .Run ("with no regex, the object is untouched" , run_TestRemoveTypedKeys (tc_TestRemoveTypedKeys {
1254
+ givenExclude : []string {},
1255
+ given : map [string ]string {"key1" : "value1" , "key2" : "value2" },
1256
+ expected : map [string ]string {"key1" : "value1" , "key2" : "value2" },
1257
+ }))
1258
+
1259
+ t .Run ("works when the map is nil" , run_TestRemoveTypedKeys (tc_TestRemoveTypedKeys {
1260
+ givenExclude : []string {"^key1$" },
1261
+ given : nil ,
1262
+ expected : nil ,
1263
+ }))
1264
+ }
1265
+
1266
+ type tc_TestRemoveTypedKeys struct {
1267
+ givenExclude []string
1268
+ given map [string ]string
1269
+ expected map [string ]string
1270
+ }
1271
+
1272
+ func run_TestRemoveTypedKeys (tc tc_TestRemoveTypedKeys ) func (t * testing.T ) {
1273
+ return func (t * testing.T ) {
1274
+ RemoveTypedKeys (toRegexps (tc .givenExclude ), tc .given )
1275
+ assert .Equal (t , tc .expected , tc .given )
1276
+ }
1277
+ }
1278
+
1279
+ func toRegexps (keys []string ) []* regexp.Regexp {
1280
+ var regexps []* regexp.Regexp
1281
+ for _ , key := range keys {
1282
+ regexps = append (regexps , regexp .MustCompile (key ))
1283
+ }
1284
+ return regexps
1285
+ }
0 commit comments