mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 09:40:49 +00:00
Compare commits
14 Commits
kyaml/v0.1
...
cmd/config
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed688a87e4 | ||
|
|
629fdee26a | ||
|
|
ca58ce775a | ||
|
|
0990d96c52 | ||
|
|
94c45e0f9f | ||
|
|
ca527a8e4c | ||
|
|
fa0b237178 | ||
|
|
a9bcf7187a | ||
|
|
a49d429909 | ||
|
|
c63288024d | ||
|
|
d203c2328a | ||
|
|
ec0e42709a | ||
|
|
abae65d8f1 | ||
|
|
054f18701a |
5
Makefile
5
Makefile
@@ -3,8 +3,11 @@
|
||||
#
|
||||
# Makefile for kustomize CLI and API.
|
||||
|
||||
MYGOBIN := $(shell go env GOPATH)/bin
|
||||
SHELL := /usr/bin/env bash
|
||||
MYGOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(MYGOBIN),)
|
||||
MYGOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
export PATH := $(MYGOBIN):$(PATH)
|
||||
MODULES := '"cmd/config" "api/" "kustomize/" "kyaml/"'
|
||||
|
||||
|
||||
4
api/filters/replacement/doc.go
Normal file
4
api/filters/replacement/doc.go
Normal file
@@ -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
|
||||
68
api/filters/replacement/example_test.go
Normal file
68
api/filters/replacement/example_test.go
Normal file
@@ -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
|
||||
}
|
||||
126
api/filters/replacement/replacement.go
Normal file
126
api/filters/replacement/replacement.go
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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
|
||||
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 t.Select == nil {
|
||||
return nil, fmt.Errorf("target must specify resources to select")
|
||||
}
|
||||
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 {
|
||||
for _, fp := range target.FieldPaths {
|
||||
t, err := node.Pipe(yaml.Lookup(strings.Split(fp, ".")...))
|
||||
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, ".")
|
||||
|
||||
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, err := n.GetNamespace()
|
||||
if err != nil {
|
||||
// Resource has no metadata (no apiVersion, kind, nor metadata field).
|
||||
// In this case, it cannot be selected.
|
||||
return &types.KrmId{}
|
||||
}
|
||||
apiVersion := n.Field(yaml.APIVersionField)
|
||||
var group, version string
|
||||
if apiVersion != nil {
|
||||
group, version = resid.ParseGroupVersion(yaml.GetValue(apiVersion.Value))
|
||||
}
|
||||
return &types.KrmId{
|
||||
Gvk: resid.Gvk{Group: group, Version: version, Kind: n.GetKind()},
|
||||
Name: n.GetName(),
|
||||
Namespace: ns,
|
||||
}
|
||||
}
|
||||
610
api/filters/replacement/replacement_test.go
Normal file
610
api/filters/replacement/replacement_test.go
Normal file
@@ -0,0 +1,610 @@
|
||||
// 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 string
|
||||
}{
|
||||
"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
|
||||
---
|
||||
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
|
||||
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
|
||||
---
|
||||
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
|
||||
`,
|
||||
},
|
||||
"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: "more than one match for source ~G_~V_Deployment",
|
||||
},
|
||||
"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: "replacements must specify a source and at least one target",
|
||||
},
|
||||
"field paths with key-value pairs": {
|
||||
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.[name=nginx-tagged].image
|
||||
targets:
|
||||
- select:
|
||||
kind: Deployment
|
||||
name: deploy1
|
||||
fieldPaths:
|
||||
- spec.template.spec.containers.[name=postgresdb].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
|
||||
`,
|
||||
},
|
||||
"select by group and version": {
|
||||
input: `apiVersion: my-group-1/v1
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group-2/v2
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group-3/v3
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
`,
|
||||
replacements: `replacements:
|
||||
- source:
|
||||
group: my-group-2
|
||||
fieldPath: spec.template.spec.containers.0.image
|
||||
targets:
|
||||
- select:
|
||||
version: v3
|
||||
fieldPaths:
|
||||
- spec.template.spec.containers.1.image
|
||||
`,
|
||||
expected: `apiVersion: my-group-1/v1
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group-2/v2
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group-3/v3
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: nginx:1.7.9
|
||||
name: postgresdb
|
||||
`,
|
||||
},
|
||||
// regression test for missing metadata handling
|
||||
"missing metadata": {
|
||||
input: `spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group/v1
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group/v1
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name-2
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
`,
|
||||
replacements: `replacements:
|
||||
- source:
|
||||
name: my-name-1
|
||||
fieldPath: spec.template.spec.containers.0.image
|
||||
targets:
|
||||
- select:
|
||||
name: my-name-2
|
||||
fieldPaths:
|
||||
- spec.template.spec.containers.1.image
|
||||
`,
|
||||
expected: `spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group/v1
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: postgres:1.8.0
|
||||
name: postgresdb
|
||||
---
|
||||
apiVersion: my-group/v1
|
||||
kind: Custom
|
||||
metadata:
|
||||
name: my-name-2
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: nginx-tagged
|
||||
- image: nginx:1.7.9
|
||||
name: postgresdb
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for tn, tc := range testCases {
|
||||
t.Run(tn, func(t *testing.T) {
|
||||
f := Filter{}
|
||||
err := yaml.Unmarshal([]byte(tc.replacements), &f)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
actual, err := filtertest.RunFilterE(t, tc.input, f)
|
||||
if err != nil {
|
||||
if tc.expectedErr == "" {
|
||||
t.Errorf("unexpected error: %s\n", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
if !assert.Equal(t, tc.expectedErr, err.Error()) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
if !assert.Equal(t, strings.TrimSpace(tc.expected), strings.TrimSpace(actual)) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@ require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/stretchr/testify v1.4.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.15
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml => ../kyaml
|
||||
|
||||
@@ -264,5 +264,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
|
||||
@@ -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 `reject` 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"`
|
||||
}
|
||||
|
||||
// FieldOptions refine the interpretation of FieldPaths.
|
||||
// TODO (#3492): Implement use of these options, they are
|
||||
// currently unused
|
||||
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"`
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy clean
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
$(GOBIN)/addlicense:
|
||||
go get github.com/google/addlicense
|
||||
|
||||
@@ -16,7 +16,5 @@ require (
|
||||
golang.org/x/text v0.3.4 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/inf.v0 v0.9.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.15
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml => ../../kyaml
|
||||
|
||||
@@ -290,3 +290,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
MYGOBIN := $(shell go env GOPATH)/bin
|
||||
MYGOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(MYGOBIN),)
|
||||
MYGOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
$(MYGOBIN)/gorepomod: usage.go
|
||||
go install .
|
||||
|
||||
@@ -7,9 +7,7 @@ require (
|
||||
github.com/spf13/cobra v1.0.0
|
||||
github.com/stretchr/testify v1.4.0
|
||||
sigs.k8s.io/kustomize/api v0.8.5
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.15
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/api => ../../api
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml => ../../kyaml
|
||||
|
||||
@@ -267,5 +267,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: license image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
license:
|
||||
(which $(GOBIN)/addlicense || go get github.com/google/addlicense)
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
GOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
@@ -14,9 +14,11 @@ version=$1
|
||||
|
||||
echo "Installing kustomize ${version}"
|
||||
|
||||
MYGOBIN=$(go env GOBIN)
|
||||
MYGOBIN="${MYGOBIN:-$(go env GOPATH)/bin}"
|
||||
# Always rebuild, never assume the installed verion is
|
||||
# the right one to test.
|
||||
rm -f $(go env GOPATH)/bin/kustomize
|
||||
rm -f $MYGOBIN/kustomize
|
||||
if [ "$version" == "HEAD" ]; then
|
||||
(cd kustomize; go install .)
|
||||
else
|
||||
@@ -35,7 +37,7 @@ if onLinuxAndNotOnRemoteCI; then
|
||||
echo "On linux, and not on remote CI. Running expensive tests."
|
||||
|
||||
# Requires helm.
|
||||
make $(go env GOPATH)/bin/helm
|
||||
make $MYGOBIN/helm
|
||||
mdrip --mode test --label helmtest examples/chart.md
|
||||
fi
|
||||
|
||||
@@ -43,6 +45,6 @@ fi
|
||||
# rely on whatever this script just did. Tests should
|
||||
# be order independent.
|
||||
echo "Removing kustomize ${version}"
|
||||
rm $(go env GOPATH)/bin/kustomize
|
||||
rm $MYGOBIN/kustomize
|
||||
|
||||
echo "Example tests passed against ${version}."
|
||||
|
||||
@@ -14,6 +14,9 @@ set -o pipefail
|
||||
|
||||
rcAccumulator=0
|
||||
|
||||
MYGOBIN=$(go env GOBIN)
|
||||
MYGOBIN="${MYGOBIN:-$(go env GOPATH)/bin}"
|
||||
|
||||
# All hack scripts should run from top level.
|
||||
. hack/shellHelpers.sh
|
||||
|
||||
@@ -49,10 +52,10 @@ function scanDir {
|
||||
|
||||
if onLinuxAndNotOnRemoteCI; then
|
||||
# Some of these tests have special deps.
|
||||
make $(go env GOPATH)/bin/helmV2
|
||||
make $(go env GOPATH)/bin/helmV3
|
||||
make $(go env GOPATH)/bin/helm
|
||||
make $(go env GOPATH)/bin/kubeval
|
||||
make $MYGOBIN/helmV2
|
||||
make $MYGOBIN/helmV3
|
||||
make $MYGOBIN/helm
|
||||
make $MYGOBIN/kubeval
|
||||
fi
|
||||
|
||||
for goMod in $(find ./plugin -name 'go.mod' -not -path "./plugin/untested/*"); do
|
||||
|
||||
@@ -9,7 +9,7 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
sigs.k8s.io/kustomize/api v0.8.5
|
||||
sigs.k8s.io/kustomize/cmd/config v0.9.7
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.15
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
@@ -21,5 +21,3 @@ exclude (
|
||||
replace sigs.k8s.io/kustomize/api => ../api
|
||||
|
||||
replace sigs.k8s.io/kustomize/cmd/config => ../cmd/config
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml => ../kyaml
|
||||
|
||||
@@ -298,5 +298,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
MYGOBIN := $(shell go env GOPATH)/bin
|
||||
MYGOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(MYGOBIN),)
|
||||
MYGOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
export PATH := $(MYGOBIN):$(PATH)
|
||||
|
||||
.PHONY: generate license fix vet fmt test lint tidy clean
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
# Copyright 2020 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
MYGOBIN := $(shell go env GOPATH)/bin
|
||||
MYGOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(MYGOBIN),)
|
||||
MYGOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
API_VERSION := "v1.19.1"
|
||||
|
||||
.PHONY: all
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright 2020 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
MYGOBIN=$(go env GOPATH)/bin
|
||||
MYGOBIN=$(go env GOBIN)
|
||||
MYGOBIN="${MYGOBIN:-$(go env GOPATH)/bin}"
|
||||
VERSION=$1
|
||||
|
||||
cp $HOME/.kube/config /tmp/kubeconfig.txt | true
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright 2020 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
MYGOBIN=$(go env GOPATH)/bin
|
||||
MYGOBIN=$(go env GOBIN)
|
||||
MYGOBIN="${MYGOBIN:-$(go env GOPATH)/bin}"
|
||||
VERSION=$1
|
||||
|
||||
$MYGOBIN/go-bindata \
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
This document describes how to perform a [semver release]
|
||||
of one of the several [Go modules] in this repository.
|
||||
|
||||
### Release sequence
|
||||
## Release sequence
|
||||
|
||||
The dependencies determine the release order:
|
||||
|
||||
@@ -40,6 +40,8 @@ kustomize openapi info
|
||||
Instructions on how to get a new OpenAPI sample can be found in the
|
||||
[OpenAPI Readme].
|
||||
|
||||
## Prep work
|
||||
|
||||
#### Make some helper functions
|
||||
|
||||
```
|
||||
@@ -86,7 +88,7 @@ function testKustomizeRepo {
|
||||
( cd cmd/gorepomod; go install . )
|
||||
```
|
||||
|
||||
#### Authenticate to github using [gh](https://github.com/cli/cli)
|
||||
#### Authenticate to github using [gh](https://github.com/cli/cli) (version [1.8.1](https://github.com/cli/cli/releases/tag/v1.8.1) or higher).
|
||||
|
||||
```
|
||||
# Use your own token
|
||||
@@ -95,6 +97,8 @@ GITHUB_TOKEN=deadbeefdeadbeef
|
||||
echo $GITHUB_TOKEN | gh auth login --scopes repo --with-token
|
||||
```
|
||||
|
||||
## Release `kyaml`
|
||||
|
||||
#### Establish clean state
|
||||
|
||||
```
|
||||
@@ -103,7 +107,10 @@ refreshMaster
|
||||
testKustomizeRepo
|
||||
```
|
||||
|
||||
#### Release `kyaml`
|
||||
kyaml has no intra-repo deps, so if the tests pass,
|
||||
it can just be released.
|
||||
|
||||
Release it:
|
||||
|
||||
```
|
||||
gorepomod release kyaml --doIt
|
||||
@@ -118,8 +125,7 @@ Undraft the release on the [kustomize repo release page],
|
||||
make sure the version number is what you expect.
|
||||
|
||||
|
||||
#### Release [`cli-utils`](https://github.com/kubernetes-sigs/cli-utils)
|
||||
|
||||
## Release [`cli-utils`](https://github.com/kubernetes-sigs/cli-utils)
|
||||
|
||||
```
|
||||
cd ../cli-utils
|
||||
@@ -161,7 +167,7 @@ Note the version:
|
||||
versionCliUtils=v0.22.4 # EDIT THIS!
|
||||
```
|
||||
|
||||
#### Release `cmd/config`
|
||||
## Release `cmd/config`
|
||||
|
||||
```
|
||||
cd ../kustomize
|
||||
@@ -226,7 +232,9 @@ Undraft the release on the [kustomize repo release page],
|
||||
make sure the version number is what you expect.
|
||||
|
||||
|
||||
#### Release `api` (the kustomize API, used by the CLI)
|
||||
## Release `api`
|
||||
|
||||
This is the kustomize API, used by the kustomize CLI.
|
||||
|
||||
|
||||
Pin to the new cmd/config:
|
||||
@@ -273,7 +281,7 @@ Undraft the release on the [kustomize repo release page],
|
||||
make sure the version number is what you expect.
|
||||
|
||||
|
||||
#### Release the kustomize CLI
|
||||
## Release the kustomize CLI
|
||||
|
||||
Pin to the new API:
|
||||
```
|
||||
@@ -311,19 +319,19 @@ gorepomod release kustomize --doIt
|
||||
|
||||
Undraft the release on the [kustomize repo release page].
|
||||
|
||||
### Important
|
||||
## Confirm the kustomize binary is correct
|
||||
|
||||
[installation instructions]: https://kubectl.docs.kubernetes.io/installation/kustomize/binaries/
|
||||
|
||||
* Follow the [installation instructions] to install your new
|
||||
releas and make sure it reports the expected version number.
|
||||
|
||||
If not, something is very wrong.
|
||||
|
||||
* Visit the [release page] and edit the release notes as desired.
|
||||
> [installation instructions]: https://kubectl.docs.kubernetes.io/installation/kustomize/binaries/
|
||||
>
|
||||
> * Follow the [installation instructions] to install your new
|
||||
> release and make sure it reports the expected version number.
|
||||
>
|
||||
> If not, something is very wrong.
|
||||
>
|
||||
> * Visit the [release page] and edit the release notes as desired.
|
||||
|
||||
|
||||
#### Unpin everything
|
||||
## Unpin everything
|
||||
|
||||
|
||||
Go back into development mode, where all modules depend on in-repo code:
|
||||
|
||||
Reference in New Issue
Block a user