7
7
"strings"
8
8
9
9
jsonpatch "github.com/evanphx/json-patch/v5"
10
+ "github.com/mitchellh/mapstructure"
10
11
log "github.com/sirupsen/logrus"
11
12
k8serrors "k8s.io/apimachinery/pkg/api/errors"
12
13
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -224,15 +225,49 @@ func (r *Reconciler) UpdateHash(canaryHash, stableHash string) error {
224
225
return nil
225
226
}
226
227
228
+ // destinationRuleReplaceExtraMarshal relace the key of "Extra" with the actual content
229
+ // e.g., "trafficpolicy" and return the bytes of the new object
230
+ func destinationRuleReplaceExtraMarshal (dRule * DestinationRule ) []byte {
231
+ dRuleNew := map [string ]interface {}{}
232
+ dRuleNew ["metadata" ] = dRule .ObjectMeta .DeepCopy ()
233
+
234
+ subsets := []map [string ]interface {}{}
235
+ for _ , subset := range dRule .Spec .Subsets {
236
+ newsubset := map [string ]interface {}{}
237
+ newsubset ["name" ] = subset .Name
238
+ newsubset ["labels" ] = subset .Labels
239
+
240
+ if subset .Extra == nil {
241
+ subsets = append (subsets , newsubset )
242
+ continue
243
+ }
244
+
245
+ extra := map [string ]interface {}{}
246
+ inputbyte , _ := json .Marshal (subset .Extra )
247
+ json .Unmarshal (inputbyte , & extra )
248
+
249
+ subset .Extra = nil
250
+ for k , v := range extra {
251
+ newsubset [k ] = v
252
+ }
253
+ subsets = append (subsets , newsubset )
254
+ }
255
+ dRuleNew ["spec" ] = map [string ]interface {}{
256
+ "subsets" : subsets ,
257
+ }
258
+
259
+ dRuleNewBytes , _ := json .Marshal (dRuleNew )
260
+ return dRuleNewBytes
261
+ }
262
+
227
263
func updateDestinationRule (ctx context.Context , client dynamic.ResourceInterface , orig []byte , dRule , dRuleNew * DestinationRule ) (bool , error ) {
228
264
dRuleBytes , err := json .Marshal (dRule )
229
265
if err != nil {
230
266
return false , err
231
267
}
232
- dRuleNewBytes , err := json .Marshal (dRuleNew )
233
- if err != nil {
234
- return false , err
235
- }
268
+ dRuleNewBytes := destinationRuleReplaceExtraMarshal (dRuleNew )
269
+ log .Debugf ("dRuleNewBytes: %s" , string (dRuleNewBytes ))
270
+
236
271
patch , err := jsonpatch .CreateMergePatch (dRuleBytes , dRuleNewBytes )
237
272
if err != nil {
238
273
return false , err
@@ -253,7 +288,7 @@ func updateDestinationRule(ctx context.Context, client dynamic.ResourceInterface
253
288
if err != nil {
254
289
return false , err
255
290
}
256
- log .Infof ("updated destinationrule: %s" , string (patch ))
291
+ log .Infof ("updating destinationrule: %s" , string (patch ))
257
292
return true , nil
258
293
}
259
294
@@ -275,12 +310,97 @@ func unstructuredToDestinationRules(un *unstructured.Unstructured) ([]byte, *Des
275
310
return dRuleBytes , dRule1 , dRule2 , nil
276
311
}
277
312
313
+ func unMarshalSubsets (dRule * DestinationRule , dRuleBytes []byte ) error {
314
+ var err error
315
+
316
+ unstructured := map [string ]interface {}{}
317
+ var extractFieldBytes func ([]byte , string ) ([]byte , error )
318
+ extractFieldBytes = func (input []byte , name string ) ([]byte , error ) {
319
+ err = json .Unmarshal (input , & unstructured )
320
+ if err != nil {
321
+ return nil , err
322
+ }
323
+ fieldBytes , err := json .Marshal (unstructured [name ])
324
+ if err != nil {
325
+ return nil , err
326
+ }
327
+ return fieldBytes , nil
328
+ }
329
+
330
+ specBytes , err := extractFieldBytes (dRuleBytes , "spec" )
331
+ if err != nil {
332
+ return err
333
+ }
334
+
335
+ subsetsBytes , err := extractFieldBytes (specBytes , "subsets" )
336
+ if err != nil {
337
+ return err
338
+ }
339
+
340
+ subsetsMap := []map [string ]interface {}{}
341
+ err = json .Unmarshal (subsetsBytes , & subsetsMap )
342
+ if err != nil {
343
+ return err
344
+ }
345
+
346
+ dRule .Spec .Subsets = []Subset {}
347
+ for _ , si := range subsetsMap {
348
+ var subset Subset
349
+
350
+ jsonInput , _ := json .Marshal (si )
351
+ extra , err := UnmarshalJson (jsonInput , & subset )
352
+ if err != nil {
353
+ return err
354
+ }
355
+
356
+ subset .Extra = extra
357
+ if len (subset .Extra ) == 0 {
358
+ subset .Extra = nil
359
+ }
360
+ dRule .Spec .Subsets = append (dRule .Spec .Subsets , subset )
361
+ }
362
+ return nil
363
+ }
364
+
365
+ func UnmarshalJson (input []byte , result interface {}) (map [string ]interface {}, error ) {
366
+ // unmarshal json to a map
367
+ foomap := make (map [string ]interface {})
368
+ json .Unmarshal (input , & foomap )
369
+
370
+ // create a mapstructure decoder
371
+ var md mapstructure.Metadata
372
+ decoder , err := mapstructure .NewDecoder (
373
+ & mapstructure.DecoderConfig {
374
+ Metadata : & md ,
375
+ Result : result ,
376
+ })
377
+ if err != nil {
378
+ return nil , err
379
+ }
380
+
381
+ // decode the unmarshalled map into the given struct
382
+ if err := decoder .Decode (foomap ); err != nil {
383
+ return nil , err
384
+ }
385
+
386
+ // copy and return unused fields
387
+ unused := map [string ]interface {}{}
388
+ for _ , k := range md .Unused {
389
+ unused [k ] = foomap [k ]
390
+ }
391
+ return unused , nil
392
+ }
393
+
278
394
func jsonBytesToDestinationRule (dRuleBytes []byte ) (* DestinationRule , error ) {
279
395
var dRule DestinationRule
280
396
err := json .Unmarshal (dRuleBytes , & dRule )
281
397
if err != nil {
282
398
return nil , err
283
399
}
400
+ err = unMarshalSubsets (& dRule , dRuleBytes )
401
+ if err != nil {
402
+ return nil , err
403
+ }
284
404
return & dRule , nil
285
405
}
286
406
0 commit comments