Merge pull request #3517 from monopole/pathSplitter

Expose smart path splitter as a utility.
This commit is contained in:
Jeff Regan
2021-01-31 07:56:42 -08:00
committed by GitHub
5 changed files with 73 additions and 74 deletions

View File

@@ -7,6 +7,7 @@ import (
"strings"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -37,7 +38,7 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
return obj, errors.Wrap(err)
}
fltr.path = splitPath(fltr.FieldSpec.Path)
fltr.path = utils.PathSplitter(fltr.FieldSpec.Path)
if err := fltr.filter(obj); err != nil {
s, _ := obj.String()
return nil, errors.WrapPrefixf(err,
@@ -165,18 +166,3 @@ func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) {
return true, nil
}
func splitPath(path string) []string {
ps := strings.Split(path, "/")
var res []string
res = append(res, ps[0])
for i := 1; i < len(ps); i++ {
lastIndex := len(res) - 1
if strings.HasSuffix(res[lastIndex], "\\") {
res[lastIndex] = strings.TrimSuffix(res[lastIndex], "\\") + "/" + ps[i]
} else {
res = append(res, ps[i])
}
}
return res
}

View File

@@ -0,0 +1,22 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import "strings"
// PathSplitter splits a slash delimited string, permitting escaped slashes.
func PathSplitter(path string) []string {
ps := strings.Split(path, "/")
var res []string
res = append(res, ps[0])
for i := 1; i < len(ps); i++ {
last := len(res) - 1
if strings.HasSuffix(res[last], `\`) {
res[last] = strings.TrimSuffix(res[last], `\`) + "/" + ps[i]
} else {
res = append(res, ps[i])
}
}
return res
}

View File

@@ -0,0 +1,49 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils_test
import (
"testing"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/internal/utils"
)
func TestPathSplitter(t *testing.T) {
for _, tc := range []struct {
exp []string
path string
}{
{
path: "",
exp: []string{""},
},
{
path: "s",
exp: []string{"s"},
},
{
path: "a/b/c",
exp: []string{"a", "b", "c"},
},
{
path: `a/b[]/c`,
exp: []string{"a", "b[]", "c"},
},
{
path: `a/b\/c/d\/e/f`,
exp: []string{"a", "b/c", "d/e", "f"},
},
{
// The actual reason for this.
path: `metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret`,
exp: []string{
"metadata",
"annotations",
"nginx.ingress.kubernetes.io/auth-secret"},
},
} {
assert.Equal(t, tc.exp, PathSplitter(tc.path))
}
}

View File

@@ -5,7 +5,6 @@ package types
import (
"fmt"
"strings"
"sigs.k8s.io/kustomize/api/resid"
)
@@ -34,11 +33,6 @@ type FieldSpec struct {
CreateIfNotPresent bool `json:"create,omitempty" yaml:"create,omitempty"`
}
const (
escapedForwardSlash = "\\/"
tempSlashReplacement = "???"
)
func (fs FieldSpec) String() string {
return fmt.Sprintf(
"%s:%v:%s", fs.Gvk.String(), fs.CreateIfNotPresent, fs.Path)
@@ -49,34 +43,6 @@ func (fs FieldSpec) effectivelyEquals(other FieldSpec) bool {
return fs.IsSelected(&other.Gvk) && fs.Path == other.Path
}
// PathSlice converts the path string to a slice of strings,
// separated by a '/'. Forward slash can be contained in a
// fieldname. such as ingress.kubernetes.io/auth-secret in
// Ingress annotations. To deal with this special case, the
// path to this field should be formatted as
//
// metadata/annotations/ingress.kubernetes.io\/auth-secret
//
// Then PathSlice will return
//
// []string{
// "metadata",
// "annotations",
// "ingress.auth-secretkubernetes.io/auth-secret"
// }
func (fs FieldSpec) PathSlice() []string {
if !strings.Contains(fs.Path, escapedForwardSlash) {
return strings.Split(fs.Path, "/")
}
s := strings.Replace(fs.Path, escapedForwardSlash, tempSlashReplacement, -1)
paths := strings.Split(s, "/")
var result []string
for _, path := range paths {
result = append(result, strings.Replace(path, tempSlashReplacement, "/", -1))
}
return result
}
type FsSlice []FieldSpec
func (s FsSlice) Len() int { return len(s) }

View File

@@ -13,30 +13,6 @@ import (
. "sigs.k8s.io/kustomize/api/types"
)
func TestPathSlice(t *testing.T) {
type path struct {
input string
parsed []string
}
paths := []path{
{
input: "spec/metadata/annotations",
parsed: []string{"spec", "metadata", "annotations"},
},
{
input: `metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret`,
parsed: []string{"metadata", "annotations", "nginx.ingress.kubernetes.io/auth-secret"},
},
}
for _, p := range paths {
fs := FieldSpec{Path: p.input}
actual := fs.PathSlice()
if !reflect.DeepEqual(actual, p.parsed) {
t.Fatalf("expected %v, but got %v", p.parsed, actual)
}
}
}
var mergeTests = []struct {
name string
original FsSlice