@@ -1086,3 +1086,200 @@ func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
10861086 return true
10871087 }
10881088}
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