Compare commits

..

26 Commits

Author SHA1 Message Date
Phillip Wittrock
c467f48bf2 update go.mod for release 2020-02-27 12:21:10 -08:00
Phillip Wittrock
054f56ceaf Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.1 2020-02-27 12:21:05 -08:00
Phillip Wittrock
d5a107074d update go.mod for release 2020-02-21 10:18:34 -08:00
Phillip Wittrock
d8bd6db880 Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-02-21 10:18:15 -08:00
Phillip Wittrock
d27135e3a3 update go.mod for release 2020-02-19 15:00:57 -08:00
Phillip Wittrock
282b1fa49a Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-02-19 15:00:38 -08:00
Phillip Wittrock
584eb236fd update go.mod for release 2020-02-05 17:46:10 -08:00
Phillip Wittrock
31a193f60f Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-02-05 17:46:04 -08:00
Phillip Wittrock
bf17b244e5 update go.mod for release 2020-01-16 16:24:55 -08:00
Phillip Wittrock
8338299529 Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-01-16 16:24:35 -08:00
Phillip Wittrock
7adf7eb271 update go.mod for release 2020-01-15 18:10:02 -08:00
Phillip Wittrock
06b091b175 Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-01-15 18:09:55 -08:00
Phillip Wittrock
bf03669e94 update go.mod for release 2020-01-13 12:49:07 -08:00
Phillip Wittrock
7f52c814a8 release cmd/config
Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0
2020-01-13 12:47:01 -08:00
Phillip Wittrock
d5aac922d9 Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-01-10 16:38:39 -08:00
Phillip Wittrock
9a62d866f3 update go.mod for release 2020-01-09 17:02:34 -08:00
Phillip Wittrock
b2812838bf release cmd/config 0.0.6
Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0
2020-01-09 17:02:08 -08:00
Phillip Wittrock
e59e477702 update go.mod for release 2020-01-03 10:01:16 -08:00
Phillip Wittrock
4264ad0ad4 release cmd/config 0.0.5 Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2020-01-03 10:01:06 -08:00
Phillip Wittrock
2554cd00eb update go.mod for release 2020-01-02 09:02:06 -08:00
Phillip Wittrock
383244cd63 Release cmd/config 0.0.4
Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0
2020-01-02 09:01:56 -08:00
Phillip Wittrock
b9da33afd4 update go.mod for release 2019-12-20 09:44:25 -08:00
Phillip Wittrock
23e339b86c Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2019-12-20 09:44:21 -08:00
Phillip Wittrock
9555009df8 update go.mod for release 2019-12-16 14:21:02 -08:00
Phillip Wittrock
91a10c560c Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.0 2019-12-16 14:20:58 -08:00
Phillip Wittrock
780cb19c4d drop replace 2019-12-13 13:50:17 -08:00
280 changed files with 3092 additions and 16254 deletions

View File

@@ -22,9 +22,7 @@ verify-kustomize: \
.PHONY: prow-presubmit-check
prow-presubmit-check: \
lint-kustomize \
test-unit-kustomize-all \
test-unit-cmd-all \
test-go-mod
test-unit-kustomize-all
.PHONY: verify-kustomize-e2e
verify-kustomize-e2e: test-examples-e2e-kustomize
@@ -35,12 +33,12 @@ verify-kustomize-e2e: test-examples-e2e-kustomize
# since everything uses the same implicit GOPATH.
# This installs in a temp dir to avoid overwriting someone else's
# linter, then installs in MYGOBIN with a new name.
# Version pinned by hack/go.mod
# Version pinned by api/go.mod
$(MYGOBIN)/golangci-lint-kustomize:
( \
set -e; \
export GOBIN=$$(mktemp -d); \
cd hack; \
export GOBIN=$$(mktemp -d) \
cd api; \
GO111MODULE=on go install github.com/golangci/golangci-lint/cmd/golangci-lint; \
mv $$GOBIN/golangci-lint $(MYGOBIN)/golangci-lint-kustomize \
)
@@ -206,12 +204,6 @@ test-unit-kustomize-all: \
test-unit-kustomize-cli \
test-unit-kustomize-plugins
test-unit-cmd-all:
./travis/kyaml-pre-commit.sh
test-go-mod:
./travis/check-go-mod.sh
.PHONY:
test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh HEAD

View File

@@ -9,4 +9,3 @@ aliases:
- mengqiy
- monopole
- pwittrock
- mortent

View File

