From fa0b23717872364a7ff388cb0aef29cd88a7edba Mon Sep 17 00:00:00 2001 From: Natasha Sarkar Date: Wed, 17 Mar 2021 13:51:31 -0700 Subject: [PATCH] add replacement filter to support replacmenttransformer --- api/filters/replacement/doc.go | 4 + api/filters/replacement/example_test.go | 68 ++++ api/filters/replacement/replacement.go | 123 +++++++ api/filters/replacement/replacement_test.go | 336 ++++++++++++++++++ api/internal/crawl/cmd/backend/main.go | 3 +- api/internal/crawl/crawler/github/crawler.go | 2 +- .../github/split_search_ranges_test.go | 2 +- api/resmap/selector_test.go | 48 +-- api/types/patch_test.go | 42 ++- api/types/replacement.go | 65 +++- api/types/selector.go | 22 +- api/types/selector_test.go | 100 ++++-- api/types/var.go | 4 +- api/types/var_test.go | 6 +- 14 files changed, 722 insertions(+), 103 deletions(-) create mode 100644 api/filters/replacement/doc.go create mode 100644 api/filters/replacement/example_test.go create mode 100644 api/filters/replacement/replacement.go create mode 100644 api/filters/replacement/replacement_test.go diff --git a/api/filters/replacement/doc.go b/api/filters/replacement/doc.go new file mode 100644 index 000000000..9d9357905 --- /dev/null +++ b/api/filters/replacement/doc.go @@ -0,0 +1,4 @@ +// Package replacement contains a kio.Filter implementation of the kustomize +// replacement transformer (accepts sources and looks for targets to replace +// their values with values from the sources). +package replacement diff --git a/api/filters/replacement/example_test.go b/api/filters/replacement/example_test.go new file mode 100644 index 000000000..c55956337 --- /dev/null +++ b/api/filters/replacement/example_test.go @@ -0,0 +1,68 @@ +// Copyright 2021 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package replacement + +import ( + "bytes" + "log" + "os" + + "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +func ExampleFilter() { + f := Filter{} + err := yaml.Unmarshal([]byte(` +replacements: +- source: + kind: Foo2 + fieldPath: spec.replicas + targets: + - select: + kind: Foo1 + fieldPaths: + - spec.replicas`), &f) + if err != nil { + log.Fatal(err) + } + + err = kio.Pipeline{ + Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(` +apiVersion: example.com/v1 +kind: Foo1 +metadata: + name: instance +spec: + replicas: 3 +--- +apiVersion: example.com/v1 +kind: Foo2 +metadata: + name: instance +spec: + replicas: 99 +`)}}, + Filters: []kio.Filter{f}, + Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}}, + }.Execute() + if err != nil { + log.Fatal(err) + } + + // Output: + // apiVersion: example.com/v1 + // kind: Foo1 + // metadata: + // name: instance + // spec: + // replicas: 99 + // --- + // apiVersion: example.com/v1 + // kind: Foo2 + // metadata: + // name: instance + // spec: + // replicas: 99 +} diff --git a/api/filters/replacement/replacement.go b/api/filters/replacement/replacement.go new file mode 100644 index 000000000..70a1a4d75 --- /dev/null +++ b/api/filters/replacement/replacement.go @@ -0,0 +1,123 @@ +// Copyright 2021 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package replacement + +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/api/resid" + "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +type Filter struct { + Replacements []types.Replacement +} + +// Filter replaces values of targets with values from sources +// TODO (#3492): Connect this to a replacement transformer plugin +func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { + for _, r := range f.Replacements { + if r.Source == nil || r.Targets == nil { + return nil, fmt.Errorf("replacements must specify a source and at least one target") + } + value, err := getReplacement(nodes, &r) + if err != nil { + return nil, err + } + nodes, err = applyReplacement(nodes, value, r.Targets) + if err != nil { + return nil, err + } + } + return nodes, nil +} + +func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.TargetSelector) ([]*yaml.RNode, error) { + for _, t := range targets { + if len(t.FieldPaths) == 0 { + t.FieldPaths = []string{types.DefaultReplacementFieldPath} + } + for _, n := range nodes { + // TODO (#3492): Don't include matches listed in the `reject` field + if t.Select.KrmId.Match(getKrmId(n)) { + err := applyToNode(n, value, t) + if err != nil { + return nil, err + } + } + } + } + return nodes, nil +} + +func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelector) error { + if target.Select == nil { + return fmt.Errorf("target must specify resources to select") + } + for _, fp := range target.FieldPaths { + fieldPath := strings.Split(fp, ".") + // TODO (#3492): Add tests for map keys in the fieldPath (e.g. .spec.containers[name=nginx]) + t, err := node.Pipe(yaml.Lookup(fieldPath...)) + if err != nil { + return err + } + if t != nil { + // TODO (#3492): Use the field options to refine interpretation of the field + t.SetYNode(value.YNode()) + } + } + return nil +} + +func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, error) { + source, err := selectSourceNode(nodes, r.Source) + if err != nil { + return nil, err + } + + if r.Source.FieldPath == "" { + r.Source.FieldPath = types.DefaultReplacementFieldPath + } + fieldPath := strings.Split(r.Source.FieldPath, ".") + + // TODO (#3492): Add tests for map keys in the fieldPath (e.g. .spec.containers[name=nginx]) + rn, err := source.Pipe(yaml.Lookup(fieldPath...)) + if err != nil { + return nil, err + } + // TODO (#3492): Use the field options to refine interpretation of the field + return rn, nil +} + +// selectSourceNode finds the node that matches the selector, returning +// an error if multiple or none are found +func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) { + var matches []*yaml.RNode + for _, n := range nodes { + if selector.KrmId.Match(getKrmId(n)) { + if len(matches) > 0 { + return nil, fmt.Errorf("more than one match for source %v", selector) + } + matches = append(matches, n) + } + } + if len(matches) == 0 { + return nil, fmt.Errorf("found no matches for source %v", selector) + } + return matches[0], nil +} + +func getKrmId(n *yaml.RNode) *types.KrmId { + ns, _ := n.GetNamespace() + apiVersion := yaml.GetValue(n.Field(yaml.APIVersionField).Value) + group, version := resid.ParseGroupVersion(apiVersion) + + return &types.KrmId{ + Gvk: resid.Gvk{Group: group, Version: version, Kind: n.GetKind()}, + Name: n.GetName(), + Namespace: ns, + } +} diff --git a/api/filters/replacement/replacement_test.go b/api/filters/replacement/replacement_test.go new file mode 100644 index 000000000..bc3bca3ba --- /dev/null +++ b/api/filters/replacement/replacement_test.go @@ -0,0 +1,336 @@ +// Copyright 2021 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package replacement + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest" + "sigs.k8s.io/yaml" +) + +func TestFilter(t *testing.T) { + testCases := map[string]struct { + input string + replacements string + expected string + expectedErr bool + }{ + "simple": { + input: `apiVersion: v1 +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +--- +apiVersion: v1 +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +`, + replacements: `replacements: +- source: + kind: Deployment + name: deploy2 + fieldPath: spec.template.spec.containers.0.image + targets: + - select: + kind: Deployment + name: deploy1 + fieldPaths: + - spec.template.spec.containers.1.image +`, + expected: `apiVersion: v1 +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: nginx:1.7.9 + name: postgresdb +--- +apiVersion: v1 +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +`, + }, + "complex type": { + input: `apiVersion: v1 +kind: Pod +metadata: + name: pod +spec: + containers: + - image: busybox + name: myapp-container +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: {} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deploy3 +spec: + template: + spec: + containers: {} +`, + replacements: `replacements: +- source: + kind: Pod + name: pod + fieldPath: spec.containers + targets: + - select: + kind: Deployment + fieldPaths: + - spec.template.spec.containers +`, + expected: `apiVersion: v1 +kind: Pod +metadata: + name: pod +spec: + containers: + - image: busybox + name: myapp-container +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: + - image: busybox + name: myapp-container +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deploy3 +spec: + template: + spec: + containers: + - image: busybox + name: myapp-container +`, + }, + "from ConfigMap": { + input: `apiVersion: apps/v1 +kind: Deployment +metadata: + name: deploy + labels: + foo: bar +spec: + template: + metadata: + labels: + foo: bar + spec: + containers: + - name: command-demo-container + image: debian + command: ["printenv"] + args: + - HOSTNAME + - PORT + - name: busybox + image: busybox:latest + args: + - echo + - HOSTNAME + - PORT +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cm +data: + HOSTNAME: example.com + PORT: 8080 +`, + replacements: `replacements: +- source: + kind: ConfigMap + name: cm + fieldPath: data.HOSTNAME + targets: + - select: + kind: Deployment + fieldPaths: + - spec.template.spec.containers.0.args.0 + - spec.template.spec.containers.1.args.1 +- source: + kind: ConfigMap + name: cm + fieldPath: data.PORT + targets: + - select: + kind: Deployment + fieldPaths: + - spec.template.spec.containers.0.args.1 + - spec.template.spec.containers.1.args.2 +`, + expected: `apiVersion: apps/v1 +kind: Deployment +metadata: + name: deploy + labels: + foo: bar +spec: + template: + metadata: + labels: + foo: bar + spec: + containers: + - name: command-demo-container + image: debian + command: ["printenv"] + args: + - example.com + - 8080 + - name: busybox + image: busybox:latest + args: + - echo + - example.com + - 8080 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cm +data: + HOSTNAME: example.com + PORT: 8080 +`, + }, + "multiple matches for source select": { + input: `apiVersion: v1 +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +--- +apiVersion: v1 +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +--- +apiVersion: v1 +kind: Deployment +metadata: + name: deploy3 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +`, + replacements: `replacements: +- source: + kind: Deployment + targets: + - select: + kind: Deployment +`, + expectedErr: true, + }, + "replacement has no source": { + input: `apiVersion: v1 +kind: Deployment +metadata: + name: deploy +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: postgres:1.8.0 + name: postgresdb +`, + replacements: `replacements: +- targets: + - select: + kind: Deployment +`, + expectedErr: true, + }, + } + + for tn, tc := range testCases { + t.Run(tn, func(t *testing.T) { + f := Filter{} + err := yaml.Unmarshal([]byte(tc.replacements), &f) + assert.NoError(t, err) + actual, err := filtertest.RunFilterE(t, tc.input, f) + assert.Equal(t, tc.expectedErr, err != nil) + if !tc.expectedErr && + !assert.Equal(t, strings.TrimSpace(tc.expected), strings.TrimSpace(actual)) { + t.FailNow() + } + }) + } +} diff --git a/api/internal/crawl/cmd/backend/main.go b/api/internal/crawl/cmd/backend/main.go index b3ab23b7f..c43e3c160 100644 --- a/api/internal/crawl/cmd/backend/main.go +++ b/api/internal/crawl/cmd/backend/main.go @@ -4,8 +4,9 @@ import ( "context" "log" "os" - server "sigs.k8s.io/kustomize/api/internal/crawl/backend" "strconv" + + server "sigs.k8s.io/kustomize/api/internal/crawl/backend" ) func main() { diff --git a/api/internal/crawl/crawler/github/crawler.go b/api/internal/crawl/crawler/github/crawler.go index d668a86b4..b357f5a94 100644 --- a/api/internal/crawl/crawler/github/crawler.go +++ b/api/internal/crawl/crawler/github/crawler.go @@ -81,7 +81,7 @@ func (gc githubCrawler) Crawl(ctx context.Context, output chan<- crawler.CrawledDocument, seen utils.SeenMap) error { ranges := []RangeWithin{ - RangeWithin{ + { start: uint64(0), end: githubMaxFileSize, }, diff --git a/api/internal/crawl/crawler/github/split_search_ranges_test.go b/api/internal/crawl/crawler/github/split_search_ranges_test.go index 788ef17bc..4e97bc132 100644 --- a/api/internal/crawl/crawler/github/split_search_ranges_test.go +++ b/api/internal/crawl/crawler/github/split_search_ranges_test.go @@ -96,6 +96,6 @@ func TestRangeSizes(t *testing.T) { returnedResult := RangeSizes(s) expectedResult := RangeWithin{uint64(2365), uint64(10000)} if !reflect.DeepEqual(returnedResult, expectedResult) { - t.Errorf("RangeSizes expected (%v), got (%v)",expectedResult, returnedResult) + t.Errorf("RangeSizes expected (%v), got (%v)", expectedResult, returnedResult) } } diff --git a/api/resmap/selector_test.go b/api/resmap/selector_test.go index 5e5f0f647..0da443f55 100644 --- a/api/resmap/selector_test.go +++ b/api/resmap/selector_test.go @@ -61,13 +61,13 @@ func TestFindPatchTargets(t *testing.T) { }{ "select_01": { target: types.Selector{ - Name: "name.*", + KrmId: types.KrmId{Name: "name.*"}, }, count: 3, }, "select_02": { target: types.Selector{ - Name: "name.*", + KrmId: types.KrmId{Name: "name.*"}, AnnotationSelector: "foo=bar", }, count: 2, @@ -80,98 +80,102 @@ func TestFindPatchTargets(t *testing.T) { }, "select_04": { target: types.Selector{ - Gvk: resid.Gvk{ - Kind: "Kind1", + KrmId: types.KrmId{ + Gvk: resid.Gvk{ + Kind: "Kind1", + }, + Name: "name.*", }, - Name: "name.*", }, count: 2, }, "select_05": { target: types.Selector{ - Name: "NotMatched", + KrmId: types.KrmId{Name: "NotMatched"}, }, count: 0, }, "select_06": { target: types.Selector{ - Name: "", + KrmId: types.KrmId{Name: ""}, }, count: 4, }, "select_07": { target: types.Selector{ - Namespace: "default", + KrmId: types.KrmId{Namespace: "default"}, }, count: 2, }, "select_08": { target: types.Selector{ - Namespace: "", + KrmId: types.KrmId{Namespace: ""}, }, count: 4, }, "select_09": { target: types.Selector{ - Namespace: "default", - Name: "name.*", - Gvk: resid.Gvk{ - Kind: "Kind1", + KrmId: types.KrmId{ + Namespace: "default", + Name: "name.*", + Gvk: resid.Gvk{ + Kind: "Kind1", + }, }, }, count: 1, }, "select_10": { target: types.Selector{ - Name: "^name.*", + KrmId: types.KrmId{Name: "^name.*"}, }, count: 3, }, "select_11": { target: types.Selector{ - Name: "name.*$", + KrmId: types.KrmId{Name: "name.*$"}, }, count: 3, }, "select_12": { target: types.Selector{ - Name: "^name.*$", + KrmId: types.KrmId{Name: "^name.*$"}, }, count: 3, }, "select_13": { target: types.Selector{ - Namespace: "^def.*", + KrmId: types.KrmId{Namespace: "^def.*"}, }, count: 2, }, "select_14": { target: types.Selector{ - Namespace: "def.*$", + KrmId: types.KrmId{Namespace: "def.*$"}, }, count: 2, }, "select_15": { target: types.Selector{ - Namespace: "^def.*$", + KrmId: types.KrmId{Namespace: "^def.*$"}, }, count: 2, }, "select_16": { target: types.Selector{ - Namespace: "default", + KrmId: types.KrmId{Namespace: "default"}, }, count: 2, }, "select_17": { target: types.Selector{ - Namespace: "NotMatched", + KrmId: types.KrmId{Namespace: "NotMatched"}, }, count: 0, }, "select_18": { target: types.Selector{ - Namespace: "ns1", + KrmId: types.KrmId{Namespace: "ns1"}, }, count: 1, }, diff --git a/api/types/patch_test.go b/api/types/patch_test.go index 1e30de0d5..5996df340 100644 --- a/api/types/patch_test.go +++ b/api/types/patch_test.go @@ -9,13 +9,15 @@ import ( func TestPatchEquals(t *testing.T) { selector := Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "version", - Kind: "kind", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "version", + Kind: "kind", + }, + Name: "name", + Namespace: "namespace", }, - Name: "name", - Namespace: "namespace", LabelSelector: "selector", AnnotationSelector: "selector", } @@ -38,13 +40,15 @@ func TestPatchEquals(t *testing.T) { Path: "foo", Patch: "bar", Target: &Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "version", - Kind: "kind", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "version", + Kind: "kind", + }, + Name: "name", + Namespace: "namespace", }, - Name: "name", - Namespace: "namespace", LabelSelector: "selector", AnnotationSelector: "selector", }, @@ -53,13 +57,15 @@ func TestPatchEquals(t *testing.T) { Path: "foo", Patch: "bar", Target: &Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "version", - Kind: "kind", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "version", + Kind: "kind", + }, + Name: "name", + Namespace: "namespace", }, - Name: "name", - Namespace: "namespace", LabelSelector: "selector", AnnotationSelector: "selector", }, diff --git a/api/types/replacement.go b/api/types/replacement.go index 57c2507ad..cd9ecbb75 100644 --- a/api/types/replacement.go +++ b/api/types/replacement.go @@ -1,27 +1,62 @@ -// Copyright 2019 The Kubernetes Authors. +// Copyright 2021 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 package types +const DefaultReplacementFieldPath = "metadata.name" + // Replacement defines how to perform a substitution // where it is from and where it is to. type Replacement struct { - Source *ReplSource `json:"source" yaml:"source"` - Target *ReplTarget `json:"target" yaml:"target"` + // The source of the value. + Source *SourceSelector `json:"source" yaml:"source"` + + // The N fields to write the value to. + Targets []*TargetSelector `json:"targets" yaml:"targets"` } -// ReplSource defines where a substitution is from -// It can from two different kinds of sources -// - from a field of one resource -// - from a string -type ReplSource struct { - ObjRef *Target `json:"objref,omitempty" yaml:"objref,omitempty"` - FieldRef string `json:"fieldref,omitempty" yaml:"fiedldref,omitempty"` - Value string `json:"value,omitempty" yaml:"value,omitempty"` +// SourceSelector is the source of the replacement transformer. +type SourceSelector struct { + // A specific object to read it from. + KrmId `json:",inline,omitempty" yaml:",inline,omitempty"` + + // Structured field path expected in the allowed object. + FieldPath string `json:"fieldPath" yaml:"fieldPath"` + + // Used to refine the interpretation of the field + Options *FieldOptions `json:"options" yaml:"options"` } -// ReplTarget defines where a substitution is to. -type ReplTarget struct { - ObjRef *Selector `json:"objref,omitempty" yaml:"objref,omitempty"` - FieldRefs []string `json:"fieldrefs,omitempty" yaml:"fieldrefs,omitempty"` +// TargetSelector specifies fields in one or more objects. +type TargetSelector struct { + // Include objects that match this. + Select *Selector `json:"select" yaml:"select"` + + // From the allowed set, remove objects that match this. + // TODO (#3492): Remove matches listed in the exclude field + // Currently this field is unused + Reject *Selector `json:"reject" yaml:"reject"` + + // Structured field paths expected in each allowed object. + FieldPaths []string `json:"fieldPaths" yaml:"fieldPaths"` + + // Used to refine the interpretation of the field + Options *FieldOptions `json:"options" yaml:"options"` +} + +// FieldPath is a structured field path to the desired object +// TODO (#3492): Implement use of these options, they are +// currently used +type FieldOptions struct { + // Used to split/join the field. + Delimiter string `json:"delimiter" yaml:"delimiter"` + + // Which position in the split to consider. + Index int `json:"index" yaml:"index"` + + // None, Base64, URL, Hex, etc + Encoding string `json:"encoding" yaml:"index"` + + // If field missing, add it + Create bool `json:"create" yaml:"create"` } diff --git a/api/types/selector.go b/api/types/selector.go index 007b508f1..4b7295c6a 100644 --- a/api/types/selector.go +++ b/api/types/selector.go @@ -13,9 +13,8 @@ import ( // Any resource that matches intersection of all conditions // is included in this set. type Selector struct { - resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` - Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` - Name string `json:"name,omitempty" yaml:"name,omitempty"` + // KrmId refers to a GVKN/Ns of a resource. + KrmId `json:",inline,omitempty" yaml:",inline,omitempty"` // AnnotationSelector is a string that follows the label selection expression // https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api @@ -28,6 +27,23 @@ type Selector struct { LabelSelector string `json:"labelSelector,omitempty" yaml:"labelSelector,omitempty"` } +// KrmId refers to a GVKN/Ns of a resource. +type KrmId struct { + resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` +} + +// Match returns true if id selects other, i.e. id's fields +// either match other's or are empty +func (id *KrmId) Match(other *KrmId) bool { + return (id.Group == "" || id.Group == other.Group) && + (id.Version == "" || id.Version == other.Version) && + (id.Kind == "" || id.Kind == other.Kind) && + (id.Name == "" || id.Name == other.Name) && + (id.Namespace == "" || id.Namespace == other.Namespace) +} + // SelectorRegex is a Selector with regex in GVK // Any resource that matches intersection of all conditions // is included in this set. diff --git a/api/types/selector_test.go b/api/types/selector_test.go index 9625d9964..ddca0c082 100644 --- a/api/types/selector_test.go +++ b/api/types/selector_test.go @@ -15,10 +15,12 @@ func TestSelectorRegexMatchGvk(t *testing.T) { }{ { S: Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "version", - Kind: "kind", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "version", + Kind: "kind", + }, }, }, G: resid.Gvk{ @@ -30,10 +32,12 @@ func TestSelectorRegexMatchGvk(t *testing.T) { }, { S: Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "", - Kind: "", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "", + Kind: "", + }, }, }, G: resid.Gvk{ @@ -45,10 +49,12 @@ func TestSelectorRegexMatchGvk(t *testing.T) { }, { S: Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "version", - Kind: "kind", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "version", + Kind: "kind", + }, }, }, G: resid.Gvk{ @@ -60,10 +66,12 @@ func TestSelectorRegexMatchGvk(t *testing.T) { }, { S: Selector{ - Gvk: resid.Gvk{ - Group: "group", - Version: "version", - Kind: "kind", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "group", + Version: "version", + Kind: "kind", + }, }, }, G: resid.Gvk{ @@ -75,10 +83,12 @@ func TestSelectorRegexMatchGvk(t *testing.T) { }, { S: Selector{ - Gvk: resid.Gvk{ - Group: "g.*", - Version: "\\d+", - Kind: ".{4}", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "g.*", + Version: "\\d+", + Kind: ".{4}", + }, }, }, G: resid.Gvk{ @@ -90,10 +100,12 @@ func TestSelectorRegexMatchGvk(t *testing.T) { }, { S: Selector{ - Gvk: resid.Gvk{ - Group: "g.*", - Version: "\\d+", - Kind: ".{4}", + KrmId: KrmId{ + Gvk: resid.Gvk{ + Group: "g.*", + Version: "\\d+", + Kind: ".{4}", + }, }, }, G: resid.Gvk{ @@ -125,30 +137,38 @@ func TestSelectorRegexMatchName(t *testing.T) { }{ { S: Selector{ - Name: "foo", - Namespace: "bar", + KrmId: KrmId{ + Name: "foo", + Namespace: "bar", + }, }, Name: "foo", Expected: true, }, { S: Selector{ - Name: "foo", - Namespace: "bar", + KrmId: KrmId{ + Name: "foo", + Namespace: "bar", + }, }, Name: "bar", Expected: false, }, { S: Selector{ - Name: "f.*", + KrmId: KrmId{ + Name: "f.*", + }, }, Name: "foo", Expected: true, }, { S: Selector{ - Name: "b.*", + KrmId: KrmId{ + Name: "b.*", + }, }, Name: "foo", Expected: false, @@ -174,30 +194,38 @@ func TestSelectorRegexMatchNamespace(t *testing.T) { }{ { S: Selector{ - Name: "bar", - Namespace: "foo", + KrmId: KrmId{ + Name: "bar", + Namespace: "foo", + }, }, Namespace: "foo", Expected: true, }, { S: Selector{ - Name: "foo", - Namespace: "bar", + KrmId: KrmId{ + Name: "foo", + Namespace: "bar", + }, }, Namespace: "foo", Expected: false, }, { S: Selector{ - Namespace: "f.*", + KrmId: KrmId{ + Namespace: "f.*", + }, }, Namespace: "foo", Expected: true, }, { S: Selector{ - Namespace: "b.*", + KrmId: KrmId{ + Namespace: "b.*", + }, }, Namespace: "foo", Expected: false, diff --git a/api/types/var.go b/api/types/var.go index f636d0d35..a95315166 100644 --- a/api/types/var.go +++ b/api/types/var.go @@ -12,8 +12,6 @@ import ( "sigs.k8s.io/kustomize/api/resid" ) -const defaultFieldPath = "metadata.name" - // Var represents a variable whose value will be sourced // from a field in a Kubernetes object. type Var struct { @@ -71,7 +69,7 @@ type FieldSelector struct { // defaulting sets reference to field used by default. func (v *Var) Defaulting() { if v.FieldRef.FieldPath == "" { - v.FieldRef.FieldPath = defaultFieldPath + v.FieldRef.FieldPath = DefaultReplacementFieldPath } v.ObjRef.GVK() } diff --git a/api/types/var_test.go b/api/types/var_test.go index acba67020..4e5e6fe21 100644 --- a/api/types/var_test.go +++ b/api/types/var_test.go @@ -69,9 +69,9 @@ func TestDefaulting(t *testing.T) { }, } v.Defaulting() - if v.FieldRef.FieldPath != defaultFieldPath { + if v.FieldRef.FieldPath != DefaultReplacementFieldPath { t.Fatalf("expected %s, got %v", - defaultFieldPath, v.FieldRef.FieldPath) + DefaultReplacementFieldPath, v.FieldRef.FieldPath) } } @@ -127,7 +127,7 @@ func TestVarSet(t *testing.T) { t.Fatalf("expected var") } // Confirm defaulting. - if v.FieldRef.FieldPath != defaultFieldPath { + if v.FieldRef.FieldPath != DefaultReplacementFieldPath { t.Fatalf("unexpected field path: %v", v.FieldRef.FieldPath) } // Confirm sorting.