mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Merge pull request #3517 from monopole/pathSplitter
Expose smart path splitter as a utility.
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"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 {
|
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
|
||||||
return obj, errors.Wrap(err)
|
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 {
|
if err := fltr.filter(obj); err != nil {
|
||||||
s, _ := obj.String()
|
s, _ := obj.String()
|
||||||
return nil, errors.WrapPrefixf(err,
|
return nil, errors.WrapPrefixf(err,
|
||||||
@@ -165,18 +166,3 @@ func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) {
|
|||||||
|
|
||||||
return true, nil
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
22
api/internal/utils/pathsplitter.go
Normal file
22
api/internal/utils/pathsplitter.go
Normal 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
|
||||||
|
}
|
||||||
49
api/internal/utils/pathsplitter_test.go
Normal file
49
api/internal/utils/pathsplitter_test.go
Normal 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
)
|
)
|
||||||
@@ -34,11 +33,6 @@ type FieldSpec struct {
|
|||||||
CreateIfNotPresent bool `json:"create,omitempty" yaml:"create,omitempty"`
|
CreateIfNotPresent bool `json:"create,omitempty" yaml:"create,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
escapedForwardSlash = "\\/"
|
|
||||||
tempSlashReplacement = "???"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (fs FieldSpec) String() string {
|
func (fs FieldSpec) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"%s:%v:%s", fs.Gvk.String(), fs.CreateIfNotPresent, fs.Path)
|
"%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
|
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
|
type FsSlice []FieldSpec
|
||||||
|
|
||||||
func (s FsSlice) Len() int { return len(s) }
|
func (s FsSlice) Len() int { return len(s) }
|
||||||
|
|||||||
@@ -13,30 +13,6 @@ import (
|
|||||||
. "sigs.k8s.io/kustomize/api/types"
|
. "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 {
|
var mergeTests = []struct {
|
||||||
name string
|
name string
|
||||||
original FsSlice
|
original FsSlice
|
||||||
|
|||||||
Reference in New Issue
Block a user