@@ -12,7 +12,8 @@ and it's like [`sed`], in that it emits edited text.
This tool is sponsored by [sig-cli] ([KEP]), and
inspired by [DAM].
[![Build Status](https://prow.k8s.io/badge.svg?jobs=kustomize-presubmit-master)](https://prow.k8s.io/job-history/kubernetes-jenkins/pr-logs/directory/kustomize-presubmit-master)
[![Build Status](https://travis-ci.org/kubernetes-sigs/kustomize.svg?branch=master)](https://travis-ci.org/kubernetes-sigs/kustomize)
[![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes-sigs/kustomize)](https://goreportcard.com/report/github.com/kubernetes-sigs/kustomize)
Download a binary from the [release page], or see
@@ -106,7 +107,7 @@ Take the work from step (1) above, move it into a
`someApp` subdirectory called `base`, then
place overlays in a sibling directory.
An overlay is just another kustomization, referring to
An overlay is just another kustomization, refering to
the base, and referring to patches to apply to that
base.

View File

@@ -4,11 +4,9 @@
package builtins
import (
"sigs.k8s.io/kustomize/api/filters/annotations"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -16,10 +14,6 @@ import (
type AnnotationsTransformerPlugin struct {
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
// YAMLSupport can be set to true to use the kyaml filter instead of the
// kunstruct transformer
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *AnnotationsTransformerPlugin) Config(
@@ -30,27 +24,14 @@ func (p *AnnotationsTransformerPlugin) Config(
}
func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
if p.YAMLSupport {
for _, r := range m.Resources() {
err := filtersutil.ApplyToJSON(annotations.Filter{
Annotations: p.Annotations,
FsSlice: p.FieldSpecs,
}, r.Kunstructured)
if err != nil {
return err
}
}
return nil
} else {
t, err := transform.NewMapTransformer(
p.FieldSpecs,
p.Annotations,
)
if err != nil {
return err
}
return t.Transform(m)
t, err := transform.NewMapTransformer(
p.FieldSpecs,
p.Annotations,
)
if err != nil {
return err
}
return t.Transform(m)
}
func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin {

View File

@@ -13,10 +13,13 @@ import (
type ConfigMapGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
types.GeneratorOptions
types.ConfigMapArgs
}
func (p *ConfigMapGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
func (p *ConfigMapGeneratorPlugin) Config(
h *resmap.PluginHelpers, config []byte) (err error) {
p.GeneratorOptions = types.GeneratorOptions{}
p.ConfigMapArgs = types.ConfigMapArgs{}
err = yaml.Unmarshal(config, p)
if p.ConfigMapArgs.Name == "" {
@@ -31,7 +34,8 @@ func (p *ConfigMapGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte
func (p *ConfigMapGeneratorPlugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromConfigMapArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.ConfigMapArgs)
kv.NewLoader(p.h.Loader(), p.h.Validator()),
&p.GeneratorOptions, p.ConfigMapArgs)
}
func NewConfigMapGeneratorPlugin() resmap.GeneratorPlugin {

View File

@@ -144,10 +144,8 @@ func (p *ImageTagTransformerPlugin) findContainers(obj map[string]interface{}) e
}
func isImageMatched(s, t string) bool {
// Tag values are limited to [a-zA-Z0-9_.{}-].
// Some tools like Bazel rules_k8s allow tag patterns with {} characters.
// More info: https://github.com/bazelbuild/rules_k8s/pull/423
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.{}-]*)?$")
// Tag values are limited to [a-zA-Z0-9_.-].
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.-]*)?$")
return pattern.MatchString(s)
}

View File

@@ -55,23 +55,26 @@ func (p *InventoryTransformerPlugin) Config(
// (e.g. some App object) become more desirable
// for this purpose.
func (p *InventoryTransformerPlugin) Transform(m resmap.ResMap) error {
inv, h, err := makeInventory(m)
if err != nil {
return err
}
args := types.ConfigMapArgs{}
args.Name = p.Name
args.Namespace = p.Namespace
args.Options = &types.GeneratorOptions{
Annotations: map[string]string{inventory.HashAnnotation: h},
opts := &types.GeneratorOptions{
Annotations: make(map[string]string),
}
err = inv.UpdateAnnotations(args.Options.Annotations)
opts.Annotations[inventory.HashAnnotation] = h
err = inv.UpdateAnnotations(opts.Annotations)
if err != nil {
return err
}
cm, err := p.h.ResmapFactory().RF().MakeConfigMap(
kv.NewLoader(p.h.Loader(), p.h.Validator()), &args)
kv.NewLoader(p.h.Loader(), p.h.Validator()), opts, &args)
if err != nil {
return err
}

View File

@@ -6,13 +6,12 @@ package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -20,11 +19,6 @@ import (
type NamespaceTransformerPlugin struct {
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
// YAMLSupport can be set to true to use the kyaml filter instead of the
// kunstruct transformer.
// TODO: change the default to use kyaml when it is stable
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *NamespaceTransformerPlugin) Config(
@@ -45,25 +39,12 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
}
id := r.OrgId()
applicableFs := p.applicableFieldSpecs(id)
if !p.YAMLSupport {
// use the old style transform
applicableFs := p.applicableFieldSpecs(id)
for _, fs := range applicableFs {
err := transform.MutateField(
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
p.changeNamespace(r))
if err != nil {
return err
}
}
} else {
// use the new style transform
err := filtersutil.ApplyToJSON(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
}, r.Kunstructured)
for _, fs := range applicableFs {
err := transform.MutateField(
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
p.changeNamespace(r))
if err != nil {
return err
}
@@ -71,7 +52,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
if len(matches) != 1 {
return fmt.Errorf("namespace transformation produces ID conflict: %+v", matches)
return fmt.Errorf("namespace tranformation produces ID conflict: %+v", matches)
}
}
return nil

View File

@@ -8,12 +8,10 @@ import (
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -23,8 +21,6 @@ type PatchJson6902TransformerPlugin struct {
Target types.PatchTarget `json:"target,omitempty" yaml:"target,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchJson6902TransformerPlugin) Config(
@@ -87,22 +83,16 @@ func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
if err != nil {
return err
}
if !p.YAMLSupport {
rawObj, err := obj.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := p.decodedPatch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.JsonOp)
}
return obj.UnmarshalJSON(modifiedObj)
} else {
return filtersutil.ApplyToJSON(patchjson6902.Filter{
Patch: p.JsonOp,
}, obj.Kunstructured)
rawObj, err := obj.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := p.decodedPatch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.JsonOp)
}
return obj.UnmarshalJSON(modifiedObj)
}
func NewPatchJson6902TransformerPlugin() resmap.TransformerPlugin {

View File

@@ -4,16 +4,11 @@
package builtins
import (
"encoding/json"
"fmt"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -22,8 +17,6 @@ type PatchStrategicMergeTransformerPlugin struct {
loadedPatches []*resource.Resource
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchStrategicMergeTransformerPlugin) Config(
@@ -76,42 +69,22 @@ func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error
if err != nil {
return err
}
if !p.YAMLSupport {
err = target.Patch(patch.Kunstructured)
err = target.Patch(patch.Kunstructured)
if err != nil {
return err
}
// remove the resource from resmap
// when the patch is to $patch: delete that target
if len(target.Map()) == 0 {
err = m.Remove(target.CurId())
if err != nil {
return err
}
// remove the resource from resmap
// when the patch is to $patch: delete that target
if len(target.Map()) == 0 {
err = m.Remove(target.CurId())
if err != nil {
return err
}
}
} else {
node, err := getRNode(patch)
if err != nil {
return err
}
err = filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, target.Kunstructured)
}
}
return nil
}
//TODO: Remove this once the next version of kyaml is released which
// exposes GetRNode from the filutersutil package.
func getRNode(k json.Marshaler) (*kyaml.RNode, error) {
j, err := k.MarshalJSON()
if err != nil {
return nil, err
}
return kyaml.Parse(string(j))
}
func NewPatchStrategicMergeTransformerPlugin() resmap.TransformerPlugin {
return &PatchStrategicMergeTransformerPlugin{}
}

View File

@@ -5,16 +5,12 @@ package builtins
import (
"fmt"
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -24,112 +20,69 @@ type PatchTransformerPlugin struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) error {
err := yaml.Unmarshal(c, p)
h *resmap.PluginHelpers, c []byte) (err error) {
err = yaml.Unmarshal(c, p)
if err != nil {
return err
}
p.Patch = strings.TrimSpace(p.Patch)
if p.Patch == "" && p.Path == "" {
return fmt.Errorf(
err = fmt.Errorf(
"must specify one of patch and path in\n%s", string(c))
return
}
if p.Patch != "" && p.Path != "" {
return fmt.Errorf(
err = fmt.Errorf(
"patch and path can't be set at the same time\n%s", string(c))
return
}
var in []byte
if p.Path != "" {
loaded, loadErr := h.Loader().Load(p.Path)
if loadErr != nil {
return loadErr
in, err = h.Loader().Load(p.Path)
if err != nil {
return
}
p.Patch = string(loaded)
}
if p.Patch != "" {
in = []byte(p.Patch)
}
patchSM, errSM := h.ResmapFactory().RF().FromBytes([]byte(p.Patch))
patchJson, errJson := jsonPatchFromBytes([]byte(p.Patch))
if (errSM == nil && errJson == nil) ||
(patchSM != nil && patchJson != nil) {
return fmt.Errorf(
"illegally qualifies as both an SM and JSON patch: [%v]",
p.Patch)
}
patchSM, errSM := h.ResmapFactory().RF().FromBytes(in)
patchJson, errJson := jsonPatchFromBytes(in)
if errSM != nil && errJson != nil {
return fmt.Errorf(
"unable to parse SM or JSON patch from [%v]", p.Patch)
err = fmt.Errorf(
"unable to get either a Strategic Merge Patch or JSON patch 6902 from %s", p.Patch)
return
}
if errSM == nil {
if errSM == nil && errJson != nil {
p.loadedPatch = patchSM
} else {
}
if errJson == nil && errSM != nil {
p.decodedPatch = patchJson
}
if patchSM != nil && patchJson != nil {
err = fmt.Errorf(
"a patch can't be both a Strategic Merge Patch and JSON patch 6902 %s", p.Patch)
}
return nil
}
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
if p.loadedPatch != nil {
// The patch was a strategic merge patch
return p.transformStrategicMerge(m, p.loadedPatch)
} else {
return p.transformJson6902(m, p.decodedPatch)
}
}
// transformStrategicMerge applies the provided strategic merge patch
// to all the resources in the ResMap that match either the Target or
// the identifier of the patch.
func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch *resource.Resource) error {
if p.Target == nil {
target, err := m.GetById(patch.OrgId())
if p.loadedPatch != nil && p.Target == nil {
target, err := m.GetById(p.loadedPatch.OrgId())
if err != nil {
return err
}
return p.applySMPatch(target, patch)
}
resources, err := m.Select(*p.Target)
if err != nil {
return err
}
for _, res := range resources {
patchCopy := patch.DeepCopy()
patchCopy.SetName(res.GetName())
patchCopy.SetNamespace(res.GetNamespace())
patchCopy.SetGvk(res.GetGvk())
err := p.applySMPatch(res, patchCopy)
err = target.Patch(p.loadedPatch.Kunstructured)
if err != nil {
return err
}
return nil
}
return nil
}
// applySMPatch applies the provided strategic merge patch to the
// given resource. Depending on the value of YAMLSupport, it will either
// use the legacy implementation or the kyaml-based solution.
func (p *PatchTransformerPlugin) applySMPatch(resource, patch *resource.Resource) error {
if !p.YAMLSupport {
return resource.Patch(patch.Kunstructured)
} else {
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
return filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, resource.Kunstructured)
}
}
// transformJson6902 applies the provided json6902 patch
// to all the resources in the ResMap that match the Target.
func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpatch.Patch) error {
if p.Target == nil {
return fmt.Errorf("must specify a target for patch %s", p.Patch)
}
@@ -139,36 +92,35 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
return err
}
for _, res := range resources {
err = p.applyJson6902Patch(res, patch)
if err != nil {
return err
if p.decodedPatch != nil {
rawObj, err := res.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := p.decodedPatch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.Patch)
}
err = res.UnmarshalJSON(modifiedObj)
if err != nil {
return err
}
}
if p.loadedPatch != nil {
patchCopy := p.loadedPatch.DeepCopy()
patchCopy.SetName(res.GetName())
patchCopy.SetNamespace(res.GetNamespace())
patchCopy.SetGvk(res.GetGvk())
err = res.Patch(patchCopy.Kunstructured)
if err != nil {
return err
}
}
}
return nil
}
// applyJson6902Patch applies the provided patch to the given resource.
// Depending on the value of YAMLSupport, it will either
// use the legacy implementation or the kyaml-based solution.
func (p *PatchTransformerPlugin) applyJson6902Patch(resource *resource.Resource, patch jsonpatch.Patch) error {
if !p.YAMLSupport {
rawObj, err := resource.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := patch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.Patch)
}
return resource.UnmarshalJSON(modifiedObj)
} else {
return filtersutil.ApplyToJSON(patchjson6902.Filter{
Patch: p.Patch,
}, resource.Kunstructured)
}
}
// jsonPatchFromBytes loads a Json 6902 patch from
// a bytes input
func jsonPatchFromBytes(

View File

@@ -13,10 +13,12 @@ import (
type SecretGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
types.GeneratorOptions
types.SecretArgs
}
func (p *SecretGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.GeneratorOptions = types.GeneratorOptions{}
p.SecretArgs = types.SecretArgs{}
err = yaml.Unmarshal(config, p)
if p.SecretArgs.Name == "" {
@@ -31,7 +33,8 @@ func (p *SecretGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (
func (p *SecretGeneratorPlugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromSecretArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.SecretArgs)
kv.NewLoader(p.h.Loader(), p.h.Validator()),
&p.GeneratorOptions, p.SecretArgs)
}
func NewSecretGeneratorPlugin() resmap.GeneratorPlugin {

View File

@@ -1,42 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package annotations
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type annoMap map[string]string
type Filter struct {
// Annotations is the set of annotations to apply to the inputs
Annotations annoMap `yaml:"annotations,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field
FsSlice types.FsSlice
}
var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
keys := filtersutil.SortedMapKeys(f.Annotations)
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
for _, k := range keys {
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: fsslice.SetEntry(k, f.Annotations[k]),
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
}); err != nil {
return nil, err
}
}
return node, nil
})).Filter(nodes)
return nodes, err
}

View File

@@ -1,139 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package annotations
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
var annosFs = builtinconfig.MakeDefaultConfig().CommonAnnotations
func TestAnnotations_Filter(t *testing.T) {
testCases := map[string]struct {
input string
expectedOutput string
filter Filter
fsslice types.FsSlice
}{
"add": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
annotations:
hero: batman
fiend: riddler
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
annotations:
hero: batman
fiend: riddler
auto: ford
bean: cannellini
clown: emmett kelley
dragon: smaug
`,
filter: Filter{Annotations: annoMap{
"clown": "emmett kelley",
"auto": "ford",
"dragon": "smaug",
"bean": "cannellini",
}},
},
"update": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
annotations:
hero: batman
fiend: riddler
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
annotations:
hero: superman
fiend: luthor
bean: cannellini
clown: emmett kelley
`,
filter: Filter{Annotations: annoMap{
"clown": "emmett kelley",
"hero": "superman",
"fiend": "luthor",
"bean": "cannellini",
}},
},
"data-fieldspecs": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
annotations:
sleater: kinney
a:
b:
sleater: kinney
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
annotations:
sleater: kinney
a:
b:
sleater: kinney
`,
filter: Filter{Annotations: annoMap{
"sleater": "kinney",
}},
fsslice: []types.FieldSpec{
{
Path: "a/b",
CreateIfNotPresent: true,
},
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
filter := tc.filter
filter.FsSlice = append(annosFs, tc.fsslice...)
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package annotations contains a kio.Filter implementation of the kustomize
// annotations transformer.
package annotations

View File

@@ -1,55 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package annotations
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
fss := builtinconfig.MakeDefaultConfig().CommonAnnotations
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`)}},
Filters: []kio.Filter{Filter{
Annotations: map[string]string{
"foo": "bar",
},
FsSlice: fss,
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// annotations:
// foo: bar
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// annotations:
// foo: bar
}

View File

@@ -1,21 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filtersutil
import (
"sort"
)
// SortedMapKeys returns a sorted slice of keys to the given map.
// Writing this function never gets old.
func SortedMapKeys(m map[string]string) []string {
keys := make([]string, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}

View File

@@ -1,34 +0,0 @@
package filtersutil_test
import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
)
func TestSortedKeys(t *testing.T) {
testCases := map[string]struct {
input map[string]string
expected []string
}{
"empty": {
input: map[string]string{},
expected: []string{}},
"one": {
input: map[string]string{"a": "aaa"},
expected: []string{"a"}},
"three": {
input: map[string]string{"c": "ccc", "b": "bbb", "a": "aaa"},
expected: []string{"a", "b", "c"}},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
if !assert.Equal(t,
filtersutil.SortedMapKeys(tc.input),
tc.expected) {
t.FailNow()
}
})
}
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package fsslice contains a yaml.Filter to modify a resource using an
// FsSlice to identify fields to be updated within the resource.
package fsslice

View File

@@ -1,62 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice_test
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func ExampleFilter() {
in := &kio.ByteReader{
Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`),
}
fltr := fsslice.Filter{
CreateKind: yaml.ScalarNode,
SetValue: fsslice.SetScalar("green"),
FsSlice: []types.FieldSpec{
{Path: "a/b", CreateIfNotPresent: true},
},
}
err := kio.Pipeline{
Inputs: []kio.Reader{in},
Filters: []kio.Filter{kio.FilterAll(fltr)},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// a:
// b: green
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// a:
// b: green
}

View File

@@ -1,145 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
import (
"strings"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// fieldSpecFilter applies a single fieldSpec to a single object
// fieldSpecFilter stores internal state and should not be reused
type fieldSpecFilter struct {
// FieldSpec contains the path to the value to set.
FieldSpec types.FieldSpec `yaml:"fieldSpec"`
// Set the field using this function
SetValue SetFn
// CreateKind defines the type of node to create if the field is not found
CreateKind yaml.Kind
// path keeps internal state about the current path
path []string
}
func (fltr fieldSpecFilter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
// check if the FieldSpec applies to the object
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
return obj, errors.Wrap(err)
}
fltr.path = strings.Split(fltr.FieldSpec.Path, "/")
if err := fltr.filter(obj); err != nil {
s, _ := obj.String()
return nil, errors.WrapPrefixf(err,
"obj %v at path %v", s, fltr.FieldSpec.Path)
}
return obj, nil
}
func (fltr fieldSpecFilter) filter(obj *yaml.RNode) error {
if len(fltr.path) == 0 {
// found the field -- set its value
return fltr.SetValue(obj)
}
switch obj.YNode().Kind {
case yaml.SequenceNode:
return fltr.seq(obj)
case yaml.MappingNode:
return fltr.field(obj)
}
// not found -- this might be an error since the type doesn't match
return errors.Errorf("unsupported yaml node")
}
// field calls filter on the field matching the next path element
func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
fieldName, isSeq := isSequenceField(fltr.path[0])
// lookup the field matching the next path element
var lookupField yaml.Filter
switch {
case !fltr.FieldSpec.CreateIfNotPresent || fltr.CreateKind == 0 || isSeq:
// dont' create the field if we don't find it
lookupField = yaml.Lookup(fieldName)
case len(fltr.path) <= 1:
// create the field if it is missing: use the provided node kind
lookupField = yaml.LookupCreate(fltr.CreateKind, fieldName)
default:
// create the field if it is missing: must be a mapping node
lookupField = yaml.LookupCreate(yaml.MappingNode, fieldName)
}
// locate (or maybe create) the field
field, err := obj.Pipe(lookupField)
if err != nil || field == nil {
return errors.WrapPrefixf(err, "fieldName: %s", fieldName)
}
// copy the current fltr and change the path on the copy
var next = fltr
// call filter for the next path element on the matching field
next.path = fltr.path[1:]
return next.filter(field)
}
// seq calls filter on all sequence elements
func (fltr fieldSpecFilter) seq(obj *yaml.RNode) error {
if err := obj.VisitElements(func(node *yaml.RNode) error {
// recurse on each element -- re-allocating a fieldSpecFilter is
// not strictly required, but is more consistent with field
// and less likely to have side effects
// keep the entire path -- it does not contain parts for sequences
return fltr.filter(node)
}); err != nil {
return errors.WrapPrefixf(err,
"visit traversal on path: %v", fltr.path)
}
return nil
}
// isSequenceField returns true if the path element is for a sequence field.
// isSequence also returns the path element with the '[]' suffix trimmed
func isSequenceField(name string) (string, bool) {
isSeq := strings.HasSuffix(name, "[]")
name = strings.TrimSuffix(name, "[]")
return name, isSeq
}
// isMatchGVK returns true if the fs.GVK matches the obj GVK.
func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) {
meta, err := obj.GetMeta()
if err != nil {
return false, err
}
if fs.Kind != "" && fs.Kind != meta.Kind {
// kind doesn't match
return false, err
}
// parse the group and version from the apiVersion field
var group, version string
parts := strings.SplitN(meta.APIVersion, "/", 2)
group = parts[0]
if len(parts) > 1 {
version = parts[1]
}
if fs.Group != "" && fs.Group != group {
// group doesn't match
return false, nil
}
if fs.Version != "" && fs.Version != version {
// version doesn't match
return false, nil
}
return true, nil
}

View File

@@ -1,78 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
import (
"strings"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// SetFn sets a value
type SetFn func(*yaml.RNode) error
// SetScalar returns a SetFn to set a scalar value
func SetScalar(value string) SetFn {
return func(node *yaml.RNode) error {
return node.PipeE(yaml.FieldSetter{StringValue: value})
}
}
// SetEntry returns a SetFn to set an entry in a map
func SetEntry(key, value string) SetFn {
return func(node *yaml.RNode) error {
return node.PipeE(yaml.FieldSetter{
Name: key, StringValue: value})
}
}
var _ yaml.Filter = Filter{}
// Filter uses an FsSlice to modify fields on a single object
type Filter struct {
// FieldSpecList list of FieldSpecs to set
FsSlice types.FsSlice `yaml:"fsSlice"`
// SetValue is called on each field that matches one of the FieldSpecs
SetValue SetFn
// CreateKind is used to create fields that do not exist
CreateKind yaml.Kind
}
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
for i := range fltr.FsSlice {
// apply this FieldSpec
// create a new filter for each iteration because they
// store internal state about the field paths
_, err := (&fieldSpecFilter{
FieldSpec: fltr.FsSlice[i],
SetValue: fltr.SetValue,
CreateKind: fltr.CreateKind,
}).Filter(obj)
if err != nil {
return nil, err
}
}
return obj, nil
}
// GetGVK parses the metadata into a GVK
func GetGVK(meta yaml.ResourceMeta) resid.Gvk {
// parse the group and version from the apiVersion field
var group, version string
parts := strings.SplitN(meta.APIVersion, "/", 2)
group = parts[0]
if len(parts) > 1 {
version = parts[1]
}
return resid.Gvk{
Group: group,
Version: version,
Kind: meta.Kind,
}
}

View File

@@ -1,354 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice_test
import (
"bytes"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type TestCase struct {
name string
input string
expected string
filter fsslice.Filter
fsSlice string
error string
}
var tests = []TestCase{
{
name: "update",
fsSlice: `
- path: a/b
group: foo
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b: e
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "update-kind-not-match",
fsSlice: `
- path: a/b
group: foo
kind: Bar1
`,
input: `
apiVersion: foo/v1beta1
kind: Bar2
a:
b: c
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar2
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "update-group-not-match",
fsSlice: `
- path: a/b
group: foo1
kind: Bar
`,
input: `
apiVersion: foo2/v1beta1
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo2/v1beta1
kind: Bar
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "update-version-not-match",
fsSlice: `
- path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
apiVersion: foo/v1beta2
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo/v1beta2
kind: Bar
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "bad-version",
fsSlice: `
- path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
apiVersion: foo/v1beta2/something
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo/v1beta2/something
kind: Bar
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "bad-meta",
fsSlice: `
- path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
error: "missing Resource metadata",
},
{
name: "miss-match-type",
fsSlice: `
- path: a/b/c
kind: Bar
`,
input: `
kind: Bar
a:
b: a
`,
error: "obj kind: Bar\na:\n b: a\n at path a/b/c: unsupported yaml node",
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "add",
fsSlice: `
- path: a/b/c/d
group: foo
create: true
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a: {b: {c: {d: e}}}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "update-in-sequence",
fsSlice: `
- path: a/b[]/c/d
group: foo
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c:
d: a
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c:
d: e
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
// Don't create a sequence
{
name: "empty-sequence-no-create",
fsSlice: `
- path: a/b[]/c/d
group: foo
create: true
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
// Create a new field for an element in a sequence
{
name: "empty-sequence-create",
fsSlice: `
- path: a/b[]/c/d
group: foo
create: true
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c: {}
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c: {d: e}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
}
func TestFilter_Filter(t *testing.T) {
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
err := yaml.Unmarshal([]byte(test.fsSlice), &test.filter.FsSlice)
if !assert.NoError(t, err) {
t.FailNow()
}
out := &bytes.Buffer{}
rw := &kio.ByteReadWriter{
Reader: bytes.NewBufferString(test.input),
Writer: out,
OmitReaderAnnotations: true,
}
// run the filter
err = kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{kio.FilterAll(test.filter)},
Outputs: []kio.Writer{rw},
}.Execute()
if test.error != "" {
if !assert.EqualError(t, err, test.error) {
t.FailNow()
}
// stop rest of test
return
}
if !assert.NoError(t, err) {
t.FailNow()
}
// check results
if !assert.Equal(t,
strings.TrimSpace(test.expected),
strings.TrimSpace(out.String())) {
t.FailNow()
}
})
}
}
func TestGetGVK(t *testing.T) {
obj, err := yaml.Parse(`
apiVersion: apps/v1
kind: Deployment
`)
if !assert.NoError(t, err) {
t.FailNow()
}
meta, err := obj.GetMeta()
if !assert.NoError(t, err) {
t.FailNow()
}
gvk := fsslice.GetGVK(meta)
expected := resid.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
if !assert.Equal(t, expected, gvk) {
t.FailNow()
}
}

View File

@@ -1,12 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package imagetag contains two kio.Filter implementations to cover the
// functionality of the kustomize imagetag transformer.
//
// Filter updates fields based on a FieldSpec and an ImageTag.
//
// LegacyFilter doesn't use a FieldSpec, and instead only updates image
// references if the field is name image and it is underneath a field called
// either containers or initContainers.
package imagetag

View File

@@ -1,126 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package imagetag
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- name: FooBar
image: nginx
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
spec:
containers:
- name: BarFoo
image: nginx:1.2.1
`)}},
Filters: []kio.Filter{Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
FsSlice: []types.FieldSpec{
{
Path: "spec/containers[]/image",
},
},
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// spec:
// containers:
// - name: FooBar
// image: apache@12345
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// spec:
// containers:
// - name: BarFoo
// image: apache@12345
}
func ExampleLegacyFilter() {
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- name: FooBar
image: nginx
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
spec:
containers:
- name: BarFoo
image: nginx:1.2.1
`)}},
Filters: []kio.Filter{LegacyFilter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// spec:
// containers:
// - name: FooBar
// image: apache@12345
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// spec:
// containers:
// - name: BarFoo
// image: apache@12345
}

View File

@@ -1,44 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package imagetag
import (
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type Filter struct {
// imageTag is the tag we want to apply to the inputs
ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
_, err := kio.FilterAll(yaml.FilterFunc(f.filter)).Filter(nodes)
return nodes, err
}
func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: updateImageTagFn(f.ImageTag),
}); err != nil {
return nil, err
}
return node, nil
}
func updateImageTagFn(imageTag types.Image) fsslice.SetFn {
return func(node *yaml.RNode) error {
return node.PipeE(imageTagUpdater{
ImageTag: imageTag,
})
}
}

View File

@@ -1,101 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package imagetag
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
func TestImageTagUpdater_Filter(t *testing.T) {
testCases := map[string]struct {
input string
expectedOutput string
filter Filter
fsSlice types.FsSlice
}{
"update with digest": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
image: nginx:1.2.1
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
image: apache@12345
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/image",
},
},
},
"multiple matches in sequence": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: not_nginx@54321
- image: nginx:1.2.1
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache:3.2.1
- image: not_nginx@54321
- image: apache:3.2.1
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
NewTag: "3.2.1",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/containers/image",
},
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
filter := tc.filter
filter.FsSlice = tc.fsSlice
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest.RunFilter(t, tc.input, filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,113 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package imagetag
import (
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// LegacyFilter is an implementation of the kio.Filter interface
// that scans through the provided kyaml data structure and updates
// any values of any image fields that is inside a sequence under
// a field called either containers or initContainers. The field is only
// update if it has a value that matches and image reference and the name
// of the image is a match with the provided ImageTag.
type LegacyFilter struct {
ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
}
var _ kio.Filter = LegacyFilter{}
func (lf LegacyFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(lf.filter)).Filter(nodes)
}
func (lf LegacyFilter) filter(node *yaml.RNode) (*yaml.RNode, error) {
meta, err := node.GetMeta()
if err != nil {
return nil, err
}
// We do not make any changes if the type of the resource
// is CustomResourceDefinition.
if meta.Kind == `CustomResourceDefinition` {
return node, nil
}
fff := findFieldsFilter{
fields: []string{"containers", "initContainers"},
fieldCallback: checkImageTagsFn(lf.ImageTag),
}
if err := node.PipeE(fff); err != nil {
return nil, err
}
return node, nil
}
type fieldCallback func(node *yaml.RNode) error
// findFieldsFilter is an implementation of the kio.Filter
// interface. It will walk the data structure and look for fields
// that matches the provided list of field names. For each match,
// the value of the field will be passed in as a parameter to the
// provided fieldCallback.
// TODO: move this to kyaml/filterutils
type findFieldsFilter struct {
fields []string
fieldCallback fieldCallback
}
func (f findFieldsFilter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
return obj, f.walk(obj)
}
func (f findFieldsFilter) walk(node *yaml.RNode) error {
switch node.YNode().Kind {
case yaml.MappingNode:
return node.VisitFields(func(n *yaml.MapNode) error {
err := f.walk(n.Value)
if err != nil {
return err
}
key := n.Key.YNode().Value
if contains(f.fields, key) {
return f.fieldCallback(n.Value)
}
return nil
})
case yaml.SequenceNode:
return node.VisitElements(func(n *yaml.RNode) error {
return f.walk(n)
})
}
return nil
}
func contains(slice []string, str string) bool {
for _, s := range slice {
if s == str {
return true
}
}
return false
}
func checkImageTagsFn(imageTag types.Image) fieldCallback {
return func(node *yaml.RNode) error {
if node.YNode().Kind != yaml.SequenceNode {
return nil
}
return node.VisitElements(func(n *yaml.RNode) error {
// Look up any fields on the provided node that is named
// image.
return n.PipeE(yaml.Get("image"), imageTagUpdater{
ImageTag: imageTag,
})
})
}
}

View File

@@ -1,136 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package imagetag
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
func TestLegacyImageTag_Filter(t *testing.T) {
testCases := map[string]struct {
input string
expectedOutput string
filter LegacyFilter
}{
"updates multiple images inside containers": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: nginx:2.1.2
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache@12345
- image: apache@12345
`,
filter: LegacyFilter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
},
},
"updates inside both containers and initContainers": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: tomcat:1.2.3
initContainers:
- image: nginx:1.2.1
- image: apache:1.2.3
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache:3.2.1
- image: tomcat:1.2.3
initContainers:
- image: apache:3.2.1
- image: apache:1.2.3
`,
filter: LegacyFilter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
NewTag: "3.2.1",
},
},
},
"updates on multiple depths": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: tomcat:1.2.3
template:
spec:
initContainers:
- image: nginx:1.2.1
- image: apache:1.2.3
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache:3.2.1
- image: tomcat:1.2.3
template:
spec:
initContainers:
- image: apache:3.2.1
- image: apache:1.2.3
`,
filter: LegacyFilter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
NewTag: "3.2.1",
},
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
filter := tc.filter
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest.RunFilter(t, tc.input, filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,43 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package imagetag
import (
"sigs.k8s.io/kustomize/api/image"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// imageTagUpdater is an implementation of the kio.Filter interface
// that will update the value of the yaml node based on the provided
// ImageTag if the current value matches the format of an image reference.
type imageTagUpdater struct {
Kind string `yaml:"kind,omitempty"`
ImageTag types.Image `yaml:"imageTag,omitempty"`
}
func (u imageTagUpdater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
if err := yaml.ErrorIfInvalid(rn, yaml.ScalarNode); err != nil {
return nil, err
}
value := rn.YNode().Value
if !image.IsImageMatched(value, u.ImageTag.Name) {
return rn, nil
}
name, tag := image.Split(value)
if u.ImageTag.NewName != "" {
name = u.ImageTag.NewName
}
if u.ImageTag.NewTag != "" {
tag = ":" + u.ImageTag.NewTag
}
if u.ImageTag.Digest != "" {
tag = "@" + u.ImageTag.Digest
}
return rn.Pipe(yaml.FieldSetter{StringValue: name + tag})
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package labels contains a kio.Filter implementation of the kustomize
// labels transformer.
package labels

View File

@@ -1,55 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package labels
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
fss := builtinconfig.MakeDefaultConfig().CommonLabels
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`)}},
Filters: []kio.Filter{Filter{
Labels: map[string]string{
"foo": "bar",
},
FsSlice: fss,
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// labels:
// foo: bar
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// labels:
// foo: bar
}

View File

@@ -1,43 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package labels
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type labelMap map[string]string
// Filter sets labels.
type Filter struct {
// Labels is the set of labels to apply to the inputs
Labels labelMap `yaml:"labels,omitempty"`
// FsSlice identifies the label fields.
FsSlice types.FsSlice
}
var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
keys := filtersutil.SortedMapKeys(f.Labels)
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
for _, k := range keys {
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: fsslice.SetEntry(k, f.Labels[k]),
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
}); err != nil {
return nil, err
}
}
return node, nil
})).Filter(nodes)
return nodes, err
}

View File

@@ -1,139 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package labels
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
var labelsFs = builtinconfig.MakeDefaultConfig().CommonLabels
func TestLabels_Filter(t *testing.T) {
testCases := map[string]struct {
input string
expectedOutput string
filter Filter
fsSlice types.FsSlice
}{
"add": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
hero: batman
fiend: riddler
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
hero: batman
fiend: riddler
auto: ford
bean: cannellini
clown: emmett kelley
dragon: smaug
`,
filter: Filter{Labels: labelMap{
"clown": "emmett kelley",
"auto": "ford",
"dragon": "smaug",
"bean": "cannellini",
}},
},
"update": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
hero: batman
fiend: riddler
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
hero: superman
fiend: luthor
bean: cannellini
clown: emmett kelley
`,
filter: Filter{Labels: labelMap{
"clown": "emmett kelley",
"hero": "superman",
"fiend": "luthor",
"bean": "cannellini",
}},
},
"data-fieldspecs": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
sleater: kinney
a:
b:
sleater: kinney
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
labels:
sleater: kinney
a:
b:
sleater: kinney
`,
filter: Filter{Labels: labelMap{
"sleater": "kinney",
}},
fsSlice: []types.FieldSpec{
{
Path: "a/b",
CreateIfNotPresent: true,
},
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
filter := tc.filter
filter.FsSlice = append(labelsFs, tc.fsSlice...)
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,9 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package namespace contains a kio.Filter implementation of the kustomize
// namespace transformer.
//
// Special cases for known Kubernetes resources have been hardcoded in addition
// to those defined by the FsSlice.
package namespace

View File

@@ -1,50 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package namespace_test
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
fss := builtinconfig.MakeDefaultConfig().NameSpace
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
namespace: bar
`)}},
Filters: []kio.Filter{namespace.Filter{Namespace: "app", FsSlice: fss}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// namespace: app
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// namespace: app
}

View File

@@ -1,167 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package namespace
import (
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type Filter struct {
// Namespace is the namespace to apply to the inputs
Namespace string `yaml:"namespace,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
var _ kio.Filter = Filter{}
func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(ns.run)).Filter(nodes)
}
// Run runs the filter on a single node rather than a slice
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
// hacks for hardcoded types -- :(
if err := ns.hacks(node); err != nil {
return nil, err
}
// Remove the fieldspecs that are for hardcoded fields. The fieldspecs
// exist for backwards compatibility with other implementations
// of this transformation.
// This implementation of the namespace transformation
// Does not use the fieldspecs for implementing cases which
// require hardcoded logic.
ns.FsSlice = ns.removeFieldSpecsForHacks(ns.FsSlice)
// transformations based on data -- :)
err := node.PipeE(fsslice.Filter{
FsSlice: ns.FsSlice,
SetValue: fsslice.SetScalar(ns.Namespace),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
})
return node, err
}
// hacks applies the namespace transforms that are hardcoded rather
// than specified through FieldSpecs.
func (ns Filter) hacks(obj *yaml.RNode) error {
meta, err := obj.GetMeta()
if err != nil {
return err
}
if err := ns.metaNamespaceHack(obj, meta); err != nil {
return err
}
return ns.roleBindingHack(obj, meta)
}
// metaNamespaceHack is a hack for implementing the namespace transform
// for the metadata.namespace field on namespace scoped resources.
// namespace scoped resources are determined by NOT being present
// in a blacklist of cluster-scoped resource types (by apiVersion and kind).
//
// This hack should be updated to allow individual resources to specify
// if they are cluster scoped through either an annotation on the resources,
// or through inlined OpenAPI on the resource as a YAML comment.
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
gvk := fsslice.GetGVK(meta)
if !gvk.IsNamespaceableKind() {
return nil
}
f := fsslice.Filter{
FsSlice: []types.FieldSpec{
{Path: metaNamespaceField, CreateIfNotPresent: true},
},
SetValue: fsslice.SetScalar(ns.Namespace),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
}
_, err := f.Filter(obj)
return err
}
// roleBindingHack is a hack for implementing the namespace transform
// for RoleBinding and ClusterRoleBinding resource types.
// RoleBinding and ClusterRoleBinding have namespace set on
// elements of the "subjects" field if and only if the subject elements
// "name" is "default". Otherwise the namespace is not set.
//
// Example:
//
// kind: RoleBinding
// subjects:
// - name: "default" # this will have the namespace set
// ...
// - name: "something-else" # this will not have the namespace set
// ...
func (ns Filter) roleBindingHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
if meta.Kind != roleBindingKind && meta.Kind != clusterRoleBindingKind {
return nil
}
// Lookup the namespace field on all elements.
// We should change the fieldspec so this isn't necessary.
obj, err := obj.Pipe(yaml.Lookup(subjectsField))
if err != nil || yaml.IsEmpty(obj) {
return err
}
// add the namespace to each "subject" with name: default
err = obj.VisitElements(func(o *yaml.RNode) error {
// copied from kunstruct based kustomize NamespaceTransformer plugin
// The only case we need to force the namespace
// if for the "service account". "default" is
// kind of hardcoded here for right now.
name, err := o.Pipe(
yaml.Lookup("name"), yaml.Match("default"),
)
if err != nil || yaml.IsEmpty(name) {
return err
}
// set the namespace for the default account
v := yaml.NewScalarRNode(ns.Namespace)
return o.PipeE(
yaml.LookupCreate(yaml.ScalarNode, "namespace"),
yaml.FieldSetter{Value: v},
)
})
return err
}
// removeFieldSpecsForHacks removes from the list fieldspecs that
// have hardcoded implementations
func (ns Filter) removeFieldSpecsForHacks(fs types.FsSlice) types.FsSlice {
var val types.FsSlice
for i := range fs {
// implemented by metaNamespaceHack
if fs[i].Path == metaNamespaceField {
continue
}
// implemented by roleBindingHack
if fs[i].Kind == roleBindingKind && fs[i].Path == subjectsField {
continue
}
// implemented by roleBindingHack
if fs[i].Kind == clusterRoleBindingKind && fs[i].Path == subjectsField {
continue
}
val = append(val, fs[i])
}
return val
}
const (
metaNamespaceField = "metadata/namespace"
subjectsField = "subjects"
roleBindingKind = "RoleBinding"
clusterRoleBindingKind = "ClusterRoleBinding"
)

