mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-18 12:42:19 +00:00
168 lines
2.9 KiB
Go
168 lines
2.9 KiB
Go
package yamlpatch
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Container is the interface for performing operations on Nodes
|
|
type Container interface {
|
|
Get(key string) (*Node, error)
|
|
Set(key string, val *Node) error
|
|
Add(key string, val *Node) error
|
|
Remove(key string) error
|
|
}
|
|
|
|
type nodeMap map[interface{}]*Node
|
|
|
|
func (n *nodeMap) Set(key string, val *Node) error {
|
|
(*n)[key] = val
|
|
return nil
|
|
}
|
|
|
|
func (n *nodeMap) Add(key string, val *Node) error {
|
|
(*n)[key] = val
|
|
return nil
|
|
}
|
|
|
|
func (n *nodeMap) Get(key string) (*Node, error) {
|
|
return (*n)[key], nil
|
|
}
|
|
|
|
func (n *nodeMap) Remove(key string) error {
|
|
_, ok := (*n)[key]
|
|
if !ok {
|
|
return fmt.Errorf("Unable to remove nonexistent key: %s", key)
|
|
}
|
|
|
|
delete(*n, key)
|
|
return nil
|
|
}
|
|
|
|
type nodeSlice []*Node
|
|
|
|
func (n *nodeSlice) Set(index string, val *Node) error {
|
|
i, err := strconv.Atoi(index)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sz := len(*n)
|
|
if i+1 > sz {
|
|
sz = i + 1
|
|
}
|
|
|
|
ary := make([]*Node, sz)
|
|
|
|
cur := *n
|
|
|
|
copy(ary, cur)
|
|
|
|
if i >= len(ary) {
|
|
return fmt.Errorf("Unable to access invalid index: %d", i)
|
|
}
|
|
|
|
ary[i] = val
|
|
|
|
*n = ary
|
|
return nil
|
|
}
|
|
|
|
func (n *nodeSlice) Add(index string, val *Node) error {
|
|
if index == "-" {
|
|
*n = append(*n, val)
|
|
return nil
|
|
}
|
|
|
|
i, err := strconv.Atoi(index)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ary := make([]*Node, len(*n)+1)
|
|
|
|
cur := *n
|
|
|
|
copy(ary[0:i], cur[0:i])
|
|
ary[i] = val
|
|
copy(ary[i+1:], cur[i:])
|
|
|
|
*n = ary
|
|
return nil
|
|
}
|
|
|
|
func (n *nodeSlice) Get(index string) (*Node, error) {
|
|
i, err := strconv.Atoi(index)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if i >= 0 && i <= len(*n)-1 {
|
|
return (*n)[i], nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("Unable to access invalid index: %d", i)
|
|
}
|
|
|
|
func (n *nodeSlice) Remove(index string) error {
|
|
i, err := strconv.Atoi(index)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cur := *n
|
|
|
|
if i >= len(cur) {
|
|
return fmt.Errorf("Unable to remove invalid index: %d", i)
|
|
}
|
|
|
|
ary := make([]*Node, len(cur)-1)
|
|
|
|
copy(ary[0:i], cur[0:i])
|
|
copy(ary[i:], cur[i+1:])
|
|
|
|
*n = ary
|
|
return nil
|
|
|
|
}
|
|
|
|
func findContainer(c Container, path *OpPath) (Container, string, error) {
|
|
parts, key, err := path.Decompose()
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
foundContainer := c
|
|
|
|
for _, part := range parts {
|
|
node, err := foundContainer.Get(decodePatchKey(part))
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
if node == nil {
|
|
return nil, "", fmt.Errorf("path does not exist: %s", path)
|
|
}
|
|
|
|
foundContainer = node.Container()
|
|
}
|
|
|
|
return foundContainer, decodePatchKey(key), nil
|
|
}
|
|
|
|
// From http://tools.ietf.org/html/rfc6901#section-4 :
|
|
//
|
|
// Evaluation of each reference token begins by decoding any escaped
|
|
// character sequence. This is performed by first transforming any
|
|
// occurrence of the sequence '~1' to '/', and then transforming any
|
|
// occurrence of the sequence '~0' to '~'.
|
|
|
|
var (
|
|
rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
|
|
)
|
|
|
|
func decodePatchKey(k string) string {
|
|
return rfc6901Decoder.Replace(k)
|
|
}
|