github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/kubernetes/patch_operations.go (about) 1 package kubernetes 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "sort" 7 "strings" 8 ) 9 10 func diffStringMap(pathPrefix string, oldV, newV map[string]interface{}) PatchOperations { 11 ops := make([]PatchOperation, 0, 0) 12 13 pathPrefix = strings.TrimRight(pathPrefix, "/") 14 15 // This is suboptimal for adding whole new map from scratch 16 // or deleting the whole map, but it's actually intention. 17 // There may be some other map items managed outside of TF 18 // and we don't want to touch these. 19 20 for k, _ := range oldV { 21 if _, ok := newV[k]; ok { 22 continue 23 } 24 ops = append(ops, &RemoveOperation{Path: pathPrefix + "/" + k}) 25 } 26 27 for k, v := range newV { 28 newValue := v.(string) 29 30 if oldValue, ok := oldV[k].(string); ok { 31 if oldValue == newValue { 32 continue 33 } 34 35 ops = append(ops, &ReplaceOperation{ 36 Path: pathPrefix + "/" + k, 37 Value: newValue, 38 }) 39 continue 40 } 41 42 ops = append(ops, &AddOperation{ 43 Path: pathPrefix + "/" + k, 44 Value: newValue, 45 }) 46 } 47 48 return ops 49 } 50 51 type PatchOperations []PatchOperation 52 53 func (po PatchOperations) MarshalJSON() ([]byte, error) { 54 var v []PatchOperation = po 55 return json.Marshal(v) 56 } 57 58 func (po PatchOperations) Equal(ops []PatchOperation) bool { 59 var v []PatchOperation = po 60 61 sort.Slice(v, sortByPathAsc(v)) 62 sort.Slice(ops, sortByPathAsc(ops)) 63 64 return reflect.DeepEqual(v, ops) 65 } 66 67 func sortByPathAsc(ops []PatchOperation) func(i, j int) bool { 68 return func(i, j int) bool { 69 return ops[i].GetPath() < ops[j].GetPath() 70 } 71 } 72 73 type PatchOperation interface { 74 MarshalJSON() ([]byte, error) 75 GetPath() string 76 } 77 78 type ReplaceOperation struct { 79 Path string `json:"path"` 80 Value interface{} `json:"value"` 81 Op string `json:"op"` 82 } 83 84 func (o *ReplaceOperation) GetPath() string { 85 return o.Path 86 } 87 88 func (o *ReplaceOperation) MarshalJSON() ([]byte, error) { 89 o.Op = "replace" 90 return json.Marshal(*o) 91 } 92 93 func (o *ReplaceOperation) String() string { 94 b, _ := o.MarshalJSON() 95 return string(b) 96 } 97 98 type AddOperation struct { 99 Path string `json:"path"` 100 Value interface{} `json:"value"` 101 Op string `json:"op"` 102 } 103 104 func (o *AddOperation) GetPath() string { 105 return o.Path 106 } 107 108 func (o *AddOperation) MarshalJSON() ([]byte, error) { 109 o.Op = "add" 110 return json.Marshal(*o) 111 } 112 113 func (o *AddOperation) String() string { 114 b, _ := o.MarshalJSON() 115 return string(b) 116 } 117 118 type RemoveOperation struct { 119 Path string `json:"path"` 120 Op string `json:"op"` 121 } 122 123 func (o *RemoveOperation) GetPath() string { 124 return o.Path 125 } 126 127 func (o *RemoveOperation) MarshalJSON() ([]byte, error) { 128 o.Op = "remove" 129 return json.Marshal(*o) 130 } 131 132 func (o *RemoveOperation) String() string { 133 b, _ := o.MarshalJSON() 134 return string(b) 135 }