View File

@@ -1,280 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package namespace_test
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
var tests = []TestCase{
{
name: "add",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
namespace: foo
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
namespace: foo
`,
filter: namespace.Filter{Namespace: "foo"},
},
{
name: "add-recurse",
input: `
apiVersion: example.com/v1
kind: Foo
---
apiVersion: example.com/v1
kind: Bar
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
namespace: foo
---
apiVersion: example.com/v1
kind: Bar
metadata:
namespace: foo
`,
filter: namespace.Filter{Namespace: "foo"},
},
{
name: "update",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
# update this namespace
namespace: bar
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
namespace: bar
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
# update this namespace
namespace: foo
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
namespace: foo
`,
filter: namespace.Filter{Namespace: "foo"},
},
{
name: "update-rolebinding",
input: `
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: default
---
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: default
namespace: foo
---
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: something
---
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: something
namespace: foo
`,
expected: `
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: default
namespace: bar
metadata:
namespace: bar
---
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: default
namespace: bar
metadata:
namespace: bar
---
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: something
metadata:
namespace: bar
---
apiVersion: example.com/v1
kind: RoleBinding
subjects:
- name: something
namespace: foo
metadata:
namespace: bar
`,
filter: namespace.Filter{Namespace: "bar"},
},
{
name: "update-clusterrolebinding",
input: `
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: default
---
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: default
namespace: foo
---
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: something
---
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: something
namespace: foo
`,
expected: `
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: default
namespace: bar
---
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: default
namespace: bar
---
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: something
---
apiVersion: example.com/v1
kind: ClusterRoleBinding
subjects:
- name: something
namespace: foo
`,
filter: namespace.Filter{Namespace: "bar"},
},
{
name: "data-fieldspecs",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
namespace: foo
a:
b:
c: foo
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
namespace: foo
a:
b:
c: foo
`,
filter: namespace.Filter{Namespace: "foo"},
fsslice: []types.FieldSpec{
{
Path: "a/b/c",
CreateIfNotPresent: true,
},
},
},
}
type TestCase struct {
name string
input string
expected string
filter namespace.Filter
fsslice types.FsSlice
}
var config = builtinconfig.MakeDefaultConfig()
func TestNamespace_Filter(t *testing.T) {
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
test.filter.FsSlice = append(config.NameSpace, test.fsslice...)
if !assert.Equal(t,
strings.TrimSpace(test.expected),
strings.TrimSpace(
filtertest_test.RunFilter(t, test.input, test.filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package namespace contains a kio.Filter implementation of the kustomize
// patchjson6902 transformer
package patchjson6902

View File

@@ -1,55 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package patchjson6902
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
namespace: bar
`)}},
Filters: []kio.Filter{
Filter{
Patch: `
- op: replace
path: /metadata/namespace
value: "ns"
`,
},
},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// namespace: ns
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// namespace: ns
}

