mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 09:40:49 +00:00
Compare commits
1 Commits
ctFormatti
...
cmd/config
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d14be985e |
12
Makefile
12
Makefile
@@ -15,7 +15,7 @@ verify-kustomize: \
|
|||||||
lint-kustomize \
|
lint-kustomize \
|
||||||
test-unit-kustomize-all \
|
test-unit-kustomize-all \
|
||||||
test-examples-kustomize-against-HEAD \
|
test-examples-kustomize-against-HEAD \
|
||||||
test-examples-kustomize-against-3.8.0
|
test-examples-kustomize-against-3.6.1
|
||||||
|
|
||||||
# The following target referenced by a file in
|
# The following target referenced by a file in
|
||||||
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
|
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
|
||||||
@@ -23,10 +23,10 @@ verify-kustomize: \
|
|||||||
prow-presubmit-check: \
|
prow-presubmit-check: \
|
||||||
lint-kustomize \
|
lint-kustomize \
|
||||||
test-unit-kustomize-all \
|
test-unit-kustomize-all \
|
||||||
test-unit-cmd-all \
|
|
||||||
test-go-mod \
|
|
||||||
test-examples-kustomize-against-HEAD \
|
test-examples-kustomize-against-HEAD \
|
||||||
test-examples-kustomize-against-3.8.0
|
test-examples-kustomize-against-3.6.1 \
|
||||||
|
test-unit-cmd-all \
|
||||||
|
test-go-mod
|
||||||
|
|
||||||
.PHONY: verify-kustomize-e2e
|
.PHONY: verify-kustomize-e2e
|
||||||
verify-kustomize-e2e: test-examples-e2e-kustomize
|
verify-kustomize-e2e: test-examples-e2e-kustomize
|
||||||
@@ -233,10 +233,10 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
|
|||||||
./hack/testExamplesAgainstKustomize.sh HEAD
|
./hack/testExamplesAgainstKustomize.sh HEAD
|
||||||
|
|
||||||
.PHONY:
|
.PHONY:
|
||||||
test-examples-kustomize-against-3.8.0: $(MYGOBIN)/mdrip
|
test-examples-kustomize-against-3.6.1: $(MYGOBIN)/mdrip
|
||||||
( \
|
( \
|
||||||
set -e; \
|
set -e; \
|
||||||
tag=v3.8.0; \
|
tag=v3.6.1; \
|
||||||
/bin/rm -f $(MYGOBIN)/kustomize; \
|
/bin/rm -f $(MYGOBIN)/kustomize; \
|
||||||
echo "Installing kustomize $$tag."; \
|
echo "Installing kustomize $$tag."; \
|
||||||
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@$${tag}; \
|
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@$${tag}; \
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
err := filtersutil.ApplyToJSON(annotations.Filter{
|
err := filtersutil.ApplyToJSON(annotations.Filter{
|
||||||
Annotations: p.Annotations,
|
Annotations: p.Annotations,
|
||||||
FsSlice: p.FieldSpecs,
|
FsSlice: p.FieldSpecs,
|
||||||
}, r)
|
}, r.Kunstructured)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
err := filtersutil.ApplyToJSON(labels.Filter{
|
err := filtersutil.ApplyToJSON(labels.Filter{
|
||||||
Labels: p.Labels,
|
Labels: p.Labels,
|
||||||
FsSlice: p.FieldSpecs,
|
FsSlice: p.FieldSpecs,
|
||||||
}, r)
|
}, r.Kunstructured)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
@@ -19,6 +20,11 @@ import (
|
|||||||
type NamespaceTransformerPlugin struct {
|
type NamespaceTransformerPlugin struct {
|
||||||
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||||
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,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.
|
||||||
|
// TODO: change the default to use kyaml when it is stable
|
||||||
|
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *NamespaceTransformerPlugin) Config(
|
func (p *NamespaceTransformerPlugin) Config(
|
||||||
@@ -37,13 +43,31 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
// Don't mutate empty objects?
|
// Don't mutate empty objects?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := filtersutil.ApplyToJSON(namespace.Filter{
|
|
||||||
Namespace: p.Namespace,
|
id := r.OrgId()
|
||||||
FsSlice: p.FieldSpecs,
|
|
||||||
}, r)
|
if p.YAMLSupport {
|
||||||
if err != nil {
|
// use the new style transform
|
||||||
return err
|
err := filtersutil.ApplyToJSON(namespace.Filter{
|
||||||
|
Namespace: p.Namespace,
|
||||||
|
FsSlice: p.FieldSpecs,
|
||||||
|
}, r.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
|
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
|
||||||
if len(matches) != 1 {
|
if len(matches) != 1 {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ type PatchJson6902TransformerPlugin struct {
|
|||||||
Target types.PatchTarget `json:"target,omitempty" yaml:"target,omitempty"`
|
Target types.PatchTarget `json:"target,omitempty" yaml:"target,omitempty"`
|
||||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||||
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
|
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
|
||||||
|
|
||||||
|
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PatchJson6902TransformerPlugin) Config(
|
func (p *PatchJson6902TransformerPlugin) Config(
|
||||||
@@ -85,9 +87,22 @@ func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return filtersutil.ApplyToJSON(patchjson6902.Filter{
|
if !p.YAMLSupport {
|
||||||
Patch: p.JsonOp,
|
rawObj, err := obj.MarshalJSON()
|
||||||
}, obj)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPatchJson6902TransformerPlugin() resmap.TransformerPlugin {
|
func NewPatchJson6902TransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
package builtins
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
|
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
@@ -21,6 +22,8 @@ type PatchStrategicMergeTransformerPlugin struct {
|
|||||||
loadedPatches []*resource.Resource
|
loadedPatches []*resource.Resource
|
||||||
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
|
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
|
||||||
|
|
||||||
|
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PatchStrategicMergeTransformerPlugin) Config(
|
func (p *PatchStrategicMergeTransformerPlugin) Config(
|
||||||
@@ -73,48 +76,42 @@ func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
patchCopy := patch.DeepCopy()
|
if !p.YAMLSupport {
|
||||||
patchCopy.SetName(target.GetName())
|
err = target.Patch(patch.Kunstructured)
|
||||||
patchCopy.SetNamespace(target.GetNamespace())
|
|
||||||
patchCopy.SetGvk(target.GetGvk())
|
|
||||||
node, err := filtersutil.GetRNode(patchCopy)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
|
|
||||||
Patch: node,
|
|
||||||
}, target)
|
|
||||||
if err != nil {
|
|
||||||
// Check for an error string from UnmarshalJSON that's indicative
|
|
||||||
// of an object that's missing basic KRM fields, and thus may have been
|
|
||||||
// entirely deleted (an acceptable outcome). This error handling should
|
|
||||||
// be deleted along with use of ResMap and apimachinery functions like
|
|
||||||
// UnmarshalJSON.
|
|
||||||
if !strings.Contains(err.Error(), "Object 'Kind' is missing") {
|
|
||||||
// Some unknown error, let it through.
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(target.Map()) != 0 {
|
|
||||||
return errors.Wrapf(
|
|
||||||
err, "with unexpectedly non-empty object map of size %d",
|
|
||||||
len(target.Map()))
|
|
||||||
}
|
|
||||||
// Fall through to handle deleted object.
|
|
||||||
}
|
|
||||||
if len(target.Map()) == 0 {
|
|
||||||
// This means all fields have been removed from the object.
|
|
||||||
// This can happen if a patch required deletion of the
|
|
||||||
// entire resource (not just a part of it). This means
|
|
||||||
// the overall resmap must shrink by one.
|
|
||||||
err = m.Remove(target.CurId())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
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 {
|
func NewPatchStrategicMergeTransformerPlugin() resmap.TransformerPlugin {
|
||||||
return &PatchStrategicMergeTransformerPlugin{}
|
return &PatchStrategicMergeTransformerPlugin{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
jsonpatch "github.com/evanphx/json-patch"
|
jsonpatch "github.com/evanphx/json-patch"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
|
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
|
||||||
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
|
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
@@ -23,6 +24,8 @@ type PatchTransformerPlugin struct {
|
|||||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||||
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||||
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
||||||
|
|
||||||
|
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PatchTransformerPlugin) Config(
|
func (p *PatchTransformerPlugin) Config(
|
||||||
@@ -70,11 +73,11 @@ func (p *PatchTransformerPlugin) Config(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
if p.loadedPatch == nil {
|
if p.loadedPatch != nil {
|
||||||
return p.transformJson6902(m, p.decodedPatch)
|
|
||||||
} else {
|
|
||||||
// The patch was a strategic merge patch
|
// The patch was a strategic merge patch
|
||||||
return p.transformStrategicMerge(m, p.loadedPatch)
|
return p.transformStrategicMerge(m, p.loadedPatch)
|
||||||
|
} else {
|
||||||
|
return p.transformJson6902(m, p.decodedPatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,15 +111,20 @@ func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applySMPatch applies the provided strategic merge patch to the
|
// applySMPatch applies the provided strategic merge patch to the
|
||||||
// given resource.
|
// 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 {
|
func (p *PatchTransformerPlugin) applySMPatch(resource, patch *resource.Resource) error {
|
||||||
node, err := filtersutil.GetRNode(patch)
|
if !p.YAMLSupport {
|
||||||
if err != nil {
|
return resource.Patch(patch.Kunstructured)
|
||||||
return err
|
} else {
|
||||||
|
node, err := filtersutil.GetRNode(patch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
|
||||||
|
Patch: node,
|
||||||
|
}, resource.Kunstructured)
|
||||||
}
|
}
|
||||||
return filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
|
|
||||||
Patch: node,
|
|
||||||
}, resource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// transformJson6902 applies the provided json6902 patch
|
// transformJson6902 applies the provided json6902 patch
|
||||||
@@ -125,14 +133,13 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
|
|||||||
if p.Target == nil {
|
if p.Target == nil {
|
||||||
return fmt.Errorf("must specify a target for patch %s", p.Patch)
|
return fmt.Errorf("must specify a target for patch %s", p.Patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
resources, err := m.Select(*p.Target)
|
resources, err := m.Select(*p.Target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, res := range resources {
|
for _, res := range resources {
|
||||||
err = filtersutil.ApplyToJSON(patchjson6902.Filter{
|
err = p.applyJson6902Patch(res, patch)
|
||||||
Patch: p.Patch,
|
|
||||||
}, res)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -140,6 +147,28 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
|
|||||||
return nil
|
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
|
// jsonPatchFromBytes loads a Json 6902 patch from
|
||||||
// a bytes input
|
// a bytes input
|
||||||
func jsonPatchFromBytes(
|
func jsonPatchFromBytes(
|
||||||
|
|||||||
@@ -5,27 +5,31 @@ package builtins
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add the given prefix and suffix to the field.
|
// Add the given prefix and suffix to the field.
|
||||||
type PrefixSuffixTransformerPlugin struct {
|
type PrefixSuffixTransformerPlugin struct {
|
||||||
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
|
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
|
||||||
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
|
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
|
||||||
FieldSpecs types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Gvk skip list for prefix/suffix modification.
|
// Not placed in a file yet due to lack of demand.
|
||||||
// hard coded for now - eventually should be part of config.
|
var prefixSuffixFieldSpecsToSkip = []types.FieldSpec{
|
||||||
var prefixSuffixFieldSpecsToSkip = types.FsSlice{
|
{
|
||||||
{Gvk: resid.Gvk{Kind: "CustomResourceDefinition"}},
|
Gvk: resid.Gvk{Kind: "CustomResourceDefinition"},
|
||||||
{Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"}},
|
},
|
||||||
|
{
|
||||||
|
Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrefixSuffixTransformerPlugin) Config(
|
func (p *PrefixSuffixTransformerPlugin) Config(
|
||||||
@@ -44,24 +48,29 @@ func (p *PrefixSuffixTransformerPlugin) Config(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
|
func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
|
||||||
// Even if both the Prefix and Suffix are empty we want
|
// Even if both the Prefix and Suffix are empty we want
|
||||||
// to proceed with the transformation. This allows to add contextual
|
// to proceed with the transformation. This allows to add contextual
|
||||||
// information to the resources (AddNamePrefix and AddNameSuffix).
|
// information to the resources (AddNamePrefix and AddNameSuffix).
|
||||||
|
|
||||||
for _, r := range m.Resources() {
|
for _, r := range m.Resources() {
|
||||||
// TODO: move this test into the filter (i.e. make a better filter)
|
|
||||||
if p.shouldSkip(r.OrgId()) {
|
if p.shouldSkip(r.OrgId()) {
|
||||||
|
// Don't change the actual definition
|
||||||
|
// of a CRD.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
id := r.OrgId()
|
id := r.OrgId()
|
||||||
// current default configuration contains
|
// current default configuration contains
|
||||||
// only one entry: "metadata/name" with no GVK
|
// only one entry: "metadata/name" with no GVK
|
||||||
for _, fs := range p.FieldSpecs {
|
for _, path := range p.FieldSpecs {
|
||||||
// TODO: this is redundant to filter (but needed for now)
|
if !id.IsSelected(&path.Gvk) {
|
||||||
if !id.IsSelected(&fs.Gvk) {
|
// With the currrent default configuration,
|
||||||
|
// because no Gvk is specified, so a wild
|
||||||
|
// card
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO: move this test into the filter.
|
|
||||||
if smellsLikeANameChange(&fs) {
|
if smellsLikeANameChange(&path) {
|
||||||
// "metadata/name" is the only field.
|
// "metadata/name" is the only field.
|
||||||
// this will add a prefix and a suffix
|
// this will add a prefix and a suffix
|
||||||
// to the resource even if those are
|
// to the resource even if those are
|
||||||
@@ -69,11 +78,15 @@ func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
r.AddNamePrefix(p.Prefix)
|
r.AddNamePrefix(p.Prefix)
|
||||||
r.AddNameSuffix(p.Suffix)
|
r.AddNameSuffix(p.Suffix)
|
||||||
}
|
}
|
||||||
err := filtersutil.ApplyToJSON(prefixsuffix.Filter{
|
|
||||||
Prefix: p.Prefix,
|
// the addPrefixSuffix method will not
|
||||||
Suffix: p.Suffix,
|
// change the name if both the prefix and suffix
|
||||||
FieldSpec: fs,
|
// are empty.
|
||||||
}, r)
|
err := transform.MutateField(
|
||||||
|
r.Map(),
|
||||||
|
path.PathSlice(),
|
||||||
|
path.CreateIfNotPresent,
|
||||||
|
p.addPrefixSuffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -86,7 +99,8 @@ func smellsLikeANameChange(fs *types.FieldSpec) bool {
|
|||||||
return fs.Path == "metadata/name"
|
return fs.Path == "metadata/name"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrefixSuffixTransformerPlugin) shouldSkip(id resid.ResId) bool {
|
func (p *PrefixSuffixTransformerPlugin) shouldSkip(
|
||||||
|
id resid.ResId) bool {
|
||||||
for _, path := range prefixSuffixFieldSpecsToSkip {
|
for _, path := range prefixSuffixFieldSpecsToSkip {
|
||||||
if id.IsSelected(&path.Gvk) {
|
if id.IsSelected(&path.Gvk) {
|
||||||
return true
|
return true
|
||||||
@@ -95,6 +109,15 @@ func (p *PrefixSuffixTransformerPlugin) shouldSkip(id resid.ResId) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PrefixSuffixTransformerPlugin) addPrefixSuffix(
|
||||||
|
in interface{}) (interface{}, error) {
|
||||||
|
s, ok := in.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%#v is expected to be %T", in, s)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s%s%s", p.Prefix, s, p.Suffix), nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewPrefixSuffixTransformerPlugin() resmap.TransformerPlugin {
|
func NewPrefixSuffixTransformerPlugin() resmap.TransformerPlugin {
|
||||||
return &PrefixSuffixTransformerPlugin{}
|
return &PrefixSuffixTransformerPlugin{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,13 +121,13 @@ func (p *ValueAddTransformerPlugin) Transform(m resmap.ResMap) (err error) {
|
|||||||
if t.FieldPath == types.MetadataNamespacePath {
|
if t.FieldPath == types.MetadataNamespacePath {
|
||||||
err = filtersutil.ApplyToJSON(namespace.Filter{
|
err = filtersutil.ApplyToJSON(namespace.Filter{
|
||||||
Namespace: p.Value,
|
Namespace: p.Value,
|
||||||
}, res)
|
}, res.Kunstructured)
|
||||||
} else {
|
} else {
|
||||||
err = filtersutil.ApplyToJSON(valueadd.Filter{
|
err = filtersutil.ApplyToJSON(valueadd.Filter{
|
||||||
Value: p.Value,
|
Value: p.Value,
|
||||||
FieldPath: t.FieldPath,
|
FieldPath: t.FieldPath,
|
||||||
FilePathPosition: t.FilePathPosition,
|
FilePathPosition: t.FilePathPosition,
|
||||||
}, res)
|
}, res.Kunstructured)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
|||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
if err := node.PipeE(fsslice.Filter{
|
if err := node.PipeE(fsslice.Filter{
|
||||||
FsSlice: f.FsSlice,
|
FsSlice: f.FsSlice,
|
||||||
SetValue: filtersutil.SetEntry(k, f.Annotations[k], yaml.StringTag),
|
SetValue: fsslice.SetEntry(k, f.Annotations[k], yaml.StringTag),
|
||||||
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
|
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
|
||||||
CreateTag: "!!map",
|
CreateTag: "!!map",
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
// Copyright 2020 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Package fieldspec contains a yaml.Filter to modify a resource
|
|
||||||
// that matches the FieldSpec.
|
|
||||||
package fieldspec
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
// Copyright 2020 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package fieldspec_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "sigs.k8s.io/kustomize/api/filters/fieldspec"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"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 := Filter{
|
|
||||||
CreateKind: yaml.ScalarNode,
|
|
||||||
SetValue: filtersutil.SetScalar("green"),
|
|
||||||
FieldSpec: 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
|
|
||||||
}
|
|
||||||
@@ -1,380 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package fieldspec_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestCase struct {
|
|
||||||
name string
|
|
||||||
input string
|
|
||||||
expected string
|
|
||||||
filter fieldspec.Filter
|
|
||||||
fieldSpec string
|
|
||||||
error string
|
|
||||||
}
|
|
||||||
|
|
||||||
var tests = []TestCase{
|
|
||||||
{
|
|
||||||
name: "update",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "update-kind-not-match",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "update-group-not-match",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "update-version-not-match",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "bad-version",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "bad-meta",
|
|
||||||
fieldSpec: `
|
|
||||||
path: a/b
|
|
||||||
group: foo
|
|
||||||
version: v1beta1
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
input: `
|
|
||||||
a:
|
|
||||||
b: c
|
|
||||||
`,
|
|
||||||
filter: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
error: "missing Resource metadata",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "miss-match-type",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "add",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
CreateKind: yaml.ScalarNode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "update-in-sequence",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// Don't create a sequence
|
|
||||||
{
|
|
||||||
name: "empty-sequence-no-create",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
CreateKind: yaml.ScalarNode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// Create a new field for an element in a sequence
|
|
||||||
{
|
|
||||||
name: "empty-sequence-create",
|
|
||||||
fieldSpec: `
|
|
||||||
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: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
CreateKind: yaml.ScalarNode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "group v1",
|
|
||||||
fieldSpec: `
|
|
||||||
path: a/b
|
|
||||||
group: v1
|
|
||||||
create: true
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
input: `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
expected: `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
filter: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
CreateKind: yaml.ScalarNode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "version v1",
|
|
||||||
fieldSpec: `
|
|
||||||
path: a/b
|
|
||||||
version: v1
|
|
||||||
create: true
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
input: `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
expected: `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Bar
|
|
||||||
a:
|
|
||||||
b: e
|
|
||||||
`,
|
|
||||||
filter: fieldspec.Filter{
|
|
||||||
SetValue: filtersutil.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.fieldSpec), &test.filter.FieldSpec)
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package filtersutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SetFn is a function that accepts an RNode to possibly modify.
|
|
||||||
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, tag string) SetFn {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Value: value,
|
|
||||||
Tag: tag,
|
|
||||||
}
|
|
||||||
if tag == yaml.StringTag && yaml.IsYaml1_1NonString(n) {
|
|
||||||
n.Style = yaml.DoubleQuotedStyle
|
|
||||||
}
|
|
||||||
return func(node *yaml.RNode) error {
|
|
||||||
return node.PipeE(yaml.FieldSetter{
|
|
||||||
Name: key,
|
|
||||||
Value: yaml.NewRNode(n),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2020 The Kubernetes Authors.
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package fsslice contains a yaml.Filter to modify a resource if
|
// Package fsslice contains a yaml.Filter to modify a resource using an
|
||||||
// it matches one or more FieldSpec entries.
|
// FsSlice to identify fields to be updated within the resource.
|
||||||
package fsslice
|
package fsslice
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
@@ -31,7 +30,7 @@ metadata:
|
|||||||
}
|
}
|
||||||
fltr := fsslice.Filter{
|
fltr := fsslice.Filter{
|
||||||
CreateKind: yaml.ScalarNode,
|
CreateKind: yaml.ScalarNode,
|
||||||
SetValue: filtersutil.SetScalar("green"),
|
SetValue: fsslice.SetScalar("green"),
|
||||||
FsSlice: []types.FieldSpec{
|
FsSlice: []types.FieldSpec{
|
||||||
{Path: "a/b", CreateIfNotPresent: true},
|
{Path: "a/b", CreateIfNotPresent: true},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package fieldspec
|
package fsslice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ yaml.Filter = Filter{}
|
// fieldSpecFilter applies a single fieldSpec to a single object
|
||||||
|
// fieldSpecFilter stores internal state and should not be reused
|
||||||
// Filter applies a single fieldSpec to a single object
|
type fieldSpecFilter struct {
|
||||||
// Filter stores internal state and should not be reused
|
|
||||||
type Filter struct {
|
|
||||||
// FieldSpec contains the path to the value to set.
|
// FieldSpec contains the path to the value to set.
|
||||||
FieldSpec types.FieldSpec `yaml:"fieldSpec"`
|
FieldSpec types.FieldSpec `yaml:"fieldSpec"`
|
||||||
|
|
||||||
// Set the field using this function
|
// Set the field using this function
|
||||||
SetValue filtersutil.SetFn
|
SetValue SetFn
|
||||||
|
|
||||||
// CreateKind defines the type of node to create if the field is not found
|
// CreateKind defines the type of node to create if the field is not found
|
||||||
CreateKind yaml.Kind
|
CreateKind yaml.Kind
|
||||||
@@ -32,7 +29,7 @@ type Filter struct {
|
|||||||
path []string
|
path []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
func (fltr fieldSpecFilter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
||||||
// check if the FieldSpec applies to the object
|
// check if the FieldSpec applies to the object
|
||||||
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
|
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
|
||||||
return obj, errors.Wrap(err)
|
return obj, errors.Wrap(err)
|
||||||
@@ -46,7 +43,7 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fltr Filter) filter(obj *yaml.RNode) error {
|
func (fltr fieldSpecFilter) filter(obj *yaml.RNode) error {
|
||||||
if len(fltr.path) == 0 {
|
if len(fltr.path) == 0 {
|
||||||
// found the field -- set its value
|
// found the field -- set its value
|
||||||
return fltr.SetValue(obj)
|
return fltr.SetValue(obj)
|
||||||
@@ -63,7 +60,7 @@ func (fltr Filter) filter(obj *yaml.RNode) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// field calls filter on the field matching the next path element
|
// field calls filter on the field matching the next path element
|
||||||
func (fltr Filter) field(obj *yaml.RNode) error {
|
func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
|
||||||
fieldName, isSeq := isSequenceField(fltr.path[0])
|
fieldName, isSeq := isSequenceField(fltr.path[0])
|
||||||
|
|
||||||
// lookup the field matching the next path element
|
// lookup the field matching the next path element
|
||||||
@@ -107,9 +104,9 @@ func (fltr Filter) field(obj *yaml.RNode) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// seq calls filter on all sequence elements
|
// seq calls filter on all sequence elements
|
||||||
func (fltr Filter) seq(obj *yaml.RNode) error {
|
func (fltr fieldSpecFilter) seq(obj *yaml.RNode) error {
|
||||||
if err := obj.VisitElements(func(node *yaml.RNode) error {
|
if err := obj.VisitElements(func(node *yaml.RNode) error {
|
||||||
// recurse on each element -- re-allocating a Filter is
|
// recurse on each element -- re-allocating a fieldSpecFilter is
|
||||||
// not strictly required, but is more consistent with field
|
// not strictly required, but is more consistent with field
|
||||||
// and less likely to have side effects
|
// and less likely to have side effects
|
||||||
// keep the entire path -- it does not contain parts for sequences
|
// keep the entire path -- it does not contain parts for sequences
|
||||||
@@ -4,22 +4,48 @@
|
|||||||
package fsslice
|
package fsslice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"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, tag string) SetFn {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: value,
|
||||||
|
Tag: tag,
|
||||||
|
}
|
||||||
|
if tag == yaml.StringTag && yaml.IsYaml1_1NonString(n) {
|
||||||
|
n.Style = yaml.DoubleQuotedStyle
|
||||||
|
}
|
||||||
|
return func(node *yaml.RNode) error {
|
||||||
|
return node.PipeE(yaml.FieldSetter{
|
||||||
|
Name: key,
|
||||||
|
Value: yaml.NewRNode(n),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var _ yaml.Filter = Filter{}
|
var _ yaml.Filter = Filter{}
|
||||||
|
|
||||||
// Filter ranges over an FsSlice to modify fields on a single object.
|
// Filter uses an FsSlice to modify fields on a single object
|
||||||
// An FsSlice is a range of FieldSpecs. A FieldSpec is a GVK plus a path.
|
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
// FieldSpecList list of FieldSpecs to set
|
// FieldSpecList list of FieldSpecs to set
|
||||||
FsSlice types.FsSlice `yaml:"fsSlice"`
|
FsSlice types.FsSlice `yaml:"fsSlice"`
|
||||||
|
|
||||||
// SetValue is called on each field that matches one of the FieldSpecs
|
// SetValue is called on each field that matches one of the FieldSpecs
|
||||||
SetValue filtersutil.SetFn
|
SetValue SetFn
|
||||||
|
|
||||||
// CreateKind is used to create fields that do not exist
|
// CreateKind is used to create fields that do not exist
|
||||||
CreateKind yaml.Kind
|
CreateKind yaml.Kind
|
||||||
@@ -33,7 +59,7 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
// apply this FieldSpec
|
// apply this FieldSpec
|
||||||
// create a new filter for each iteration because they
|
// create a new filter for each iteration because they
|
||||||
// store internal state about the field paths
|
// store internal state about the field paths
|
||||||
_, err := (&fieldspec.Filter{
|
_, err := (&fieldSpecFilter{
|
||||||
FieldSpec: fltr.FsSlice[i],
|
FieldSpec: fltr.FsSlice[i],
|
||||||
SetValue: fltr.SetValue,
|
SetValue: fltr.SetValue,
|
||||||
CreateKind: fltr.CreateKind,
|
CreateKind: fltr.CreateKind,
|
||||||
|
|||||||
@@ -9,77 +9,335 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
. "sigs.k8s.io/kustomize/api/filters/fsslice"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
|
name string
|
||||||
input string
|
input string
|
||||||
expected string
|
expected string
|
||||||
filter Filter
|
filter fsslice.Filter
|
||||||
fsSlice string
|
fsSlice string
|
||||||
error string
|
error string
|
||||||
}
|
}
|
||||||
|
|
||||||
var tests = map[string]TestCase{
|
var tests = []TestCase{
|
||||||
"empty": {
|
{
|
||||||
fsSlice: `
|
name: "update",
|
||||||
`,
|
|
||||||
input: `
|
|
||||||
apiVersion: foo/v1
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
expected: `
|
|
||||||
apiVersion: foo/v1
|
|
||||||
kind: Bar
|
|
||||||
`,
|
|
||||||
filter: Filter{
|
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
|
||||||
CreateKind: yaml.ScalarNode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"two": {
|
|
||||||
fsSlice: `
|
fsSlice: `
|
||||||
- path: a/b
|
- path: a/b
|
||||||
group: foo
|
group: foo
|
||||||
version: v1
|
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
|
create: true
|
||||||
kind: Bar
|
kind: Bar
|
||||||
- path: q/r[]/s/t
|
`,
|
||||||
|
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
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "group v1",
|
||||||
|
fsSlice: `
|
||||||
|
- path: a/b
|
||||||
|
group: v1
|
||||||
|
create: true
|
||||||
|
kind: Bar
|
||||||
|
`,
|
||||||
|
input: `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Bar
|
||||||
|
`,
|
||||||
|
expected: `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Bar
|
||||||
|
`,
|
||||||
|
filter: fsslice.Filter{
|
||||||
|
SetValue: fsslice.SetScalar("e"),
|
||||||
|
CreateKind: yaml.ScalarNode,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "version v1",
|
||||||
|
fsSlice: `
|
||||||
|
- path: a/b
|
||||||
version: v1
|
version: v1
|
||||||
create: true
|
create: true
|
||||||
kind: Bar
|
kind: Bar
|
||||||
`,
|
`,
|
||||||
input: `
|
input: `
|
||||||
apiVersion: foo/v1
|
apiVersion: v1
|
||||||
kind: Bar
|
kind: Bar
|
||||||
q:
|
|
||||||
r:
|
|
||||||
- s: {}
|
|
||||||
`,
|
`,
|
||||||
expected: `
|
expected: `
|
||||||
apiVersion: foo/v1
|
apiVersion: v1
|
||||||
kind: Bar
|
kind: Bar
|
||||||
q:
|
|
||||||
r:
|
|
||||||
- s: {t: e}
|
|
||||||
a:
|
a:
|
||||||
b: e
|
b: e
|
||||||
`,
|
`,
|
||||||
filter: Filter{
|
filter: fsslice.Filter{
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
SetValue: fsslice.SetScalar("e"),
|
||||||
CreateKind: yaml.ScalarNode,
|
CreateKind: yaml.ScalarNode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
func TestFilter_Filter(t *testing.T) {
|
||||||
for name := range tests {
|
for i := range tests {
|
||||||
test := tests[name]
|
test := tests[i]
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
err := yaml.Unmarshal([]byte(test.fsSlice), &test.filter.FsSlice)
|
err := yaml.Unmarshal([]byte(test.fsSlice), &test.filter.FsSlice)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
package fieldspec
|
package fsslice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
package fieldspec
|
package fsslice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
package imagetag
|
package imagetag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
@@ -36,7 +35,7 @@ func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateImageTagFn(imageTag types.Image) filtersutil.SetFn {
|
func updateImageTagFn(imageTag types.Image) fsslice.SetFn {
|
||||||
return func(node *yaml.RNode) error {
|
return func(node *yaml.RNode) error {
|
||||||
return node.PipeE(imageTagUpdater{
|
return node.PipeE(imageTagUpdater{
|
||||||
ImageTag: imageTag,
|
ImageTag: imageTag,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
|||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
if err := node.PipeE(fsslice.Filter{
|
if err := node.PipeE(fsslice.Filter{
|
||||||
FsSlice: f.FsSlice,
|
FsSlice: f.FsSlice,
|
||||||
SetValue: filtersutil.SetEntry(k, f.Labels[k], yaml.StringTag),
|
SetValue: fsslice.SetEntry(k, f.Labels[k], yaml.StringTag),
|
||||||
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
|
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
|
||||||
CreateTag: "!!map",
|
CreateTag: "!!map",
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
package namespace
|
package namespace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
@@ -44,7 +42,7 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
// transformations based on data -- :)
|
// transformations based on data -- :)
|
||||||
err := node.PipeE(fsslice.Filter{
|
err := node.PipeE(fsslice.Filter{
|
||||||
FsSlice: ns.FsSlice,
|
FsSlice: ns.FsSlice,
|
||||||
SetValue: filtersutil.SetScalar(ns.Namespace),
|
SetValue: fsslice.SetScalar(ns.Namespace),
|
||||||
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
||||||
CreateTag: yaml.StringTag,
|
CreateTag: yaml.StringTag,
|
||||||
})
|
})
|
||||||
@@ -75,7 +73,7 @@ func (ns Filter) hacks(obj *yaml.RNode) error {
|
|||||||
// if they are cluster scoped through either an annotation on the resources,
|
// if they are cluster scoped through either an annotation on the resources,
|
||||||
// or through inlined OpenAPI on the resource as a YAML comment.
|
// or through inlined OpenAPI on the resource as a YAML comment.
|
||||||
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
|
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
|
||||||
gvk := fieldspec.GetGVK(meta)
|
gvk := fsslice.GetGVK(meta)
|
||||||
if !gvk.IsNamespaceableKind() {
|
if !gvk.IsNamespaceableKind() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -83,7 +81,7 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) erro
|
|||||||
FsSlice: []types.FieldSpec{
|
FsSlice: []types.FieldSpec{
|
||||||
{Path: types.MetadataNamespacePath, CreateIfNotPresent: true},
|
{Path: types.MetadataNamespacePath, CreateIfNotPresent: true},
|
||||||
},
|
},
|
||||||
SetValue: filtersutil.SetScalar(ns.Namespace),
|
SetValue: fsslice.SetScalar(ns.Namespace),
|
||||||
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
||||||
}
|
}
|
||||||
_, err := f.Filter(obj)
|
_, err := f.Filter(obj)
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package patchstrategicmerge
|
package patchstrategicmerge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -16,13 +13,9 @@ type Filter struct {
|
|||||||
var _ kio.Filter = Filter{}
|
var _ kio.Filter = Filter{}
|
||||||
|
|
||||||
func (pf Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (pf Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
var result []*yaml.RNode
|
return kio.FilterAll(yaml.FilterFunc(pf.run)).Filter(nodes)
|
||||||
for i := range nodes {
|
}
|
||||||
r, err := merge2.Merge(pf.Patch, nodes[i])
|
|
||||||
if err != nil {
|
func (pf Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
||||||
return nil, err
|
return merge2.Merge(pf.Patch, node)
|
||||||
}
|
|
||||||
result = append(result, r)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,86 +31,6 @@ apiVersion: apps/v1
|
|||||||
metadata:
|
metadata:
|
||||||
name: yourDeploy
|
name: yourDeploy
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
`,
|
|
||||||
},
|
|
||||||
"container patch": {
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: myDeploy
|
|
||||||
kind: Deployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: foo1
|
|
||||||
- name: foo2
|
|
||||||
- name: foo3
|
|
||||||
`,
|
|
||||||
patch: yaml.MustParse(`
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: myDeploy
|
|
||||||
kind: Deployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: foo0
|
|
||||||
`),
|
|
||||||
expected: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: myDeploy
|
|
||||||
kind: Deployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: foo1
|
|
||||||
- name: foo2
|
|
||||||
- name: foo3
|
|
||||||
- name: foo0
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
"volumes patch": {
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: myDeploy
|
|
||||||
kind: Deployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: foo1
|
|
||||||
- name: foo2
|
|
||||||
- name: foo3
|
|
||||||
`,
|
|
||||||
patch: yaml.MustParse(`
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: myDeploy
|
|
||||||
kind: Deployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: foo0
|
|
||||||
`),
|
|
||||||
expected: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: myDeploy
|
|
||||||
kind: Deployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: foo1
|
|
||||||
- name: foo2
|
|
||||||
- name: foo3
|
|
||||||
- name: foo0
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
"nested patch": {
|
"nested patch": {
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleFilter() {
|
func ExampleFilter() {
|
||||||
|
fss := builtinconfig.MakeDefaultConfig().NamePrefix
|
||||||
err := kio.Pipeline{
|
err := kio.Pipeline{
|
||||||
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
|
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
@@ -26,8 +27,7 @@ kind: Bar
|
|||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: instance
|
||||||
`)}},
|
`)}},
|
||||||
Filters: []kio.Filter{prefixsuffix.Filter{
|
Filters: []kio.Filter{prefixsuffix.Filter{Prefix: "baz-", FsSlice: fss}},
|
||||||
Prefix: "baz-", FieldSpec: types.FieldSpec{Path: "metadata/name"}}},
|
|
||||||
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
|
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
|
||||||
}.Execute()
|
}.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ package prefixsuffix
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
@@ -18,26 +17,28 @@ type Filter struct {
|
|||||||
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
|
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
|
||||||
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
|
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
|
||||||
|
|
||||||
FieldSpec types.FieldSpec `json:"fieldSpec,omitempty" yaml:"fieldSpec,omitempty"`
|
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ kio.Filter = Filter{}
|
var _ kio.Filter = Filter{}
|
||||||
|
|
||||||
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
return kio.FilterAll(yaml.FilterFunc(f.run)).Filter(nodes)
|
return kio.FilterAll(yaml.FilterFunc(ns.run)).Filter(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
// Run runs the filter on a single node rather than a slice
|
||||||
err := node.PipeE(fieldspec.Filter{
|
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
||||||
FieldSpec: f.FieldSpec,
|
// transformations based on data -- :)
|
||||||
SetValue: f.evaluateField,
|
err := node.PipeE(fsslice.Filter{
|
||||||
|
FsSlice: ns.FsSlice,
|
||||||
|
SetValue: ns.set,
|
||||||
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
|
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
|
||||||
CreateTag: yaml.StringTag,
|
CreateTag: yaml.StringTag,
|
||||||
})
|
})
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Filter) evaluateField(node *yaml.RNode) error {
|
func (ns Filter) set(node *yaml.RNode) error {
|
||||||
return filtersutil.SetScalar(fmt.Sprintf(
|
return fsslice.SetScalar(fmt.Sprintf(
|
||||||
"%s%s%s", f.Prefix, node.YNode().Value, f.Suffix))(node)
|
"%s%s%s", ns.Prefix, node.YNode().Value, ns.Suffix))(node)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var tests = map[string]TestCase{
|
var tests = []TestCase{
|
||||||
"prefix": {
|
{
|
||||||
|
name: "prefix",
|
||||||
input: `
|
input: `
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
kind: Foo
|
kind: Foo
|
||||||
@@ -38,10 +40,10 @@ metadata:
|
|||||||
name: foo-instance
|
name: foo-instance
|
||||||
`,
|
`,
|
||||||
filter: prefixsuffix.Filter{Prefix: "foo-"},
|
filter: prefixsuffix.Filter{Prefix: "foo-"},
|
||||||
fs: types.FieldSpec{Path: "metadata/name"},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"suffix": {
|
{
|
||||||
|
name: "suffix",
|
||||||
input: `
|
input: `
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
kind: Foo
|
kind: Foo
|
||||||
@@ -65,10 +67,10 @@ metadata:
|
|||||||
name: instance-foo
|
name: instance-foo
|
||||||
`,
|
`,
|
||||||
filter: prefixsuffix.Filter{Suffix: "-foo"},
|
filter: prefixsuffix.Filter{Suffix: "-foo"},
|
||||||
fs: types.FieldSpec{Path: "metadata/name"},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"prefix-suffix": {
|
{
|
||||||
|
name: "prefix-suffix",
|
||||||
input: `
|
input: `
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
kind: Foo
|
kind: Foo
|
||||||
@@ -92,10 +94,10 @@ metadata:
|
|||||||
name: bar-instance-foo
|
name: bar-instance-foo
|
||||||
`,
|
`,
|
||||||
filter: prefixsuffix.Filter{Prefix: "bar-", Suffix: "-foo"},
|
filter: prefixsuffix.Filter{Prefix: "bar-", Suffix: "-foo"},
|
||||||
fs: types.FieldSpec{Path: "metadata/name"},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"data-fieldspecs": {
|
{
|
||||||
|
name: "data-fieldspecs",
|
||||||
input: `
|
input: `
|
||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
kind: Foo
|
kind: Foo
|
||||||
@@ -117,7 +119,7 @@ a:
|
|||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
kind: Foo
|
kind: Foo
|
||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: foo-instance
|
||||||
a:
|
a:
|
||||||
b:
|
b:
|
||||||
c: foo-d
|
c: foo-d
|
||||||
@@ -125,28 +127,35 @@ a:
|
|||||||
apiVersion: example.com/v1
|
apiVersion: example.com/v1
|
||||||
kind: Bar
|
kind: Bar
|
||||||
metadata:
|
metadata:
|
||||||
name: instance
|
name: foo-instance
|
||||||
a:
|
a:
|
||||||
b:
|
b:
|
||||||
c: foo-d
|
c: foo-d
|
||||||
`,
|
`,
|
||||||
filter: prefixsuffix.Filter{Prefix: "foo-"},
|
filter: prefixsuffix.Filter{Prefix: "foo-"},
|
||||||
fs: types.FieldSpec{Path: "a/b/c"},
|
fsslice: []types.FieldSpec{
|
||||||
|
{
|
||||||
|
Path: "a/b/c",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
|
name string
|
||||||
input string
|
input string
|
||||||
expected string
|
expected string
|
||||||
filter prefixsuffix.Filter
|
filter prefixsuffix.Filter
|
||||||
fs types.FieldSpec
|
fsslice types.FsSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var config = builtinconfig.MakeDefaultConfig()
|
||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
func TestFilter(t *testing.T) {
|
||||||
for name := range tests {
|
for i := range tests {
|
||||||
test := tests[name]
|
test := tests[i]
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
test.filter.FieldSpec = test.fs
|
test.filter.FsSlice = append(config.NamePrefix, test.fsslice...)
|
||||||
if !assert.Equal(t,
|
if !assert.Equal(t,
|
||||||
strings.TrimSpace(test.expected),
|
strings.TrimSpace(test.expected),
|
||||||
strings.TrimSpace(
|
strings.TrimSpace(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package replicacount
|
|||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
@@ -46,5 +45,5 @@ func (rc Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rc Filter) set(node *yaml.RNode) error {
|
func (rc Filter) set(node *yaml.RNode) error {
|
||||||
return filtersutil.SetScalar(strconv.FormatInt(rc.Replica.Count, 10))(node)
|
return fsslice.SetScalar(strconv.FormatInt(rc.Replica.Count, 10))(node)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,11 @@ require (
|
|||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/yujunz/go-getter v1.4.1-lite
|
github.com/yujunz/go-getter v1.4.1-lite
|
||||||
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff
|
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff
|
||||||
gopkg.in/yaml.v2 v2.3.0
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
k8s.io/api v0.17.0
|
k8s.io/api v0.17.0
|
||||||
k8s.io/apimachinery v0.17.0
|
k8s.io/apimachinery v0.17.0
|
||||||
k8s.io/client-go v0.17.0
|
k8s.io/client-go v0.17.0
|
||||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
||||||
sigs.k8s.io/kustomize/kyaml v0.4.1
|
sigs.k8s.io/kustomize/kyaml v0.1.11
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace sigs.k8s.io/kustomize/kyaml v0.4.1 => ../kyaml
|
|
||||||
|
|||||||
@@ -340,7 +340,6 @@ 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-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
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/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
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/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/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/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
@@ -424,7 +423,6 @@ go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL
|
|||||||
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
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-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=
|
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/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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
@@ -550,10 +548,9 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
|||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/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 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@@ -580,6 +577,8 @@ 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/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 h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
|
||||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.1.11 h1:/VvWxVIgH5gG1K4A7trgbyLgO3tRBiAWNhLFVU1HEmo=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.1.11/go.mod h1:72/rLkSi+L/pHM1oCjwrf3ClU+tH5kZQvvdLSqIHwWU=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
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=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
|||||||
@@ -41,33 +41,33 @@ type Loader interface {
|
|||||||
// Kunstructured allows manipulation of k8s objects
|
// Kunstructured allows manipulation of k8s objects
|
||||||
// that do not have Golang structs.
|
// that do not have Golang structs.
|
||||||
type Kunstructured interface {
|
type Kunstructured interface {
|
||||||
Copy() Kunstructured
|
|
||||||
GetAnnotations() map[string]string
|
|
||||||
GetBool(path string) (bool, error)
|
|
||||||
GetFieldValue(string) (interface{}, error)
|
|
||||||
GetFloat64(path string) (float64, error)
|
|
||||||
GetGvk() resid.Gvk
|
|
||||||
GetInt64(path string) (int64, error)
|
|
||||||
GetKind() string
|
|
||||||
GetLabels() map[string]string
|
|
||||||
GetMap(path string) (map[string]interface{}, error)
|
|
||||||
GetName() string
|
|
||||||
GetSlice(path string) ([]interface{}, error)
|
|
||||||
GetString(string) (string, error)
|
|
||||||
GetStringMap(path string) (map[string]string, error)
|
|
||||||
GetStringSlice(string) ([]string, error)
|
|
||||||
Map() map[string]interface{}
|
Map() map[string]interface{}
|
||||||
MarshalJSON() ([]byte, error)
|
|
||||||
MatchesAnnotationSelector(selector string) (bool, error)
|
|
||||||
MatchesLabelSelector(selector string) (bool, error)
|
|
||||||
Patch(Kunstructured) error
|
|
||||||
SetAnnotations(map[string]string)
|
|
||||||
SetGvk(resid.Gvk)
|
|
||||||
SetLabels(map[string]string)
|
|
||||||
SetMap(map[string]interface{})
|
SetMap(map[string]interface{})
|
||||||
|
Copy() Kunstructured
|
||||||
|
GetFieldValue(string) (interface{}, error)
|
||||||
|
GetString(string) (string, error)
|
||||||
|
GetStringSlice(string) ([]string, error)
|
||||||
|
GetBool(path string) (bool, error)
|
||||||
|
GetFloat64(path string) (float64, error)
|
||||||
|
GetInt64(path string) (int64, error)
|
||||||
|
GetSlice(path string) ([]interface{}, error)
|
||||||
|
GetStringMap(path string) (map[string]string, error)
|
||||||
|
GetMap(path string) (map[string]interface{}, error)
|
||||||
|
MarshalJSON() ([]byte, error)
|
||||||
|
UnmarshalJSON([]byte) error
|
||||||
|
GetGvk() resid.Gvk
|
||||||
|
SetGvk(resid.Gvk)
|
||||||
|
GetKind() string
|
||||||
|
GetName() string
|
||||||
SetName(string)
|
SetName(string)
|
||||||
SetNamespace(string)
|
SetNamespace(string)
|
||||||
UnmarshalJSON([]byte) error
|
GetLabels() map[string]string
|
||||||
|
SetLabels(map[string]string)
|
||||||
|
GetAnnotations() map[string]string
|
||||||
|
SetAnnotations(map[string]string)
|
||||||
|
MatchesLabelSelector(selector string) (bool, error)
|
||||||
|
MatchesAnnotationSelector(selector string) (bool, error)
|
||||||
|
Patch(Kunstructured) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// KunstructuredFactory makes instances of Kunstructured.
|
// KunstructuredFactory makes instances of Kunstructured.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.14 AS build
|
FROM golang:1.11 AS build
|
||||||
|
|
||||||
ARG GO111MODULE=on
|
ARG GO111MODULE=on
|
||||||
|
|
||||||
|
|||||||
@@ -159,31 +159,40 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query := []byte(`{ "query":{ "match_all":{} } }`)
|
seedDocs := make(crawler.CrawlSeed, 0)
|
||||||
it := idx.IterateQuery(query, 10000, 60*time.Second)
|
|
||||||
|
// get all the documents in the index
|
||||||
|
getSeedDocsFunc := func() {
|
||||||
|
query := []byte(`{ "query":{ "match_all":{} } }`)
|
||||||
|
it := idx.IterateQuery(query, 10000, 60*time.Second)
|
||||||
|
for it.Next() {
|
||||||
|
for _, hit := range it.Value().Hits.Hits {
|
||||||
|
seedDocs = append(seedDocs, hit.Document.Document.Copy())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := it.Err(); err != nil {
|
||||||
|
log.Fatalf("getSeedDocsFunc Error iterating: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case CrawlIndexAndGithub:
|
case CrawlIndexAndGithub:
|
||||||
|
getSeedDocsFunc()
|
||||||
crawlers := []crawler.Crawler{ghCrawlerConstructor("", "")}
|
crawlers := []crawler.Crawler{ghCrawlerConstructor("", "")}
|
||||||
crawler.CrawlFromSeedIterator(ctx, it, crawlers, docConverter, indexFunc, seen)
|
crawler.CrawlFromSeed(ctx, seedDocs, crawlers, docConverter, indexFunc, seen)
|
||||||
crawler.CrawlGithub(ctx, crawlers, docConverter, indexFunc, seen)
|
crawler.CrawlGithub(ctx, crawlers, docConverter, indexFunc, seen)
|
||||||
case CrawlIndex:
|
case CrawlIndex:
|
||||||
|
getSeedDocsFunc()
|
||||||
crawlers := []crawler.Crawler{ghCrawlerConstructor("", "")}
|
crawlers := []crawler.Crawler{ghCrawlerConstructor("", "")}
|
||||||
crawler.CrawlFromSeedIterator(ctx, it, crawlers, docConverter, indexFunc, seen)
|
crawler.CrawlFromSeed(ctx, seedDocs, crawlers, docConverter, indexFunc, seen)
|
||||||
case CrawlGithub:
|
case CrawlGithub:
|
||||||
crawlers := []crawler.Crawler{ghCrawlerConstructor("", "")}
|
crawlers := []crawler.Crawler{ghCrawlerConstructor("", "")}
|
||||||
// add all the documents in the index into seen.
|
// add all the documents in the index into seen.
|
||||||
// this greatly reduces the time overhead of CrawlGithub.
|
// this greatly reduces the time overhead of CrawlGithub.
|
||||||
for it.Next() {
|
getSeedDocsFunc()
|
||||||
for _, hit := range it.Value().Hits.Hits {
|
for _, d := range seedDocs {
|
||||||
d := hit.Document.Document
|
seen[d.ID()] = d.FileType
|
||||||
seen.Set(d.ID(), d.FileType)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err := it.Err(); err != nil {
|
|
||||||
log.Fatalf("Error iterating the index: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
crawler.CrawlGithub(ctx, crawlers, docConverter, indexFunc, seen)
|
crawler.CrawlGithub(ctx, crawlers, docConverter, indexFunc, seen)
|
||||||
case CrawlUser:
|
case CrawlUser:
|
||||||
if *githubUserPtr == "" {
|
if *githubUserPtr == "" {
|
||||||
|
|||||||
@@ -213,36 +213,21 @@ func doCrawl(ctx context.Context, docsPtr *CrawlSeed, crawlers []Crawler, conv C
|
|||||||
logger.Printf("\t%d documents cannot be converted but still were inserted or updated in the index\n", convErrCount)
|
logger.Printf("\t%d documents cannot be converted but still were inserted or updated in the index\n", convErrCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CrawlFromSeedIterator iterates all the documents in the index and call CrawlFromSeed for each document.
|
|
||||||
func CrawlFromSeedIterator(ctx context.Context, it *index.KustomizeIterator, crawlers []Crawler,
|
|
||||||
conv Converter, indx IndexFunc, seen utils.SeenMap) {
|
|
||||||
docCount := 0
|
|
||||||
for it.Next() {
|
|
||||||
for _, hit := range it.Value().Hits.Hits {
|
|
||||||
docCount++
|
|
||||||
logger.Printf("updating document %d from seed\n", docCount)
|
|
||||||
|
|
||||||
singleSeed := CrawlSeed{&(hit.Document.Document)}
|
|
||||||
CrawlFromSeed(ctx, singleSeed, crawlers, conv, indx, seen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := it.Err(); err != nil {
|
|
||||||
log.Fatalf("Error iterating the index: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CrawlFromSeed updates all the documents in seed, and crawls all the new
|
// CrawlFromSeed updates all the documents in seed, and crawls all the new
|
||||||
// documents referred in the seed.
|
// documents referred in the seed.
|
||||||
func CrawlFromSeed(ctx context.Context, seed CrawlSeed, crawlers []Crawler,
|
func CrawlFromSeed(ctx context.Context, seed CrawlSeed, crawlers []Crawler,
|
||||||
conv Converter, indx IndexFunc, seen utils.SeenMap) {
|
conv Converter, indx IndexFunc, seen utils.SeenMap) {
|
||||||
|
|
||||||
// stack tracks the documents directly referred in the seed.
|
// stack tracks the documents directly referred in other documents.
|
||||||
stack := make(CrawlSeed, 0)
|
stack := make(CrawlSeed, 0)
|
||||||
|
|
||||||
|
// Exploit seed to update bulk of corpus.
|
||||||
|
logger.Printf("updating %d documents from seed\n", len(seed))
|
||||||
// each unique document in seed will be crawled once.
|
// each unique document in seed will be crawled once.
|
||||||
doCrawl(ctx, &seed, crawlers, conv, indx, seen, &stack, true, false)
|
doCrawl(ctx, &seed, crawlers, conv, indx, seen, &stack, true, false)
|
||||||
|
|
||||||
logger.Printf("crawling %d new documents referred by doc\n", len(stack))
|
// Traverse any new documents added while updating corpus.
|
||||||
|
logger.Printf("crawling %d new documents found in the seed\n", len(stack))
|
||||||
// While crawling each document in stack, the documents directly referred in the document
|
// While crawling each document in stack, the documents directly referred in the document
|
||||||
// will be added into stack.
|
// will be added into stack.
|
||||||
// After this statement is done, stack will become empty.
|
// After this statement is done, stack will become empty.
|
||||||
@@ -312,6 +297,8 @@ func CrawlGithubRunner(ctx context.Context, output chan<- CrawledDocument,
|
|||||||
// CrawlGithub crawls all the kustomization files on Github.
|
// CrawlGithub crawls all the kustomization files on Github.
|
||||||
func CrawlGithub(ctx context.Context, crawlers []Crawler, conv Converter,
|
func CrawlGithub(ctx context.Context, crawlers []Crawler, conv Converter,
|
||||||
indx IndexFunc, seen utils.SeenMap) {
|
indx IndexFunc, seen utils.SeenMap) {
|
||||||
|
// stack tracks the documents directly referred in other documents.
|
||||||
|
stack := make(CrawlSeed, 0)
|
||||||
|
|
||||||
// ch is channel where all the crawlers sends the crawled documents to.
|
// ch is channel where all the crawlers sends the crawled documents to.
|
||||||
ch := make(chan CrawledDocument, 1<<10)
|
ch := make(chan CrawledDocument, 1<<10)
|
||||||
@@ -337,20 +324,7 @@ func CrawlGithub(ctx context.Context, crawlers []Crawler, conv Converter,
|
|||||||
"%v could not match any crawler", cdoc))
|
"%v could not match any crawler", cdoc))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// stack tracks the documents directly referred in the document.
|
|
||||||
stack := make(CrawlSeed, 0)
|
|
||||||
|
|
||||||
addBranches(cdoc, match, indx, seen, &stack)
|
addBranches(cdoc, match, indx, seen, &stack)
|
||||||
|
|
||||||
if len(stack) > 0 {
|
|
||||||
// here the documents referred in a kustomization file are crawled separately,
|
|
||||||
// to avoid accumulating all the referred documents into a single gigantic
|
|
||||||
// mem-inentive stack.
|
|
||||||
logger.Printf("crawling the %d new documents referred in doc %d",
|
|
||||||
len(stack), docCount)
|
|
||||||
doCrawl(ctx, &stack, crawlers, conv, indx, seen, &stack, false, true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -362,4 +336,9 @@ func CrawlGithub(ctx context.Context, crawlers []Crawler, conv Converter,
|
|||||||
}
|
}
|
||||||
close(ch)
|
close(ch)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
// Handle deps of newly discovered documents.
|
||||||
|
logger.Printf("crawling the %d new documents referred by other documents",
|
||||||
|
len(stack))
|
||||||
|
doCrawl(ctx, &stack, crawlers, conv, indx, seen, &stack, false, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,15 +82,14 @@ func (gc githubCrawler) Crawl(ctx context.Context,
|
|||||||
|
|
||||||
ranges := []RangeWithin{
|
ranges := []RangeWithin{
|
||||||
RangeWithin{
|
RangeWithin{
|
||||||
start: uint64(0),
|
start: uint64(0),
|
||||||
end: githubMaxFileSize,
|
end: githubMaxFileSize,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := make(multiError, 0)
|
errs := make(multiError, 0)
|
||||||
for len(ranges) > 0 {
|
for len(ranges) > 0 {
|
||||||
logger.Printf("Current ranges: %v (len: %d)\n", ranges, len(ranges))
|
tailRange := ranges[len(ranges) - 1]
|
||||||
tailRange := ranges[len(ranges)-1]
|
|
||||||
ranges = ranges[:(len(ranges) - 1)]
|
ranges = ranges[:(len(ranges) - 1)]
|
||||||
reProcessQueryRanges, err := gc.CrawlSingleRange(ctx, output, seen, tailRange.start, tailRange.end)
|
reProcessQueryRanges, err := gc.CrawlSingleRange(ctx, output, seen, tailRange.start, tailRange.end)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -152,15 +151,7 @@ func (gc githubCrawler) CrawlSingleRange(ctx context.Context,
|
|||||||
}
|
}
|
||||||
queryResult.Add(rangeResult)
|
queryResult.Add(rangeResult)
|
||||||
if reProcessQuery {
|
if reProcessQuery {
|
||||||
// if the size of a range is 0, such as [245, 245], and reProcessQuery is true,
|
reProcessQueryRanges = append(reProcessQueryRanges, RangeSizes(query))
|
||||||
// it means that there are more than 1000 results for the query range.
|
|
||||||
// Reprocessing the query range will not help because the GitHub Search API
|
|
||||||
// only provides up to 1,000 results for each search.
|
|
||||||
if RangeSizes(query).Size() == 0 {
|
|
||||||
logger.Printf("range size is 0 includes more than 1000 results: %s", query)
|
|
||||||
} else {
|
|
||||||
reProcessQueryRanges = append(reProcessQueryRanges, RangeSizes(query))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -225,7 +225,3 @@ type RangeWithin struct {
|
|||||||
func (r RangeWithin) RangeString() string {
|
func (r RangeWithin) RangeString() string {
|
||||||
return fmt.Sprintf("%d..%d", r.start, r.end)
|
return fmt.Sprintf("%d..%d", r.start, r.end)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r RangeWithin) Size() uint64 {
|
|
||||||
return r.end - r.start
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -189,8 +189,13 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
|||||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
|
||||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
|
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
|
||||||
|
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
@@ -263,6 +268,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
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/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/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
|
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
|
||||||
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
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/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=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
@@ -483,6 +489,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
|||||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
@@ -490,10 +497,9 @@ 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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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-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.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@@ -515,7 +521,7 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
|||||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.4.1/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw=
|
sigs.k8s.io/kustomize/kyaml v0.1.11/go.mod h1:72/rLkSi+L/pHM1oCjwrf3ClU+tH5kZQvvdLSqIHwWU=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
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 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
|||||||
8102
api/internal/crawl/ui/package-lock.json
generated
8102
api/internal/crawl/ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,21 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import "sync"
|
type SeenMap map[string]string
|
||||||
|
|
||||||
type SeenMap struct {
|
|
||||||
data map[string]string
|
|
||||||
lock sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add lock to avoid race condition
|
|
||||||
func (seen SeenMap) Seen(item string) bool {
|
func (seen SeenMap) Seen(item string) bool {
|
||||||
seen.lock.RLock()
|
_, ok := seen[item]
|
||||||
_, ok := seen.data[item]
|
|
||||||
seen.lock.RUnlock()
|
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (seen SeenMap) Set(k, v string) {
|
func (seen SeenMap) Set(k, v string) {
|
||||||
seen.lock.Lock()
|
seen[k] = v
|
||||||
seen.data[k] = v
|
|
||||||
seen.lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The caller should make sure that key is in the map.
|
// The caller should make sure that key is in the map.
|
||||||
func (seen SeenMap) Value(k string) string {
|
func (seen SeenMap) Value(k string) string {
|
||||||
seen.lock.RLock()
|
return seen[k]
|
||||||
v := seen.data[k]
|
|
||||||
seen.lock.RUnlock()
|
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSeenMap() SeenMap {
|
func NewSeenMap() SeenMap {
|
||||||
return SeenMap{
|
return make(map[string]string)
|
||||||
data: make(map[string]string),
|
|
||||||
lock: sync.RWMutex{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,17 +9,22 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/shlex"
|
"github.com/google/shlex"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
idAnnotation = "kustomize.config.k8s.io/id"
|
||||||
|
HashAnnotation = "kustomize.config.k8s.io/needs-hash"
|
||||||
|
BehaviorAnnotation = "kustomize.config.k8s.io/behavior"
|
||||||
tmpConfigFilePrefix = "kust-plugin-config-"
|
tmpConfigFilePrefix = "kust-plugin-config-"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -109,12 +114,12 @@ func (p *ExecPlugin) Generate() (resmap.ResMap, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return utils.UpdateResourceOptions(rm)
|
return p.UpdateResourceOptions(rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
|
func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
|
||||||
// add ResIds as annotations to all objects so that we can add them back
|
// add ResIds as annotations to all objects so that we can add them back
|
||||||
inputRM, err := utils.GetResMapWithIDAnnotation(rm)
|
inputRM, err := p.getResMapWithIdAnnotation(rm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -132,7 +137,7 @@ func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update the original ResMap based on the output
|
// update the original ResMap based on the output
|
||||||
return utils.UpdateResMapValues(p.path, p.h, output, rm)
|
return p.updateResMapValues(output, rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// invokePlugin writes plugin config to a temp file, then
|
// invokePlugin writes plugin config to a temp file, then
|
||||||
@@ -179,3 +184,91 @@ func (p *ExecPlugin) getEnv() []string {
|
|||||||
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.h.Loader().Root())
|
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.h.Loader().Root())
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a new copy of the given ResMap with the ResIds annotated in each Resource
|
||||||
|
func (p *ExecPlugin) getResMapWithIdAnnotation(rm resmap.ResMap) (resmap.ResMap, error) {
|
||||||
|
inputRM := rm.DeepCopy()
|
||||||
|
for _, r := range inputRM.Resources() {
|
||||||
|
idString, err := yaml.Marshal(r.CurId())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
annotations := r.GetAnnotations()
|
||||||
|
if annotations == nil {
|
||||||
|
annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
annotations[idAnnotation] = string(idString)
|
||||||
|
r.SetAnnotations(annotations)
|
||||||
|
}
|
||||||
|
return inputRM, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateResMapValues updates the Resource value in the given ResMap
|
||||||
|
// with the emitted Resource values in output.
|
||||||
|
func (p *ExecPlugin) updateResMapValues(output []byte, rm resmap.ResMap) error {
|
||||||
|
outputRM, err := p.h.ResmapFactory().NewResMapFromBytes(output)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, r := range outputRM.Resources() {
|
||||||
|
// for each emitted Resource, find the matching Resource in the original ResMap
|
||||||
|
// using its id
|
||||||
|
annotations := r.GetAnnotations()
|
||||||
|
idString, ok := annotations[idAnnotation]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("the transformer %s should not remove annotation %s",
|
||||||
|
p.path, idAnnotation)
|
||||||
|
}
|
||||||
|
id := resid.ResId{}
|
||||||
|
err := yaml.Unmarshal([]byte(idString), &id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res, err := rm.GetByCurrentId(id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to find unique match to %s", id.String())
|
||||||
|
}
|
||||||
|
// remove the annotation set by Kustomize to track the resource
|
||||||
|
delete(annotations, idAnnotation)
|
||||||
|
if len(annotations) == 0 {
|
||||||
|
annotations = nil
|
||||||
|
}
|
||||||
|
r.SetAnnotations(annotations)
|
||||||
|
|
||||||
|
// update the ResMap resource value with the transformed object
|
||||||
|
res.Kunstructured = r.Kunstructured
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateResourceOptions updates the generator options for each resource in the
|
||||||
|
// given ResMap based on plugin provided annotations.
|
||||||
|
func (p *ExecPlugin) UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {
|
||||||
|
for _, r := range rm.Resources() {
|
||||||
|
// Disable name hashing by default and require plugin to explicitly
|
||||||
|
// request it for each resource.
|
||||||
|
annotations := r.GetAnnotations()
|
||||||
|
behavior := annotations[BehaviorAnnotation]
|
||||||
|
var needsHash bool
|
||||||
|
if val, ok := annotations[HashAnnotation]; ok {
|
||||||
|
b, err := strconv.ParseBool(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"the annotation %q contains an invalid value (%q)",
|
||||||
|
HashAnnotation, val)
|
||||||
|
}
|
||||||
|
needsHash = b
|
||||||
|
}
|
||||||
|
delete(annotations, HashAnnotation)
|
||||||
|
delete(annotations, BehaviorAnnotation)
|
||||||
|
if len(annotations) == 0 {
|
||||||
|
annotations = nil
|
||||||
|
}
|
||||||
|
r.SetAnnotations(annotations)
|
||||||
|
r.SetOptions(types.NewGenArgs(
|
||||||
|
&types.GeneratorArgs{
|
||||||
|
Behavior: behavior,
|
||||||
|
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
|
||||||
|
}
|
||||||
|
return rm, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package execplugin_test
|
package execplugin_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExecPluginConfig(t *testing.T) {
|
func TestExecPluginConfig(t *testing.T) {
|
||||||
@@ -89,3 +91,107 @@ metadata:
|
|||||||
t.Fatalf("unexpected arg array: %#v", p.Args())
|
t.Fatalf("unexpected arg array: %#v", p.Args())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeConfigMap(rf *resource.Factory, name, behavior string, hashValue *string) *resource.Resource {
|
||||||
|
r := rf.FromMap(map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{"name": name},
|
||||||
|
})
|
||||||
|
annotations := map[string]string{}
|
||||||
|
if behavior != "" {
|
||||||
|
annotations[BehaviorAnnotation] = behavior
|
||||||
|
}
|
||||||
|
if hashValue != nil {
|
||||||
|
annotations[HashAnnotation] = *hashValue
|
||||||
|
}
|
||||||
|
if len(annotations) > 0 {
|
||||||
|
r.SetAnnotations(annotations)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHash bool) *resource.Resource {
|
||||||
|
return rf.FromMapAndOption(map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{"name": name},
|
||||||
|
}, &types.GeneratorArgs{
|
||||||
|
Behavior: behavior,
|
||||||
|
Options: &types.GeneratorOptions{DisableNameSuffixHash: disableHash}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func strptr(s string) *string {
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateResourceOptions(t *testing.T) {
|
||||||
|
p := NewExecPlugin("")
|
||||||
|
if err := p.ErrIfNotExecutable(); err == nil {
|
||||||
|
t.Fatalf("expected unexecutable error")
|
||||||
|
}
|
||||||
|
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
in := resmap.New()
|
||||||
|
expected := resmap.New()
|
||||||
|
cases := []struct {
|
||||||
|
behavior string
|
||||||
|
needsHash bool
|
||||||
|
hashValue *string
|
||||||
|
}{
|
||||||
|
{hashValue: strptr("false")},
|
||||||
|
{hashValue: strptr("true"), needsHash: true},
|
||||||
|
{behavior: "replace"},
|
||||||
|
{behavior: "merge"},
|
||||||
|
{behavior: "create"},
|
||||||
|
{behavior: "nonsense"},
|
||||||
|
{behavior: "merge", hashValue: strptr("false")},
|
||||||
|
{behavior: "merge", hashValue: strptr("true"), needsHash: true},
|
||||||
|
}
|
||||||
|
for i, c := range cases {
|
||||||
|
name := fmt.Sprintf("test%d", i)
|
||||||
|
in.Append(makeConfigMap(rf, name, c.behavior, c.hashValue))
|
||||||
|
expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
|
||||||
|
}
|
||||||
|
actual, err := p.UpdateResourceOptions(in)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
for i, a := range expected.Resources() {
|
||||||
|
b := actual.GetByIndex(i)
|
||||||
|
if b == nil {
|
||||||
|
t.Fatalf("resource %d missing from processed map", i)
|
||||||
|
}
|
||||||
|
if !a.Equals(b) {
|
||||||
|
t.Errorf("expected %v got %v", a, b)
|
||||||
|
}
|
||||||
|
if a.NeedHashSuffix() != b.NeedHashSuffix() {
|
||||||
|
t.Errorf("")
|
||||||
|
}
|
||||||
|
if a.Behavior() != b.Behavior() {
|
||||||
|
t.Errorf("expected %v got %v", a.Behavior(), b.Behavior())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
|
||||||
|
p := NewExecPlugin("")
|
||||||
|
if err := p.ErrIfNotExecutable(); err == nil {
|
||||||
|
t.Fatalf("expected unexecutable error")
|
||||||
|
}
|
||||||
|
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
cases := []string{
|
||||||
|
"",
|
||||||
|
"FaLsE",
|
||||||
|
"TrUe",
|
||||||
|
"potato",
|
||||||
|
}
|
||||||
|
for i, c := range cases {
|
||||||
|
name := fmt.Sprintf("test%d", i)
|
||||||
|
in := resmap.New()
|
||||||
|
in.Append(makeConfigMap(rf, name, "", &c))
|
||||||
|
_, err := p.UpdateResourceOptions(in)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected error from value %q", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package fnplugin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/runfn"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FnPlugin is the struct to hold function information
|
|
||||||
type FnPlugin struct {
|
|
||||||
// Function runner
|
|
||||||
runFns runfn.RunFns
|
|
||||||
|
|
||||||
// Plugin configuration data.
|
|
||||||
cfg []byte
|
|
||||||
|
|
||||||
// Plugin name cache for error output
|
|
||||||
pluginName string
|
|
||||||
|
|
||||||
// PluginHelpers
|
|
||||||
h *resmap.PluginHelpers
|
|
||||||
}
|
|
||||||
|
|
||||||
func bytesToRNode(yml []byte) (*yaml.RNode, error) {
|
|
||||||
rnode, err := yaml.Parse(string(yml))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return rnode, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourceToRNode(res *resource.Resource) (*yaml.RNode, error) {
|
|
||||||
yml, err := res.AsYAML()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesToRNode(yml)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFunctionSpec return function spec is there is. Otherwise return nil
|
|
||||||
func GetFunctionSpec(res *resource.Resource) *runtimeutil.FunctionSpec {
|
|
||||||
rnode, err := resourceToRNode(res)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return runtimeutil.GetFunctionSpec(rnode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func toStorageMounts(mounts []string) []runtimeutil.StorageMount {
|
|
||||||
var sms []runtimeutil.StorageMount
|
|
||||||
for _, mount := range mounts {
|
|
||||||
sms = append(sms, runtimeutil.StringToStorageMount(mount))
|
|
||||||
}
|
|
||||||
return sms
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFnPlugin creates a FnPlugin struct
|
|
||||||
func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin {
|
|
||||||
return &FnPlugin{
|
|
||||||
runFns: runfn.RunFns{
|
|
||||||
Functions: []*yaml.RNode{},
|
|
||||||
Network: o.Network,
|
|
||||||
NetworkName: o.NetworkName,
|
|
||||||
EnableStarlark: o.EnableStar,
|
|
||||||
EnableExec: o.EnableExec,
|
|
||||||
StorageMounts: toStorageMounts(o.Mounts),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cfg returns function config
|
|
||||||
func (p *FnPlugin) Cfg() []byte {
|
|
||||||
return p.cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config is called by kustomize to pass-in config information
|
|
||||||
func (p *FnPlugin) Config(h *resmap.PluginHelpers, config []byte) error {
|
|
||||||
p.h = h
|
|
||||||
p.cfg = config
|
|
||||||
|
|
||||||
fn, err := bytesToRNode(p.cfg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
meta, err := fn.GetMeta()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.pluginName = fmt.Sprintf("api: %s, kind: %s, name: %s",
|
|
||||||
meta.APIVersion, meta.Kind, meta.Name)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate is called when run as generator
|
|
||||||
func (p *FnPlugin) Generate() (resmap.ResMap, error) {
|
|
||||||
output, err := p.invokePlugin(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rm, err := p.h.ResmapFactory().NewResMapFromBytes(output)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return utils.UpdateResourceOptions(rm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform is called when run as transformer
|
|
||||||
func (p *FnPlugin) Transform(rm resmap.ResMap) error {
|
|
||||||
// add ResIds as annotations to all objects so that we can add them back
|
|
||||||
inputRM, err := utils.GetResMapWithIDAnnotation(rm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode the ResMap so it can be fed to the plugin
|
|
||||||
resources, err := inputRM.AsYaml()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// invoke the plugin with resources as the input
|
|
||||||
output, err := p.invokePlugin(resources)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%v %s", err, string(output))
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the original ResMap based on the output
|
|
||||||
return utils.UpdateResMapValues(p.pluginName, p.h, output, rm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func injectAnnotation(input *yaml.RNode, k, v string) error {
|
|
||||||
err := input.PipeE(yaml.SetAnnotation(k, v))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// invokePlugin uses Function runner to run function as plugin
|
|
||||||
func (p *FnPlugin) invokePlugin(input []byte) ([]byte, error) {
|
|
||||||
// get function config rnode
|
|
||||||
functionConfig, err := bytesToRNode(p.cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// This annotation will let kustomize ingnore this item in output
|
|
||||||
err = injectAnnotation(functionConfig, "config.kubernetes.io/local-config", "true")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// we need to add config as input for generators. Some of them don't work with FunctionConfig
|
|
||||||
// and in addition kio.Pipeline won't create anything if there are no objects
|
|
||||||
// see https://github.com/kubernetes-sigs/kustomize/blob/master/kyaml/kio/kio.go#L93
|
|
||||||
// Since we added `local-config` annotation so it will be ignored in generator output
|
|
||||||
// TODO(donnyxia): This is actually not used by generator and only used to bypass a kio limitation.
|
|
||||||
// Need better solution.
|
|
||||||
if input == nil {
|
|
||||||
yaml, err := functionConfig.String()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
input = []byte(yaml)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure and Execute Fn. We don't need to convert resources to ResourceList here
|
|
||||||
// because function runtime will do that. See kyaml/fn/runtime/runtimeutil/runtimeutil.go
|
|
||||||
var ouputBuffer bytes.Buffer
|
|
||||||
p.runFns.Input = bytes.NewReader(input)
|
|
||||||
p.runFns.Functions = append(p.runFns.Functions, functionConfig)
|
|
||||||
p.runFns.Output = &ouputBuffer
|
|
||||||
|
|
||||||
err = p.runFns.Execute()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(
|
|
||||||
err, "couldn't execute function")
|
|
||||||
}
|
|
||||||
|
|
||||||
return ouputBuffer.Bytes(), nil
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/fnplugin"
|
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
@@ -117,7 +116,7 @@ func (l *Loader) loadAndConfigurePlugin(
|
|||||||
if isBuiltinPlugin(res) {
|
if isBuiltinPlugin(res) {
|
||||||
switch l.pc.BpLoadingOptions {
|
switch l.pc.BpLoadingOptions {
|
||||||
case types.BploLoadFromFileSys:
|
case types.BploLoadFromFileSys:
|
||||||
c, err = l.loadPlugin(res)
|
c, err = l.loadPlugin(res.OrgId())
|
||||||
case types.BploUseStaticallyLinked:
|
case types.BploUseStaticallyLinked:
|
||||||
// Instead of looking for and loading a .so file,
|
// Instead of looking for and loading a .so file,
|
||||||
// instantiate the plugin from a generated factory
|
// instantiate the plugin from a generated factory
|
||||||
@@ -132,7 +131,7 @@ func (l *Loader) loadAndConfigurePlugin(
|
|||||||
} else {
|
} else {
|
||||||
switch l.pc.PluginRestrictions {
|
switch l.pc.PluginRestrictions {
|
||||||
case types.PluginRestrictionsNone:
|
case types.PluginRestrictionsNone:
|
||||||
c, err = l.loadPlugin(res)
|
c, err = l.loadPlugin(res.OrgId())
|
||||||
case types.PluginRestrictionsBuiltinsOnly:
|
case types.PluginRestrictionsBuiltinsOnly:
|
||||||
err = types.NewErrOnlyBuiltinPluginsAllowed(res.OrgId().Kind)
|
err = types.NewErrOnlyBuiltinPluginsAllowed(res.OrgId().Kind)
|
||||||
default:
|
default:
|
||||||
@@ -167,15 +166,7 @@ func (l *Loader) makeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
|
|||||||
return nil, errors.Errorf("unable to load builtin %s", r)
|
return nil, errors.Errorf("unable to load builtin %s", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loader) loadPlugin(res *resource.Resource) (resmap.Configurable, error) {
|
func (l *Loader) loadPlugin(resId resid.ResId) (resmap.Configurable, error) {
|
||||||
spec := fnplugin.GetFunctionSpec(res)
|
|
||||||
if spec != nil {
|
|
||||||
return fnplugin.NewFnPlugin(&l.pc.FnpLoadingOptions), nil
|
|
||||||
}
|
|
||||||
return l.loadExecOrGoPlugin(res.OrgId())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, error) {
|
|
||||||
// First try to load the plugin as an executable.
|
// First try to load the plugin as an executable.
|
||||||
p := execplugin.NewExecPlugin(l.absolutePluginPath(resId))
|
p := execplugin.NewExecPlugin(l.absolutePluginPath(resId))
|
||||||
err := p.ErrIfNotExecutable()
|
err := p.ErrIfNotExecutable()
|
||||||
|
|||||||
@@ -4,25 +4,13 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
idAnnotation = "kustomize.config.k8s.io/id"
|
|
||||||
HashAnnotation = "kustomize.config.k8s.io/needs-hash"
|
|
||||||
BehaviorAnnotation = "kustomize.config.k8s.io/behavior"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GoBin() string {
|
func GoBin() string {
|
||||||
@@ -125,91 +113,3 @@ func FileExists(path string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResMapWithIDAnnotation returns a new copy of the given ResMap with the ResIds annotated in each Resource
|
|
||||||
func GetResMapWithIDAnnotation(rm resmap.ResMap) (resmap.ResMap, error) {
|
|
||||||
inputRM := rm.DeepCopy()
|
|
||||||
for _, r := range inputRM.Resources() {
|
|
||||||
idString, err := yaml.Marshal(r.CurId())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
annotations := r.GetAnnotations()
|
|
||||||
if annotations == nil {
|
|
||||||
annotations = make(map[string]string)
|
|
||||||
}
|
|
||||||
annotations[idAnnotation] = string(idString)
|
|
||||||
r.SetAnnotations(annotations)
|
|
||||||
}
|
|
||||||
return inputRM, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResMapValues updates the Resource value in the given ResMap
|
|
||||||
// with the emitted Resource values in output.
|
|
||||||
func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byte, rm resmap.ResMap) error {
|
|
||||||
outputRM, err := h.ResmapFactory().NewResMapFromBytes(output)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, r := range outputRM.Resources() {
|
|
||||||
// for each emitted Resource, find the matching Resource in the original ResMap
|
|
||||||
// using its id
|
|
||||||
annotations := r.GetAnnotations()
|
|
||||||
idString, ok := annotations[idAnnotation]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("the transformer %s should not remove annotation %s",
|
|
||||||
pluginName, idAnnotation)
|
|
||||||
}
|
|
||||||
id := resid.ResId{}
|
|
||||||
err := yaml.Unmarshal([]byte(idString), &id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
res, err := rm.GetByCurrentId(id)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to find unique match to %s", id.String())
|
|
||||||
}
|
|
||||||
// remove the annotation set by Kustomize to track the resource
|
|
||||||
delete(annotations, idAnnotation)
|
|
||||||
if len(annotations) == 0 {
|
|
||||||
annotations = nil
|
|
||||||
}
|
|
||||||
r.SetAnnotations(annotations)
|
|
||||||
|
|
||||||
// update the resource value with the transformed object
|
|
||||||
res.ResetPrimaryData(r)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResourceOptions updates the generator options for each resource in the
|
|
||||||
// given ResMap based on plugin provided annotations.
|
|
||||||
func UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {
|
|
||||||
for _, r := range rm.Resources() {
|
|
||||||
// Disable name hashing by default and require plugin to explicitly
|
|
||||||
// request it for each resource.
|
|
||||||
annotations := r.GetAnnotations()
|
|
||||||
behavior := annotations[BehaviorAnnotation]
|
|
||||||
var needsHash bool
|
|
||||||
if val, ok := annotations[HashAnnotation]; ok {
|
|
||||||
b, err := strconv.ParseBool(val)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"the annotation %q contains an invalid value (%q)",
|
|
||||||
HashAnnotation, val)
|
|
||||||
}
|
|
||||||
needsHash = b
|
|
||||||
}
|
|
||||||
delete(annotations, HashAnnotation)
|
|
||||||
delete(annotations, BehaviorAnnotation)
|
|
||||||
if len(annotations) == 0 {
|
|
||||||
annotations = nil
|
|
||||||
}
|
|
||||||
r.SetAnnotations(annotations)
|
|
||||||
r.SetOptions(types.NewGenArgs(
|
|
||||||
&types.GeneratorArgs{
|
|
||||||
Behavior: behavior,
|
|
||||||
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
|
|
||||||
}
|
|
||||||
return rm, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,17 +4,12 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeterminePluginSrcRoot(t *testing.T) {
|
func TestDeterminePluginSrcRoot(t *testing.T) {
|
||||||
@@ -29,99 +24,3 @@ func TestDeterminePluginSrcRoot(t *testing.T) {
|
|||||||
t.Errorf("expected suffix '%s' in '%s'", konfig.RelPluginHome, actual)
|
t.Errorf("expected suffix '%s' in '%s'", konfig.RelPluginHome, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeConfigMap(rf *resource.Factory, name, behavior string, hashValue *string) *resource.Resource {
|
|
||||||
r := rf.FromMap(map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "ConfigMap",
|
|
||||||
"metadata": map[string]interface{}{"name": name},
|
|
||||||
})
|
|
||||||
annotations := map[string]string{}
|
|
||||||
if behavior != "" {
|
|
||||||
annotations[BehaviorAnnotation] = behavior
|
|
||||||
}
|
|
||||||
if hashValue != nil {
|
|
||||||
annotations[HashAnnotation] = *hashValue
|
|
||||||
}
|
|
||||||
if len(annotations) > 0 {
|
|
||||||
r.SetAnnotations(annotations)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHash bool) *resource.Resource {
|
|
||||||
return rf.FromMapAndOption(map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "ConfigMap",
|
|
||||||
"metadata": map[string]interface{}{"name": name},
|
|
||||||
}, &types.GeneratorArgs{
|
|
||||||
Behavior: behavior,
|
|
||||||
Options: &types.GeneratorOptions{DisableNameSuffixHash: disableHash}})
|
|
||||||
}
|
|
||||||
|
|
||||||
func strptr(s string) *string {
|
|
||||||
return &s
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateResourceOptions(t *testing.T) {
|
|
||||||
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
|
||||||
in := resmap.New()
|
|
||||||
expected := resmap.New()
|
|
||||||
cases := []struct {
|
|
||||||
behavior string
|
|
||||||
needsHash bool
|
|
||||||
hashValue *string
|
|
||||||
}{
|
|
||||||
{hashValue: strptr("false")},
|
|
||||||
{hashValue: strptr("true"), needsHash: true},
|
|
||||||
{behavior: "replace"},
|
|
||||||
{behavior: "merge"},
|
|
||||||
{behavior: "create"},
|
|
||||||
{behavior: "nonsense"},
|
|
||||||
{behavior: "merge", hashValue: strptr("false")},
|
|
||||||
{behavior: "merge", hashValue: strptr("true"), needsHash: true},
|
|
||||||
}
|
|
||||||
for i, c := range cases {
|
|
||||||
name := fmt.Sprintf("test%d", i)
|
|
||||||
in.Append(makeConfigMap(rf, name, c.behavior, c.hashValue))
|
|
||||||
expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
|
|
||||||
}
|
|
||||||
actual, err := UpdateResourceOptions(in)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err.Error())
|
|
||||||
}
|
|
||||||
for i, a := range expected.Resources() {
|
|
||||||
b := actual.GetByIndex(i)
|
|
||||||
if b == nil {
|
|
||||||
t.Fatalf("resource %d missing from processed map", i)
|
|
||||||
}
|
|
||||||
if !a.Equals(b) {
|
|
||||||
t.Errorf("expected %v got %v", a, b)
|
|
||||||
}
|
|
||||||
if a.NeedHashSuffix() != b.NeedHashSuffix() {
|
|
||||||
t.Errorf("")
|
|
||||||
}
|
|
||||||
if a.Behavior() != b.Behavior() {
|
|
||||||
t.Errorf("expected %v got %v", a.Behavior(), b.Behavior())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
|
|
||||||
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
|
||||||
cases := []string{
|
|
||||||
"",
|
|
||||||
"FaLsE",
|
|
||||||
"TrUe",
|
|
||||||
"potato",
|
|
||||||
}
|
|
||||||
for i, c := range cases {
|
|
||||||
name := fmt.Sprintf("test%d", i)
|
|
||||||
in := resmap.New()
|
|
||||||
in.Append(makeConfigMap(rf, name, "", &c))
|
|
||||||
_, err := UpdateResourceOptions(in)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("expected error from value %q", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package target
|
package target
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -59,7 +60,7 @@ func (kt *KustTarget) Load() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var k types.Kustomization
|
var k types.Kustomization
|
||||||
err = k.Unmarshal(content)
|
err = unmarshal(content, &k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -103,8 +104,18 @@ func loadKustFile(ldr ifc.Loader) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshal(y []byte, o interface{}) error {
|
||||||
|
j, err := yaml.YAMLToJSON(y)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dec := json.NewDecoder(bytes.NewReader(j))
|
||||||
|
dec.DisallowUnknownFields()
|
||||||
|
return dec.Decode(o)
|
||||||
|
}
|
||||||
|
|
||||||
// MakeCustomizedResMap creates a fully customized ResMap
|
// MakeCustomizedResMap creates a fully customized ResMap
|
||||||
// per the instructions contained in its kustomization instance.
|
// per the instructions contained in its kustomiztion instance.
|
||||||
func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
|
func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
|
||||||
return kt.makeCustomizedResMap()
|
return kt.makeCustomizedResMap()
|
||||||
}
|
}
|
||||||
@@ -198,10 +209,6 @@ func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = kt.runValidators(ra)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = ra.MergeVars(kt.kustomization.Vars)
|
err = ra.MergeVars(kt.kustomization.Vars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
@@ -253,7 +260,7 @@ func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r = append(r, lts...)
|
r = append(r, lts...)
|
||||||
lts, err = kt.configureExternalTransformers(kt.kustomization.Transformers)
|
lts, err = kt.configureExternalTransformers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -262,54 +269,15 @@ func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
|||||||
return ra.Transform(t)
|
return ra.Transform(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]resmap.Transformer, error) {
|
func (kt *KustTarget) configureExternalTransformers() ([]resmap.Transformer, error) {
|
||||||
ra := accumulator.MakeEmptyAccumulator()
|
ra := accumulator.MakeEmptyAccumulator()
|
||||||
ra, err := kt.accumulateResources(ra, transformers)
|
ra, err := kt.accumulateResources(ra, kt.kustomization.Transformers)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return kt.pLdr.LoadTransformers(kt.ldr, kt.validator, ra.ResMap())
|
return kt.pLdr.LoadTransformers(kt.ldr, kt.validator, ra.ResMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) runValidators(ra *accumulator.ResAccumulator) error {
|
|
||||||
validators, err := kt.configureExternalTransformers(kt.kustomization.Validators)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, v := range validators {
|
|
||||||
// Validators shouldn't modify the resource map
|
|
||||||
orignal := ra.ResMap().DeepCopy()
|
|
||||||
err = v.Transform(ra.ResMap())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
new := ra.ResMap().DeepCopy()
|
|
||||||
kt.removeValidatedByLabel(new)
|
|
||||||
if err = orignal.ErrorIfNotEqualSets(new); err != nil {
|
|
||||||
return fmt.Errorf("validator shouldn't modify the resource map: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) {
|
|
||||||
|
|
||||||
resources := rm.Resources()
|
|
||||||
for _, r := range resources {
|
|
||||||
labels := r.GetLabels()
|
|
||||||
if _, found := labels[konfig.ValidatedByLabelKey]; !found {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
delete(labels, konfig.ValidatedByLabelKey)
|
|
||||||
if len(labels) == 0 {
|
|
||||||
r.SetLabels(nil)
|
|
||||||
} else {
|
|
||||||
r.SetLabels(labels)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// accumulateResources fills the given resourceAccumulator
|
// accumulateResources fills the given resourceAccumulator
|
||||||
// with resources read from the given list of paths.
|
// with resources read from the given list of paths.
|
||||||
func (kt *KustTarget) accumulateResources(
|
func (kt *KustTarget) accumulateResources(
|
||||||
|
|||||||
@@ -252,10 +252,6 @@ nameReference:
|
|||||||
kind: Role
|
kind: Role
|
||||||
- path: rules/resourceNames
|
- path: rules/resourceNames
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
|
||||||
kind: Service
|
|
||||||
group: serving.knative.dev
|
|
||||||
version: v1
|
|
||||||
|
|
||||||
- kind: Service
|
- kind: Service
|
||||||
version: v1
|
version: v1
|
||||||
|
|||||||
@@ -36,7 +36,4 @@ const (
|
|||||||
|
|
||||||
// An environment variable to turn on/off adding the ManagedByLabelKey
|
// An environment variable to turn on/off adding the ManagedByLabelKey
|
||||||
EnableManagedbyLabelEnv = "KUSTOMIZE_ENABLE_MANAGEDBY_LABEL"
|
EnableManagedbyLabelEnv = "KUSTOMIZE_ENABLE_MANAGEDBY_LABEL"
|
||||||
|
|
||||||
// Label key that indicates the resources are validated by a validator
|
|
||||||
ValidatedByLabelKey = "validated-by"
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -225,13 +225,13 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- env:
|
- env:
|
||||||
- name: foo
|
|
||||||
value: bar
|
|
||||||
- name: FOO
|
- name: FOO
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
key: somekey
|
key: somekey
|
||||||
name: test-infra-app-env-ffmd9b969m
|
name: test-infra-app-env-ffmd9b969m
|
||||||
|
- name: foo
|
||||||
|
value: bar
|
||||||
image: nginx:1.8.0
|
image: nginx:1.8.0
|
||||||
name: nginx
|
name: nginx
|
||||||
ports:
|
ports:
|
||||||
@@ -292,7 +292,8 @@ metadata:
|
|||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
nonsense: "Lorem ipsum dolor sit amet, consectetur\nadipiscing elit, sed do eiusmod tempor\nincididunt ut labore et dolore magna aliqua. \n"
|
nonsense: "Lorem ipsum dolor sit amet, consectetur\nadipiscing elit, sed do eiusmod
|
||||||
|
tempor\nincididunt ut labore et dolore magna aliqua. \n"
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
|||||||
@@ -132,54 +132,6 @@ spec:
|
|||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTinyOverlay(t *testing.T) {
|
|
||||||
th := kusttest_test.MakeHarness(t)
|
|
||||||
th.WriteK("base", `
|
|
||||||
namePrefix: a-
|
|
||||||
resources:
|
|
||||||
- deployment.yaml
|
|
||||||
`)
|
|
||||||
th.WriteF("base/deployment.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: myDeployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: whatever
|
|
||||||
`)
|
|
||||||
th.WriteK("overlay", `
|
|
||||||
namePrefix: b-
|
|
||||||
resources:
|
|
||||||
- ../base
|
|
||||||
patchesStrategicMerge:
|
|
||||||
- depPatch.yaml
|
|
||||||
`)
|
|
||||||
th.WriteF("overlay/depPatch.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: myDeployment
|
|
||||||
spec:
|
|
||||||
replicas: 999
|
|
||||||
`)
|
|
||||||
m := th.Run("overlay", th.MakeDefaultOptions())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: b-a-myDeployment
|
|
||||||
spec:
|
|
||||||
replicas: 999
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: whatever
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeSmallBase(th kusttest_test.Harness) {
|
func writeSmallBase(th kusttest_test.Harness) {
|
||||||
th.WriteK("/app/base", `
|
th.WriteK("/app/base", `
|
||||||
namePrefix: a-
|
namePrefix: a-
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ resources:
|
|||||||
configMapGenerator:
|
configMapGenerator:
|
||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
literals:
|
literals:
|
||||||
- testValue=1
|
- testValue=1
|
||||||
- otherValue=10
|
- otherValue=10
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/deploy.yaml", `
|
th.WriteF("/app/base/deploy.yaml", `
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@@ -59,13 +59,13 @@ replicas:
|
|||||||
- name: storefront
|
- name: storefront
|
||||||
count: 3
|
count: 3
|
||||||
resources:
|
resources:
|
||||||
- stub.yaml
|
- stub.yaml
|
||||||
configMapGenerator:
|
configMapGenerator:
|
||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
behavior: merge
|
behavior: merge
|
||||||
literals:
|
literals:
|
||||||
- testValue=2
|
- testValue=2
|
||||||
- compValue=5
|
- compValue=5
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/comp/stub.yaml", `
|
th.WriteF("/app/comp/stub.yaml", `
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@@ -156,7 +156,7 @@ configMapGenerator:
|
|||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
behavior: merge
|
behavior: merge
|
||||||
literals:
|
literals:
|
||||||
- otherValue=9
|
- otherValue=9
|
||||||
`),
|
`),
|
||||||
writeK("/app/prod", `
|
writeK("/app/prod", `
|
||||||
resources:
|
resources:
|
||||||
@@ -211,8 +211,8 @@ components:
|
|||||||
configMapGenerator:
|
configMapGenerator:
|
||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
behavior: merge
|
behavior: merge
|
||||||
literals:
|
literals:
|
||||||
- otherValue=9
|
- otherValue=9
|
||||||
`),
|
`),
|
||||||
writeK("/app/prod", `
|
writeK("/app/prod", `
|
||||||
resources:
|
resources:
|
||||||
@@ -327,8 +327,8 @@ configMapGenerator:
|
|||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
behavior: merge
|
behavior: merge
|
||||||
literals:
|
literals:
|
||||||
- compValue=5
|
- compValue=5
|
||||||
- testValue=2
|
- testValue=2
|
||||||
`),
|
`),
|
||||||
},
|
},
|
||||||
runPath: "/app/direct-component",
|
runPath: "/app/direct-component",
|
||||||
@@ -360,7 +360,7 @@ configMapGenerator:
|
|||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
behavior: merge
|
behavior: merge
|
||||||
literals:
|
literals:
|
||||||
- otherValue=9
|
- otherValue=9
|
||||||
`),
|
`),
|
||||||
},
|
},
|
||||||
runPath: "/app/prod",
|
runPath: "/app/prod",
|
||||||
@@ -574,7 +574,7 @@ configMapGenerator:
|
|||||||
- name: my-configmap
|
- name: my-configmap
|
||||||
behavior: merge
|
behavior: merge
|
||||||
literals:
|
literals:
|
||||||
- otherValue=9
|
- otherValue=9
|
||||||
`),
|
`),
|
||||||
},
|
},
|
||||||
runPath: "/app/prod",
|
runPath: "/app/prod",
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ metadata:
|
|||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
druid_segmentCache_locations: '[{"path": "var/druid/segment-cache", "maxSize": 32000000000, "freeSpacePercent": 1.0}]'
|
druid_segmentCache_locations: '[{"path": "var/druid/segment-cache", "maxSize":
|
||||||
|
32000000000, "freeSpacePercent": 1.0}]'
|
||||||
v2: '[{"path": "var/druid/segment-cache"}]'
|
v2: '[{"path": "var/druid/segment-cache"}]'
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ spec:
|
|||||||
location: SW
|
location: SW
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/animalPark.yaml", `
|
th.WriteF("/app/base/animalPark.yaml", `
|
||||||
apiVersion: foo
|
|
||||||
kind: AnimalPark
|
kind: AnimalPark
|
||||||
metadata:
|
metadata:
|
||||||
name: sandiego
|
name: sandiego
|
||||||
@@ -94,7 +93,6 @@ varReference:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: foo
|
|
||||||
kind: AnimalPark
|
kind: AnimalPark
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -163,7 +161,6 @@ varReference:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: foo
|
|
||||||
kind: AnimalPark
|
kind: AnimalPark
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -215,17 +212,14 @@ func TestFixedBug605_BaseCustomizationAvailableInOverlay(t *testing.T) {
|
|||||||
nameReference:
|
nameReference:
|
||||||
- kind: Gorilla
|
- kind: Gorilla
|
||||||
fieldSpecs:
|
fieldSpecs:
|
||||||
- apiVersion: foo
|
- kind: AnimalPark
|
||||||
kind: AnimalPark
|
|
||||||
path: spec/gorillaRef/name
|
path: spec/gorillaRef/name
|
||||||
- kind: Giraffe
|
- kind: Giraffe
|
||||||
fieldSpecs:
|
fieldSpecs:
|
||||||
- apiVersion: foo
|
- kind: AnimalPark
|
||||||
kind: AnimalPark
|
|
||||||
path: spec/giraffeRef/name
|
path: spec/giraffeRef/name
|
||||||
varReference:
|
varReference:
|
||||||
- path: spec/food
|
- path: spec/food
|
||||||
apiVersion: foo
|
|
||||||
kind: AnimalPark
|
kind: AnimalPark
|
||||||
`)
|
`)
|
||||||
th.WriteK("/app/overlay", `
|
th.WriteK("/app/overlay", `
|
||||||
@@ -248,7 +242,6 @@ spec:
|
|||||||
`)
|
`)
|
||||||
// The following replaces the gorillaRef in the AnimalPark.
|
// The following replaces the gorillaRef in the AnimalPark.
|
||||||
th.WriteF("/app/overlay/animalPark.yaml", `
|
th.WriteF("/app/overlay/animalPark.yaml", `
|
||||||
apiVersion: foo
|
|
||||||
kind: AnimalPark
|
kind: AnimalPark
|
||||||
metadata:
|
metadata:
|
||||||
name: sandiego
|
name: sandiego
|
||||||
@@ -258,7 +251,6 @@ spec:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/overlay", th.MakeDefaultOptions())
|
m := th.Run("/app/overlay", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: foo
|
|
||||||
kind: AnimalPark
|
kind: AnimalPark
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func makeCommonFileForExtendedPatchTest(th kusttest_test.Harness) {
|
func makeCommonFileForExtendedPatchTest(th kusttest_test.Harness) {
|
||||||
th.WriteF("/app/base/deployment.yaml", `
|
th.WriteF("/app/base/deployment.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -36,7 +36,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -101,7 +101,7 @@ patches:
|
|||||||
name: busybox
|
name: busybox
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -110,7 +110,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -135,7 +135,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -156,7 +156,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -202,7 +203,7 @@ patches:
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -211,7 +212,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -232,12 +233,13 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -258,7 +260,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -302,7 +305,7 @@ patches:
|
|||||||
labelSelector: app=nginx
|
labelSelector: app=nginx
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -311,7 +314,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -332,12 +335,13 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -404,7 +408,7 @@ patches:
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -413,7 +417,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -438,7 +442,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -459,7 +463,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -504,7 +509,7 @@ patches:
|
|||||||
labelSelector: app=busybox
|
labelSelector: app=busybox
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -513,7 +518,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -538,7 +543,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -559,7 +564,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -606,7 +612,7 @@ patches:
|
|||||||
labelSelector: app=busybox
|
labelSelector: app=busybox
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -615,7 +621,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -640,7 +646,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -661,7 +667,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -707,7 +714,7 @@ patches:
|
|||||||
labelSelector: app=busybox
|
labelSelector: app=busybox
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -716,7 +723,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -741,7 +748,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -762,7 +769,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -806,7 +814,7 @@ patches:
|
|||||||
name: no-match
|
name: no-match
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -815,7 +823,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -840,7 +848,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -902,7 +910,7 @@ patches:
|
|||||||
- path: patch.yaml
|
- path: patch.yaml
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -911,7 +919,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -936,7 +944,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -957,7 +965,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -1005,7 +1014,7 @@ patches:
|
|||||||
kind: Job
|
kind: Job
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch.yaml", `
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -1014,7 +1023,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -1039,7 +1048,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -1107,7 +1116,7 @@ patches:
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch1.yaml", `
|
th.WriteF("/app/base/patch1.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -1115,7 +1124,7 @@ metadata:
|
|||||||
new-key-from-patch1: new-value
|
new-key-from-patch1: new-value
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/patch2.yaml", `
|
th.WriteF("/app/base/patch2.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox
|
name: busybox
|
||||||
@@ -1124,7 +1133,7 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/base", th.MakeDefaultOptions())
|
m := th.Run("/app/base", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -1149,7 +1158,7 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -1171,7 +1180,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: busybox-persistent-storage
|
name: busybox-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: busybox-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
|
|||||||
@@ -1,466 +0,0 @@
|
|||||||
package krusty_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFnExecGenerator(t *testing.T) {
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
|
||||||
defer th.Reset()
|
|
||||||
|
|
||||||
th.WriteK("/app", `
|
|
||||||
resources:
|
|
||||||
- short_secret.yaml
|
|
||||||
generators:
|
|
||||||
- gener.yaml
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Create some additional resource just to make sure everything is added
|
|
||||||
th.WriteF("/app/short_secret.yaml", `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
airshipit.org/ephemeral-user-data: "true"
|
|
||||||
name: node1-bmc-secret
|
|
||||||
type: Opaque
|
|
||||||
stringData:
|
|
||||||
userData: |
|
|
||||||
bootcmd:
|
|
||||||
- mkdir /mnt/vda
|
|
||||||
`)
|
|
||||||
|
|
||||||
th.WriteF("/app/gener.yaml", `
|
|
||||||
kind: executable
|
|
||||||
metadata:
|
|
||||||
name: demo
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/function: |
|
|
||||||
exec:
|
|
||||||
path: ./fnplugin_test/fnexectest.sh
|
|
||||||
spec:
|
|
||||||
`)
|
|
||||||
o := th.MakeOptionsPluginsEnabled()
|
|
||||||
o.PluginConfig.FnpLoadingOptions.EnableExec = true
|
|
||||||
m := th.Run("/app", o)
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
airshipit.org/ephemeral-user-data: "true"
|
|
||||||
name: node1-bmc-secret
|
|
||||||
stringData:
|
|
||||||
userData: |
|
|
||||||
bootcmd:
|
|
||||||
- mkdir /mnt/vda
|
|
||||||
type: Opaque
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: deployment_nginx.yaml
|
|
||||||
tshirt-size: small
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
name: nginx
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: nginx
|
|
||||||
name: nginx
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func skipIfNoDocker(t *testing.T) {
|
|
||||||
if _, err := exec.LookPath("docker"); err != nil {
|
|
||||||
t.Skip("skipping because docker binary wasn't found in PATH")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFnContainerGenerator(t *testing.T) {
|
|
||||||
skipIfNoDocker(t)
|
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
|
||||||
defer th.Reset()
|
|
||||||
|
|
||||||
th.WriteK("/app", `
|
|
||||||
resources:
|
|
||||||
- short_secret.yaml
|
|
||||||
generators:
|
|
||||||
- gener.yaml
|
|
||||||
`)
|
|
||||||
// Create generator config
|
|
||||||
th.WriteF("/app/gener.yaml", `
|
|
||||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
|
||||||
kind: CockroachDB
|
|
||||||
metadata:
|
|
||||||
name: demo
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/function: |
|
|
||||||
container:
|
|
||||||
image: gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
`)
|
|
||||||
// Create some additional resource just to make sure everything is added
|
|
||||||
th.WriteF("/app/short_secret.yaml", `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
airshipit.org/ephemeral-user-data: "true"
|
|
||||||
name: node1-bmc-secret
|
|
||||||
type: Opaque
|
|
||||||
stringData:
|
|
||||||
userData: |
|
|
||||||
bootcmd:
|
|
||||||
- mkdir /mnt/vda
|
|
||||||
`)
|
|
||||||
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
airshipit.org/ephemeral-user-data: "true"
|
|
||||||
name: node1-bmc-secret
|
|
||||||
stringData:
|
|
||||||
userData: |
|
|
||||||
bootcmd:
|
|
||||||
- mkdir /mnt/vda
|
|
||||||
type: Opaque
|
|
||||||
---
|
|
||||||
apiVersion: policy/v1beta1
|
|
||||||
kind: PodDisruptionBudget
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo-budget_poddisruptionbudget.yaml
|
|
||||||
labels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
name: demo-budget
|
|
||||||
spec:
|
|
||||||
minAvailable: 67%
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo-public_service.yaml
|
|
||||||
labels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
name: demo-public
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: grpc
|
|
||||||
port: 26257
|
|
||||||
targetPort: 26257
|
|
||||||
- name: http
|
|
||||||
port: 8080
|
|
||||||
targetPort: 8080
|
|
||||||
selector:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo_service.yaml
|
|
||||||
prometheus.io/path: _status/vars
|
|
||||||
prometheus.io/port: "8080"
|
|
||||||
prometheus.io/scrape: "true"
|
|
||||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
|
||||||
labels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
name: demo
|
|
||||||
spec:
|
|
||||||
clusterIP: None
|
|
||||||
ports:
|
|
||||||
- name: grpc
|
|
||||||
port: 26257
|
|
||||||
targetPort: 26257
|
|
||||||
- name: http
|
|
||||||
port: 8080
|
|
||||||
targetPort: 8080
|
|
||||||
selector:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: StatefulSet
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo_statefulset.yaml
|
|
||||||
labels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
name: demo
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
serviceName: demo
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cockroachdb
|
|
||||||
name: demo
|
|
||||||
spec:
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
preferredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- podAffinityTerm:
|
|
||||||
labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- cockroachdb
|
|
||||||
topologyKey: kubernetes.io/hostname
|
|
||||||
weight: 100
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /bin/bash
|
|
||||||
- -ecx
|
|
||||||
- |
|
|
||||||
# The use of qualified `+"`hostname -f`"+` is crucial:
|
|
||||||
# Other nodes aren't able to look up the unqualified hostname.
|
|
||||||
CRARGS=("start" "--logtostderr" "--insecure" "--host" "$(hostname -f)" "--http-host" "0.0.0.0")
|
|
||||||
# We only want to initialize a new cluster (by omitting the join flag)
|
|
||||||
# if we're sure that we're the first node (i.e. index 0) and that
|
|
||||||
# there aren't any other nodes running as part of the cluster that
|
|
||||||
# this is supposed to be a part of (which indicates that a cluster
|
|
||||||
# already exists and we should make sure not to create a new one).
|
|
||||||
# It's fine to run without --join on a restart if there aren't any
|
|
||||||
# other nodes.
|
|
||||||
if [ ! "$(hostname)" == "cockroachdb-0" ] || [ -e "/cockroach/cockroach-data/cluster_exists_marker" ]
|
|
||||||
then
|
|
||||||
# We don't join cockroachdb in order to avoid a node attempting
|
|
||||||
# to join itself, which currently doesn't work
|
|
||||||
# (https://github.com/cockroachdb/cockroach/issues/9625).
|
|
||||||
CRARGS+=("--join" "cockroachdb-public")
|
|
||||||
fi
|
|
||||||
exec /cockroach/cockroach ${CRARGS[*]}
|
|
||||||
image: cockroachdb/cockroach:v1.1.0
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
name: demo
|
|
||||||
ports:
|
|
||||||
- containerPort: 26257
|
|
||||||
name: grpc
|
|
||||||
- containerPort: 8080
|
|
||||||
name: http
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /cockroach/cockroach-data
|
|
||||||
name: datadir
|
|
||||||
initContainers:
|
|
||||||
- args:
|
|
||||||
- -on-start=/on-start.sh
|
|
||||||
- -service=cockroachdb
|
|
||||||
env:
|
|
||||||
- name: POD_NAMESPACE
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.namespace
|
|
||||||
image: cockroachdb/cockroach-k8s-init:0.1
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
name: bootstrap
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /cockroach/cockroach-data
|
|
||||||
name: datadir
|
|
||||||
terminationGracePeriodSeconds: 60
|
|
||||||
volumes:
|
|
||||||
- name: datadir
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: datadir
|
|
||||||
volumeClaimTemplates:
|
|
||||||
- metadata:
|
|
||||||
name: datadir
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 1Gi
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFnContainerTransformer(t *testing.T) {
|
|
||||||
skipIfNoDocker(t)
|
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
|
||||||
defer th.Reset()
|
|
||||||
|
|
||||||
th.WriteK("/app", `
|
|
||||||
resources:
|
|
||||||
- data.yaml
|
|
||||||
transformers:
|
|
||||||
- transf1.yaml
|
|
||||||
- transf2.yaml
|
|
||||||
`)
|
|
||||||
|
|
||||||
th.WriteF("/app/data.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
annotations:
|
|
||||||
tshirt-size: small # this injects the resource reservations
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
`)
|
|
||||||
// This transformer should add resource reservations based on annotation in data.yaml
|
|
||||||
// See https://github.com/kubernetes-sigs/kustomize/tree/master/functions/examples/injection-tshirt-sizes
|
|
||||||
th.WriteF("/app/transf1.yaml", `
|
|
||||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
|
||||||
kind: Validator
|
|
||||||
metadata:
|
|
||||||
name: valid
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/function: |-
|
|
||||||
container:
|
|
||||||
image: gcr.io/kustomize-functions/example-tshirt:v0.2.0
|
|
||||||
`)
|
|
||||||
// This transformer will check resources without and won't do any changes
|
|
||||||
// See https://github.com/kubernetes-sigs/kustomize/tree/master/functions/examples/validator-kubeval
|
|
||||||
th.WriteF("/app/transf2.yaml", `
|
|
||||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
|
||||||
kind: Kubeval
|
|
||||||
metadata:
|
|
||||||
name: validate
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/function: |
|
|
||||||
container:
|
|
||||||
image: gcr.io/kustomize-functions/example-validator-kubeval:v0.1.0
|
|
||||||
spec:
|
|
||||||
strict: true
|
|
||||||
ignoreMissingSchemas: true
|
|
||||||
|
|
||||||
# TODO: Update this to use network/volumes features.
|
|
||||||
# Relevant issues:
|
|
||||||
# - https://github.com/kubernetes-sigs/kustomize/issues/1901
|
|
||||||
# - https://github.com/kubernetes-sigs/kustomize/issues/1902
|
|
||||||
kubernetesVersion: "1.16.0"
|
|
||||||
schemaLocation: "file:///schemas"
|
|
||||||
`)
|
|
||||||
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: deployment_nginx.yaml
|
|
||||||
tshirt-size: small
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
name: nginx
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: nginx
|
|
||||||
name: nginx
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 200m
|
|
||||||
memory: 50M
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFnContainerTransformerWithConfig(t *testing.T) {
|
|
||||||
skipIfNoDocker(t)
|
|
||||||
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t)
|
|
||||||
defer th.Reset()
|
|
||||||
|
|
||||||
th.WriteK("/app", `
|
|
||||||
resources:
|
|
||||||
- data1.yaml
|
|
||||||
- data2.yaml
|
|
||||||
transformers:
|
|
||||||
- label_namespace.yaml
|
|
||||||
`)
|
|
||||||
|
|
||||||
th.WriteF("/app/data1.yaml", `apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: my-namespace
|
|
||||||
`)
|
|
||||||
th.WriteF("/app/data2.yaml", `apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: another-namespace
|
|
||||||
`)
|
|
||||||
|
|
||||||
th.WriteF("/app/label_namespace.yaml", `apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: label_namespace
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/function: |-
|
|
||||||
container:
|
|
||||||
image: gcr.io/kpt-functions/label-namespace@sha256:4f030738d6d25a207641ca517916431517578bd0eb8d98a8bde04e3bb9315dcd
|
|
||||||
data:
|
|
||||||
label_name: my-ns-name
|
|
||||||
label_value: function-test
|
|
||||||
`)
|
|
||||||
|
|
||||||
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: namespace_my-namespace.yaml
|
|
||||||
labels:
|
|
||||||
my-ns-name: function-test
|
|
||||||
name: my-namespace
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: namespace_another-namespace.yaml
|
|
||||||
labels:
|
|
||||||
my-ns-name: function-test
|
|
||||||
name: another-namespace
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
annotations:
|
|
||||||
tshirt-size: small # this injects the resource reservations
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
EOF
|
|
||||||
@@ -56,7 +56,7 @@ spec:
|
|||||||
app: nginx
|
app: nginx
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/deployment.yaml", `
|
th.WriteF("/app/base/deployment.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -92,7 +92,7 @@ spec:
|
|||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: foo
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -150,6 +150,8 @@ spec:
|
|||||||
|
|
||||||
func makeBaseWithGenerators(th kusttest_test.Harness) {
|
func makeBaseWithGenerators(th kusttest_test.Harness) {
|
||||||
th.WriteK("/app", `
|
th.WriteK("/app", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
namePrefix: team-foo-
|
namePrefix: team-foo-
|
||||||
commonLabels:
|
commonLabels:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
@@ -171,7 +173,7 @@ secretGenerator:
|
|||||||
- password=somepw
|
- password=somepw
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/deployment.yaml", `
|
th.WriteF("/app/deployment.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -216,7 +218,7 @@ func TestBaseWithGeneratorsAlone(t *testing.T) {
|
|||||||
makeBaseWithGenerators(th)
|
makeBaseWithGenerators(th)
|
||||||
m := th.Run("/app", th.MakeDefaultOptions())
|
m := th.Run("/app", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -306,7 +308,7 @@ func TestMergeAndReplaceGenerators(t *testing.T) {
|
|||||||
th := kusttest_test.MakeHarness(t)
|
th := kusttest_test.MakeHarness(t)
|
||||||
makeBaseWithGenerators(th)
|
makeBaseWithGenerators(th)
|
||||||
th.WriteF("/overlay/deployment.yaml", `
|
th.WriteF("/overlay/deployment.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -323,6 +325,8 @@ spec:
|
|||||||
name: configmap-in-overlay
|
name: configmap-in-overlay
|
||||||
`)
|
`)
|
||||||
th.WriteK("/overlay", `
|
th.WriteK("/overlay", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
namePrefix: staging-
|
namePrefix: staging-
|
||||||
commonLabels:
|
commonLabels:
|
||||||
env: staging
|
env: staging
|
||||||
@@ -347,7 +351,7 @@ secretGenerator:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/overlay", th.MakeDefaultOptions())
|
m := th.Run("/overlay", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -385,12 +389,12 @@ spec:
|
|||||||
- gcePersistentDisk:
|
- gcePersistentDisk:
|
||||||
pdName: nginx-persistent-storage
|
pdName: nginx-persistent-storage
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
|
||||||
name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
|
||||||
name: configmap-in-base
|
|
||||||
- configMap:
|
- configMap:
|
||||||
name: staging-configmap-in-overlay-k7cbc75tg8
|
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||||
name: configmap-in-overlay
|
name: configmap-in-overlay
|
||||||
|
- configMap:
|
||||||
|
name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||||
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -222,7 +223,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
package krusty_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestKeepEmptyArray(t *testing.T) {
|
|
||||||
th := kusttest_test.MakeHarness(t)
|
|
||||||
th.WriteF("/app/resources.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: testing123
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector: null
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: event
|
|
||||||
image: testing123
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
imagePullSecrets: []`)
|
|
||||||
|
|
||||||
th.WriteK("/app", `
|
|
||||||
resources:
|
|
||||||
- resources.yaml`)
|
|
||||||
|
|
||||||
m := th.Run("/app", th.MakeDefaultOptions())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: testing123
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector: null
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: testing123
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
name: event
|
|
||||||
imagePullSecrets: []
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
@@ -10,186 +10,10 @@ import (
|
|||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSimpleMultiplePatches(t *testing.T) {
|
|
||||||
th := kusttest_test.MakeHarness(t)
|
|
||||||
th.WriteK("base", `
|
|
||||||
namePrefix: b-
|
|
||||||
commonLabels:
|
|
||||||
team: foo
|
|
||||||
resources:
|
|
||||||
- deployment.yaml
|
|
||||||
- service.yaml
|
|
||||||
configMapGenerator:
|
|
||||||
- name: configmap-in-base
|
|
||||||
literals:
|
|
||||||
- foo=bar
|
|
||||||
`)
|
|
||||||
th.WriteF("base/deployment.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
volumeMounts:
|
|
||||||
- name: nginx-persistent-storage
|
|
||||||
mountPath: /tmp/ps
|
|
||||||
- name: sidecar
|
|
||||||
image: sidecar:latest
|
|
||||||
volumes:
|
|
||||||
- name: nginx-persistent-storage
|
|
||||||
emptyDir: {}
|
|
||||||
- configMap:
|
|
||||||
name: configmap-in-base
|
|
||||||
name: configmap-in-base
|
|
||||||
`)
|
|
||||||
th.WriteF("base/service.yaml", `
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
`)
|
|
||||||
th.WriteK("overlay", `
|
|
||||||
namePrefix: a-
|
|
||||||
commonLabels:
|
|
||||||
env: staging
|
|
||||||
patchesStrategicMerge:
|
|
||||||
- deployment-patch1.yaml
|
|
||||||
- deployment-patch2.yaml
|
|
||||||
resources:
|
|
||||||
- ../base
|
|
||||||
configMapGenerator:
|
|
||||||
- name: configmap-in-overlay
|
|
||||||
literals:
|
|
||||||
- hello=world
|
|
||||||
`)
|
|
||||||
th.WriteF("overlay/deployment-patch1.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:latest
|
|
||||||
env:
|
|
||||||
- name: ENVKEY
|
|
||||||
value: ENVVALUE
|
|
||||||
volumes:
|
|
||||||
- name: nginx-persistent-storage
|
|
||||||
emptyDir: null
|
|
||||||
gcePersistentDisk:
|
|
||||||
pdName: nginx-persistent-storage
|
|
||||||
- configMap:
|
|
||||||
name: configmap-in-overlay
|
|
||||||
name: configmap-in-overlay
|
|
||||||
`)
|
|
||||||
th.WriteF("overlay/deployment-patch2.yaml", `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
env:
|
|
||||||
- name: ANOTHERENV
|
|
||||||
value: FOO
|
|
||||||
volumes:
|
|
||||||
- name: nginx-persistent-storage
|
|
||||||
`)
|
|
||||||
m := th.Run("overlay", th.MakeDefaultOptions())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
env: staging
|
|
||||||
team: foo
|
|
||||||
name: a-b-nginx
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
env: staging
|
|
||||||
team: foo
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
env: staging
|
|
||||||
team: foo
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: ANOTHERENV
|
|
||||||
value: FOO
|
|
||||||
- name: ENVKEY
|
|
||||||
value: ENVVALUE
|
|
||||||
image: nginx:latest
|
|
||||||
name: nginx
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /tmp/ps
|
|
||||||
name: nginx-persistent-storage
|
|
||||||
- image: sidecar:latest
|
|
||||||
name: sidecar
|
|
||||||
volumes:
|
|
||||||
- gcePersistentDisk:
|
|
||||||
pdName: nginx-persistent-storage
|
|
||||||
name: nginx-persistent-storage
|
|
||||||
- configMap:
|
|
||||||
name: a-b-configmap-in-base-fm96mhk4dt
|
|
||||||
name: configmap-in-base
|
|
||||||
- configMap:
|
|
||||||
name: a-configmap-in-overlay-ffm9hf78mc
|
|
||||||
name: configmap-in-overlay
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
env: staging
|
|
||||||
team: foo
|
|
||||||
name: a-b-nginx
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
selector:
|
|
||||||
env: staging
|
|
||||||
team: foo
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
data:
|
|
||||||
foo: bar
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
env: staging
|
|
||||||
team: foo
|
|
||||||
name: a-b-configmap-in-base-fm96mhk4dt
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
data:
|
|
||||||
hello: world
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
env: staging
|
|
||||||
name: a-configmap-in-overlay-ffm9hf78mc
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeCommonFileForMultiplePatchTest(th kusttest_test.Harness) {
|
func makeCommonFileForMultiplePatchTest(th kusttest_test.Harness) {
|
||||||
th.WriteK("/app/base", `
|
th.WriteK("/app/base", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
namePrefix: team-foo-
|
namePrefix: team-foo-
|
||||||
commonLabels:
|
commonLabels:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
@@ -206,7 +30,7 @@ configMapGenerator:
|
|||||||
- foo=bar
|
- foo=bar
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/base/deployment.yaml", `
|
th.WriteF("/app/base/deployment.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -247,6 +71,8 @@ spec:
|
|||||||
app: nginx
|
app: nginx
|
||||||
`)
|
`)
|
||||||
th.WriteK("/app/overlay/staging", `
|
th.WriteK("/app/overlay/staging", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
namePrefix: staging-
|
namePrefix: staging-
|
||||||
commonLabels:
|
commonLabels:
|
||||||
env: staging
|
env: staging
|
||||||
@@ -266,7 +92,7 @@ func TestMultiplePatchesNoConflict(t *testing.T) {
|
|||||||
th := kusttest_test.MakeHarness(t)
|
th := kusttest_test.MakeHarness(t)
|
||||||
makeCommonFileForMultiplePatchTest(th)
|
makeCommonFileForMultiplePatchTest(th)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -289,7 +115,7 @@ spec:
|
|||||||
name: configmap-in-overlay
|
name: configmap-in-overlay
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -306,7 +132,7 @@ spec:
|
|||||||
`)
|
`)
|
||||||
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
|
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `
|
th.AssertActualEqualsExpected(m, `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -351,12 +177,12 @@ spec:
|
|||||||
- gcePersistentDisk:
|
- gcePersistentDisk:
|
||||||
pdName: nginx-persistent-storage
|
pdName: nginx-persistent-storage
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
|
||||||
name: staging-team-foo-configmap-in-base-g7k6gt2889
|
|
||||||
name: configmap-in-base
|
|
||||||
- configMap:
|
- configMap:
|
||||||
name: staging-configmap-in-overlay-k7cbc75tg8
|
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||||
name: configmap-in-overlay
|
name: configmap-in-overlay
|
||||||
|
- configMap:
|
||||||
|
name: staging-team-foo-configmap-in-base-g7k6gt2889
|
||||||
|
name: configmap-in-base
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
@@ -407,7 +233,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) {
|
|||||||
th := kusttest_test.MakeHarness(t)
|
th := kusttest_test.MakeHarness(t)
|
||||||
makeCommonFileForMultiplePatchTest(th)
|
makeCommonFileForMultiplePatchTest(th)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -429,7 +255,7 @@ spec:
|
|||||||
name: configmap-in-overlay
|
name: configmap-in-overlay
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -453,7 +279,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiplePatchesWithOnePatchDeleteDirective(t *testing.T) {
|
func TestMultiplePatchesWithOnePatchDeleteDirective(t *testing.T) {
|
||||||
additivePatch := `apiVersion: apps/v1
|
additivePatch := `apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -466,7 +292,7 @@ spec:
|
|||||||
- name: SOME_NAME
|
- name: SOME_NAME
|
||||||
value: somevalue
|
value: somevalue
|
||||||
`
|
`
|
||||||
deletePatch := `apiVersion: apps/v1
|
deletePatch := `apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -502,7 +328,7 @@ spec:
|
|||||||
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", c.patch1)
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", c.patch1)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", c.patch2)
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", c.patch2)
|
||||||
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
|
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
|
||||||
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
|
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -540,7 +366,8 @@ spec:
|
|||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: staging-team-foo-configmap-in-base-g7k6gt2889
|
name: staging-team-foo-configmap-in-base-g7k6gt2889
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
@@ -596,7 +423,7 @@ func TestMultiplePatchesBothWithPatchDeleteDirective(t *testing.T) {
|
|||||||
th := kusttest_test.MakeHarness(t)
|
th := kusttest_test.MakeHarness(t)
|
||||||
makeCommonFileForMultiplePatchTest(th)
|
makeCommonFileForMultiplePatchTest(th)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -608,7 +435,7 @@ spec:
|
|||||||
name: sidecar
|
name: sidecar
|
||||||
`)
|
`)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
|
|||||||
@@ -10,6 +10,24 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func writeDeployment(th *kusttest_test.HarnessEnhanced, path string) {
|
||||||
|
th.WriteF(path, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
backend: awesome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: whatever
|
||||||
|
image: whatever
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func writeStringPrefixer(th *kusttest_test.HarnessEnhanced, path, name string) {
|
func writeStringPrefixer(th *kusttest_test.HarnessEnhanced, path, name string) {
|
||||||
th.WriteF(path, `
|
th.WriteF(path, `
|
||||||
apiVersion: someteam.example.com/v1
|
apiVersion: someteam.example.com/v1
|
||||||
@@ -19,6 +37,53 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeDatePrefixer(th *kusttest_test.HarnessEnhanced, path, name string) {
|
||||||
|
th.WriteF(path, `
|
||||||
|
apiVersion: someteam.example.com/v1
|
||||||
|
kind: DatePrefixer
|
||||||
|
metadata:
|
||||||
|
name: `+name+`
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderedTransformers(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t).
|
||||||
|
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
|
||||||
|
BuildGoPlugin("someteam.example.com", "v1", "DatePrefixer")
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
transformers:
|
||||||
|
- peachPrefixer.yaml
|
||||||
|
- date1Prefixer.yaml
|
||||||
|
- applePrefixer.yaml
|
||||||
|
- date2Prefixer.yaml
|
||||||
|
`)
|
||||||
|
writeDeployment(th, "/app/deployment.yaml")
|
||||||
|
writeStringPrefixer(th, "/app/applePrefixer.yaml", "apple")
|
||||||
|
writeStringPrefixer(th, "/app/peachPrefixer.yaml", "peach")
|
||||||
|
writeDatePrefixer(th, "/app/date1Prefixer.yaml", "date1")
|
||||||
|
writeDatePrefixer(th, "/app/date2Prefixer.yaml", "date2")
|
||||||
|
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: 2018-05-11-apple-2018-05-11-peach-myDeployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
backend: awesome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: whatever
|
||||||
|
name: whatever
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPluginsNotEnabled(t *testing.T) {
|
func TestPluginsNotEnabled(t *testing.T) {
|
||||||
th := kusttest_test.MakeEnhancedHarness(t).
|
th := kusttest_test.MakeEnhancedHarness(t).
|
||||||
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer")
|
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer")
|
||||||
@@ -100,78 +165,6 @@ metadata:
|
|||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
The tests below are disabled until the StringPrefixer and DatePrefixer
|
|
||||||
can be rewritten using kyaml, instead of depending on the
|
|
||||||
PrefixSuffixTransformerPlugin. That dependency is causing
|
|
||||||
failures in the test loader.
|
|
||||||
|
|
||||||
func writeDeployment(th *kusttest_test.HarnessEnhanced, path string) {
|
|
||||||
th.WriteF(path, `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: myDeployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
backend: awesome
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: whatever
|
|
||||||
image: whatever
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeDatePrefixer(th *kusttest_test.HarnessEnhanced, path, name string) {
|
|
||||||
th.WriteF(path, `
|
|
||||||
apiVersion: someteam.example.com/v1
|
|
||||||
kind: DatePrefixer
|
|
||||||
metadata:
|
|
||||||
name: `+name+`
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOrderedTransformers(t *testing.T) {
|
|
||||||
th := kusttest_test.MakeEnhancedHarness(t).
|
|
||||||
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
|
|
||||||
BuildGoPlugin("someteam.example.com", "v1", "DatePrefixer")
|
|
||||||
defer th.Reset()
|
|
||||||
|
|
||||||
th.WriteK("/app", `
|
|
||||||
resources:
|
|
||||||
- deployment.yaml
|
|
||||||
transformers:
|
|
||||||
- peachPrefixer.yaml
|
|
||||||
- date1Prefixer.yaml
|
|
||||||
- applePrefixer.yaml
|
|
||||||
- date2Prefixer.yaml
|
|
||||||
`)
|
|
||||||
writeDeployment(th, "/app/deployment.yaml")
|
|
||||||
writeStringPrefixer(th, "/app/applePrefixer.yaml", "apple")
|
|
||||||
writeStringPrefixer(th, "/app/peachPrefixer.yaml", "peach")
|
|
||||||
writeDatePrefixer(th, "/app/date1Prefixer.yaml", "date1")
|
|
||||||
writeDatePrefixer(th, "/app/date2Prefixer.yaml", "date2")
|
|
||||||
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
|
|
||||||
th.AssertActualEqualsExpected(m, `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: 2018-05-11-apple-2018-05-11-peach-myDeployment
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
backend: awesome
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: whatever
|
|
||||||
name: whatever
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTransformedTransformers(t *testing.T) {
|
func TestTransformedTransformers(t *testing.T) {
|
||||||
th := kusttest_test.MakeEnhancedHarness(t).
|
th := kusttest_test.MakeEnhancedHarness(t).
|
||||||
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
|
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
|
||||||
@@ -212,4 +205,3 @@ spec:
|
|||||||
name: whatever
|
name: whatever
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
@@ -844,7 +844,8 @@ spec:
|
|||||||
- -namespace=${POD_NAMESPACE}
|
- -namespace=${POD_NAMESPACE}
|
||||||
- -certs-dir=/cockroach-certs
|
- -certs-dir=/cockroach-certs
|
||||||
- -type=node
|
- -type=node
|
||||||
- -addresses=localhost,127.0.0.1,${POD_IP},$(hostname -f),$(hostname -f|cut -f 1-2 -d '.'),dev-base-cockroachdb-public
|
- -addresses=localhost,127.0.0.1,${POD_IP},$(hostname -f),$(hostname -f|cut
|
||||||
|
-f 1-2 -d '.'),dev-base-cockroachdb-public
|
||||||
- -symlink-ca-from=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
- -symlink-ca-from=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
env:
|
env:
|
||||||
- name: POD_IP
|
- name: POD_IP
|
||||||
|
|||||||
@@ -69,10 +69,10 @@ func (rf *Factory) makeOne(
|
|||||||
o = types.NewGenArgs(nil)
|
o = types.NewGenArgs(nil)
|
||||||
}
|
}
|
||||||
r := &Resource{
|
r := &Resource{
|
||||||
kunStr: u,
|
Kunstructured: u,
|
||||||
options: o,
|
options: o,
|
||||||
}
|
}
|
||||||
return r.setOriginalName(r.kunStr.GetName()).setOriginalNs(r.GetNamespace())
|
return r.setOriginalName(r.GetName()).setOriginalNs(r.GetNamespace())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SliceFromPatches returns a slice of resources given a patch path
|
// SliceFromPatches returns a slice of resources given a patch path
|
||||||
|
|||||||
@@ -13,178 +13,6 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSliceFromBytes(t *testing.T) {
|
|
||||||
type testCase struct {
|
|
||||||
input string
|
|
||||||
expected []string
|
|
||||||
}
|
|
||||||
testCases := map[string]testCase{
|
|
||||||
"empty1": {
|
|
||||||
input: "",
|
|
||||||
expected: []string{},
|
|
||||||
},
|
|
||||||
"empty2": {
|
|
||||||
input: `
|
|
||||||
---
|
|
||||||
---
|
|
||||||
`,
|
|
||||||
expected: []string{},
|
|
||||||
},
|
|
||||||
"deployment1": {
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: pooh
|
|
||||||
---
|
|
||||||
`,
|
|
||||||
expected: []string{
|
|
||||||
`apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: pooh
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"deployment2": {
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
baseAnno: This is a base annotation
|
|
||||||
labels:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
name: baseprefix-mungebot
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
foo: bar
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
baseAnno: This is a base annotation
|
|
||||||
labels:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: foo
|
|
||||||
value: bar
|
|
||||||
image: nginx
|
|
||||||
name: nginx
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
baseAnno: This is a base annotation
|
|
||||||
labels:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
name: baseprefix-mungebot-service
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 7002
|
|
||||||
selector:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
`,
|
|
||||||
expected: []string{
|
|
||||||
`apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
baseAnno: This is a base annotation
|
|
||||||
labels:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
name: baseprefix-mungebot
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
foo: bar
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
baseAnno: This is a base annotation
|
|
||||||
labels:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: foo
|
|
||||||
value: bar
|
|
||||||
image: nginx
|
|
||||||
name: nginx
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
`,
|
|
||||||
`apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
baseAnno: This is a base annotation
|
|
||||||
labels:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
name: baseprefix-mungebot-service
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 7002
|
|
||||||
selector:
|
|
||||||
app: mungebot
|
|
||||||
foo: bar
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name := range testCases {
|
|
||||||
tc := testCases[name]
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
result, err := factory.SliceFromBytes([]byte(tc.input))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("%v: fails with err: %v", name, err)
|
|
||||||
}
|
|
||||||
if len(result) != len(tc.expected) {
|
|
||||||
for i := range result {
|
|
||||||
bytes, err := result[i].AsYAML()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("%v: result to YAML fails with err: %v", name, err)
|
|
||||||
}
|
|
||||||
tmp := string(bytes)
|
|
||||||
t.Logf("--- %d:\n%s", i, tmp)
|
|
||||||
}
|
|
||||||
t.Fatalf(
|
|
||||||
"%v: actual len %d != expected len %d",
|
|
||||||
name, len(result), len(tc.expected))
|
|
||||||
}
|
|
||||||
for i := range tc.expected {
|
|
||||||
bytes, err := result[i].AsYAML()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("%v: result to YAML fails with err: %v", name, err)
|
|
||||||
}
|
|
||||||
tmp := string(bytes)
|
|
||||||
if tmp != tc.expected[i] {
|
|
||||||
t.Fatalf(
|
|
||||||
"%v: string mismatch in item %d\n"+
|
|
||||||
"actual:\n-----\n%s\n-----\n"+
|
|
||||||
"expected:\n-----\n%s\n-----\n",
|
|
||||||
name, i, tmp, tc.expected[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSliceFromPatches(t *testing.T) {
|
func TestSliceFromPatches(t *testing.T) {
|
||||||
patchGood1 := types.PatchStrategicMerge("patch1.yaml")
|
patchGood1 := types.PatchStrategicMerge("patch1.yaml")
|
||||||
patch1 := `
|
patch1 := `
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package resource implements representations of k8s API resources.
|
// Package resource implements representations of k8s API resources as "unstructured" objects.
|
||||||
package resource
|
package resource
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -14,57 +14,10 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Resource is a representation of a Kubernetes Resource Model object paired
|
// Resource is map representation of a Kubernetes API resource object
|
||||||
// with metadata used by kustomize.
|
// paired with a GenerationBehavior.
|
||||||
//
|
|
||||||
// At time of writing Resource is changing from being based on an object
|
|
||||||
// sitting behind
|
|
||||||
//
|
|
||||||
// sigs.k8s.io/kustomize/api/ifc.Unstructured
|
|
||||||
//
|
|
||||||
// to being based on an instance of
|
|
||||||
//
|
|
||||||
// sigs.k8s.io/kustomize/kyaml/yaml.RNode
|
|
||||||
//
|
|
||||||
// Ultimately, use of the Resource struct in kustomize should be entirely
|
|
||||||
// replaced by instances of RNode for direct use in kyaml, with all metadata
|
|
||||||
// stored directly in the RNodes as short-lived annotations, to be deleted
|
|
||||||
// before final output as part of a final filtration step. Using annotations
|
|
||||||
// will allow pipelined KRM Config Functions to share metadata that would
|
|
||||||
// otherwise be hidden in kustomize-only structures.
|
|
||||||
//
|
|
||||||
// ifc.Unstructured is an interface hiding an instance of
|
|
||||||
// sigs.k8s.io/kustomize/api/k8sdeps/kunstruct.UnstructAdapter
|
|
||||||
// which in turn adapts an instance of
|
|
||||||
// k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
|
|
||||||
// to the ifc.Unstructured interface. This latter code handles
|
|
||||||
// mutations in the old code.
|
|
||||||
//
|
|
||||||
// The rule in kustomize development has been
|
|
||||||
// api/
|
|
||||||
// k8sdeps/ ifc/ krusty/ theRest/
|
|
||||||
//
|
|
||||||
// 1) Depend on k8s.io/ only via sigs.k8s.io/kustomize/api/k8sdeps.
|
|
||||||
//
|
|
||||||
// 2) Instances created in k8sdeps/ can only be injected into theRest/
|
|
||||||
// behind interfaces defined in ifc/, arranged by a small bit of code
|
|
||||||
// in krusty/. Nothing in theRest/ can import k8sdeps/.
|
|
||||||
//
|
|
||||||
// This was to allow for importing kustomize code into kubectl, which also
|
|
||||||
// depends on k8s.io/apimachinery, albeit via a strange, old arrangement
|
|
||||||
// predating Go modules. The idea was to copy the k8sdeps/ tree into kubectl
|
|
||||||
// via a large PR, and depend on the rest via vendoring (and a small copy of
|
|
||||||
// krusty/ code). Over 2019, however, kubectl underwent large code changes
|
|
||||||
// including a switch to Go modules, and an attempt to extract it from the
|
|
||||||
// k8s repo, and this made large kustomize integration PRs hard to get through
|
|
||||||
// code review.
|
|
||||||
//
|
|
||||||
// The new plan is to eliminate k8sdeps/ entirely, along with its k8s.io/
|
|
||||||
// dependence, switch to kyaml, and thus allow kustomize to be imported into
|
|
||||||
// kubectl via normal Go module imports.
|
|
||||||
//
|
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
kunStr ifc.Kunstructured
|
ifc.Kunstructured
|
||||||
originalName string
|
originalName string
|
||||||
originalNs string
|
originalNs string
|
||||||
options *types.GenArgs
|
options *types.GenArgs
|
||||||
@@ -74,118 +27,6 @@ type Resource struct {
|
|||||||
nameSuffixes []string
|
nameSuffixes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) ResetPrimaryData(incoming *Resource) {
|
|
||||||
r.kunStr = incoming.kunStr.Copy()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetAnnotations() map[string]string {
|
|
||||||
return r.kunStr.GetAnnotations()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) Copy() ifc.Kunstructured {
|
|
||||||
return r.kunStr.Copy()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetBool(p string) (bool, error) {
|
|
||||||
return r.kunStr.GetBool(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetFieldValue(f string) (interface{}, error) {
|
|
||||||
return r.kunStr.GetFieldValue(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetFloat64(p string) (float64, error) {
|
|
||||||
return r.kunStr.GetFloat64(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetGvk() resid.Gvk {
|
|
||||||
return r.kunStr.GetGvk()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetInt64(p string) (int64, error) {
|
|
||||||
return r.kunStr.GetInt64(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetKind() string {
|
|
||||||
return r.kunStr.GetKind()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetLabels() map[string]string {
|
|
||||||
return r.kunStr.GetLabels()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetMap(p string) (map[string]interface{}, error) {
|
|
||||||
return r.kunStr.GetMap(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetName() string {
|
|
||||||
return r.kunStr.GetName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetSlice(p string) ([]interface{}, error) {
|
|
||||||
return r.kunStr.GetSlice(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetString(p string) (string, error) {
|
|
||||||
return r.kunStr.GetString(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetStringMap(p string) (map[string]string, error) {
|
|
||||||
return r.kunStr.GetStringMap(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) GetStringSlice(p string) ([]string, error) {
|
|
||||||
return r.kunStr.GetStringSlice(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) Map() map[string]interface{} {
|
|
||||||
return r.kunStr.Map()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) MarshalJSON() ([]byte, error) {
|
|
||||||
return r.kunStr.MarshalJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) MatchesLabelSelector(selector string) (bool, error) {
|
|
||||||
return r.kunStr.MatchesLabelSelector(selector)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) MatchesAnnotationSelector(selector string) (bool, error) {
|
|
||||||
return r.kunStr.MatchesAnnotationSelector(selector)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) Patch(other ifc.Kunstructured) error {
|
|
||||||
return r.kunStr.Patch(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) SetAnnotations(m map[string]string) {
|
|
||||||
r.kunStr.SetAnnotations(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) SetGvk(gvk resid.Gvk) {
|
|
||||||
r.kunStr.SetGvk(gvk)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) SetLabels(m map[string]string) {
|
|
||||||
r.kunStr.SetLabels(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) SetMap(m map[string]interface{}) {
|
|
||||||
r.kunStr.SetMap(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) SetName(n string) {
|
|
||||||
r.kunStr.SetName(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) SetNamespace(n string) {
|
|
||||||
r.kunStr.SetNamespace(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resource) UnmarshalJSON(s []byte) error {
|
|
||||||
return r.kunStr.UnmarshalJSON(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResCtx is an interface describing the contextual added
|
// ResCtx is an interface describing the contextual added
|
||||||
// kept kustomize in the context of each Resource object.
|
// kept kustomize in the context of each Resource object.
|
||||||
// Currently mainly the name prefix and name suffix are added.
|
// Currently mainly the name prefix and name suffix are added.
|
||||||
@@ -205,7 +46,7 @@ type ResCtxMatcher func(ResCtx) bool
|
|||||||
// DeepCopy returns a new copy of resource
|
// DeepCopy returns a new copy of resource
|
||||||
func (r *Resource) DeepCopy() *Resource {
|
func (r *Resource) DeepCopy() *Resource {
|
||||||
rc := &Resource{
|
rc := &Resource{
|
||||||
kunStr: r.kunStr.Copy(),
|
Kunstructured: r.Kunstructured.Copy(),
|
||||||
}
|
}
|
||||||
rc.copyOtherFields(r)
|
rc.copyOtherFields(r)
|
||||||
return rc
|
return rc
|
||||||
@@ -213,11 +54,11 @@ func (r *Resource) DeepCopy() *Resource {
|
|||||||
|
|
||||||
// Replace performs replace with other resource.
|
// Replace performs replace with other resource.
|
||||||
func (r *Resource) Replace(other *Resource) {
|
func (r *Resource) Replace(other *Resource) {
|
||||||
r.kunStr.SetLabels(mergeStringMaps(other.kunStr.GetLabels(), r.kunStr.GetLabels()))
|
r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels()))
|
||||||
r.kunStr.SetAnnotations(
|
r.SetAnnotations(
|
||||||
mergeStringMaps(other.kunStr.GetAnnotations(), r.kunStr.GetAnnotations()))
|
mergeStringMaps(other.GetAnnotations(), r.GetAnnotations()))
|
||||||
r.kunStr.SetName(other.GetName())
|
r.SetName(other.GetName())
|
||||||
r.kunStr.SetNamespace(other.GetNamespace())
|
r.SetNamespace(other.GetNamespace())
|
||||||
r.copyOtherFields(other)
|
r.copyOtherFields(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +74,7 @@ func (r *Resource) copyOtherFields(other *Resource) {
|
|||||||
|
|
||||||
func (r *Resource) Equals(o *Resource) bool {
|
func (r *Resource) Equals(o *Resource) bool {
|
||||||
return r.ReferencesEqual(o) &&
|
return r.ReferencesEqual(o) &&
|
||||||
reflect.DeepEqual(r.kunStr, o.kunStr)
|
reflect.DeepEqual(r.Kunstructured, o.Kunstructured)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) ReferencesEqual(o *Resource) bool {
|
func (r *Resource) ReferencesEqual(o *Resource) bool {
|
||||||
@@ -252,13 +93,13 @@ func (r *Resource) ReferencesEqual(o *Resource) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) KunstructEqual(o *Resource) bool {
|
func (r *Resource) KunstructEqual(o *Resource) bool {
|
||||||
return reflect.DeepEqual(r.kunStr, o.kunStr)
|
return reflect.DeepEqual(r.Kunstructured, o.Kunstructured)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge performs merge with other resource.
|
// Merge performs merge with other resource.
|
||||||
func (r *Resource) Merge(other *Resource) {
|
func (r *Resource) Merge(other *Resource) {
|
||||||
r.Replace(other)
|
r.Replace(other)
|
||||||
mergeConfigmap(r.kunStr.Map(), other.Map(), r.Map())
|
mergeConfigmap(r.Map(), other.Map(), r.Map())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) copyRefBy() []resid.ResId {
|
func (r *Resource) copyRefBy() []resid.ResId {
|
||||||
@@ -384,7 +225,7 @@ func (r *Resource) setOriginalNs(n string) *Resource {
|
|||||||
|
|
||||||
// String returns resource as JSON.
|
// String returns resource as JSON.
|
||||||
func (r *Resource) String() string {
|
func (r *Resource) String() string {
|
||||||
bs, err := r.kunStr.MarshalJSON()
|
bs, err := r.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "<" + err.Error() + ">"
|
return "<" + err.Error() + ">"
|
||||||
}
|
}
|
||||||
@@ -394,7 +235,7 @@ func (r *Resource) String() string {
|
|||||||
// AsYAML returns the resource in Yaml form.
|
// AsYAML returns the resource in Yaml form.
|
||||||
// Easier to read than JSON.
|
// Easier to read than JSON.
|
||||||
func (r *Resource) AsYAML() ([]byte, error) {
|
func (r *Resource) AsYAML() ([]byte, error) {
|
||||||
json, err := r.kunStr.MarshalJSON()
|
json, err := r.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -419,7 +260,7 @@ func (r *Resource) NeedHashSuffix() bool {
|
|||||||
|
|
||||||
// GetNamespace returns the namespace the resource thinks it's in.
|
// GetNamespace returns the namespace the resource thinks it's in.
|
||||||
func (r *Resource) GetNamespace() string {
|
func (r *Resource) GetNamespace() string {
|
||||||
namespace, _ := r.kunStr.GetString("metadata.namespace")
|
namespace, _ := r.GetString("metadata.namespace")
|
||||||
// if err, namespace is empty, so no need to check.
|
// if err, namespace is empty, so no need to check.
|
||||||
return namespace
|
return namespace
|
||||||
}
|
}
|
||||||
@@ -429,7 +270,7 @@ func (r *Resource) GetNamespace() string {
|
|||||||
// TODO: compute this once and save it in the resource.
|
// TODO: compute this once and save it in the resource.
|
||||||
func (r *Resource) OrgId() resid.ResId {
|
func (r *Resource) OrgId() resid.ResId {
|
||||||
return resid.NewResIdWithNamespace(
|
return resid.NewResIdWithNamespace(
|
||||||
r.kunStr.GetGvk(), r.GetOriginalName(), r.GetOriginalNs())
|
r.GetGvk(), r.GetOriginalName(), r.GetOriginalNs())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurId returns a ResId for the resource using the
|
// CurId returns a ResId for the resource using the
|
||||||
@@ -437,7 +278,7 @@ func (r *Resource) OrgId() resid.ResId {
|
|||||||
// This should be unique in any ResMap.
|
// This should be unique in any ResMap.
|
||||||
func (r *Resource) CurId() resid.ResId {
|
func (r *Resource) CurId() resid.ResId {
|
||||||
return resid.NewResIdWithNamespace(
|
return resid.NewResIdWithNamespace(
|
||||||
r.kunStr.GetGvk(), r.kunStr.GetName(), r.GetNamespace())
|
r.GetGvk(), r.GetName(), r.GetNamespace())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRefBy returns the ResIds that referred to current resource
|
// GetRefBy returns the ResIds that referred to current resource
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
package kusttest_test
|
package kusttest_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
@@ -17,6 +20,8 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HarnessEnhanced manages a full plugin environment for tests.
|
// HarnessEnhanced manages a full plugin environment for tests.
|
||||||
@@ -125,8 +130,42 @@ func (th *HarnessEnhanced) LoadAndRunTransformer(
|
|||||||
|
|
||||||
func (th *HarnessEnhanced) RunTransformerAndCheckResult(
|
func (th *HarnessEnhanced) RunTransformerAndCheckResult(
|
||||||
config, input, expected string) {
|
config, input, expected string) {
|
||||||
resMap := th.LoadAndRunTransformer(config, input)
|
for _, b := range []bool{true, false} {
|
||||||
th.AssertActualEqualsExpected(resMap, expected)
|
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(
|
func (th *HarnessEnhanced) ErrorFromLoadAndRunTransformer(
|
||||||
@@ -139,8 +178,16 @@ type AssertFunc func(t *testing.T, err error)
|
|||||||
|
|
||||||
func (th *HarnessEnhanced) RunTransformerAndCheckError(
|
func (th *HarnessEnhanced) RunTransformerAndCheckError(
|
||||||
config, input string, assertFn AssertFunc) {
|
config, input string, assertFn AssertFunc) {
|
||||||
_, err := th.RunTransformer(config, input)
|
for _, b := range []bool{true, false} {
|
||||||
assertFn(th.t, err)
|
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(
|
func (th *HarnessEnhanced) RunTransformer(
|
||||||
@@ -156,7 +203,6 @@ func (th *HarnessEnhanced) RunTransformerFromResMap(
|
|||||||
config string, resMap resmap.ResMap) (resmap.ResMap, error) {
|
config string, resMap resmap.ResMap) (resmap.ResMap, error) {
|
||||||
transConfig, err := th.rf.RF().FromBytes([]byte(config))
|
transConfig, err := th.rf.RF().FromBytes([]byte(config))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
th.t.Logf("config: '%s'", config)
|
|
||||||
th.t.Fatalf("Err: %v", err)
|
th.t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
g, err := th.pl.LoadTransformer(
|
g, err := th.pl.LoadTransformer(
|
||||||
|
|||||||
@@ -3,13 +3,6 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KustomizationVersion = "kustomize.config.k8s.io/v1beta1"
|
KustomizationVersion = "kustomize.config.k8s.io/v1beta1"
|
||||||
KustomizationKind = "Kustomization"
|
KustomizationKind = "Kustomization"
|
||||||
@@ -131,9 +124,6 @@ type Kustomization struct {
|
|||||||
// Transformers is a list of files containing transformers
|
// Transformers is a list of files containing transformers
|
||||||
Transformers []string `json:"transformers,omitempty" yaml:"transformers,omitempty"`
|
Transformers []string `json:"transformers,omitempty" yaml:"transformers,omitempty"`
|
||||||
|
|
||||||
// Validators is a list of files containing validators
|
|
||||||
Validators []string `json:"validators,omitempty" yaml:"validators,omitempty"`
|
|
||||||
|
|
||||||
// Inventory appends an object that contains the record
|
// Inventory appends an object that contains the record
|
||||||
// of all other objects, which can be used in apply, prune and delete
|
// of all other objects, which can be used in apply, prune and delete
|
||||||
Inventory *Inventory `json:"inventory,omitempty" yaml:"inventory,omitempty"`
|
Inventory *Inventory `json:"inventory,omitempty" yaml:"inventory,omitempty"`
|
||||||
@@ -172,20 +162,3 @@ func (k *Kustomization) EnforceFields() []string {
|
|||||||
}
|
}
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal replace k with the content in YAML input y
|
|
||||||
func (k *Kustomization) Unmarshal(y []byte) error {
|
|
||||||
j, err := yaml.YAMLToJSON(y)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dec := json.NewDecoder(bytes.NewReader(j))
|
|
||||||
dec.DisallowUnknownFields()
|
|
||||||
var nk Kustomization
|
|
||||||
err = dec.Decode(&nk)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*k = nk
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,184 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fixKustomizationPostUnmarshallingCheck(k, e *Kustomization) bool {
|
|
||||||
return (k.Kind == e.Kind && k.APIVersion == e.APIVersion &&
|
|
||||||
len(k.Resources) == len(e.Resources) && k.Resources[0] == e.Resources[0] &&
|
|
||||||
k.Bases == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFixKustomizationPostUnmarshalling(t *testing.T) {
|
|
||||||
var k Kustomization
|
|
||||||
k.Bases = append(k.Bases, "foo")
|
|
||||||
k.FixKustomizationPostUnmarshalling()
|
|
||||||
|
|
||||||
expected := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: KustomizationKind,
|
|
||||||
APIVersion: KustomizationVersion,
|
|
||||||
},
|
|
||||||
Resources: []string{"foo"},
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fixKustomizationPostUnmarshallingCheck(&k, &expected) {
|
|
||||||
t.Fatalf("unexpected output: %v", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFixKustomizationPostUnmarshalling_2(t *testing.T) {
|
|
||||||
k := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: ComponentKind,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
k.Bases = append(k.Bases, "foo")
|
|
||||||
k.FixKustomizationPostUnmarshalling()
|
|
||||||
|
|
||||||
expected := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: ComponentKind,
|
|
||||||
APIVersion: ComponentVersion,
|
|
||||||
},
|
|
||||||
Resources: []string{"foo"},
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fixKustomizationPostUnmarshallingCheck(&k, &expected) {
|
|
||||||
t.Fatalf("unexpected output: %v", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnforceFields_InvalidKindAndVersion(t *testing.T) {
|
|
||||||
k := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: "foo",
|
|
||||||
APIVersion: "bar",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := k.EnforceFields()
|
|
||||||
if len(errs) != 2 {
|
|
||||||
t.Fatalf("number of errors should be 2 but got: %v", errs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnforceFields_InvalidKind(t *testing.T) {
|
|
||||||
k := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: "foo",
|
|
||||||
APIVersion: KustomizationVersion,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := k.EnforceFields()
|
|
||||||
if len(errs) != 1 {
|
|
||||||
t.Fatalf("number of errors should be 1 but got: %v", errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := "kind should be " + KustomizationKind + " or " + ComponentKind
|
|
||||||
if errs[0] != expected {
|
|
||||||
t.Fatalf("error should be %v but got: %v", expected, errs[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnforceFields_InvalidVersion(t *testing.T) {
|
|
||||||
k := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: KustomizationKind,
|
|
||||||
APIVersion: "bar",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := k.EnforceFields()
|
|
||||||
if len(errs) != 1 {
|
|
||||||
t.Fatalf("number of errors should be 1 but got: %v", errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := "apiVersion for " + k.Kind + " should be " + KustomizationVersion
|
|
||||||
if errs[0] != expected {
|
|
||||||
t.Fatalf("error should be %v but got: %v", expected, errs[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnforceFields_ComponentKind(t *testing.T) {
|
|
||||||
k := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: ComponentKind,
|
|
||||||
APIVersion: "bar",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := k.EnforceFields()
|
|
||||||
if len(errs) != 1 {
|
|
||||||
t.Fatalf("number of errors should be 1 but got: %v", errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := "apiVersion for " + k.Kind + " should be " + ComponentVersion
|
|
||||||
if errs[0] != expected {
|
|
||||||
t.Fatalf("error should be %v but got: %v", expected, errs[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnforceFields(t *testing.T) {
|
|
||||||
k := Kustomization{
|
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
Kind: KustomizationKind,
|
|
||||||
APIVersion: KustomizationVersion,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := k.EnforceFields()
|
|
||||||
if len(errs) != 0 {
|
|
||||||
t.Fatalf("number of errors should be 0 but got: %v", errs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshal(t *testing.T) {
|
|
||||||
y := []byte(`
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
resources:
|
|
||||||
- foo
|
|
||||||
- bar
|
|
||||||
nameSuffix: dog
|
|
||||||
namePrefix: cat`)
|
|
||||||
var k Kustomization
|
|
||||||
err := k.Unmarshal(y)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if k.Kind != KustomizationKind || k.APIVersion != KustomizationVersion ||
|
|
||||||
len(k.Resources) != 2 || k.NamePrefix != "cat" || k.NameSuffix != "dog" {
|
|
||||||
t.Fatalf("wrong unmarshal result: %v", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshal_UnkownField(t *testing.T) {
|
|
||||||
y := []byte(`
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
unknown: foo`)
|
|
||||||
var k Kustomization
|
|
||||||
err := k.Unmarshal(y)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("expect an error")
|
|
||||||
}
|
|
||||||
expect := "json: unknown field \"unknown\""
|
|
||||||
if err.Error() != expect {
|
|
||||||
t.Fatalf("expect %v but got: %v", expect, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshal_InvalidYaml(t *testing.T) {
|
|
||||||
y := []byte(`
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
unknown`)
|
|
||||||
var k Kustomization
|
|
||||||
err := k.Unmarshal(y)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("expect an error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -29,7 +29,4 @@ type PluginConfig struct {
|
|||||||
|
|
||||||
// BpLoadingOptions distinguishes builtin plugin behaviors.
|
// BpLoadingOptions distinguishes builtin plugin behaviors.
|
||||||
BpLoadingOptions BuiltinPluginLoadingOptions
|
BpLoadingOptions BuiltinPluginLoadingOptions
|
||||||
|
|
||||||
// FnpLoadingOptions sets the way function-based plugin behaviors.
|
|
||||||
FnpLoadingOptions FnPluginLoadingOptions
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,16 +41,3 @@ const (
|
|||||||
// to generate static code.
|
// to generate static code.
|
||||||
BploLoadFromFileSys
|
BploLoadFromFileSys
|
||||||
)
|
)
|
||||||
|
|
||||||
// FnPluginLoadingOptions set way functions-based pluing are restricted
|
|
||||||
type FnPluginLoadingOptions struct {
|
|
||||||
// Allow to run executables
|
|
||||||
EnableExec bool
|
|
||||||
// Allow to run starlark
|
|
||||||
EnableStar bool
|
|
||||||
// Allow container access to network
|
|
||||||
Network bool
|
|
||||||
NetworkName string
|
|
||||||
// list of mounts
|
|
||||||
Mounts []string
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ var (
|
|||||||
Count = commands.CountCommand
|
Count = commands.CountCommand
|
||||||
CreateSetter = commands.CreateSetterCommand
|
CreateSetter = commands.CreateSetterCommand
|
||||||
CreateSubstitution = commands.CreateSubstitutionCommand
|
CreateSubstitution = commands.CreateSubstitutionCommand
|
||||||
DeleteSetter = commands.DeleteSetterCommand
|
|
||||||
Fmt = commands.FmtCommand
|
Fmt = commands.FmtCommand
|
||||||
Grep = commands.GrepCommand
|
Grep = commands.GrepCommand
|
||||||
Init = commands.InitCommand
|
Init = commands.InitCommand
|
||||||
|
|||||||
@@ -116,14 +116,14 @@ metadata:
|
|||||||
name: my-instance
|
name: my-instance
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/local-config: "true"
|
config.kubernetes.io/local-config: "true"
|
||||||
config.kubernetes.io/function: |
|
config.k8s.io/function: |
|
||||||
container:
|
container:
|
||||||
image: gcr.io/example-functions/nginx-template:v1.0.0
|
image: gcr.io/example-functions/nginx-template:v1.0.0
|
||||||
spec:
|
spec:
|
||||||
replicas: 5
|
replicas: 5
|
||||||
```
|
```
|
||||||
|
|
||||||
- `annotations[config.kubernetes.io/function].container.image`: the image to use for this API
|
- `annotations[config.k8s.io/function].container.image`: the image to use for this API
|
||||||
- `annotations[config.kubernetes.io/local-config]`: mark this as not a Resource that should
|
- `annotations[config.kubernetes.io/local-config]`: mark this as not a Resource that should
|
||||||
be applied
|
be applied
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ containers that can be chained together as part of a configuration management pi
|
|||||||
The end result of such a pipeline are fully rendered configurations that can then be
|
The end result of such a pipeline are fully rendered configurations that can then be
|
||||||
applied to a control plane (e.g. Using ‘kubectl apply’ for Kubernetes control plane).
|
applied to a control plane (e.g. Using ‘kubectl apply’ for Kubernetes control plane).
|
||||||
As such, although this document references Kubernetes Resource Model and API conventions,
|
As such, although this document references Kubernetes Resource Model and API conventions,
|
||||||
it is completely decoupled from Kubernetes API machinery and does not depend on any
|
it is completely decoupled from Kuberentes API machinery and does not depend on any
|
||||||
in-cluster components.
|
in-cluster components.
|
||||||
|
|
||||||
This document references terms described in [Kubernetes API Conventions][1].
|
This document references terms described in [Kubernetes API Conventions][1].
|
||||||
@@ -33,7 +33,7 @@ _Configuration functions_ enable shift-left practices (client-side) through:
|
|||||||
Performing these on the client rather than the server enables:
|
Performing these on the client rather than the server enables:
|
||||||
|
|
||||||
- Configuration to be reviewed prior to being sent to the API server
|
- Configuration to be reviewed prior to being sent to the API server
|
||||||
- Configuration to be validated as part of the CI/CD pipeline
|
- Configuration to be validated as part of the CI?CD pipeline
|
||||||
- Configuration for Resources to validated holistically rather than individually
|
- Configuration for Resources to validated holistically rather than individually
|
||||||
per-Resource
|
per-Resource
|
||||||
- e.g. ensure the `Service.selector` and `Deployment.spec.template` labels
|
- e.g. ensure the `Service.selector` and `Deployment.spec.template` labels
|
||||||
@@ -114,7 +114,7 @@ functionConfig:
|
|||||||
name: staging
|
name: staging
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/function: |
|
config.k8s.io/function: |
|
||||||
container:
|
container:
|
||||||
image: gcr.io/example/foo:v1.0.0
|
image: gcr.io/example/foo:v1.0.0
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
## delete-setter
|
|
||||||
|
|
||||||
[Alpha] Delete a custom setter for a Resource field
|
|
||||||
|
|
||||||
### Synopsis
|
|
||||||
|
|
||||||
Delete a custom setter for a Resource field.
|
|
||||||
|
|
||||||
DIR
|
|
||||||
|
|
||||||
A directory containing Resource configuration.
|
|
||||||
|
|
||||||
NAME
|
|
||||||
|
|
||||||
The name of the setter to create.
|
|
||||||
|
|
||||||
### Deleting a Custom Setter
|
|
||||||
|
|
||||||
**Given the YAML:**
|
|
||||||
|
|
||||||
# resource.yaml
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
...
|
|
||||||
spec:
|
|
||||||
...
|
|
||||||
ports:
|
|
||||||
...
|
|
||||||
- name: http
|
|
||||||
port: 8080 # {"type":"integer","x-kustomize":{"partialFieldSetters":[{"name":"http-port","value":"8080"}]}}
|
|
||||||
...
|
|
||||||
|
|
||||||
**Delete setter:**
|
|
||||||
|
|
||||||
# delete a setter for ports
|
|
||||||
$ kustomize cfg set create DIR/ http-port
|
|
||||||
|
|
||||||
comment will be removed for this field is not settable any more.
|
|
||||||
|
|
||||||
**Newly modified YAML:**
|
|
||||||
|
|
||||||
# resource.yaml
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
...
|
|
||||||
spec:
|
|
||||||
...
|
|
||||||
ports:
|
|
||||||
...
|
|
||||||
- name: http
|
|
||||||
port: 8080
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
### Deleting a setter used in substitution
|
|
||||||
|
|
||||||
If the setter is also used in substitution, it will ask you to delete the substitution first.
|
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
# delete a setter for port
|
|
||||||
kustomize cfg create-setter DIR/ port
|
|
||||||
@@ -14,8 +14,6 @@ require (
|
|||||||
k8s.io/cli-runtime v0.17.3
|
k8s.io/cli-runtime v0.17.3
|
||||||
k8s.io/client-go v0.17.3
|
k8s.io/client-go v0.17.3
|
||||||
k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd
|
k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd
|
||||||
sigs.k8s.io/cli-utils v0.16.0
|
sigs.k8s.io/cli-utils v0.12.0
|
||||||
sigs.k8s.io/kustomize/kyaml v0.4.1
|
sigs.k8s.io/kustomize/kyaml v0.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace sigs.k8s.io/kustomize/kyaml => ../../kyaml
|
|
||||||
|
|||||||
@@ -550,10 +550,9 @@ gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
|||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
|
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -616,12 +615,16 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
|||||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||||
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
||||||
sigs.k8s.io/cli-utils v0.16.0 h1:Wr32m1oxjIqc9G9l+igr13PeIM9LCyq8jQ8KjXKelvg=
|
sigs.k8s.io/cli-utils v0.12.0 h1:+CvYwQAEtKvcx/NaUVF9rDKvY91VwJj+i7D2lWBMYc0=
|
||||||
sigs.k8s.io/cli-utils v0.16.0/go.mod h1:9Jqm9K2W6ShhCxsEuaz6HSRKKOXigPUx3ZfypGgxBLY=
|
sigs.k8s.io/cli-utils v0.12.0/go.mod h1:H35YA5iJIM7EVNgqDTjX2dgt4wE23zmnXOTSTlyD+PE=
|
||||||
sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
|
sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
|
||||||
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
|
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.1.4 h1:cDG2u7v6CTAZmWKzCjk0hKG7AIN+2mCHx2ifwPbvKrs=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.1.4/go.mod h1:461i94nj0h0ylJ6w83jLkR4SqqVhn1iY6fjD0JSTQeE=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.3.0 h1:Q0xajrIrKlt2tljTB3It2fnL9HXa7AfF3dxU6a01+vg=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.3.0/go.mod h1:LjuK+fiy63C7cz/6I0OqxIth8nZzytzzDOgpjBHCtG8=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
|
||||||
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
|
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
|
||||||
@@ -630,6 +633,4 @@ sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH
|
|||||||
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
|
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
|
||||||
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=
|
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ func NewCreateSetterRunner(parent string) *CreateSetterRunner {
|
|||||||
set.Flags().MarkHidden("partial")
|
set.Flags().MarkHidden("partial")
|
||||||
set.Flags().StringVar(&setterVersion, "version", "",
|
set.Flags().StringVar(&setterVersion, "version", "",
|
||||||
"use this version of the setter format")
|
"use this version of the setter format")
|
||||||
set.Flags().BoolVar(&r.CreateSetter.Required, "required", false,
|
|
||||||
"indicates that this setter must be set by package consumer before live apply/preview")
|
|
||||||
set.Flags().StringVar(&r.CreateSetter.SchemaPath, "schema-path", "",
|
set.Flags().StringVar(&r.CreateSetter.SchemaPath, "schema-path", "",
|
||||||
`openAPI schema file path for setter constraints -- file content `+
|
`openAPI schema file path for setter constraints -- file content `+
|
||||||
`e.g. {"type": "string", "maxLength": 15, "enum": ["allowedValue1", "allowedValue2"]}`)
|
`e.g. {"type": "string", "maxLength": 15, "enum": ["allowedValue1", "allowedValue2"]}`)
|
||||||
|
|||||||
@@ -65,44 +65,6 @@ spec:
|
|||||||
replicas: 3 # {"$openapi":"replicas"}
|
replicas: 3 # {"$openapi":"replicas"}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
name: "add replicas no match",
|
|
||||||
args: []string{"replicas", "3", "--description", "hello world", "--set-by", "me"},
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
foo: 2
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.replicas:
|
|
||||||
description: hello world
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: replicas
|
|
||||||
value: "3"
|
|
||||||
setBy: me
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
foo: 2
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "error if substitution with same name exists",
|
name: "error if substitution with same name exists",
|
||||||
args: []string{"my-image", "3", "--description", "hello world", "--set-by", "me"},
|
args: []string{"my-image", "3", "--description", "hello world", "--set-by", "me"},
|
||||||
@@ -186,21 +148,6 @@ spec:
|
|||||||
- "a"
|
- "a"
|
||||||
- "b"
|
- "b"
|
||||||
- "c"
|
- "c"
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
namespace: myspace
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: sidecar
|
|
||||||
image: nginx:1.7.9
|
|
||||||
- name: nginx
|
|
||||||
image: otherspace/nginx:1.7.9
|
|
||||||
`,
|
`,
|
||||||
inputOpenAPI: `
|
inputOpenAPI: `
|
||||||
apiVersion: v1alpha1
|
apiVersion: v1alpha1
|
||||||
@@ -243,21 +190,6 @@ spec:
|
|||||||
- "a"
|
- "a"
|
||||||
- "b"
|
- "b"
|
||||||
- "c"
|
- "c"
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
namespace: myspace
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: sidecar
|
|
||||||
image: nginx:1.7.9
|
|
||||||
- name: nginx
|
|
||||||
image: otherspace/nginx:1.7.9
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -372,41 +304,6 @@ metadata:
|
|||||||
name: nginx-deployment
|
name: nginx-deployment
|
||||||
spec:
|
spec:
|
||||||
replicas: 3 # {"$openapi":"replicas"}
|
replicas: 3 # {"$openapi":"replicas"}
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "add setter with . in the name",
|
|
||||||
args: []string{"foo.bar", "3"},
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.foo.bar:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: foo.bar
|
|
||||||
value: "3"
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3 # {"$openapi":"foo.bar"}
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,17 +86,14 @@ func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
|
|||||||
|
|
||||||
// extract setter name tokens from pattern enclosed in ${}
|
// extract setter name tokens from pattern enclosed in ${}
|
||||||
re := regexp.MustCompile(`\$\{([^}]*)\}`)
|
re := regexp.MustCompile(`\$\{([^}]*)\}`)
|
||||||
markers := re.FindAllString(r.CreateSubstitution.Pattern, -1)
|
markers := re.FindAll([]byte(r.CreateSubstitution.Pattern), -1)
|
||||||
if len(markers) == 0 {
|
if len(markers) == 0 {
|
||||||
return errors.Errorf("unable to find setter or substitution names in pattern, " +
|
return errors.Errorf("unable to find setter or substitution names in pattern, " +
|
||||||
"setter names must be enclosed in ${}")
|
"setter names must be enclosed in ${}")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, marker := range markers {
|
for _, marker := range markers {
|
||||||
name := strings.TrimSuffix(strings.TrimPrefix(marker, "${"), "}")
|
name := strings.TrimSuffix(strings.TrimPrefix(string(marker), "${"), "}")
|
||||||
if name == r.CreateSubstitution.Name {
|
|
||||||
return fmt.Errorf("setters must have different name than the substitution: %s", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
ref, err := spec.NewRef(fieldmeta.DefinitionsPrefix + fieldmeta.SubstitutionDefinitionPrefix + name)
|
ref, err := spec.NewRef(fieldmeta.DefinitionsPrefix + fieldmeta.SubstitutionDefinitionPrefix + name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -115,7 +112,7 @@ func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
|
|||||||
|
|
||||||
r.CreateSubstitution.Values = append(
|
r.CreateSubstitution.Values = append(
|
||||||
r.CreateSubstitution.Values,
|
r.CreateSubstitution.Values,
|
||||||
setters2.Value{Marker: marker, Ref: markerRef},
|
setters2.Value{Marker: string(marker), Ref: markerRef},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -408,39 +408,6 @@ spec:
|
|||||||
`,
|
`,
|
||||||
err: "cyclic substitution detected with name my-nested-subst",
|
err: "cyclic substitution detected with name my-nested-subst",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "substitution with non-existing setter with same name",
|
|
||||||
args: []string{
|
|
||||||
"foo", "--field-value", "prefix-1234", "--pattern", "prefix-${foo}"},
|
|
||||||
input: `
|
|
||||||
apiVersion: test/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
name: foo
|
|
||||||
spec:
|
|
||||||
setterVal: 1234
|
|
||||||
substVal: prefix-1234
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: test/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
name: foo
|
|
||||||
spec:
|
|
||||||
setterVal: 1234
|
|
||||||
substVal: prefix-1234
|
|
||||||
|
|
||||||
`,
|
|
||||||
err: "setters must have different name than the substitution: foo",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for i := range tests {
|
for i := range tests {
|
||||||
test := tests[i]
|
test := tests[i]
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDeleteRunner returns a command runner.
|
|
||||||
func NewDeleteSetterRunner(parent string) *DeleteSetterRunner {
|
|
||||||
r := &DeleteSetterRunner{}
|
|
||||||
c := &cobra.Command{
|
|
||||||
Use: "delete-setter DIR NAME",
|
|
||||||
Args: cobra.MinimumNArgs(2),
|
|
||||||
Short: commands.DeleteSetterShort,
|
|
||||||
Long: commands.DeleteSetterLong,
|
|
||||||
Example: commands.DeleteSetterExamples,
|
|
||||||
PreRunE: r.preRunE,
|
|
||||||
RunE: r.runE,
|
|
||||||
}
|
|
||||||
fixDocs(parent, c)
|
|
||||||
r.Command = c
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteSetterCommand(parent string) *cobra.Command {
|
|
||||||
return NewDeleteSetterRunner(parent).Command
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteSetterRunner struct {
|
|
||||||
Command *cobra.Command
|
|
||||||
DeleteSetter settersutil.DeleterCreator
|
|
||||||
OpenAPIFile string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DeleteSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
|
||||||
var err error
|
|
||||||
r.DeleteSetter.Name = args[1]
|
|
||||||
|
|
||||||
r.OpenAPIFile, err = ext.GetOpenAPIFile(args)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := openapi.AddSchemaFromFile(r.OpenAPIFile); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DeleteSetterRunner) runE(c *cobra.Command, args []string) error {
|
|
||||||
return handleError(c, r.delete(c, args))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DeleteSetterRunner) delete(c *cobra.Command, args []string) error {
|
|
||||||
return r.DeleteSetter.Delete(r.OpenAPIFile, args[0])
|
|
||||||
}
|
|
||||||
@@ -1,302 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package commands_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDeleteSetterCommand(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
name string
|
|
||||||
input string
|
|
||||||
args []string
|
|
||||||
schema string
|
|
||||||
out string
|
|
||||||
inputOpenAPI string
|
|
||||||
expectedOpenAPI string
|
|
||||||
expectedResources string
|
|
||||||
err string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "delete replicas",
|
|
||||||
args: []string{"replicas", "hello world"},
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3 # {"$openapi" : "replicas"}}
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.replicas:
|
|
||||||
description: hello world
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: replicas
|
|
||||||
value: "3"
|
|
||||||
setBy: me
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "delete only one setter",
|
|
||||||
args: []string{"replicas", "hello world"},
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3 # {"$openapi" : "replicas"}}
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.replicas:
|
|
||||||
description: hello world
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: replicas
|
|
||||||
value: "3"
|
|
||||||
setBy: me
|
|
||||||
io.k8s.cli.setters.image:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: image
|
|
||||||
value: 1.0
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.image:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: image
|
|
||||||
value: 1.0
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "delete non exist setter error",
|
|
||||||
args: []string{"image", "hello world"},
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3 # {"$openapi" : "replicas"}}
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.replicas:
|
|
||||||
description: hello world
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: replicas
|
|
||||||
value: "3"
|
|
||||||
setBy: me
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
apiVersion: v1alpha1
|
|
||||||
kind: Example
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.replicas:
|
|
||||||
description: hello world
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: replicas
|
|
||||||
value: "3"
|
|
||||||
setBy: me
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3 # {"$openapi" : "replicas"}}
|
|
||||||
`,
|
|
||||||
err: `setter does not exist`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "delete setter used in substitution error",
|
|
||||||
args: []string{"image-name", "hello world"},
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
`,
|
|
||||||
inputOpenAPI: `
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.image-name:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: image-name
|
|
||||||
value: "nginx"
|
|
||||||
io.k8s.cli.setters.image-tag:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: image-tag
|
|
||||||
value: "1.8.1"
|
|
||||||
io.k8s.cli.substitutions.image:
|
|
||||||
x-k8s-cli:
|
|
||||||
substitution:
|
|
||||||
name: image
|
|
||||||
pattern: IMAGE_NAME:IMAGE_TAG
|
|
||||||
values:
|
|
||||||
- marker: "IMAGE_NAME"
|
|
||||||
ref: "#/definitions/io.k8s.cli.setters.image-name"
|
|
||||||
- marker: "IMAGE_TAG"
|
|
||||||
ref: "#/definitions/io.k8s.cli.setters.image-tag"
|
|
||||||
`,
|
|
||||||
expectedOpenAPI: `
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.image-name:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: image-name
|
|
||||||
value: "nginx"
|
|
||||||
io.k8s.cli.setters.image-tag:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: image-tag
|
|
||||||
value: "1.8.1"
|
|
||||||
io.k8s.cli.substitutions.image:
|
|
||||||
x-k8s-cli:
|
|
||||||
substitution:
|
|
||||||
name: image
|
|
||||||
pattern: IMAGE_NAME:IMAGE_TAG
|
|
||||||
values:
|
|
||||||
- marker: "IMAGE_NAME"
|
|
||||||
ref: "#/definitions/io.k8s.cli.setters.image-name"
|
|
||||||
- marker: "IMAGE_TAG"
|
|
||||||
ref: "#/definitions/io.k8s.cli.setters.image-tag"
|
|
||||||
`,
|
|
||||||
expectedResources: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
`,
|
|
||||||
err: `setter is used in substitution image, please delete the substitution first`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for i := range tests {
|
|
||||||
test := tests[i]
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
// reset the openAPI afterward
|
|
||||||
openapi.ResetOpenAPI()
|
|
||||||
defer openapi.ResetOpenAPI()
|
|
||||||
|
|
||||||
f, err := ioutil.TempFile("", "k8s-cli-")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
defer os.Remove(f.Name())
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(f.Name(), []byte(test.inputOpenAPI), 0600)
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
old := ext.GetOpenAPIFile
|
|
||||||
defer func() { ext.GetOpenAPIFile = old }()
|
|
||||||
ext.GetOpenAPIFile = func(args []string) (s string, err error) {
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := ioutil.TempFile("", "k8s-cli-*.yaml")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
defer os.Remove(r.Name())
|
|
||||||
err = ioutil.WriteFile(r.Name(), []byte(test.input), 0600)
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
runner := commands.NewDeleteSetterRunner("")
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
runner.Command.SetOut(out)
|
|
||||||
runner.Command.SetArgs(append([]string{r.Name()}, test.args...))
|
|
||||||
err = runner.Command.Execute()
|
|
||||||
if test.err != "" {
|
|
||||||
if !assert.NotNil(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
} else {
|
|
||||||
assert.Equal(t, err.Error(), test.err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !assert.Equal(t, test.out, out.String()) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
actualResources, err := ioutil.ReadFile(r.Name())
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t,
|
|
||||||
strings.TrimSpace(test.expectedResources),
|
|
||||||
strings.TrimSpace(string(actualResources))) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
actualOpenAPI, err := ioutil.ReadFile(f.Name())
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t,
|
|
||||||
strings.TrimSpace(test.expectedOpenAPI),
|
|
||||||
strings.TrimSpace(string(actualOpenAPI))) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -32,8 +32,6 @@ func NewListSettersRunner(parent string) *ListSettersRunner {
|
|||||||
}
|
}
|
||||||
c.Flags().BoolVar(&r.Markdown, "markdown", false,
|
c.Flags().BoolVar(&r.Markdown, "markdown", false,
|
||||||
"output as github markdown")
|
"output as github markdown")
|
||||||
c.Flags().BoolVar(&r.IncludeSubst, "include-subst", false,
|
|
||||||
"include substitutions in the output")
|
|
||||||
fixDocs(parent, c)
|
fixDocs(parent, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
return r
|
return r
|
||||||
@@ -44,11 +42,10 @@ func ListSettersCommand(parent string) *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListSettersRunner struct {
|
type ListSettersRunner struct {
|
||||||
Command *cobra.Command
|
Command *cobra.Command
|
||||||
Lookup setters.LookupSetters
|
Lookup setters.LookupSetters
|
||||||
List setters2.List
|
List setters2.List
|
||||||
Markdown bool
|
Markdown bool
|
||||||
IncludeSubst bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
|
func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
@@ -66,10 +63,7 @@ func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
|
|||||||
if err := r.ListSetters(c, args); err != nil {
|
if err := r.ListSetters(c, args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if r.IncludeSubst {
|
return r.ListSubstitutions(c, args)
|
||||||
return r.ListSubstitutions(c, args)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleError(c, lookup(r.Lookup, c, args))
|
return handleError(c, lookup(r.Lookup, c, args))
|
||||||
@@ -85,7 +79,7 @@ func (r *ListSettersRunner) ListSetters(c *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
table := newTable(c.OutOrStdout(), r.Markdown)
|
table := newTable(c.OutOrStdout(), r.Markdown)
|
||||||
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT", "REQUIRED"})
|
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT"})
|
||||||
for i := range r.List.Setters {
|
for i := range r.List.Setters {
|
||||||
s := r.List.Setters[i]
|
s := r.List.Setters[i]
|
||||||
v := s.Value
|
v := s.Value
|
||||||
@@ -95,14 +89,8 @@ func (r *ListSettersRunner) ListSetters(c *cobra.Command, args []string) error {
|
|||||||
v = strings.Join(s.ListValues, ",")
|
v = strings.Join(s.ListValues, ",")
|
||||||
v = fmt.Sprintf("[%s]", v)
|
v = fmt.Sprintf("[%s]", v)
|
||||||
}
|
}
|
||||||
var required string
|
|
||||||
if s.Required {
|
|
||||||
required = "Yes"
|
|
||||||
} else {
|
|
||||||
required = "No"
|
|
||||||
}
|
|
||||||
table.Append([]string{
|
table.Append([]string{
|
||||||
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count), required})
|
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
|
||||||
}
|
}
|
||||||
table.Render()
|
table.Render()
|
||||||
|
|
||||||
@@ -125,9 +113,6 @@ func (r *ListSettersRunner) ListSubstitutions(c *cobra.Command, args []string) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
table := newTable(c.OutOrStdout(), r.Markdown)
|
table := newTable(c.OutOrStdout(), r.Markdown)
|
||||||
b := tablewriter.Border{Top: true}
|
|
||||||
table.SetBorders(b)
|
|
||||||
|
|
||||||
table.SetHeader([]string{"SUBSTITUTION", "PATTERN", "REFERENCES"})
|
table.SetHeader([]string{"SUBSTITUTION", "PATTERN", "REFERENCES"})
|
||||||
for i := range r.List.Substitutions {
|
for i := range r.List.Substitutions {
|
||||||
s := r.List.Substitutions[i]
|
s := r.List.Substitutions[i]
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -35,7 +34,6 @@ openAPI:
|
|||||||
name: replicas
|
name: replicas
|
||||||
value: "3"
|
value: "3"
|
||||||
setBy: me
|
setBy: me
|
||||||
required: true
|
|
||||||
description: "hello world"
|
description: "hello world"
|
||||||
`,
|
`,
|
||||||
input: `
|
input: `
|
||||||
@@ -46,39 +44,12 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||||
`,
|
`,
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
replicas 3 me hello world 1 Yes
|
replicas 3 me hello world 1
|
||||||
`,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "list-replicas inconsistent with openapi",
|
|
||||||
openapi: `
|
|
||||||
openAPI:
|
|
||||||
definitions:
|
|
||||||
io.k8s.cli.setters.replicas:
|
|
||||||
x-k8s-cli:
|
|
||||||
setter:
|
|
||||||
name: replicas
|
|
||||||
value: "4"
|
|
||||||
setBy: me
|
|
||||||
description: "hello world"
|
|
||||||
`,
|
|
||||||
input: `
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
|
||||||
`,
|
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
|
||||||
replicas 4 me hello world 1 No
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "list-multiple",
|
name: "list-multiple",
|
||||||
args: []string{"--include-subst"},
|
|
||||||
openapi: `
|
openapi: `
|
||||||
openAPI:
|
openAPI:
|
||||||
definitions:
|
definitions:
|
||||||
@@ -103,8 +74,6 @@ openAPI:
|
|||||||
name: tag
|
name: tag
|
||||||
value: "1.7.9"
|
value: "1.7.9"
|
||||||
setBy: me3
|
setBy: me3
|
||||||
required: true
|
|
||||||
isSet: false
|
|
||||||
io.k8s.cli.substitutions.image:
|
io.k8s.cli.substitutions.image:
|
||||||
x-k8s-cli:
|
x-k8s-cli:
|
||||||
substitution:
|
substitution:
|
||||||
@@ -131,18 +100,16 @@ spec:
|
|||||||
- name: nginx2
|
- name: nginx2
|
||||||
image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"}
|
image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"}
|
||||||
`,
|
`,
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
image nginx me2 hello world 2 2 No
|
image nginx me2 hello world 2 2
|
||||||
replicas 3 me1 hello world 1 1 No
|
replicas 3 me1 hello world 1 1
|
||||||
tag 1.7.9 me3 hello world 3 1 Yes
|
tag 1.7.9 me3 hello world 3 1
|
||||||
--------------- ----------- --------------
|
|
||||||
SUBSTITUTION PATTERN REFERENCES
|
SUBSTITUTION PATTERN REFERENCES
|
||||||
image IMAGE:TAG [image,tag]
|
image IMAGE:TAG [image,tag]
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "list-multiple-resources",
|
name: "list-multiple-resources",
|
||||||
args: []string{"--include-subst"},
|
|
||||||
openapi: `
|
openapi: `
|
||||||
openAPI:
|
openAPI:
|
||||||
definitions:
|
definitions:
|
||||||
@@ -207,11 +174,10 @@ spec:
|
|||||||
- name: nginx2
|
- name: nginx2
|
||||||
image: nginx
|
image: nginx
|
||||||
`,
|
`,
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
image nginx me2 hello world 2 3 No
|
image nginx me2 hello world 2 3
|
||||||
replicas 3 me1 hello world 1 2 No
|
replicas 3 me1 hello world 1 2
|
||||||
tag 1.7.9 me3 hello world 3 2 No
|
tag 1.7.9 me3 hello world 3 2
|
||||||
--------------- ----------- --------------
|
|
||||||
SUBSTITUTION PATTERN REFERENCES
|
SUBSTITUTION PATTERN REFERENCES
|
||||||
image IMAGE:TAG [image,tag]
|
image IMAGE:TAG [image,tag]
|
||||||
`,
|
`,
|
||||||
@@ -236,7 +202,6 @@ openAPI:
|
|||||||
name: image
|
name: image
|
||||||
value: "nginx"
|
value: "nginx"
|
||||||
setBy: me2
|
setBy: me2
|
||||||
required: true
|
|
||||||
io.k8s.cli.setters.tag:
|
io.k8s.cli.setters.tag:
|
||||||
description: "hello world 3"
|
description: "hello world 3"
|
||||||
x-k8s-cli:
|
x-k8s-cli:
|
||||||
@@ -244,10 +209,10 @@ openAPI:
|
|||||||
name: tag
|
name: tag
|
||||||
value: "1.7.9"
|
value: "1.7.9"
|
||||||
setBy: me3
|
setBy: me3
|
||||||
io.k8s.cli.substitutions.image-subst:
|
io.k8s.cli.substitutions.image:
|
||||||
x-k8s-cli:
|
x-k8s-cli:
|
||||||
substitution:
|
substitution:
|
||||||
name: image-subst
|
name: image
|
||||||
pattern: IMAGE:TAG
|
pattern: IMAGE:TAG
|
||||||
values:
|
values:
|
||||||
- marker: IMAGE
|
- marker: IMAGE
|
||||||
@@ -266,7 +231,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: nginx
|
- name: nginx
|
||||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-subst"}
|
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||||
- name: nginx2
|
- name: nginx2
|
||||||
image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"}
|
image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"}
|
||||||
---
|
---
|
||||||
@@ -280,12 +245,14 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: nginx
|
- name: nginx
|
||||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-subst"}
|
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||||
- name: nginx2
|
- name: nginx2
|
||||||
image: nginx
|
image: nginx
|
||||||
`,
|
`,
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
image nginx me2 hello world 2 3 Yes
|
image nginx me2 hello world 2 3
|
||||||
|
SUBSTITUTION PATTERN REFERENCES
|
||||||
|
image IMAGE:TAG [image,tag]
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -310,7 +277,6 @@ openAPI:
|
|||||||
- b
|
- b
|
||||||
- c
|
- c
|
||||||
setBy: me
|
setBy: me
|
||||||
required: true
|
|
||||||
`,
|
`,
|
||||||
input: `
|
input: `
|
||||||
apiVersion: example.com/v1beta1
|
apiVersion: example.com/v1beta1
|
||||||
@@ -324,14 +290,13 @@ spec:
|
|||||||
- "b"
|
- "b"
|
||||||
- "c"
|
- "c"
|
||||||
`,
|
`,
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
list [a,b,c] me hello world 1 Yes
|
list [a,b,c] me hello world 1
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "nested substitution",
|
name: "nested substitution",
|
||||||
args: []string{"--include-subst"},
|
|
||||||
input: `
|
input: `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@@ -362,8 +327,6 @@ openAPI:
|
|||||||
setter:
|
setter:
|
||||||
name: my-tag-setter
|
name: my-tag-setter
|
||||||
value: 1.7.9
|
value: 1.7.9
|
||||||
required: true
|
|
||||||
isSet: true
|
|
||||||
io.k8s.cli.substitutions.my-image-subst:
|
io.k8s.cli.substitutions.my-image-subst:
|
||||||
x-k8s-cli:
|
x-k8s-cli:
|
||||||
substitution:
|
substitution:
|
||||||
@@ -390,11 +353,10 @@ openAPI:
|
|||||||
name: my-other-setter
|
name: my-other-setter
|
||||||
value: nginxotherthing
|
value: nginxotherthing
|
||||||
`,
|
`,
|
||||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
my-image-setter nginx 2 No
|
my-image-setter nginx 2
|
||||||
my-other-setter nginxotherthing 1 No
|
my-other-setter nginxotherthing 1
|
||||||
my-tag-setter 1.7.9 2 Yes
|
my-tag-setter 1.7.9 2
|
||||||
------------------ ------------------------------------------------ -----------------------------------
|
|
||||||
SUBSTITUTION PATTERN REFERENCES
|
SUBSTITUTION PATTERN REFERENCES
|
||||||
my-image-subst ${my-image-setter}::${my-tag-setter} [my-image-setter,my-tag-setter]
|
my-image-subst ${my-image-setter}::${my-tag-setter} [my-image-setter,my-tag-setter]
|
||||||
my-nested-subst something/${my-image-subst}/${my-other-setter} [my-image-subst,my-other-setter]
|
my-nested-subst something/${my-image-subst}/${my-other-setter} [my-image-subst,my-other-setter]
|
||||||
@@ -445,27 +407,6 @@ openAPI:
|
|||||||
if !assert.Equal(t, test.expected, actual.String()) {
|
if !assert.Equal(t, test.expected, actual.String()) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure that the resources are not altered
|
|
||||||
actualResources, err := ioutil.ReadFile(r.Name())
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t,
|
|
||||||
strings.TrimSpace(test.input),
|
|
||||||
strings.TrimSpace(string(actualResources))) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
actualOpenAPI, err := ioutil.ReadFile(f.Name())
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t,
|
|
||||||
strings.TrimSpace(test.openapi),
|
|
||||||
strings.TrimSpace(string(actualOpenAPI))) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ openAPI:
|
|||||||
name: replicas
|
name: replicas
|
||||||
value: "4"
|
value: "4"
|
||||||
setBy: pw
|
setBy: pw
|
||||||
isSet: true
|
|
||||||
`,
|
`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
@@ -159,7 +158,6 @@ openAPI:
|
|||||||
setter:
|
setter:
|
||||||
name: replicas
|
name: replicas
|
||||||
value: "4"
|
value: "4"
|
||||||
isSet: true
|
|
||||||
`,
|
`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
@@ -231,7 +229,6 @@ openAPI:
|
|||||||
setter:
|
setter:
|
||||||
name: tag
|
name: tag
|
||||||
value: "1.8.1"
|
value: "1.8.1"
|
||||||
isSet: true
|
|
||||||
io.k8s.cli.substitutions.image:
|
io.k8s.cli.substitutions.image:
|
||||||
x-k8s-cli:
|
x-k8s-cli:
|
||||||
substitution:
|
substitution:
|
||||||
@@ -542,7 +539,6 @@ openAPI:
|
|||||||
setter:
|
setter:
|
||||||
name: replicas
|
name: replicas
|
||||||
value: "4"
|
value: "4"
|
||||||
isSet: true
|
|
||||||
`,
|
`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
@@ -643,7 +639,6 @@ openAPI:
|
|||||||
listValues:
|
listValues:
|
||||||
- "10"
|
- "10"
|
||||||
- "11"
|
- "11"
|
||||||
isSet: true
|
|
||||||
`,
|
`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: example.com/v1beta1
|
apiVersion: example.com/v1beta1
|
||||||
@@ -776,7 +771,6 @@ openAPI:
|
|||||||
setter:
|
setter:
|
||||||
name: my-image-setter
|
name: my-image-setter
|
||||||
value: ubuntu
|
value: ubuntu
|
||||||
isSet: true
|
|
||||||
io.k8s.cli.setters.my-tag-setter:
|
io.k8s.cli.setters.my-tag-setter:
|
||||||
x-k8s-cli:
|
x-k8s-cli:
|
||||||
setter:
|
setter:
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ func TestRunE2e(t *testing.T) {
|
|||||||
expectedErr string
|
expectedErr string
|
||||||
skipIfFalseEnv string
|
skipIfFalseEnv string
|
||||||
}{
|
}{
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "exec_function_no_args",
|
name: "exec_function_no_args",
|
||||||
args: func(d string) []string {
|
args: func(d string) []string {
|
||||||
@@ -64,36 +63,6 @@ metadata:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
name: "exec_function_no_args_json",
|
|
||||||
args: func(d string) []string {
|
|
||||||
return []string{
|
|
||||||
"--enable-exec", "--exec-path", filepath.Join(d, "e2econtainerconfig"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
files: func(d string) map[string]string {
|
|
||||||
return map[string]string{
|
|
||||||
"deployment.json": `
|
|
||||||
{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": {
|
|
||||||
"name": "foo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expectedFiles: func(d string) map[string]string {
|
|
||||||
return map[string]string{
|
|
||||||
"deployment.json": `
|
|
||||||
{"apiVersion": "apps/v1", "kind": "Deployment", "metadata": {"name": "foo", annotations: {
|
|
||||||
a-string-value: '', a-int-value: '0', a-bool-value: 'false'}}}
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "exec_function_args",
|
name: "exec_function_args",
|
||||||
args: func(d string) []string {
|
args: func(d string) []string {
|
||||||
@@ -499,6 +468,7 @@ def run(r, fc):
|
|||||||
resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"]
|
resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"]
|
||||||
resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"]
|
resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"]
|
||||||
resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"]
|
resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"]
|
||||||
|
|
||||||
run(ctx.resource_list["items"], ctx.resource_list["functionConfig"])
|
run(ctx.resource_list["items"], ctx.resource_list["functionConfig"])
|
||||||
`,
|
`,
|
||||||
"config.yaml": `
|
"config.yaml": `
|
||||||
@@ -575,6 +545,7 @@ def run(r, fc):
|
|||||||
resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"]
|
resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"]
|
||||||
resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"]
|
resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"]
|
||||||
resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"]
|
resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"]
|
||||||
|
|
||||||
run(ctx.resource_list["items"], ctx.resource_list["functionConfig"])
|
run(ctx.resource_list["items"], ctx.resource_list["functionConfig"])
|
||||||
`,
|
`,
|
||||||
"deployment.yaml": `
|
"deployment.yaml": `
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ openAPI:
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
expectedStdOut: `
|
expectedStdOut: `
|
||||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
NAME VALUE SET BY DESCRIPTION COUNT
|
||||||
replicas 3 1 No
|
replicas 3 1
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ openAPI:
|
|||||||
setter:
|
setter:
|
||||||
name: replicas
|
name: replicas
|
||||||
value: "4"
|
value: "4"
|
||||||
isSet: true
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ func GetGrepRunner(name string) *GrepRunner {
|
|||||||
"also print resources from subpackages.")
|
"also print resources from subpackages.")
|
||||||
c.Flags().BoolVar(&r.KeepAnnotations, "annotate", true,
|
c.Flags().BoolVar(&r.KeepAnnotations, "annotate", true,
|
||||||
"annotate resources with their file origins.")
|
"annotate resources with their file origins.")
|
||||||
c.Flags().BoolVarP(&r.InvertMatch, "invert-match", "", false,
|
c.Flags().BoolVarP(&r.InvertMatch, "invert-match", "v", false,
|
||||||
"Selected Resources are those not matching any of the specified patterns..")
|
" Selected Resources are those not matching any of the specified patterns..")
|
||||||
|
|
||||||
r.Command = c
|
r.Command = c
|
||||||
return r
|
return r
|
||||||
|
|||||||
@@ -136,51 +136,6 @@ spec:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSinkCommandJSON(t *testing.T) {
|
|
||||||
d, err := ioutil.TempDir("", "kustomize-source-test")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(d)
|
|
||||||
|
|
||||||
r := commands.GetSinkRunner("")
|
|
||||||
r.Command.SetIn(bytes.NewBufferString(`apiVersion: config.kubernetes.io/v1alpha1
|
|
||||||
kind: ResourceList
|
|
||||||
items:
|
|
||||||
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo",
|
|
||||||
"annotations": {"app": "nginx2", config.kubernetes.io/index: '0',
|
|
||||||
config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}}
|
|
||||||
`))
|
|
||||||
r.Command.SetArgs([]string{d})
|
|
||||||
if !assert.NoError(t, r.Command.Execute()) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual, err := ioutil.ReadFile(filepath.Join(d, "f1.json"))
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
expected := `{
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": {
|
|
||||||
"annotations": {
|
|
||||||
"app": "nginx2"
|
|
||||||
},
|
|
||||||
"labels": {
|
|
||||||
"app": "nginx2"
|
|
||||||
},
|
|
||||||
"name": "foo"
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"replicas": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
if !assert.Equal(t, expected, string(actual)) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSinkCommand_Stdout(t *testing.T) {
|
func TestSinkCommand_Stdout(t *testing.T) {
|
||||||
d, err := ioutil.TempDir("", "kustomize-source-test")
|
d, err := ioutil.TempDir("", "kustomize-source-test")
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -294,49 +249,3 @@ spec:
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSinkCommandJSON_Stdout(t *testing.T) {
|
|
||||||
d, err := ioutil.TempDir("", "kustomize-source-test")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(d)
|
|
||||||
|
|
||||||
// fmt the files
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
r := commands.GetSinkRunner("")
|
|
||||||
r.Command.SetIn(bytes.NewBufferString(`apiVersion: config.kubernetes.io/v1alpha1
|
|
||||||
kind: ResourceList
|
|
||||||
items:
|
|
||||||
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo",
|
|
||||||
"annotations": {"app": "nginx2", config.kubernetes.io/index: '0',
|
|
||||||
config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}}
|
|
||||||
`))
|
|
||||||
|
|
||||||
r.Command.SetOut(out)
|
|
||||||
r.Command.SetArgs([]string{})
|
|
||||||
if !assert.NoError(t, r.Command.Execute()) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := `{
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": {
|
|
||||||
"annotations": {
|
|
||||||
"app": "nginx2"
|
|
||||||
},
|
|
||||||
"labels": {
|
|
||||||
"app": "nginx2"
|
|
||||||
},
|
|
||||||
"name": "foo"
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"replicas": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
if !assert.Equal(t, expected, out.String()) {
|
|
||||||
println(out.String())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func (r *SourceRunner) runE(c *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
var inputs []kio.Reader
|
var inputs []kio.Reader
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
inputs = append(inputs, kio.LocalPackageReader{PackagePath: a, MatchFilesGlob: kio.MatchAll})
|
inputs = append(inputs, kio.LocalPackageReader{PackagePath: a})
|
||||||
}
|
}
|
||||||
if len(inputs) == 0 {
|
if len(inputs) == 0 {
|
||||||
inputs = []kio.Reader{&kio.ByteReader{Reader: c.InOrStdin()}}
|
inputs = []kio.Reader{&kio.ByteReader{Reader: c.InOrStdin()}}
|
||||||
|
|||||||
@@ -135,77 +135,6 @@ items:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSourceCommandJSON(t *testing.T) {
|
|
||||||
d, err := ioutil.TempDir("", "kustomize-source-test")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(d)
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(filepath.Join(d, "f1.json"), []byte(`
|
|
||||||
{
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": {
|
|
||||||
"labels": {
|
|
||||||
"app": "nginx2"
|
|
||||||
},
|
|
||||||
"name": "foo",
|
|
||||||
"annotations": {
|
|
||||||
"app": "nginx2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"replicas": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`), 0600)
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(filepath.Join(d, "f2.json"), []byte(`
|
|
||||||
{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "Abstraction",
|
|
||||||
"metadata": {
|
|
||||||
"name": "foo",
|
|
||||||
"annotations": {
|
|
||||||
"config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n",
|
|
||||||
"config.kubernetes.io/local-config": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"replicas": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`), 0600)
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmt the files
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
r := commands.GetSourceRunner("")
|
|
||||||
r.Command.SetArgs([]string{d})
|
|
||||||
r.Command.SetOut(b)
|
|
||||||
if !assert.NoError(t, r.Command.Execute()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
|
||||||
kind: ResourceList
|
|
||||||
items:
|
|
||||||
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo",
|
|
||||||
"annotations": {"app": "nginx2", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f1.json'}},
|
|
||||||
"spec": {"replicas": 1}}
|
|
||||||
- {"apiVersion": "v1", "kind": "Abstraction", "metadata": {"name": "foo", "annotations": {
|
|
||||||
"config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n",
|
|
||||||
"config.kubernetes.io/local-config": "true", config.kubernetes.io/index: '0',
|
|
||||||
config.kubernetes.io/path: 'f2.json'}}, "spec": {"replicas": 3}}
|
|
||||||
`, b.String()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSourceCommand_Stdin(t *testing.T) {
|
func TestSourceCommand_Stdin(t *testing.T) {
|
||||||
d, err := ioutil.TempDir("", "kustomize-source-test")
|
d, err := ioutil.TempDir("", "kustomize-source-test")
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -269,48 +198,3 @@ items:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSourceCommandJSON_Stdin(t *testing.T) {
|
|
||||||
d, err := ioutil.TempDir("", "kustomize-source-test")
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(d)
|
|
||||||
|
|
||||||
in := bytes.NewBufferString(`
|
|
||||||
{
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": {
|
|
||||||
"labels": {
|
|
||||||
"app": "nginx2"
|
|
||||||
},
|
|
||||||
"name": "foo",
|
|
||||||
"annotations": {
|
|
||||||
"app": "nginx2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"replicas": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
r := commands.GetSourceRunner("")
|
|
||||||
r.Command.SetArgs([]string{})
|
|
||||||
r.Command.SetIn(in)
|
|
||||||
r.Command.SetOut(out)
|
|
||||||
if !assert.NoError(t, r.Command.Execute()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
|
||||||
kind: ResourceList
|
|
||||||
items:
|
|
||||||
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo",
|
|
||||||
"annotations": {"app": "nginx2", config.kubernetes.io/index: '0'}}, "spec": {
|
|
||||||
"replicas": 1}}
|
|
||||||
`, out.String()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -175,13 +175,13 @@ are passed to the Function through the ` + "`" + `ResourceList.functionConfig` +
|
|||||||
name: my-instance
|
name: my-instance
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/local-config: "true"
|
config.kubernetes.io/local-config: "true"
|
||||||
config.kubernetes.io/function: |
|
config.k8s.io/function: |
|
||||||
container:
|
container:
|
||||||
image: gcr.io/example-functions/nginx-template:v1.0.0
|
image: gcr.io/example-functions/nginx-template:v1.0.0
|
||||||
spec:
|
spec:
|
||||||
replicas: 5
|
replicas: 5
|
||||||
|
|
||||||
- ` + "`" + `annotations[config.kubernetes.io/function].container.image` + "`" + `: the image to use for this API
|
- ` + "`" + `annotations[config.k8s.io/function].container.image` + "`" + `: the image to use for this API
|
||||||
- ` + "`" + `annotations[config.kubernetes.io/local-config]` + "`" + `: mark this as not a Resource that should
|
- ` + "`" + `annotations[config.kubernetes.io/local-config]` + "`" + `: mark this as not a Resource that should
|
||||||
be applied
|
be applied
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ containers that can be chained together as part of a configuration management pi
|
|||||||
The end result of such a pipeline are fully rendered configurations that can then be
|
The end result of such a pipeline are fully rendered configurations that can then be
|
||||||
applied to a control plane (e.g. Using ‘kubectl apply’ for Kubernetes control plane).
|
applied to a control plane (e.g. Using ‘kubectl apply’ for Kubernetes control plane).
|
||||||
As such, although this document references Kubernetes Resource Model and API conventions,
|
As such, although this document references Kubernetes Resource Model and API conventions,
|
||||||
it is completely decoupled from Kubernetes API machinery and does not depend on any
|
it is completely decoupled from Kuberentes API machinery and does not depend on any
|
||||||
in-cluster components.
|
in-cluster components.
|
||||||
|
|
||||||
This document references terms described in [Kubernetes API Conventions][1].
|
This document references terms described in [Kubernetes API Conventions][1].
|
||||||
@@ -267,7 +267,7 @@ interpreted as described in [RFC 2119][2].
|
|||||||
Performing these on the client rather than the server enables:
|
Performing these on the client rather than the server enables:
|
||||||
|
|
||||||
- Configuration to be reviewed prior to being sent to the API server
|
- Configuration to be reviewed prior to being sent to the API server
|
||||||
- Configuration to be validated as part of the CI/CD pipeline
|
- Configuration to be validated as part of the CI?CD pipeline
|
||||||
- Configuration for Resources to validated holistically rather than individually
|
- Configuration for Resources to validated holistically rather than individually
|
||||||
per-Resource
|
per-Resource
|
||||||
- e.g. ensure the ` + "`" + `Service.selector` + "`" + ` and ` + "`" + `Deployment.spec.template` + "`" + ` labels
|
- e.g. ensure the ` + "`" + `Service.selector` + "`" + ` and ` + "`" + `Deployment.spec.template` + "`" + ` labels
|
||||||
@@ -343,7 +343,7 @@ An example using ` + "`" + `config.kubernetes.io/v1beta1/ResourceList` + "`" + `
|
|||||||
name: staging
|
name: staging
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/function: |
|
config.k8s.io/function: |
|
||||||
container:
|
container:
|
||||||
image: gcr.io/example/foo:v1.0.0
|
image: gcr.io/example/foo:v1.0.0
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
@@ -89,22 +89,6 @@ var CreateSetterExamples = `
|
|||||||
kustomize cfg create-setter DIR/ image-tag v1.0.1 --type "string" \
|
kustomize cfg create-setter DIR/ image-tag v1.0.1 --type "string" \
|
||||||
--field image --description "current stable release"`
|
--field image --description "current stable release"`
|
||||||
|
|
||||||
var DeleteSetterShort = `[Alpha] Delete a custom setter for a Resource field`
|
|
||||||
var DeleteSetterLong = `
|
|
||||||
Delete a custom setter for a Resource field.
|
|
||||||
|
|
||||||
DIR
|
|
||||||
|
|
||||||
A directory containing Resource configuration.
|
|
||||||
|
|
||||||
NAME
|
|
||||||
|
|
||||||
The name of the setter to create.
|
|
||||||
`
|
|
||||||
var DeleteSetterExamples = `
|
|
||||||
# delete a setter for port
|
|
||||||
kustomize cfg create-setter DIR/ port`
|
|
||||||
|
|
||||||
var FmtShort = `[Alpha] Format yaml configuration files.`
|
var FmtShort = `[Alpha] Format yaml configuration files.`
|
||||||
var FmtLong = `
|
var FmtLong = `
|
||||||
[Alpha] Format yaml configuration files.
|
[Alpha] Format yaml configuration files.
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
|
English | [简体中文](zh/README.md)
|
||||||
|
|
||||||
Moved to [https://kubernetes-sigs.github.io/kustomize](https://kubernetes-sigs.github.io/kustomize)
|
Moved to [https://kubernetes-sigs.github.io/kustomize](https://kubernetes-sigs.github.io/kustomize)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="generator" content="Hugo 0.68.3" />
|
<meta name="generator" content="Hugo 0.73.0-DEV" />
|
||||||
|
|
||||||
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
|
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
|
||||||
|
|
||||||
@@ -99,14 +99,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link" href="https://github.com/kubernetes-sigs/kustomize/tree/master/examples" target="_blank" ><span>Example</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link" href="/kustomize/faq/" ><span>FAQ</span></a>
|
<a class="nav-link" href="/kustomize/faq/" ><span>FAQ</span></a>
|
||||||
@@ -134,19 +126,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="nav-item dropdown d-none d-lg-block">
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
English
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/kustomize/zh/api-reference/glossary/">简体中文</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-nav d-none d-lg-block">
|
<div class="navbar-nav d-none d-lg-block">
|
||||||
@@ -174,19 +153,6 @@
|
|||||||
|
|
||||||
<nav class="collapse td-sidebar-nav pt-2 pl-4" id="td-section-nav">
|
<nav class="collapse td-sidebar-nav pt-2 pl-4" id="td-section-nav">
|
||||||
|
|
||||||
<div class="nav-item dropdown d-block d-lg-none">
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
English
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/kustomize/zh/api-reference/glossary/">简体中文</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -911,8 +877,8 @@ absolute path, or by relative path.</p>
|
|||||||
<li><strong>B</strong> may not <em>depend on</em> <strong>A</strong>, even transitively.</li>
|
<li><strong>B</strong> may not <em>depend on</em> <strong>A</strong>, even transitively.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><strong>A</strong> may contain <strong>B</strong>, but in this case it might be
|
<p><strong>A</strong> may contain <strong>B</strong>, but in this case it might be
|
||||||
simplest to have <strong>A</strong> directly depend on <strong>B</strong>‘s
|
simplest to have <strong>A</strong> directly depend on <strong>B</strong>’s
|
||||||
resources and eliminate <strong>B</strong>‘s kustomization.yaml file
|
resources and eliminate <strong>B</strong>’s kustomization.yaml file
|
||||||
(i.e. absorb <strong>B</strong> into <strong>A</strong>).</p>
|
(i.e. absorb <strong>B</strong> into <strong>A</strong>).</p>
|
||||||
<p>Conventionally, <strong>B</strong> is in a directory that’s sibling
|
<p>Conventionally, <strong>B</strong> is in a directory that’s sibling
|
||||||
to <strong>A</strong>, or <strong>B</strong> is off in a completely independent
|
to <strong>A</strong>, or <strong>B</strong> is off in a completely independent
|
||||||
@@ -1046,7 +1012,7 @@ syntax. See this <a href="https://github.com/kubernetes-sigs/kustomize/tree/mas
|
|||||||
<p>A chunk of code used by kustomize, but not necessarily
|
<p>A chunk of code used by kustomize, but not necessarily
|
||||||
compiled into kustomize, to generate and/or transform a
|
compiled into kustomize, to generate and/or transform a
|
||||||
kubernetes resource as part of a kustomization.</p>
|
kubernetes resource as part of a kustomization.</p>
|
||||||
<p>Details <a href="../../guides/plugins">here</a>.</p>
|
<p>Details <a href="plugins">here</a>.</p>
|
||||||
<h2 id="resource">resource</h2>
|
<h2 id="resource">resource</h2>
|
||||||
<p>A <em>resource</em> in the context of a REST-ful API is the
|
<p>A <em>resource</em> in the context of a REST-ful API is the
|
||||||
target object of an HTTP operation like <em>GET</em>, <em>PUT</em> or
|
target object of an HTTP operation like <em>GET</em>, <em>PUT</em> or
|
||||||
@@ -1147,7 +1113,7 @@ cpu and memory requests.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="text-muted mt-5 pt-3 border-top">Last modified June 15, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/518147c129f831913d33226cf17068d0d4270f41">add zh docsy (518147c1)</a>
|
<div class="text-muted mt-5 pt-3 border-top">Last modified June 7, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/42497c664f619a36cc86156e366b53099bd633cb">Convert docs to docsy (42497c66)</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="generator" content="Hugo 0.68.3" />
|
<meta name="generator" content="Hugo 0.73.0-DEV" />
|
||||||
|
|
||||||
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
|
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
|
||||||
|
|
||||||
@@ -99,14 +99,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link" href="https://github.com/kubernetes-sigs/kustomize/tree/master/examples" target="_blank" ><span>Example</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link" href="/kustomize/faq/" ><span>FAQ</span></a>
|
<a class="nav-link" href="/kustomize/faq/" ><span>FAQ</span></a>
|
||||||
@@ -134,19 +126,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="nav-item dropdown d-none d-lg-block">
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
English
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/kustomize/zh/api-reference/">简体中文</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-nav d-none d-lg-block">
|
<div class="navbar-nav d-none d-lg-block">
|
||||||
@@ -174,19 +153,6 @@
|
|||||||
|
|
||||||
<nav class="collapse td-sidebar-nav pt-2 pl-4" id="td-section-nav">
|
<nav class="collapse td-sidebar-nav pt-2 pl-4" id="td-section-nav">
|
||||||
|
|
||||||
<div class="nav-item dropdown d-block d-lg-none">
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
English
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/kustomize/zh/api-reference/">简体中文</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="generator" content="Hugo 0.68.3" />
|
<meta name="generator" content="Hugo 0.73.0-DEV" />
|
||||||
|
|
||||||
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
|
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
|
||||||
|
|
||||||
@@ -99,14 +99,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link" href="https://github.com/kubernetes-sigs/kustomize/tree/master/examples" target="_blank" ><span>Example</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link" href="/kustomize/faq/" ><span>FAQ</span></a>
|
<a class="nav-link" href="/kustomize/faq/" ><span>FAQ</span></a>
|
||||||
@@ -134,19 +126,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="nav-item dropdown d-none d-lg-block">
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
English
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/kustomize/zh/api-reference/kustomization/bases/">简体中文</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-nav d-none d-lg-block">
|
<div class="navbar-nav d-none d-lg-block">
|
||||||
@@ -174,19 +153,6 @@
|
|||||||
|
|
||||||
<nav class="collapse td-sidebar-nav pt-2 pl-4" id="td-section-nav">
|
<nav class="collapse td-sidebar-nav pt-2 pl-4" id="td-section-nav">
|
||||||
|
|
||||||
<div class="nav-item dropdown d-block d-lg-none">
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
English
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/kustomize/zh/api-reference/kustomization/bases/">简体中文</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user