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  }