View File

@@ -1,65 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package patchjson6902
import (
"strings"
jsonpatch "github.com/evanphx/json-patch"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
k8syaml "sigs.k8s.io/yaml"
)
type Filter struct {
Patch string
decodedPatch jsonpatch.Patch
}
var _ kio.Filter = Filter{}
func (pf Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
decodedPatch, err := pf.decodePatch()
if err != nil {
return nil, err
}
pf.decodedPatch = decodedPatch
return kio.FilterAll(yaml.FilterFunc(pf.run)).Filter(nodes)
}
func (pf Filter) decodePatch() (jsonpatch.Patch, error) {
patch := pf.Patch
// If the patch doesn't look like a JSON6902 patch, we
// try to parse it to json.
if !strings.HasPrefix(pf.Patch, "[") {
p, err := k8syaml.YAMLToJSON([]byte(patch))
if err != nil {
return nil, err
}
patch = string(p)
}
decodedPatch, err := jsonpatch.DecodePatch([]byte(patch))
if err != nil {
return nil, err
}
return decodedPatch, nil
}
func (pf Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
// We don't actually use the kyaml library for manipulating the
// yaml here. We just marshal it to json and rely on the
// jsonpatch library to take care of applying the patch.
// This means ordering might not be preserved with this filter.
b, err := node.MarshalJSON()
if err != nil {
return nil, err
}
res, err := pf.decodedPatch.Apply(b)
if err != nil {
return nil, err
}
err = node.UnmarshalJSON(res)
return node, err
}

View File

@@ -1,173 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package patchjson6902
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest"
)
const input = `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
spec:
replica: 2
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- image: nginx
name: nginx
`
func TestSomething(t *testing.T) {
testCases := []struct {
testName string
input string
filter Filter
expectedOutput string
}{
{
testName: "single operation, json",
input: input,
filter: Filter{
Patch: `[
{"op": "replace", "path": "/spec/replica", "value": 5}
]`,
},
expectedOutput: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
spec:
replica: 5
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- image: nginx
name: nginx
`,
},
{
testName: "multiple operations, json",
input: input,
filter: Filter{
Patch: `[
{"op": "replace", "path": "/spec/template/spec/containers/0/name", "value": "my-nginx"},
{"op": "add", "path": "/spec/replica", "value": 999},
{"op": "add", "path": "/spec/template/spec/containers/0/command", "value": ["arg1", "arg2", "arg3"]}
]`,
},
expectedOutput: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
spec:
replica: 999
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- command:
- arg1
- arg2
- arg3
image: nginx
name: my-nginx
`,
},
{
testName: "single operation, yaml",
input: input,
filter: Filter{
Patch: `
- op: replace
path: /spec/replica
value: 5
`,
},
expectedOutput: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
spec:
replica: 5
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- image: nginx
name: nginx
`,
},
{
testName: "multiple operations, yaml",
input: input,
filter: Filter{
Patch: `
- op: replace
path: /spec/template/spec/containers/0/name
value: my-nginx
- op: add
path: /spec/replica
value: 999
- op: add
path: /spec/template/spec/containers/0/command
value:
- arg1
- arg2
- arg3
`,
},
expectedOutput: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
spec:
replica: 999
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- command:
- arg1
- arg2
- arg3
image: nginx
name: my-nginx
`,
},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(
filtertest.RunFilter(t, tc.input, tc.filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package patchstrategicmerge contains a kio.Filter implementation of the
// kustomize strategic merge patch transformer.
package patchstrategicmerge

View File

@@ -1,49 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package patchstrategicmerge
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func ExampleFilter() {
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
replicas: 3
`)}},
Filters: []kio.Filter{Filter{
Patch: yaml.MustParse(`
spec:
template:
containers:
- image: nginx
`),
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// spec:
// replicas: 3
// template:
// containers:
// - image: nginx
}

View File

@@ -1,21 +0,0 @@
package patchstrategicmerge
import (
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/kustomize/kyaml/yaml/merge2"
)
type Filter struct {
Patch *yaml.RNode
}
var _ kio.Filter = Filter{}
func (pf Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(pf.run)).Filter(nodes)
}
func (pf Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
return merge2.Merge(pf.Patch, node)
}

View File

@@ -1,82 +0,0 @@
package patchstrategicmerge
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func TestFilter(t *testing.T) {
testCases := map[string]struct {
input string
patch *yaml.RNode
expected string
}{
"simple patch": {
input: `
apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
`,
patch: yaml.MustParse(`
metadata:
name: yourDeploy
`),
expected: `
apiVersion: apps/v1
metadata:
name: yourDeploy
kind: Deployment
`,
},
"nested patch": {
input: `
apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
spec:
containers:
- name: nginx
args:
- abc
`,
patch: yaml.MustParse(`
spec:
containers:
- name: nginx
args:
- def
`),
expected: `
apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
spec:
containers:
- name: nginx
args:
- def
`,
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
f := Filter{
Patch: tc.patch,
}
if !assert.Equal(t,
strings.TrimSpace(tc.expected),
strings.TrimSpace(
filtertest.RunFilter(t, tc.input, f))) {
t.FailNow()
}
})
}
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package prefixsuffix contains a kio.Filter implementation of the kustomize
// PrefixSuffixTransformer.
package prefixsuffix

View File

@@ -1,47 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package prefixsuffix_test
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
fss := builtinconfig.MakeDefaultConfig().NamePrefix
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`)}},
Filters: []kio.Filter{prefixsuffix.Filter{Prefix: "baz-", FsSlice: fss}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: baz-instance
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: baz-instance
}

View File

@@ -1,43 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package prefixsuffix
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Filter applies resource name prefix's and suffix's using the fieldSpecs
type Filter struct {
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
var _ kio.Filter = Filter{}
func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(ns.run)).Filter(nodes)
}
// Run runs the filter on a single node rather than a slice
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
// transformations based on data -- :)
err := node.PipeE(fsslice.Filter{
FsSlice: ns.FsSlice,
SetValue: ns.set,
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
})
return node, err
}
func (ns Filter) set(node *yaml.RNode) error {
return fsslice.SetScalar(fmt.Sprintf(
"%s%s%s", ns.Prefix, node.YNode().Value, ns.Suffix))(node)
}

View File

@@ -1,167 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package prefixsuffix_test
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
var tests = []TestCase{
{
name: "prefix",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: foo-instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: foo-instance
`,
filter: prefixsuffix.Filter{Prefix: "foo-"},
},
{
name: "suffix",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance-foo
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance-foo
`,
filter: prefixsuffix.Filter{Suffix: "-foo"},
},
{
name: "prefix-suffix",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: bar-instance-foo
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: bar-instance-foo
`,
filter: prefixsuffix.Filter{Prefix: "bar-", Suffix: "-foo"},
},
{
name: "data-fieldspecs",
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
a:
b:
c: d
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
a:
b:
c: d
`,
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: foo-instance
a:
b:
c: foo-d
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: foo-instance
a:
b:
c: foo-d
`,
filter: prefixsuffix.Filter{Prefix: "foo-"},
fsslice: []types.FieldSpec{
{
Path: "a/b/c",
},
},
},
}
type TestCase struct {
name string
input string
expected string
filter prefixsuffix.Filter
fsslice types.FsSlice
}
var config = builtinconfig.MakeDefaultConfig()
func TestFilter(t *testing.T) {
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
test.filter.FsSlice = append(config.NamePrefix, test.fsslice...)
if !assert.Equal(t,
strings.TrimSpace(test.expected),
strings.TrimSpace(
filtertest_test.RunFilter(t, test.input, test.filter))) {
t.FailNow()
}
})
}
}

View File

@@ -1,6 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package replicacount contains a kio.Filter implementation of the kustomize
// ReplicaCountTransformer.
package replicacount

View File

@@ -1,64 +0,0 @@
package replicacount
import (
"bytes"
"log"
"os"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
template:
replicas: 5
---
apiVersion: example.com/v1
kind: Bar
metadata:
name: instance
spec:
template:
replicas: 5
`)}},
Filters: []kio.Filter{Filter{
Replica: types.Replica{
Count: 42,
Name: "instance",
},
FsSlice: types.FsSlice{
{
Path: "spec/template/replicas",
},
},
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {
log.Fatal(err)
}
// Output:
// apiVersion: example.com/v1
// kind: Foo
// metadata:
// name: instance
// spec:
// template:
// replicas: 42
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// spec:
// template:
// replicas: 42
}

View File

@@ -1,48 +0,0 @@
package replicacount
import (
"strconv"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Filter updates/sets replicas fields using the fieldSpecs
type Filter struct {
Replica types.Replica `json:"replica,omitempty" yaml:"replica,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
var _ kio.Filter = Filter{}
func (rc Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(rc.run)).Filter(nodes)
}
// run processes each node individually.
func (rc Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
meta, err := node.GetMeta()
if err != nil {
return nil, err
}
// only update resources where the name matches the Replica name.
if meta.Name != rc.Replica.Name {
return node, nil
}
err = node.PipeE(fsslice.Filter{
FsSlice: rc.FsSlice,
SetValue: rc.set,
CreateKind: yaml.ScalarNode, // replicas is a ScalarNode
})
return node, err
}
func (rc Filter) set(node *yaml.RNode) error {
return fsslice.SetScalar(strconv.FormatInt(rc.Replica.Count, 10))(node)
}

View File

@@ -1,164 +0,0 @@
package replicacount
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
func TestFilter(t *testing.T) {
var config = builtinconfig.MakeDefaultConfig()
testCases := map[string]struct {
input string
expected string
filter Filter
fsslice types.FsSlice
}{
"update field": {
input: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
spec:
replicas: 5
`,
expected: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
spec:
replicas: 42
`,
filter: Filter{
Replica: types.Replica{
Name: "dep",
Count: 42,
},
},
fsslice: types.FsSlice{
{
Path: "spec/replicas",
},
},
},
"add field": {
input: `
apiVersion: custom/v1
kind: Custom
metadata:
name: cus
spec:
template:
other: something
`,
expected: `
apiVersion: custom/v1
kind: Custom
metadata:
name: cus
spec:
template:
other: something
replicas: 42
`,
filter: Filter{
Replica: types.Replica{
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
Path: "spec/template/replicas",
CreateIfNotPresent: true,
},
},
},
"no update if CreateIfNotPresent is false": {
input: `
apiVersion: custom/v1
kind: Custom
metadata:
name: cus
spec:
template:
other: something
`,
expected: `
apiVersion: custom/v1
kind: Custom
metadata:
name: cus
spec:
template:
other: something
`,
filter: Filter{
Replica: types.Replica{
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
Path: "spec/template/replicas",
},
},
},
"update multiple fields": {
input: `
apiVersion: custom/v1
kind: Custom
metadata:
name: cus
spec:
replicas: 5
template:
replicas: 5
`,
expected: `
apiVersion: custom/v1
kind: Custom
metadata:
name: cus
spec:
replicas: 42
template:
replicas: 42
`,
filter: Filter{
Replica: types.Replica{
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
Path: "spec/template/replicas",
},
{
Path: "spec/replicas",
},
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
tc.filter.FsSlice = append(config.Replicas, tc.fsslice...)
if !assert.Equal(t,
strings.TrimSpace(tc.expected),
strings.TrimSpace(
filtertest_test.RunFilter(t, tc.input, tc.filter))) {
t.FailNow()
}
})
}
}

View File

@@ -4,18 +4,15 @@ go 1.13
require (
github.com/evanphx/json-patch v4.5.0+incompatible
github.com/go-openapi/spec v0.19.5
github.com/go-openapi/spec v0.19.4
github.com/golangci/golangci-lint v1.21.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.4.0
github.com/yujunz/go-getter v1.4.1-lite
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff
gopkg.in/yaml.v2 v2.2.7
gopkg.in/yaml.v2 v2.2.4
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
sigs.k8s.io/kustomize/kyaml v0.1.5
sigs.k8s.io/yaml v1.1.0
)

View File

@@ -1,7 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
@@ -15,7 +14,6 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@@ -25,18 +23,12 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bombsimon/wsl v1.2.5 h1:9gTOkIwVtoDZywvX802SDHokeX4kW1cKnV8ZTVAPkRs=
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -53,7 +45,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@@ -68,8 +59,6 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db h1:GYXWx7Vr3+zv833u+8IoXbNnQY0AdXsxAgI0kX7xcwA=
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0=
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
@@ -85,8 +74,8 @@ github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw=
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo=
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
@@ -187,12 +176,6 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@@ -222,6 +205,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -241,12 +225,9 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -256,7 +237,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -271,7 +251,6 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -290,14 +269,12 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d h1:BzRvVq1EHuIjxpijCEKpAxzKUUMurOQ4sknehIATRh8=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM=
@@ -333,7 +310,6 @@ github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -342,8 +318,6 @@ github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiff
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg=
@@ -355,15 +329,9 @@ github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -372,6 +340,7 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -381,7 +350,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -419,10 +387,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -444,6 +412,8 @@ golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -478,10 +448,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
@@ -506,15 +472,6 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize/kyaml v0.1.1 h1:nGUNYINljZNmlAS8uoobUv/wx/s3Pg8dNxYo+W7uYh0=
sigs.k8s.io/kustomize/kyaml v0.1.1/go.mod h1:/NdPPfrperSCGjm55cwEro1loBVtbtVIXSb7FguK6uk=
sigs.k8s.io/kustomize/kyaml v0.1.2 h1:l12+QGl+ETUHhP8/bZAi6TknU7H194fXL/9b2gUxZFY=
sigs.k8s.io/kustomize/kyaml v0.1.3 h1:zbeHVTMCQPtWgjIH/YYJZC45mm7coTdw2TblyJ79BrY=
sigs.k8s.io/kustomize/kyaml v0.1.3/go.mod h1:461i94nj0h0ylJ6w83jLkR4SqqVhn1iY6fjD0JSTQeE=
sigs.k8s.io/kustomize/kyaml v0.1.5 h1:NicBWYTwkuOfVyZDbNkfSBSCwSgin4uirkedtyZltIc=
sigs.k8s.io/kustomize/kyaml v0.1.5/go.mod h1:461i94nj0h0ylJ6w83jLkR4SqqVhn1iY6fjD0JSTQeE=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -75,8 +75,14 @@ type KunstructuredFactory interface {
SliceFromBytes([]byte) ([]Kunstructured, error)
FromMap(m map[string]interface{}) Kunstructured
Hasher() KunstructuredHasher
MakeConfigMap(kvLdr KvLoader, args *types.ConfigMapArgs) (Kunstructured, error)
MakeSecret(kvLdr KvLoader, args *types.SecretArgs) (Kunstructured, error)
MakeConfigMap(
kvLdr KvLoader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (Kunstructured, error)
MakeSecret(
kvLdr KvLoader,
options *types.GeneratorOptions,
args *types.SecretArgs) (Kunstructured, error)
}
// KunstructuredHasher returns a hash of the argument

View File

@@ -1,50 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package image
import (
"regexp"
"strings"
)
// IsImageMatched returns true if the value of t is identical to the
// image name in the full image name and tag as given by s.
func IsImageMatched(s, t string) bool {
// Tag values are limited to [a-zA-Z0-9_.{}-].
// Some tools like Bazel rules_k8s allow tag patterns with {} characters.
// More info: https://github.com/bazelbuild/rules_k8s/pull/423
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.{}-]*)?$")
return pattern.MatchString(s)
}
// Split separates and returns the name and tag parts
// from the image string using either colon `:` or at `@` separators.
// Note that the returned tag keeps its separator.
func Split(imageName string) (name string, tag string) {
// check if image name contains a domain
// if domain is present, ignore domain and check for `:`
ic := -1
if slashIndex := strings.Index(imageName, "/"); slashIndex < 0 {
ic = strings.LastIndex(imageName, ":")
} else {
lastIc := strings.LastIndex(imageName[slashIndex:], ":")
// set ic only if `:` is present
if lastIc > 0 {
ic = slashIndex + lastIc
}
}
ia := strings.LastIndex(imageName, "@")
if ic < 0 && ia < 0 {
return imageName, ""
}
i := ic
if ia > 0 {
i = ia
}
name = imageName[:i]
tag = imageName[i:]
return
}

View File

@@ -1,80 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package image
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsImageMatched(t *testing.T) {
testCases := []struct {
testName string
value string
name string
isMatched bool
}{
{
testName: "identical",
value: "nginx",
name: "nginx",
isMatched: true,
},
{
testName: "name is match",
value: "nginx:12345",
name: "nginx",
isMatched: true,
},
{
testName: "name is not a match",
value: "apache:12345",
name: "nginx",
isMatched: false,
},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
assert.Equal(t, tc.isMatched, IsImageMatched(tc.value, tc.name))
})
}
}
func TestSplit(t *testing.T) {
testCases := []struct {
testName string
value string
name string
tag string
}{
{
testName: "no tag",
value: "nginx",
name: "nginx",
tag: "",
},
{
testName: "with tag",
value: "nginx:1.2.3",
name: "nginx",
tag: ":1.2.3",
},
{
testName: "with digest",
value: "nginx@12345",
name: "nginx",
tag: "@12345",
},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
name, tag := Split(tc.value)
assert.Equal(t, tc.name, name)
assert.Equal(t, tc.tag, tag)
})
}
}

View File

@@ -209,7 +209,7 @@ but they are functional.
## Technical details
### Overall design and implementations
### Overall design and imlpementation
There are a few components that are all running together in order to get
the overall application to work smoothly. This section will provide a brief

View File

@@ -11,7 +11,7 @@ metadata:
spec:
storage:
gcs:
# the bucket must exist for the snapshot repository to be created successfully.
# the bucket must exist for the snapshot respository to be created successfully.
bucket: kustomize-backup
# the path does not need to exist.
# If the path does not exist, the controller will create the folder in the GCS bucket.

View File

@@ -1,4 +1,4 @@
Find all the transformer files whose `kinds` field includes `HelmValues`, and
Find all the trasnformer files whose `kinds` field includes `HelmValues`, and
only output certain fields of each document:
```
curl -s -X GET "${ElasticSearchURL}:9200/${INDEXNAME}/_search?pretty" -H 'Content-Type: application/json' -d'

View File

@@ -25,7 +25,8 @@ func makeFreshConfigMap(
}
// MakeConfigMap returns a new ConfigMap, or nil and an error.
func (f *Factory) MakeConfigMap(args *types.ConfigMapArgs) (*corev1.ConfigMap, error) {
func (f *Factory) MakeConfigMap(
args *types.ConfigMapArgs) (*corev1.ConfigMap, error) {
all, err := f.kvLdr.Load(args.KvPairSources)
if err != nil {
return nil, errors.Wrap(err, "loading KV pairs")
@@ -37,7 +38,10 @@ func (f *Factory) MakeConfigMap(args *types.ConfigMapArgs) (*corev1.ConfigMap, e
return nil, errors.Wrap(err, "trouble mapping")
}
}
f.copyLabelsAndAnnotations(cm, args.Options)
if f.options != nil {
cm.SetLabels(f.options.Labels)
cm.SetAnnotations(f.options.Annotations)
}
return cm, nil
}

View File

@@ -53,7 +53,7 @@ BAR=baz
}
}
func makeLiteralConfigMap(name string, labels, annotations map[string]string) *corev1.ConfigMap {
func makeLiteralConfigMap(name string) *corev1.ConfigMap {
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
@@ -69,12 +69,7 @@ func makeLiteralConfigMap(name string, labels, annotations map[string]string) *c
"d": "true",
},
}
if labels != nil {
cm.SetLabels(labels)
}
if annotations != nil {
cm.SetAnnotations(annotations)
}
cm.SetLabels(map[string]string{"foo": "bar"})
return cm
}
@@ -82,6 +77,7 @@ func TestConstructConfigMap(t *testing.T) {
type testCase struct {
description string
input types.ConfigMapArgs
options *types.GeneratorOptions
expected *corev1.ConfigMap
}
@@ -98,6 +94,7 @@ func TestConstructConfigMap(t *testing.T) {
},
},
},
options: nil,
expected: makeEnvConfigMap("envConfigMap"),
},
{
@@ -113,6 +110,7 @@ func TestConstructConfigMap(t *testing.T) {
},
},
},
options: nil,
expected: makeFileConfigMap("fileConfigMap"),
},
{
@@ -123,44 +121,14 @@ func TestConstructConfigMap(t *testing.T) {
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
},
},
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
"foo": "bar",
}, nil),
},
{
description: "construct config map from literal with GeneratorOptions in ConfigMapArgs",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalConfigMap",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "changed",
"cat": "dog",
},
Annotations: map[string]string{
"foo": "changed",
"cat": "dog",
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
"foo": "changed",
"cat": "dog",
}, map[string]string{
"foo": "changed",
"cat": "dog",
}),
expected: makeLiteralConfigMap("literalConfigMap"),
},
}
@@ -178,7 +146,8 @@ func TestConstructConfigMap(t *testing.T) {
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for _, tc := range testCases {
cm, err := NewFactory(kvLdr).MakeConfigMap(&tc.input)
f := NewFactory(kvLdr, tc.options)
cm, err := f.MakeConfigMap(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@@ -4,34 +4,20 @@
package configmapandsecret
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
)
// Factory makes ConfigMaps and Secrets.
type Factory struct {
kvLdr ifc.KvLoader
kvLdr ifc.KvLoader
options *types.GeneratorOptions
}
// NewFactory returns a new factory that makes ConfigMaps and Secrets.
func NewFactory(kvLdr ifc.KvLoader) *Factory {
return &Factory{kvLdr: kvLdr}
}
// copyLabelsAndAnnotations copies labels and annotations from
// GeneratorOptions into the given object.
func (f *Factory) copyLabelsAndAnnotations(
obj metav1.Object, opts *types.GeneratorOptions) {
if opts == nil {
return
}
if opts.Labels != nil {
obj.SetLabels(types.CopyMap(opts.Labels))
}
if opts.Annotations != nil {
obj.SetAnnotations(types.CopyMap(opts.Annotations))
}
func NewFactory(
kvLdr ifc.KvLoader, o *types.GeneratorOptions) *Factory {
return &Factory{kvLdr: kvLdr, options: o}
}
const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v"

View File

@@ -26,7 +26,8 @@ func makeFreshSecret(
}
// MakeSecret returns a new secret.
func (f *Factory) MakeSecret(args *types.SecretArgs) (*corev1.Secret, error) {
func (f *Factory) MakeSecret(
args *types.SecretArgs) (*corev1.Secret, error) {
all, err := f.kvLdr.Load(args.KvPairSources)
if err != nil {
return nil, err
@@ -38,7 +39,10 @@ func (f *Factory) MakeSecret(args *types.SecretArgs) (*corev1.Secret, error) {
return nil, err
}
}
f.copyLabelsAndAnnotations(s, args.Options)
if f.options != nil {
s.SetLabels(f.options.Labels)
s.SetAnnotations(f.options.Annotations)
}
return s, nil
}

View File

@@ -51,7 +51,7 @@ BAR=baz
}
}
func makeLiteralSecret(name string, labels, annotations map[string]string) *corev1.Secret {
func makeLiteralSecret(name string) *corev1.Secret {
s := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
@@ -66,12 +66,7 @@ func makeLiteralSecret(name string, labels, annotations map[string]string) *core
},
Type: "Opaque",
}
if labels != nil {
s.SetLabels(labels)
}
if annotations != nil {
s.SetAnnotations(annotations)
}
s.SetLabels(map[string]string{"foo": "bar"})
return s
}
@@ -79,6 +74,7 @@ func TestConstructSecret(t *testing.T) {
type testCase struct {
description string
input types.SecretArgs
options *types.GeneratorOptions
expected *corev1.Secret
}
@@ -93,6 +89,7 @@ func TestConstructSecret(t *testing.T) {
},
},
},
options: nil,
expected: makeEnvSecret("envSecret"),
},
{
@@ -105,6 +102,7 @@ func TestConstructSecret(t *testing.T) {
},
},
},
options: nil,
expected: makeFileSecret("fileSecret"),
},
{
@@ -115,23 +113,14 @@ func TestConstructSecret(t *testing.T) {
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
Annotations: map[string]string{
"fruit": "banana",
"pet": "dog",
},
},
},
},
expected: makeLiteralSecret("literalSecret", map[string]string{
"foo": "bar",
}, map[string]string{
"fruit": "banana",
"pet": "dog",
}),
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
expected: makeLiteralSecret("literalSecret"),
},
}
@@ -142,7 +131,7 @@ func TestConstructSecret(t *testing.T) {
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for _, tc := range testCases {
f := NewFactory(kvLdr)
f := NewFactory(kvLdr, tc.options)
cm, err := f.MakeSecret(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)

View File

@@ -266,9 +266,8 @@ func (p *ExecPlugin) UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, err
}
r.SetAnnotations(annotations)
r.SetOptions(types.NewGenArgs(
&types.GeneratorArgs{
Behavior: behavior,
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
&types.GeneratorArgs{Behavior: behavior},
&types.GeneratorOptions{DisableNameSuffixHash: !needsHash}))
}
return rm, nil
}

View File

@@ -116,9 +116,7 @@ func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHa
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{"name": name},
}, &types.GeneratorArgs{
Behavior: behavior,
Options: &types.GeneratorOptions{DisableNameSuffixHash: disableHash}})
}, &types.GeneratorArgs{Behavior: behavior}, &types.GeneratorOptions{DisableNameSuffixHash: disableHash})
}
func strptr(s string) *string {

View File

@@ -7,6 +7,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"log"
"strings"
"github.com/pkg/errors"
@@ -301,15 +302,18 @@ func (kt *KustTarget) configureExternalTransformers() ([]resmap.Transformer, err
func (kt *KustTarget) accumulateResources(
ra *accumulator.ResAccumulator, paths []string) error {
for _, path := range paths {
// try loading resource as file then as base (directory or git repository)
if errF := kt.accumulateFile(ra, path); errF != nil {
ldr, errL := kt.ldr.New(path)
if errL != nil {
return fmt.Errorf("accumulateFile %q, loader.New %q", errF, errL)
ldr, err := kt.ldr.New(path)
if err == nil {
err = kt.accumulateDirectory(ra, ldr)
if err != nil {
return err
}
errD := kt.accumulateDirectory(ra, ldr)
if errD != nil {
return fmt.Errorf("accumulateFile %q, accumulateDirector: %q", errF, errD)
} else {
err2 := kt.accumulateFile(ra, path)
if err2 != nil {
// Log ldr.New() error to highlight git failures.
log.Print(err.Error())
return err2
}
}
}

View File

@@ -74,12 +74,14 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.SecretGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
result []resmap.Generator, err error) {
var c struct {
types.GeneratorOptions
types.SecretArgs
}
if kt.kustomization.GeneratorOptions != nil {
c.GeneratorOptions = *kt.kustomization.GeneratorOptions
}
for _, args := range kt.kustomization.SecretGenerator {
c.SecretArgs = args
c.SecretArgs.Options = types.MergeGlobalOptionsIntoLocal(
c.SecretArgs.Options, kt.kustomization.GeneratorOptions)
p := f()
err := kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
@@ -93,12 +95,14 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.ConfigMapGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
result []resmap.Generator, err error) {
var c struct {
types.GeneratorOptions
types.ConfigMapArgs
}
if kt.kustomization.GeneratorOptions != nil {
c.GeneratorOptions = *kt.kustomization.GeneratorOptions
}
for _, args := range kt.kustomization.ConfigMapGenerator {
c.ConfigMapArgs = args
c.ConfigMapArgs.Options = types.MergeGlobalOptionsIntoLocal(
c.ConfigMapArgs.Options, kt.kustomization.GeneratorOptions)
p := f()
err := kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {

View File

@@ -75,8 +75,11 @@ func (kf *KunstructuredFactoryImpl) FromMap(
// MakeConfigMap returns an instance of Kunstructured for ConfigMap
func (kf *KunstructuredFactoryImpl) MakeConfigMap(
kvLdr ifc.KvLoader, args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(kvLdr).MakeConfigMap(args)
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(
kvLdr, options).MakeConfigMap(args)
if err != nil {
return nil, err
}
@@ -85,8 +88,11 @@ func (kf *KunstructuredFactoryImpl) MakeConfigMap(
// MakeSecret returns an instance of Kunstructured for Secret
func (kf *KunstructuredFactoryImpl) MakeSecret(
kvLdr ifc.KvLoader, args *types.SecretArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(kvLdr).MakeSecret(args)
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.SecretArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(
kvLdr, options).MakeSecret(args)
if err != nil {
return nil, err
}

View File

@@ -133,7 +133,7 @@ func (fs *UnstructAdapter) selectSubtree(path string) (map[string]interface{}, [
func (fs *UnstructAdapter) GetFieldValue(path string) (interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
s, found, err := unstructured.NestedFieldNoCopy(
@@ -141,14 +141,14 @@ func (fs *UnstructAdapter) GetFieldValue(path string) (interface{}, error) {
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
// GetString returns value at the given fieldpath.
func (fs *UnstructAdapter) GetString(path string) (string, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return "", NoFieldError{Field: path}
return "", noFieldError{Field: path}
}
s, found, err := unstructured.NestedString(
@@ -156,14 +156,14 @@ func (fs *UnstructAdapter) GetString(path string) (string, error) {
if found || err != nil {
return s, err
}
return "", NoFieldError{Field: path}
return "", noFieldError{Field: path}
}
// GetStringSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringSlice(path string) ([]string, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return []string{}, NoFieldError{Field: path}
return []string{}, noFieldError{Field: path}
}
s, found, err := unstructured.NestedStringSlice(
@@ -171,14 +171,14 @@ func (fs *UnstructAdapter) GetStringSlice(path string) ([]string, error) {
if found || err != nil {
return s, err
}
return []string{}, NoFieldError{Field: path}
return []string{}, noFieldError{Field: path}
}
// GetBool returns value at the given fieldpath.
func (fs *UnstructAdapter) GetBool(path string) (bool, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return false, NoFieldError{Field: path}
return false, noFieldError{Field: path}
}
s, found, err := unstructured.NestedBool(
@@ -186,7 +186,7 @@ func (fs *UnstructAdapter) GetBool(path string) (bool, error) {
if found || err != nil {
return s, err
}
return false, NoFieldError{Field: path}
return false, noFieldError{Field: path}
}
// GetFloat64 returns value at the given fieldpath.
@@ -201,14 +201,14 @@ func (fs *UnstructAdapter) GetFloat64(path string) (float64, error) {
if found || err != nil {
return s, err
}
return 0, NoFieldError{Field: path}
return 0, noFieldError{Field: path}
}
// GetInt64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetInt64(path string) (int64, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return 0, NoFieldError{Field: path}
return 0, noFieldError{Field: path}
}
s, found, err := unstructured.NestedInt64(
@@ -216,14 +216,14 @@ func (fs *UnstructAdapter) GetInt64(path string) (int64, error) {
if found || err != nil {
return s, err
}
return 0, NoFieldError{Field: path}
return 0, noFieldError{Field: path}
}
// GetSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetSlice(path string) ([]interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
s, found, err := unstructured.NestedSlice(
@@ -231,14 +231,14 @@ func (fs *UnstructAdapter) GetSlice(path string) ([]interface{}, error) {
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
// GetStringMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringMap(path string) (map[string]string, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
s, found, err := unstructured.NestedStringMap(
@@ -246,14 +246,14 @@ func (fs *UnstructAdapter) GetStringMap(path string) (map[string]string, error)
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
// GetMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
s, found, err := unstructured.NestedMap(
@@ -261,7 +261,7 @@ func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
return nil, noFieldError{Field: path}
}
func (fs *UnstructAdapter) MatchesLabelSelector(selector string) (bool, error) {
@@ -340,11 +340,11 @@ func toSchemaGvk(x resid.Gvk) schema.GroupVersionKind {
}
}
// NoFieldError is returned when a field is expected, but missing.
type NoFieldError struct {
// noFieldError is returned when a field is expected, but missing.
type noFieldError struct {
Field string
}
func (e NoFieldError) Error() string {
func (e noFieldError) Error() string {
return fmt.Sprintf("no field named '%s'", e.Field)
}

View File

@@ -345,24 +345,5 @@ nameReference:
kind: PersistentVolumeClaim
- path: spec/volumeClaimTemplates/spec/storageClassName
kind: StatefulSet
- kind: PriorityClass
version: v1
group: scheduling.k8s.io
fieldSpecs:
- path: spec/priorityClassName
kind: Pod
- path: spec/template/spec/priorityClassName
kind: StatefulSet
- path: spec/template/spec/priorityClassName
kind: Deployment
- path: spec/template/spec/priorityClassName
kind: ReplicationController
- path: spec/jobTemplate/spec/template/spec/priorityClassName
kind: CronJob
- path: spec/template/spec/priorityClassName
kind: Job
- path: spec/template/spec/priorityClassName
kind: DaemonSet
`
)

View File

@@ -30,9 +30,6 @@ varReference:
- path: spec/jobTemplate/spec/template/spec/initContainers/volumeMounts/mountPath
kind: CronJob
- path: spec/jobTemplate/spec/template/volumes/nfs/server
kind: CronJob
- path: spec/template/spec/containers/args
kind: DaemonSet
@@ -57,9 +54,6 @@ varReference:
- path: spec/template/spec/initContainers/volumeMounts/mountPath
kind: DaemonSet
- path: spec/template/spec/volumes/nfs/server
kind: DaemonSet
- path: spec/template/spec/containers/args
kind: Deployment
@@ -84,9 +78,6 @@ varReference:
- path: spec/template/spec/initContainers/volumeMounts/mountPath
kind: Deployment
- path: spec/template/spec/volumes/nfs/server
kind: Deployment
- path: spec/rules/host
kind: Ingress
@@ -120,9 +111,6 @@ varReference:
- path: spec/template/spec/initContainers/volumeMounts/mountPath
kind: Job
- path: spec/template/spec/volumes/nfs/server
kind: Job
- path: spec/containers/args
kind: Pod
@@ -147,9 +135,6 @@ varReference:
- path: spec/initContainers/volumeMounts/mountPath
kind: Pod
- path: spec/volumes/nfs/server
kind: Pod
- path: spec/template/spec/containers/args
kind: ReplicaSet
@@ -174,9 +159,6 @@ varReference:
- path: spec/template/spec/initContainers/volumeMounts/mountPath
kind: ReplicaSet
- path: spec/template/spec/volumes/nfs/server
kind: ReplicaSet
- path: spec/ports/port
kind: Service
@@ -207,12 +189,6 @@ varReference:
- path: spec/template/spec/initContainers/volumeMounts/mountPath
kind: StatefulSet
- path: spec/volumeClaimTemplates/spec/nfs/server
kind: StatefulSet
- path: spec/nfs/server
kind: PersistentVolume
- path: metadata/labels
- path: metadata/annotations

View File

@@ -74,7 +74,7 @@ spec:
if err == nil {
t.Fatalf("expected an error")
}
if !strings.Contains(err.Error(), "accumulating resources") {
if !IsMissingKustomizationFileError(err) {
t.Fatalf("unexpected error: %q", err)
}
}
@@ -89,7 +89,7 @@ resources:
if err == nil {
t.Fatalf("expected an error")
}
if !strings.Contains(err.Error(), "accumulating resources") {
if !strings.Contains(err.Error(), "'/app/deployment.yaml' doesn't exist") {
t.Fatalf("unexpected error: %q", err)
}
}

View File

@@ -143,8 +143,7 @@ apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: my-config
options:
disableNameSuffixHash: true
disableNameSuffixHash: true
literals:
- MY_ENV=foo
`)

View File

@@ -12,12 +12,10 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func findSecret(m resmap.ResMap, prefix string) *resource.Resource {
func findSecret(m resmap.ResMap) *resource.Resource {
for _, r := range m.Resources() {
if r.OrgId().Kind == "Secret" {
if prefix == "" || strings.HasPrefix(r.GetName(), prefix) {
return r
}
return r
}
}
return nil
@@ -79,7 +77,7 @@ metadata:
m := th.Run("/whatever", th.MakeDefaultOptions())
secret := findSecret(m, "")
secret := findSecret(m)
if secret == nil {
t.Errorf("Expected to find a Secret")
}
@@ -92,7 +90,7 @@ metadata:
"disableNameSuffixHash: false",
"disableNameSuffixHash: true", -1))
m = th.Run("/whatever", th.MakeDefaultOptions())
secret = findSecret(m, "")
secret = findSecret(m)
if secret == nil {
t.Errorf("Expected to find a Secret")
}
@@ -100,47 +98,3 @@ metadata:
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}
func TestDisableNameSuffixHashPerObject(t *testing.T) {
th := kusttest_test.MakeHarness(t)
const kustomizationContent = `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
generatorOptions:
disableNameSuffixHash: false
secretGenerator:
- name: nohash
options:
disableNameSuffixHash: true
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
type: Opaque
- name: yeshash
options:
disableNameSuffixHash: false
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
type: Opaque
`
th.WriteK("/whatever", kustomizationContent)
m := th.Run("/whatever", th.MakeDefaultOptions())
secret := findSecret(m, "nohash")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "nohash" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
secret = findSecret(m, "yeshash")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "yeshash-mcgcmdcm69" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}

View File

@@ -4,7 +4,6 @@
package krusty_test
import (
"strings"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
@@ -22,7 +21,7 @@ func TestEmptyFileSystem(t *testing.T) {
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), "'noSuchThing' doesn't exist") {
if err.Error() != "'noSuchThing' doesn't exist" {
t.Fatalf("unexpected error: %v", err)
}
}

View File

@@ -1336,637 +1336,3 @@ spec:
protocol: TCP
`)
}
func TestVariableRefNFSServer(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
resources:
- pv_pvc.yaml
- nfs_deployment.yaml
- nfs_service.yaml
- Deployment.yaml
- CronJob.yaml
- DaemonSet.yaml
- ReplicaSet.yaml
- StatefulSet.yaml
- Pod.yaml
- Job.yaml
- nfs_pv.yaml
vars:
- name: NFS_SERVER_SERVICE_NAME
objref:
kind: Service
name: nfs-server-service
apiVersion: v1
fieldref:
fieldpath: metadata.name
`)
th.WriteF("/app/base/pv_pvc.yaml", `
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-volume-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
th.WriteF("/app/base/nfs_deployment.yaml", `
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-server
spec:
replicas: 1
template:
spec:
metadata:
labels:
role: nfs-server
containers:
- name: nfs-server
image: gcr.io/google_containers/volume-nfs:0.8
ports:
- name: nfs
containerPort: 2049
- name: mountd
containerPort: 20048
- name: rpcbind
containerPort: 111
securityContext:
privileged: true
volumeMounts:
- mountPath: /exports
name: shared-files
volumes:
- name: shared-files
persistentVolumeClaim:
claimName: shared-volume-claim
`)
th.WriteF("/app/base/nfs_service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: nfs-server-service
spec:
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
selector:
role: nfs-server
`)
th.WriteF("/app/base/Deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app.kubernetes.io/component: nginx
spec:
selector:
matchLabels:
app.kubernetes.io/component: nginx
template:
metadata:
labels:
app.kubernetes.io/component: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.7-alpine
ports:
- name: http
containerPort: 80
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteF("/app/base/CronJob.yaml", `
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteF("/app/base/DaemonSet.yaml", `
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- mountPath: /app/shared-files
name: nfs-files-vol
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: nfs-files-vol
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteF("/app/base/ReplicaSet.yaml", `
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# modify replicas according to your case
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteF("/app/base/Job.yaml", `
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
restartPolicy: Never
volumes:
- name: nfs-files-vol
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
backoffLimit: 4
`)
th.WriteF("/app/base/StatefulSet.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteMany" ]
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteF("/app/base/Pod.yaml", `
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx:1.15.7-alpine
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nfs-files-vol
mountPath: /app/shared-files
volumes:
- name: nfs-files-vol
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteF("/app/base/nfs_pv.yaml", `
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-files-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
path: /
readOnly: false
`)
th.WriteK("/app/overlay", `
nameprefix: kustomized-
resources:
- ../base
`)
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: kustomized-shared-volume-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kustomized-nfs-server
spec:
replicas: 1
template:
spec:
containers:
- image: gcr.io/google_containers/volume-nfs:0.8
name: nfs-server
ports:
- containerPort: 2049
name: nfs
- containerPort: 20048
name: mountd
- containerPort: 111
name: rpcbind
securityContext:
privileged: true
volumeMounts:
- mountPath: /exports
name: shared-files
metadata:
labels:
role: nfs-server
volumes:
- name: shared-files
persistentVolumeClaim:
claimName: kustomized-shared-volume-claim
---
apiVersion: v1
kind: Service
metadata:
name: kustomized-nfs-server-service
spec:
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
selector:
role: nfs-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: nginx
name: kustomized-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/component: nginx
template:
metadata:
labels:
app.kubernetes.io/component: nginx
spec:
containers:
- image: nginx:1.15.7-alpine
name: nginx
ports:
- containerPort: 80
name: http
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: kustomized-hello
spec:
jobTemplate:
spec:
template:
spec:
containers:
- args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
image: busybox
name: hello
restartPolicy: OnFailure
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
schedule: '*/1 * * * *'
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: fluentd-logging
name: kustomized-fluentd-elasticsearch
namespace: kube-system
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
containers:
- image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
name: fluentd-elasticsearch
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- mountPath: /var/log
name: varlog
- mountPath: /var/lib/docker/containers
name: varlibdockercontainers
readOnly: true
- mountPath: /app/shared-files
name: nfs-files-vol
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
volumes:
- hostPath:
path: /var/log
name: varlog
- hostPath:
path: /var/lib/docker/containers
name: varlibdockercontainers
- name: nfs-files-vol
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
labels:
app: guestbook
tier: frontend
name: kustomized-frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- image: gcr.io/google_samples/gb-frontend:v3
name: php-redis
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: kustomized-web
spec:
replicas: 3
selector:
matchLabels:
app: nginx
serviceName: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
name: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- mountPath: /usr/share/nginx/html
name: www
terminationGracePeriodSeconds: 10
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes:
- ReadWriteMany
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: myapp
name: kustomized-myapp-pod
spec:
containers:
- image: nginx:1.15.7-alpine
name: nginx
ports:
- containerPort: 80
name: http
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
volumes:
- name: nfs-files-vol
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
---
apiVersion: batch/v1
kind: Job
metadata:
name: kustomized-pi
spec:
backoffLimit: 4
template:
spec:
containers:
- command:
- perl
- -Mbignum=bpi
- -wle
- print bpi(2000)
image: perl
name: pi
volumeMounts:
- mountPath: /app/shared-files
name: nfs-files-vol
restartPolicy: Never
volumes:
- name: nfs-files-vol
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: kustomized-nfs-files-pv
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 10Gi
nfs:
path: /
readOnly: false
server: kustomized-nfs-server-service.default.srv.cluster.local
`)
}

View File

@@ -5,10 +5,7 @@ package loader
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"path/filepath"
"strings"
@@ -89,19 +86,9 @@ type fileLoader struct {
// File system utilities.
fSys filesys.FileSystem
// Used to load from HTTP
http *http.Client
// Used to clone repositories.
cloner git.Cloner
// If this is non-nil, the files were
// obtained from the given resource
rscSpec *remoteTargetSpec
// Used to get resources
getter remoteTargetGetter
// Used to clean up, as needed.
cleaner func() error
}
@@ -134,21 +121,20 @@ func newLoaderOrDie(
log.Fatalf("unable to make loader at '%s'; %v", path, err)
}
return newLoaderAtConfirmedDir(
lr, root, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget)
lr, root, fSys, nil, git.ClonerUsingGitExec)
}
// newLoaderAtConfirmedDir returns a new fileLoader with given root.
func newLoaderAtConfirmedDir(
lr LoadRestrictorFunc,
root filesys.ConfirmedDir, fSys filesys.FileSystem,
referrer *fileLoader, cloner git.Cloner, getter remoteTargetGetter) *fileLoader {
referrer *fileLoader, cloner git.Cloner) *fileLoader {
return &fileLoader{
loadRestrictor: lr,
root: root,
referrer: referrer,
fSys: fSys,
cloner: cloner,
getter: getter,
cleaner: func() error { return nil },
}
}
@@ -178,44 +164,37 @@ func (fl *fileLoader) New(path string) (ifc.Loader, error) {
if path == "" {
return nil, fmt.Errorf("new root cannot be empty")
}
ldr, errGet := newLoaderAtGetter(path, fl.fSys, nil, fl.cloner, fl.getter)
if errGet == nil {
return ldr, nil
}
repoSpec, errGit := git.NewRepoSpecFromUrl(path)
if errGit == nil {
repoSpec, err := git.NewRepoSpecFromUrl(path)
if err == nil {
// Treat this as git repo clone request.
if errGit := fl.errIfRepoCycle(repoSpec); errGit != nil {
return nil, errGit
if err := fl.errIfRepoCycle(repoSpec); err != nil {
return nil, err
}
return newLoaderAtGitClone(
repoSpec, fl.fSys, fl, fl.cloner, fl.getter)
repoSpec, fl.fSys, fl, fl.cloner)
}
if filepath.IsAbs(path) {
return nil, fmt.Errorf("new root '%s' cannot be absolute", path)
}
root, errDir := demandDirectoryRoot(fl.fSys, fl.root.Join(path))
if errDir != nil {
return nil, fmt.Errorf("Error loading %s with git: %v, dir: %v, get: %v", path, errGit, errDir, errGet)
root, err := demandDirectoryRoot(fl.fSys, fl.root.Join(path))
if err != nil {
return nil, err
}
if errDir := fl.errIfGitContainmentViolation(root); errDir != nil {
return nil, errDir
if err := fl.errIfGitContainmentViolation(root); err != nil {
return nil, err
}
if errDir := fl.errIfArgEqualOrHigher(root); errDir != nil {
return nil, errDir
if err := fl.errIfArgEqualOrHigher(root); err != nil {
return nil, err
}
return newLoaderAtConfirmedDir(
fl.loadRestrictor, root, fl.fSys, fl, fl.cloner, fl.getter), nil
fl.loadRestrictor, root, fl.fSys, fl, fl.cloner), nil
}
// newLoaderAtGitClone returns a new Loader pinned to a temporary
// directory holding a cloned git repo.
func newLoaderAtGitClone(
repoSpec *git.RepoSpec, fSys filesys.FileSystem,
referrer *fileLoader, cloner git.Cloner, getter remoteTargetGetter) (ifc.Loader, error) {
referrer *fileLoader, cloner git.Cloner) (ifc.Loader, error) {
cleaner := repoSpec.Cleaner(fSys)
err := cloner(repoSpec)
if err != nil {
@@ -245,7 +224,6 @@ func newLoaderAtGitClone(
repoSpec: repoSpec,
fSys: fSys,
cloner: cloner,
getter: getter,
cleaner: cleaner,
}, nil
}
@@ -315,25 +293,6 @@ func (fl *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
// else an error. Relative paths are taken relative
// to the root.
func (fl *fileLoader) Load(path string) ([]byte, error) {
if u, err := url.Parse(path); err == nil && (u.Scheme == "http" || u.Scheme == "https") {
var hc *http.Client
if fl.http != nil {
hc = fl.http
} else {
hc = &http.Client{}
}
resp, err := hc.Get(path)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
if !filepath.IsAbs(path) {
path = fl.root.Join(path)
}

View File

@@ -4,9 +4,7 @@
package loader
import (
"bytes"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
@@ -56,7 +54,6 @@ func makeLoader() *fileLoader {
return NewFileLoaderAtRoot(MakeFakeFs(testCases))
}
func TestLoaderLoad(t *testing.T) {
l1 := makeLoader()
if "/" != l1.Root() {
@@ -388,7 +385,7 @@ whatever
}
l, err := newLoaderAtGitClone(
repoSpec, fSys, nil,
git.DoNothingCloner(filesys.ConfirmedDir(coRoot)), getNothing)
git.DoNothingCloner(filesys.ConfirmedDir(coRoot)))
if err != nil {
t.Fatalf("unexpected err: %v\n", err)
}
@@ -467,7 +464,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
}
l1, err = newLoaderAtGitClone(
repoSpec, fSys, nil,
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)), getNothing)
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
if err != nil {
t.Fatalf("unexpected err: %v\n", err)
}
@@ -506,7 +503,7 @@ func TestLocalLoaderReferencingGitBase(t *testing.T) {
}
l1 := newLoaderAtConfirmedDir(
RestrictionRootOnly, root, fSys, nil,
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)), getNothing)
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
if l1.Root() != topDir {
t.Fatalf("unexpected root %s", l1.Root())
}
@@ -532,7 +529,7 @@ func TestRepoDirectCycleDetection(t *testing.T) {
}
l1 := newLoaderAtConfirmedDir(
RestrictionRootOnly, root, fSys, nil,
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)), getNothing)
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
p1 := "github.com/someOrg/someRepo/foo"
rs1, err := git.NewRepoSpecFromUrl(p1)
if err != nil {
@@ -561,7 +558,7 @@ func TestRepoIndirectCycleDetection(t *testing.T) {
}
l0 := newLoaderAtConfirmedDir(
RestrictionRootOnly, root, fSys, nil,
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)), getNothing)
git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
p1 := "github.com/someOrg/someRepo1"
p2 := "github.com/someOrg/someRepo2"
@@ -582,93 +579,3 @@ func TestRepoIndirectCycleDetection(t *testing.T) {
t.Fatalf("unexpected err: %v", err)
}
}
// Inspired by https://hassansin.github.io/Unit-Testing-http-client-in-Go
type fakeRoundTripper func(req *http.Request) *http.Response
func (f fakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req), nil
}
func makeFakeHTTPClient(fn fakeRoundTripper) *http.Client {
return &http.Client{
Transport: fn,
}
}
// TestLoaderHTTP test http file loader
func TestLoaderHTTP(t *testing.T) {
var testCasesFile = []testData{
{
path: "http/file.yaml",
expectedContent: "file content",
},
}
l1 := NewFileLoaderAtRoot(MakeFakeFs(testCasesFile))
if "/" != l1.Root() {
t.Fatalf("incorrect root: '%s'\n", l1.Root())
}
for _, x := range testCasesFile {
b, err := l1.Load(x.path)
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
if !reflect.DeepEqual([]byte(x.expectedContent), b) {
t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
}
}
var testCasesHTTP = []testData{
{
path: "http://example.com/resource.yaml",
expectedContent: "http content",
},
{
path: "https://example.com/resource.yaml",
expectedContent: "https content",
},
}
for _, x := range testCasesHTTP {
hc := makeFakeHTTPClient(func(req *http.Request) *http.Response {
u := req.URL.String()
if x.path != u {
t.Fatalf("expected URL %s, but got %s", x.path, u)
}
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString(x.expectedContent)),
Header: make(http.Header),
}
})
l2 := l1
l2.http = hc
b, err := l2.Load(x.path)
if err != nil {
t.Fatalf("unexpected load error: %v", err)
}
if !reflect.DeepEqual([]byte(x.expectedContent), b) {
t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
}
}
var testCaseUnsupported = []testData{
{
path: "httpsnotreal://example.com/resource.yaml",
expectedContent: "invalid",
},
}
for _, x := range testCaseUnsupported {
hc := makeFakeHTTPClient(func(req *http.Request) *http.Response {
t.Fatalf("unexpected request to URL %s", req.URL.String())
return nil
})
l2 := l1
l2.http = hc
_, err := l2.Load(x.path)
if err == nil {
t.Fatalf("expect error but get %v", err)
}
}
}

View File

@@ -1,101 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package loader
import (
"context"
"log"
"os"
"github.com/yujunz/go-getter"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/git"
)
type remoteTargetSpec struct {
// Raw is the original resource in kustomization.yaml
Raw string
// Dir is where the resource is saved
Dir filesys.ConfirmedDir
}
// Getter is a function that can gets resource
type remoteTargetGetter func(rs *remoteTargetSpec) error
func newLoaderAtGetter(raw string, fSys filesys.FileSystem, referrer *fileLoader, cloner git.Cloner, getter remoteTargetGetter) (ifc.Loader, error) {
rs := &remoteTargetSpec{
Raw: raw,
}
cleaner := func() error {
return fSys.RemoveAll(rs.Dir.String())
}
if err := getter(rs); err != nil {
cleaner()
return nil, err
}
return &fileLoader{
loadRestrictor: RestrictionRootOnly,
// TODO(yujunz): limit to getter root
root: rs.Dir,
referrer: referrer,
fSys: fSys,
cloner: cloner,
rscSpec: rs,
getter: getter,
cleaner: cleaner,
}, nil
}
func getRemoteTarget(rs *remoteTargetSpec) error {
var err error
rs.Dir, err = filesys.NewTmpConfirmedDir()
if err != nil {
return err
}
// Get the pwd
pwd, err := os.Getwd()
if err != nil {
log.Fatalf("Error getting wd: %s", err)
}
opts := []getter.ClientOption{}
client := &getter.Client{
Ctx: context.TODO(),
Src: rs.Raw,
Dst: rs.Dir.String(),
Pwd: pwd,
Mode: getter.ClientModeAny,
Detectors: []getter.Detector{
new(getter.GitHubDetector),
new(getter.GitDetector),
new(getter.BitBucketDetector),
},
Options: opts,
}
return client.Get()
}
func getNothing(rs *remoteTargetSpec) error {
var err error
rs.Dir, err = filesys.NewTmpConfirmedDir()
if err != nil {
return err
}
// Get the pwd
pwd, err := os.Getwd()
if err != nil {
log.Fatalf("Error getting wd: %s", err)
}
_, err = getter.Detect(rs.Raw, pwd, []getter.Detector{})
return err
}

View File

@@ -5,8 +5,6 @@
package loader
import (
"fmt"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/git"
@@ -21,23 +19,16 @@ import (
func NewLoader(
lr LoadRestrictorFunc,
target string, fSys filesys.FileSystem) (ifc.Loader, error) {
ldr, errGet := newLoaderAtGetter(target, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget)
if errGet == nil {
return ldr, nil
}
repoSpec, errGit := git.NewRepoSpecFromUrl(target)
if errGit == nil {
repoSpec, err := git.NewRepoSpecFromUrl(target)
if err == nil {
// The target qualifies as a remote git target.
return newLoaderAtGitClone(
repoSpec, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget)
repoSpec, fSys, nil, git.ClonerUsingGitExec)
}
root, errDir := demandDirectoryRoot(fSys, target)
if errDir == nil {
return newLoaderAtConfirmedDir(lr, root, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget), nil
root, err := demandDirectoryRoot(fSys, target)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("Error creating new loader with git: %v, dir: %v, get: %v", errGit, errDir, errGet)
return newLoaderAtConfirmedDir(
lr, root, fSys, nil, git.ClonerUsingGitExec), nil
}

View File

@@ -66,10 +66,12 @@ func (rmF *Factory) NewResMapFromBytes(b []byte) (ResMap, error) {
// NewResMapFromConfigMapArgs returns a Resource slice given
// a configmap metadata slice from kustomization file.
func (rmF *Factory) NewResMapFromConfigMapArgs(
kvLdr ifc.KvLoader, argList []types.ConfigMapArgs) (ResMap, error) {
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
argList []types.ConfigMapArgs) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argList {
res, err := rmF.resF.MakeConfigMap(kvLdr, &args)
res, err := rmF.resF.MakeConfigMap(kvLdr, options, &args)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromConfigMapArgs")
}
@@ -79,8 +81,10 @@ func (rmF *Factory) NewResMapFromConfigMapArgs(
}
func (rmF *Factory) FromConfigMapArgs(
kvLdr ifc.KvLoader, args types.ConfigMapArgs) (ResMap, error) {
res, err := rmF.resF.MakeConfigMap(kvLdr, &args)
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args types.ConfigMapArgs) (ResMap, error) {
res, err := rmF.resF.MakeConfigMap(kvLdr, options, &args)
if err != nil {
return nil, err
}
@@ -90,10 +94,12 @@ func (rmF *Factory) FromConfigMapArgs(
// NewResMapFromSecretArgs takes a SecretArgs slice, generates
// secrets from each entry, and accumulates them in a ResMap.
func (rmF *Factory) NewResMapFromSecretArgs(
kvLdr ifc.KvLoader, argsList []types.SecretArgs) (ResMap, error) {
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
argsList []types.SecretArgs) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argsList {
res, err := rmF.resF.MakeSecret(kvLdr, &args)
res, err := rmF.resF.MakeSecret(kvLdr, options, &args)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromSecretArgs")
}
@@ -103,8 +109,10 @@ func (rmF *Factory) NewResMapFromSecretArgs(
}
func (rmF *Factory) FromSecretArgs(
kvLdr ifc.KvLoader, args types.SecretArgs) (ResMap, error) {
res, err := rmF.resF.MakeSecret(kvLdr, &args)
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args types.SecretArgs) (ResMap, error) {
res, err := rmF.resF.MakeSecret(kvLdr, options, &args)
if err != nil {
return nil, err
}

View File

@@ -227,7 +227,7 @@ BAR=baz
t.Fatalf("error adding file '%s': %v\n", tc.filepath, fErr)
}
}
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, nil, tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
@@ -258,7 +258,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
actual, err := rmF.NewResMapFromSecretArgs(
kv.NewLoader(
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator()), secrets)
valtest_test.MakeFakeValidator()), nil, secrets)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@@ -826,7 +826,7 @@ func makeMap1() ResMap {
},
}, &types.GeneratorArgs{
Behavior: "create",
}))
}, nil))
}
func makeMap2(b types.GenerationBehavior) ResMap {
@@ -844,7 +844,7 @@ func makeMap2(b types.GenerationBehavior) ResMap {
},
}, &types.GeneratorArgs{
Behavior: b.String(),
}))
}, nil))
}
func TestAbsorbAll(t *testing.T) {
@@ -864,7 +864,7 @@ func TestAbsorbAll(t *testing.T) {
},
}, &types.GeneratorArgs{
Behavior: "create",
}))
}, nil))
w := makeMap1()
if err := w.AbsorbAll(makeMap2(types.BehaviorMerge)); err != nil {
t.Fatalf("unexpected error: %v", err)

View File

@@ -50,8 +50,8 @@ func (rf *Factory) FromMapWithNamespaceAndName(ns string, n string, m map[string
// FromMapAndOption returns a new instance of Resource with given options.
func (rf *Factory) FromMapAndOption(
m map[string]interface{}, args *types.GeneratorArgs) *Resource {
return rf.makeOne(rf.kf.FromMap(m), types.NewGenArgs(args))
m map[string]interface{}, args *types.GeneratorArgs, option *types.GeneratorOptions) *Resource {
return rf.makeOne(rf.kf.FromMap(m), types.NewGenArgs(args, option))
}
// FromKunstructured returns a new instance of Resource.
@@ -66,7 +66,7 @@ func (rf *Factory) makeOne(
log.Fatal("unstruct ifc must not be null")
}
if o == nil {
o = types.NewGenArgs(nil)
o = types.NewGenArgs(nil, nil)
}
r := &Resource{
Kunstructured: u,
@@ -147,19 +147,33 @@ func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) {
}
// MakeConfigMap makes an instance of Resource for ConfigMap
func (rf *Factory) MakeConfigMap(kvLdr ifc.KvLoader, args *types.ConfigMapArgs) (*Resource, error) {
u, err := rf.kf.MakeConfigMap(kvLdr, args)
func (rf *Factory) MakeConfigMap(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (*Resource, error) {
u, err := rf.kf.MakeConfigMap(kvLdr, options, args)
if err != nil {
return nil, err
}
return rf.makeOne(u, types.NewGenArgs(&args.GeneratorArgs)), nil
return rf.makeOne(
u,
types.NewGenArgs(
&types.GeneratorArgs{Behavior: args.Behavior},
options)), nil
}
// MakeSecret makes an instance of Resource for Secret
func (rf *Factory) MakeSecret(kvLdr ifc.KvLoader, args *types.SecretArgs) (*Resource, error) {
u, err := rf.kf.MakeSecret(kvLdr, args)
func (rf *Factory) MakeSecret(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.SecretArgs) (*Resource, error) {
u, err := rf.kf.MakeSecret(kvLdr, options, args)
if err != nil {
return nil, err
}
return rf.makeOne(u, types.NewGenArgs(&args.GeneratorArgs)), nil
return rf.makeOne(
u,
types.NewGenArgs(
&types.GeneratorArgs{Behavior: args.Behavior},
options)), nil
}

View File

@@ -1,30 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filtertest_test
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func RunFilter(t *testing.T, input string, f kio.Filter) string {
var out bytes.Buffer
rw := kio.ByteReadWriter{
Reader: bytes.NewBufferString(input),
Writer: &out,
}
err := kio.Pipeline{
Inputs: []kio.Reader{&rw},
Filters: []kio.Filter{f},
Outputs: []kio.Writer{&rw},
}.Execute()
if !assert.NoError(t, err) {
t.FailNow()
}
return out.String()
}

View File

@@ -4,9 +4,6 @@
package kusttest_test
import (
"bytes"
"fmt"
"strconv"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
@@ -19,8 +16,6 @@ import (
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// HarnessEnhanced manages a full plugin environment for tests.
@@ -114,69 +109,12 @@ func (th *HarnessEnhanced) LoadAndRunTransformer(
return resMap
}
func (th *HarnessEnhanced) RunTransformerAndCheckResult(
config, input, expected string) {
for _, b := range []bool{true, false} {
th.t.Run(fmt.Sprintf("yaml-%v", b), func(t *testing.T) {
c, err := toggleYamlSupportField(config, b)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
resMap, err := th.RunTransformer(c, input)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
th.AssertActualEqualsExpected(resMap, expected)
})
}
}
func toggleYamlSupportField(config string, yamlSupport bool) (string, error) {
var out bytes.Buffer
rw := kio.ByteReadWriter{
Reader: bytes.NewBufferString(config),
Writer: &out,
}
err := kio.Pipeline{
Inputs: []kio.Reader{&rw},
Filters: []kio.Filter{
kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
return node.Pipe(yaml.FieldSetter{
Name: "yamlSupport",
StringValue: strconv.FormatBool(yamlSupport),
})
}),
),
},
Outputs: []kio.Writer{&rw},
}.Execute()
return out.String(), err
}
func (th *HarnessEnhanced) ErrorFromLoadAndRunTransformer(
config, input string) error {
_, err := th.RunTransformer(config, input)
return err
}
type AssertFunc func(t *testing.T, err error)
func (th *HarnessEnhanced) RunTransformerAndCheckError(
config, input string, assertFn AssertFunc) {
for _, b := range []bool{true, false} {
th.t.Run(fmt.Sprintf("yaml-%v", b), func(t *testing.T) {
c, err := toggleYamlSupportField(config, b)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
_, err = th.RunTransformer(c, input)
assertFn(t, err)
})
}
}
func (th *HarnessEnhanced) RunTransformer(
config, input string) (resmap.ResMap, error) {
resMap, err := th.rf.NewResMapFromBytes([]byte(input))

View File

@@ -8,14 +8,18 @@ import (
"strings"
)
// GenArgs is a facade over GeneratorArgs, exposing a few readonly properties.
// GenArgs contains both GeneratorArgs and GeneratorOptions.
type GenArgs struct {
args *GeneratorArgs
opts *GeneratorOptions
}
// NewGenArgs returns a new instance of GenArgs.
func NewGenArgs(args *GeneratorArgs) *GenArgs {
return &GenArgs{args: args}
// NewGenArgs returns a new object of GenArgs
func NewGenArgs(args *GeneratorArgs, opts *GeneratorOptions) *GenArgs {
return &GenArgs{
args: args,
opts: opts,
}
}
func (g *GenArgs) String() string {
@@ -34,7 +38,7 @@ func (g *GenArgs) String() string {
// content hash should be appended to the name of the resource.
func (g *GenArgs) ShouldAddHashSuffixToName() bool {
return g.args != nil &&
(g.args.Options == nil || !g.args.Options.DisableNameSuffixHash)
(g.opts == nil || !g.opts.DisableNameSuffixHash)
}
// Behavior returns Behavior field of GeneratorArgs

View File

@@ -24,10 +24,8 @@ func TestGenArgs_String(t *testing.T) {
},
{
ga: NewGenArgs(
&GeneratorArgs{
Behavior: "merge",
Options: &GeneratorOptions{DisableNameSuffixHash: false},
}),
&GeneratorArgs{Behavior: "merge"},
&GeneratorOptions{DisableNameSuffixHash: false}),
expected: "{nsfx:true,beh:merge}",
},
}

View File

@@ -21,7 +21,4 @@ type GeneratorArgs struct {
// KvPairSources for the generator.
KvPairSources `json:",inline,omitempty" yaml:",inline,omitempty"`
// Local overrides to global generatorOptions field.
Options *GeneratorOptions `json:"options,omitempty" yaml:"options,omitempty"`
}

View File

@@ -16,55 +16,3 @@ type GeneratorOptions struct {
// resource contents.
DisableNameSuffixHash bool `json:"disableNameSuffixHash,omitempty" yaml:"disableNameSuffixHash,omitempty"`
}
// MergeGlobalOptionsIntoLocal merges two instances of GeneratorOptions.
// Values in the first 'local' argument cannot be overridden by the second
// 'global' argument, except in the case of booleans.
//
// With booleans, there's no way to distinguish an 'intentional'
// false from 'default' false. So the rule is, if the global value
// of the value of a boolean is true, i.e. disable, it trumps the
// local value. If the global value is false, then the local value is
// respected. Bottom line: a local false cannot override a global true.
//
// boolean fields are always a bad idea; should always use enums instead.
func MergeGlobalOptionsIntoLocal(
localOpts *GeneratorOptions,
globalOpts *GeneratorOptions) *GeneratorOptions {
if globalOpts == nil {
return localOpts
}
if localOpts == nil {
localOpts = &GeneratorOptions{}
}
overrideMap(&localOpts.Labels, globalOpts.Labels)
overrideMap(&localOpts.Annotations, globalOpts.Annotations)
if globalOpts.DisableNameSuffixHash {
localOpts.DisableNameSuffixHash = true
}
return localOpts
}
func overrideMap(localMap *map[string]string, globalMap map[string]string) {
if *localMap == nil {
if globalMap != nil {
*localMap = CopyMap(globalMap)
}
return
}
for k, v := range globalMap {
_, ok := (*localMap)[k]
if !ok {
(*localMap)[k] = v
}
}
}
// CopyMap copies a map.
func CopyMap(in map[string]string) map[string]string {
out := make(map[string]string)
for k, v := range in {
out[k] = v
}
return out
}

View File

@@ -1,125 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package types_test
import (
"reflect"
"testing"
. "sigs.k8s.io/kustomize/api/types"
)
func TestMergeGlobalOptionsIntoLocal(t *testing.T) {
tests := []struct {
name string
local *GeneratorOptions
global *GeneratorOptions
expected *GeneratorOptions
}{
{
name: "everything nil",
local: nil,
global: nil,
expected: nil,
},
{
name: "nil global",
local: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
},
global: nil,
expected: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
DisableNameSuffixHash: false,
},
},
{
name: "nil local",
local: nil,
global: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
},
expected: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
DisableNameSuffixHash: false,
},
},
{
name: "global doesn't damage local",
local: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{
"fruit": "apple"},
},
global: &GeneratorOptions{
Labels: map[string]string{
"pet": "cat",
"simpson": "homer",
},
Annotations: map[string]string{
"fruit": "peach",
"tesla": "Y",
},
},
expected: &GeneratorOptions{
Labels: map[string]string{
"pet": "dog",
"simpson": "homer",
},
Annotations: map[string]string{
"fruit": "apple",
"tesla": "Y",
},
DisableNameSuffixHash: false,
},
},
{
name: "global disable trumps local",
local: &GeneratorOptions{
DisableNameSuffixHash: false,
},
global: &GeneratorOptions{
DisableNameSuffixHash: true,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
},
},
{
name: "local disable works",
local: &GeneratorOptions{
DisableNameSuffixHash: true,
},
global: &GeneratorOptions{
DisableNameSuffixHash: false,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
},
},
{
name: "everyone wants disable",
local: &GeneratorOptions{
DisableNameSuffixHash: true,
},
global: &GeneratorOptions{
DisableNameSuffixHash: true,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
},
},
}
for _, tc := range tests {
actual := MergeGlobalOptionsIntoLocal(tc.local, tc.global)
if !reflect.DeepEqual(tc.expected, actual) {
t.Fatalf("%s annotations: Expected '%v', got '%v'",
tc.name, tc.expected, *actual)
}
}
}

View File

@@ -18,6 +18,6 @@ List setters for Resources.
Show setters:
$ config list-setters DIR/
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix '' PREFIX string 2

View File

@@ -28,8 +28,8 @@ the configuration as comments.
Optional. The value to set on the field.
To print the possible setters for the Resources in a directory, run
`list-setters` on a directory -- e.g. `kustomize config list-setters DIR/`.
To print the possible setters for the Resources in a directory, run `set` on
a directory -- e.g. `kustomize config set DIR/`.
#### Tips
@@ -58,7 +58,7 @@ To create a custom setter for a field see: `kustomize help config create-setter`
List setters: Show the possible setters
$ config list-setters DIR/
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix '' PREFIX string 2
@@ -69,7 +69,7 @@ To create a custom setter for a field see: `kustomize help config create-setter`
List setters: Show the new values
$ config list-setters DIR/
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix 'test environment' test string 2 dev

View File

@@ -10,7 +10,5 @@ require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.4.0
k8s.io/apimachinery v0.17.0
sigs.k8s.io/kustomize/kyaml v0.0.0
sigs.k8s.io/kustomize/kyaml v0.1.0
)
replace sigs.k8s.io/kustomize/kyaml v0.0.0 => ../../kyaml

View File

@@ -1,18 +1,12 @@
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -22,7 +16,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -89,7 +82,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
@@ -99,7 +91,6 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -109,8 +100,6 @@ github.com/posener/complete/v2 v2.0.1-alpha.12 h1:0wvkuDfHb5vSZlNBYgpEH4XQHpF46M
github.com/posener/complete/v2 v2.0.1-alpha.12/go.mod h1://JlL91cS2JV7rOl6LVHrRqBXoBUecJu3ILQPgbJiMQ=
github.com/posener/script v1.0.4 h1:nSuXW5ZdmFnQIueLB2s0qvs4oNsUloM1Zydzh75v42w=
github.com/posener/script v1.0.4/go.mod h1:Rg3ijooqulo05aGLyGsHoLmIOUzHUVK19WVgrYBPU/E=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -127,7 +116,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -135,16 +123,10 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -155,7 +137,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@@ -185,5 +166,7 @@ k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
sigs.k8s.io/kustomize/kyaml v0.1.0 h1:bpdlb136YAqxeL6+ziESe34SXRSBBpiUvoTu2dQG5Ss=
sigs.k8s.io/kustomize/kyaml v0.1.0/go.mod h1:/NdPPfrperSCGjm55cwEro1loBVtbtVIXSb7FguK6uk=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"os"
"strings"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
@@ -29,8 +28,6 @@ func NewListSettersRunner(parent string) *ListSettersRunner {
PreRunE: r.preRunE,
RunE: r.runE,
}
c.Flags().BoolVar(&r.Markdown, "markdown", false,
"output as github markdown")
fixDocs(parent, c)
r.Command = c
return r
@@ -41,10 +38,9 @@ func ListSettersCommand(parent string) *cobra.Command {
}
type ListSettersRunner struct {
Command *cobra.Command
Lookup setters.LookupSetters
List setters2.List
Markdown bool
Command *cobra.Command
Lookup setters.LookupSetters
List setters2.List
}
func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
@@ -67,19 +63,12 @@ func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
if err := r.List.List(path, args[0]); err != nil {
return err
}
table := newTable(c.OutOrStdout(), r.Markdown)
table := newTable(c.OutOrStdout())
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT"})
for i := range r.List.Setters {
s := r.List.Setters[i]
v := s.Value
// if the setter is for a list, populate the values
if len(s.ListValues) > 0 {
v = strings.Join(s.ListValues, ",")
v = fmt.Sprintf("[%s]", v)
}
table.Append([]string{
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
s.Name, s.Value, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
}
table.Render()
@@ -95,19 +84,13 @@ func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
return handleError(c, lookup(r.Lookup, c, args))
}
func newTable(o io.Writer, m bool) *tablewriter.Table {
func newTable(o io.Writer) *tablewriter.Table {
table := tablewriter.NewWriter(o)
table.SetRowLine(false)
if m {
// markdown format
table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false})
table.SetCenterSeparator("|")
} else {
table.SetBorder(false)
table.SetHeaderLine(false)
table.SetColumnSeparator(" ")
table.SetCenterSeparator(" ")
}
table.SetBorder(false)
table.SetHeaderLine(false)
table.SetColumnSeparator(" ")
table.SetCenterSeparator(" ")
table.SetAlignment(tablewriter.ALIGN_LEFT)
return table
}

Some files were not shown because too many files have changed in this diff Show More