Compare commits

...

105 Commits

Author SHA1 Message Date
Kubernetes Prow Robot
7f5ce3e6f0 Merge pull request #2770 from mortent/BumpDepsForCmdConfig
Bump cli-utils version in cmd/config for relase
2020-07-24 13:54:17 -07:00
Morten Torkildsen
0ec901a9a9 Bump cli-utils version in cmd/config for relase 2020-07-24 13:30:45 -07:00
Jeff Regan
c48e584d1a Merge pull request #2766 from monopole/swicthToKyamlV0_4_2
Switch to kyaml v0.4.2
2020-07-24 12:48:46 -07:00
jregan
f06a64e9cc Switch to kyaml v0.4.2 2020-07-24 11:59:01 -07:00
Jeff Regan
51f9a84358 Update cloudbuild.sh 2020-07-24 11:54:39 -07:00
Jeff Regan
07c25eb458 Update cloudbuild.sh 2020-07-24 11:46:53 -07:00
Jeff Regan
ba57cdbd99 Merge pull request #2765 from monopole/updateCloudbuild
Try goreleaser's skip to deal with no-binary releases
2020-07-24 11:35:50 -07:00
jregan
8a9dc011f4 Try goreleaser skip to deal with no-binary releases 2020-07-24 11:34:57 -07:00
Jeff Regan
fd196f5d70 Merge pull request #2762 from kzwang/components-field
Retain components field in edit
2020-07-24 11:31:19 -07:00
Jeff Regan
4c577f6667 Merge pull request #2764 from Shell32-Natsu/seqtag
Add seq tag in kyaml
2020-07-24 11:30:59 -07:00
Donny Xia
65fd7c3e6e Add seq tag in kyaml 2020-07-24 11:17:31 -07:00
Jeff Regan
1dff481883 Merge pull request #2763 from monopole/updateReleaseInstructions
Update release instructions.
2020-07-24 10:28:55 -07:00
jregan
d437f67035 Update release instructions. 2020-07-24 10:27:31 -07:00
Kevin Wang
ee57e9db12 Retain components field in edit 2020-07-23 21:39:55 -07:00
Jeff Regan
a0fdcfe2e3 Merge pull request #2757 from phanimarupaka/revert-2738-ListSettersRecursively
Revert "List and set setters in folders recursively"
2020-07-22 14:56:26 -07:00
phani
d9fe98a289 Revert "List and set setters in folders recursively" 2020-07-22 13:51:42 -07:00
Jeff Regan
8b9829f222 Merge pull request #2738 from phanimarupaka/ListSettersRecursively
List and set setters in folders recursively
2020-07-22 13:14:13 -07:00
Jeff Regan
2114b97969 Merge pull request #2737 from tinselspoon/hash-arbitrary-objects
Allow hash suffixing of arbitrary types
2020-07-22 13:12:44 -07:00
Kubernetes Prow Robot
508d193e7a Merge pull request #2753 from phanimarupaka/AddV1CreateSetterTest
Add v1 create setter tests
2020-07-22 12:51:39 -07:00
Phani Teja Marupaka
e0eb79adcc Add v1 create setter tests 2020-07-22 12:11:19 -07:00
Jeff Regan
dcab3cbb5f Merge pull request #2739 from Shell32-Natsu/rolebinding
Role binding for serviceaccount across namesapce.
2020-07-22 11:45:05 -07:00
Jeff Regan
8225ca45a8 Merge pull request #2752 from monopole/convertImageTagTransformer
Convert image transformer to kyaml.
2020-07-22 11:37:04 -07:00
jregan
ef924a5c9c Convert image transformer to kyaml. 2020-07-22 11:10:52 -07:00
Jeff Regan
33b03fce89 remove a blank 2020-07-22 11:06:26 -07:00
Donny Xia
3907643880 Add function to check role binding namespace 2020-07-22 11:01:23 -07:00
Donny Xia
b7f7536cfa Update comment 2020-07-22 11:01:23 -07:00
Donny Xia
15bc399d5a Support RoleBinding for ServiceAccount across namespace 2020-07-22 11:01:23 -07:00
Jeff Regan
46a6bf0bb4 Merge pull request #2751 from monopole/moreImageTagTests
Add more tests to imagetag filter
2020-07-22 10:59:27 -07:00
Jeff Regan
6717bbd36b Merge pull request #2750 from Shell32-Natsu/rolebinding-test
Add test for role binding across namespace.
2020-07-22 10:54:17 -07:00
Kubernetes Prow Robot
6fccb7fd48 Merge pull request #2743 from phanimarupaka/FixV1Setters
Fix V1 setters
2020-07-22 10:52:06 -07:00
jregan
370a3d2e74 Add more imagetag tests to support refactor. 2020-07-22 10:46:20 -07:00
Phani Teja Marupaka
eb7beba8ad Fix V1 setters 2020-07-22 10:17:10 -07:00
Jeff Regan
1e3bc51645 Merge pull request #2748 from monopole/tweakSequenceTreatment
Tweak sequence treatment in fieldspecs
2020-07-22 10:01:21 -07:00
Donny Xia
92e1d452b7 Add test for role binding across namespace. 2020-07-22 10:00:34 -07:00
Kubernetes Prow Robot
7abedcf87b Merge pull request #2749 from pwittrock/default
Update kustomize FAQ with kubectl explanation
2020-07-22 09:52:05 -07:00
Phillip Wittrock
aa991956ef Docs: build site 2020-07-22 09:27:32 -07:00
Phillip Wittrock
c6524f984c Docs: Update FAQ with why kubectl has kustomize 2 2020-07-22 09:27:07 -07:00
Jeff Regan
a70c6b3496 Tweak sequence treatment in fieldspecs 2020-07-22 09:23:47 -07:00
Jeff Regan
166c7f3167 Merge pull request #2742 from techniumlabs/master
Avoiding Prefix Transformer for Namespace resource
2020-07-21 17:21:29 -07:00
Kubernetes Prow Robot
10371aa1b5 Merge pull request #2595 from phanimarupaka/FixAnnotations
Error for null files while reading
2020-07-21 17:16:05 -07:00
Jeff Regan
95fb639fa8 Merge pull request #2728 from prachirp/markdownlint
Docs: Auto-fix markdownlint issues
2020-07-21 16:56:45 -07:00
Jeff Regan
0f7aae38e3 Merge pull request #2735 from monopole/moreBadness
Switch replica count transformer to kyaml.
2020-07-21 16:55:55 -07:00
ageekymonk
c660fd33ae Avoiding Prefix Transformer for Namespace resource 2020-07-21 18:33:42 +10:00
Phani Teja Marupaka
108195185f List and set setters in folders recursively 2020-07-20 00:50:04 -07:00
Nick
4fbe565b36 Allow hash suffixing of arbitrary types 2020-07-19 23:29:24 +01:00
jregan
e9bc2c00c1 Switch prefix transformer to kyaml. 2020-07-17 19:48:13 -07:00
Jeff Regan
45eed23b26 Merge pull request #2733 from kubernetes-sigs/ctFormatting
Update formatting of component_test.go
2020-07-17 19:48:06 -07:00
Jeff Regan
27b2c7f294 Update formatting of component_test.go 2020-07-17 18:31:54 -07:00
Jeff Regan
03d6229c0b Merge pull request #2732 from monopole/beanPole
Switch prefix transformer to kyaml.
2020-07-17 18:09:19 -07:00
jregan
71b7b00bd8 Switch prefix transformer to kyaml. 2020-07-17 16:08:41 -07:00
Jeff Regan
e9396dca2c Merge pull request #2731 from prachirp/go-plugins
Fix go plugins caveats link
2020-07-17 15:49:36 -07:00
Prachi Pendse
bc581b70bf Fix go plugins caveats link 2020-07-17 12:03:19 -07:00
Jeff Regan
ac1c31c82b Merge pull request #2730 from monopole/addTest
Add a test and temporarily disable some plugin tests.
2020-07-17 10:25:07 -07:00
jregan
c878957d0b Add a test and temporarily disable some plugin tests. 2020-07-17 08:23:11 -07:00
Prachi Pendse
f9ee578aed Docs: Auto-fix markdownlint issues 2020-07-16 12:57:18 -07:00
Jeff Regan
0b359d0ef0 Merge pull request #2727 from monopole/addE2eTests
Pre v3.8.1; Add e2e tests pinned at v3.8.0
2020-07-15 17:54:54 -07:00
jregan
22ee7cbd49 Pre v3.8.1; Add e2e tests pinned at v3.8.0 2020-07-15 17:33:43 -07:00
Jeff Regan
7bf9c7002f Merge pull request #2726 from monopole/pinToKustomizeApiV_0_5_1
Pin to kustomize/api v0.5.1
2020-07-15 17:26:12 -07:00
jregan
155411f229 Pin to kustomize/api v0.5.1 2020-07-15 17:00:33 -07:00
Jeff Regan
699cc70a7c Merge pull request #2725 from monopole/pinToKyamlv0_4_1
Pin To Kyaml/v0.4.1
2020-07-15 16:44:17 -07:00
jregan
a63a472024 Pin To Kyaml/v0.4.1 2020-07-15 16:17:12 -07:00
Phani Teja Marupaka
e894756003 Error for null files while reading 2020-07-15 16:05:52 -07:00
Jeff Regan
55f55a5091 Merge pull request #2718 from Shell32-Natsu/unknown-fields
Uniform unmarshal function
2020-07-15 14:36:06 -07:00
Donny Xia
8401196ef9 fix typo 2020-07-15 11:47:47 -07:00
Donny Xia
14edc3890c Add tests for kustomization.go 2020-07-15 11:42:50 -07:00
Donny Xia
897698fb29 Uniform unmarshal function 2020-07-14 17:01:43 -07:00
Jeff Regan
ec9ae3d7b0 Merge pull request #2713 from Shell32-Natsu/empty-list-in-patch
Keep empty array in output
2020-07-14 13:50:37 -07:00
Donny Xia
3a828941fa Improve tests 2020-07-14 11:38:29 -07:00
Jeff Regan
b63b5ce7cc Merge pull request #2683 from Shell32-Natsu/function-benchmark
KRM Function benchmark
2020-07-14 09:05:31 -07:00
Donny Xia
23bd4390d3 code review 2020-07-13 16:40:34 -07:00
Kubernetes Prow Robot
21a0fd33a2 Merge pull request #2696 from arrikto/feature-site-components-guide
docs: Add guide for components
2020-07-13 14:29:20 -07:00
Donny Xia
c6b6dec91f Add tests for IsEmpty and IsMissingorNull 2020-07-13 14:15:55 -07:00
Kubernetes Prow Robot
9cf4367db7 Merge pull request #2709 from aodinokov/fixmount
Fixed incorrect docker mount arguments generation
2020-07-13 12:35:22 -07:00
Jeff Regan
e9c118fd55 Update readme.md 2020-07-13 12:24:34 -07:00
Kubernetes Prow Robot
bfbb1971d4 Merge pull request #2695 from sunny0826/master
add favicons for doc site
2020-07-13 12:09:20 -07:00
Donny Xia
6fabfe963e code review 2020-07-13 12:05:03 -07:00
Donny Xia
67cdd2e27e Add test for keeping empty array 2020-07-13 11:50:01 -07:00
Jeff Regan
6c6b5f744d Merge pull request #2641 from jijiew/doc
doc for kustomize config delete setter
2020-07-13 11:38:43 -07:00
Jeff Regan
7775666c50 Merge pull request #2702 from kubernetes-sigs/dependabot/npm_and_yarn/api/internal/crawl/ui/npm-registry-fetch-4.0.5
Bump npm-registry-fetch from 4.0.2 to 4.0.5 in /api/internal/crawl/ui
2020-07-13 11:36:55 -07:00
Kubernetes Prow Robot
bdd7ae085e Merge pull request #2708 from monopole/byeByeFlag
Removing YAMLSupport==false code path.
2020-07-13 11:11:20 -07:00
Alexey Odinokov
ba3e09849a Made mountString params more similar to docker params
see [1]
kept support for the previous field names similarly to
docker behavior.

[1]
https://docs.docker.com/storage/bind-mounts/#use-a-read-only-bind-mount
2020-07-13 17:21:37 +00:00
Donny Xia
236ae29e9a Don't consider empty array as "empty" 2020-07-13 10:03:24 -07:00
Kubernetes Prow Robot
5c3bd83252 Merge pull request #2707 from mortent/FixDotInSetterName
Allow setters/substitutions with . in the name
2020-07-13 10:03:20 -07:00
Kubernetes Prow Robot
3674e0a91d Merge pull request #2711 from mortent/SubstitutionWithSameNameSetter
Don't allow creating setter with same name as substitution
2020-07-12 23:02:32 -07:00
Morten Torkildsen
f9631e4bb2 Don't allow creating setter with same name as substitution 2020-07-12 11:28:09 -07:00
Morten Torkildsen
c419c1efc3 Allow setters/substitutions with . in the name 2020-07-11 10:41:27 -07:00
Alexey Odinokov
63f9f79fc0 Fixed incorrect docker mount arguments generation
The previous implementation combined --mount and -v notation
of argument [1] adding :ro to make the read-only mount point.
E.g. the command [2] called docker with the following
params: [3]. As a result instead of the read-only
folder /tmp/source, the read-write folder /tmp/source/:ro/'
is created.

This PR:
1. substitutes ':ro' with correct ',readonly'.
2. changes 'src=' and 'dst=' with 'source=' and 'target=' as
   it is stated in the documentation [1]
3. introduces the ability to EXPLICITLY create a mountpoint
   with read-write access. To do so it's necessary to add
   ',rw=true' to the --mount argument
4. corrects UTs adds some additional coverage for added
   functionality

[1]
https://docs.docker.com/storage/bind-mounts/#use-a-read-only-bind-mount

[2]
kustomize fn run ./d --mount type=bind,src=$(pwd)/test/,dst=/tmp/source/

[3]
--mount type=bind,src=/home/ubuntu/kpt-functions-catalog/functions/ts/test/,dst=/tmp/source/:ro
2020-07-11 17:03:44 +00:00
jregan
33e68c0f97 Removing YAMLSupport==false code path.
This continues work on the master and v3.8.* branches
to eliminate apimachinery dependence.
2020-07-10 19:06:26 -07:00
Kubernetes Prow Robot
556eb48651 Merge pull request #2706 from mortent/FixCmdConfigGoMod
Fix go.mod file in cmd/config
2020-07-10 18:53:22 -07:00
Morten Torkildsen
5b26c3b4cc Fix go.mod file in cmd/config 2020-07-10 17:14:49 -07:00
Donny Xia
42e19d610a Improve cleanup 2020-07-08 11:08:19 -07:00
dependabot[bot]
950b1c895f Bump npm-registry-fetch from 4.0.2 to 4.0.5 in /api/internal/crawl/ui
Bumps [npm-registry-fetch](https://github.com/npm/registry-fetch) from 4.0.2 to 4.0.5.
- [Release notes](https://github.com/npm/registry-fetch/releases)
- [Changelog](https://github.com/npm/npm-registry-fetch/blob/latest/CHANGELOG.md)
- [Commits](https://github.com/npm/registry-fetch/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-08 00:49:07 +00:00
Kubernetes Prow Robot
ca5feb7751 Merge pull request #2700 from jijiew/win-seperator
modify the byteioreader to handler windows line ending.
2020-07-07 10:13:58 -07:00
Jijie Wei
488a88ec6e modify the bytereader to handler windows line ending. 2020-07-07 09:49:17 -07:00
Morten Torkildsen
fd3a4a88be Merge pull request #2699 from mortent/ReturnCmdConfigRedirects
Return go.mod replace directives
2020-07-06 21:28:37 -07:00
Morten Torkildsen
e6147347a8 Return go.mod replace directives 2020-07-06 21:12:32 -07:00
Ioannis Androulidakis
1b531c6ac7 docs: Add guide for components
Extend the list of Kustomize guides available in the official website
with one about components, so that users can familiarize with this use
case and feature.

Signed-off-by: Ioannis Androulidakis <ioannis@arrikto.com>
2020-07-06 23:15:49 +03:00
Donny Xia
f6cac7e7e8 Add newline to the end of file 2020-07-06 09:38:31 -07:00
guoxudong
fe0577a15f add favicons 2020-07-06 09:42:23 +08:00
guoxudong
f68740be66 add favicons 2020-07-06 09:42:09 +08:00
Donny Xia
c2ccfd72ad Update readme 2020-07-01 12:55:38 -07:00
Donny Xia
6d324d70c4 Add benchmark for containerized KRM function in kustomize 2020-07-01 12:47:16 -07:00
Jijie Wei
e32aa8ddb2 revert generated doc change 2020-06-23 14:22:09 -07:00
Jijie Wei
b92de5cb80 revert change in generated doc 2020-06-23 14:17:39 -07:00
Jijie Wei
ecfa732a04 doc for kustomize config delete setter 2020-06-23 13:47:19 -07:00
398 changed files with 13956 additions and 2203 deletions

View File

@@ -14,8 +14,8 @@ all: verify-kustomize
verify-kustomize: \
lint-kustomize \
test-unit-kustomize-all \
test-examples-kustomize-against-HEAD
# test-examples-kustomize-against-3.7.0
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.0
# The following target referenced by a file in
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
@@ -23,10 +23,10 @@ verify-kustomize: \
prow-presubmit-check: \
lint-kustomize \
test-unit-kustomize-all \
test-examples-kustomize-against-HEAD \
test-unit-cmd-all \
test-go-mod
# test-examples-kustomize-against-3.7.0 \
test-go-mod \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.0
.PHONY: verify-kustomize-e2e
verify-kustomize-e2e: test-examples-e2e-kustomize
@@ -233,10 +233,10 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh HEAD
.PHONY:
test-examples-kustomize-against-3.7.0: $(MYGOBIN)/mdrip
test-examples-kustomize-against-3.8.0: $(MYGOBIN)/mdrip
( \
set -e; \
tag=v3.7.0; \
tag=v3.8.0; \
/bin/rm -f $(MYGOBIN)/kustomize; \
echo "Installing kustomize $$tag."; \
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@$${tag}; \

View File

@@ -8,10 +8,10 @@ import (
"regexp"
"strings"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/api/filters/imagetag"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -31,18 +31,18 @@ func (p *ImageTagTransformerPlugin) Config(
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
for _, r := range m.Resources() {
for _, path := range p.FieldSpecs {
if !r.OrgId().IsSelected(&path.Gvk) {
continue
}
err := transform.MutateField(
r.Map(), path.PathSlice(), false, p.mutateImage)
if err != nil {
return err
}
}
// Kept for backward compatibility
if err := p.findAndReplaceImage(r.Map()); err != nil && r.OrgId().Kind != `CustomResourceDefinition` {
// If you're here because someone expected any field containing
// the string "containers" or "initContainers" to get an image
// update (not just spec/template/spec/containers[], etc.) then
// a code change is needed. See api/filters/imagetag/legacy
// for the start of an implementation that won't use an
// allowlist like FsSlice, and instead walks the object looking
// for fields named containers or initContainers.
err := filtersutil.ApplyToJSON(imagetag.Filter{
ImageTag: p.ImageTag,
FsSlice: p.FieldSpecs,
}, r)
if err != nil {
return err
}
}

View File

@@ -5,13 +5,11 @@ package builtins
import (
"fmt"
"strings"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
@@ -21,22 +19,12 @@ import (
type NamespaceTransformerPlugin struct {
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
// YAMLSupport can be set to true to use the kyaml filter instead of the
// kunstruct transformer.
// TODO: change the default to use kyaml when it is stable
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *NamespaceTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Namespace = ""
p.FieldSpecs = nil
if !strings.Contains(string(c), "yamlSupport") {
// If not explicitly denied,
// activate kyaml-based transformation.
p.YAMLSupport = true
}
return yaml.Unmarshal(c, p)
}
@@ -49,31 +37,13 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
// Don't mutate empty objects?
continue
}
id := r.OrgId()
if p.YAMLSupport {
// use the new style transform
err := filtersutil.ApplyToJSON(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
}, r)
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
}
}
err := filtersutil.ApplyToJSON(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
}, r)
if err != nil {
return err
}
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
if len(matches) != 1 {
return fmt.Errorf(

View File

@@ -5,7 +5,6 @@ package builtins
import (
"fmt"
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
@@ -24,8 +23,6 @@ type PatchJson6902TransformerPlugin struct {
Target types.PatchTarget `json:"target,omitempty" yaml:"target,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchJson6902TransformerPlugin) Config(
@@ -35,11 +32,6 @@ func (p *PatchJson6902TransformerPlugin) Config(
if err != nil {
return err
}
if !strings.Contains(string(c), "yamlSupport") {
// If not explicitly denied,
// activate kyaml-based transformation.
p.YAMLSupport = true
}
if p.Target.Name == "" {
return fmt.Errorf("must specify the target name")
}
@@ -93,22 +85,9 @@ func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
if err != nil {
return err
}
if !p.YAMLSupport {
rawObj, err := obj.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := p.decodedPatch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.JsonOp)
}
return obj.UnmarshalJSON(modifiedObj)
} else {
return filtersutil.ApplyToJSON(patchjson6902.Filter{
Patch: p.JsonOp,
}, obj)
}
return filtersutil.ApplyToJSON(patchjson6902.Filter{
Patch: p.JsonOp,
}, obj)
}
func NewPatchJson6902TransformerPlugin() resmap.TransformerPlugin {

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
@@ -20,8 +21,6 @@ type PatchStrategicMergeTransformerPlugin struct {
loadedPatches []*resource.Resource
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchStrategicMergeTransformerPlugin) Config(
@@ -31,11 +30,6 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
if err != nil {
return err
}
if !strings.Contains(string(c), "yamlSupport") {
// If not explicitly denied,
// activate kyaml-based transformation.
p.YAMLSupport = true
}
if len(p.Paths) == 0 && p.Patches == "" {
return fmt.Errorf("empty file path and empty patch content")
}
@@ -79,24 +73,34 @@ func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error
if err != nil {
return err
}
if !p.YAMLSupport {
err = target.Patch(patch.Copy())
} else {
patchCopy := patch.DeepCopy()
patchCopy.SetName(target.GetName())
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)
}
patchCopy := patch.DeepCopy()
patchCopy.SetName(target.GetName())
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

View File

@@ -8,7 +8,6 @@ import (
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
@@ -24,8 +23,6 @@ type PatchTransformerPlugin struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchTransformerPlugin) Config(
@@ -34,11 +31,6 @@ func (p *PatchTransformerPlugin) Config(
if err != nil {
return err
}
if !strings.Contains(string(c), "yamlSupport") {
// If not explicitly denied,
// activate kyaml-based transformation.
p.YAMLSupport = true
}
p.Patch = strings.TrimSpace(p.Patch)
if p.Patch == "" && p.Path == "" {
return fmt.Errorf(
@@ -78,11 +70,11 @@ func (p *PatchTransformerPlugin) Config(
}
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
return p.transformStrategicMerge(m, p.loadedPatch)
} else {
return p.transformJson6902(m, p.decodedPatch)
}
}
@@ -116,20 +108,15 @@ func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch
}
// applySMPatch applies the provided strategic merge patch to the
// given resource. Depending on the value of YAMLSupport, it will either
// use the legacy implementation or the kyaml-based solution.
// given resource.
func (p *PatchTransformerPlugin) applySMPatch(resource, patch *resource.Resource) error {
if !p.YAMLSupport {
return resource.Patch(patch.Copy())
} else {
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
return filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, resource)
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
return filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, resource)
}
// transformJson6902 applies the provided json6902 patch
@@ -138,13 +125,14 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
if p.Target == nil {
return fmt.Errorf("must specify a target for patch %s", p.Patch)
}
resources, err := m.Select(*p.Target)
if err != nil {
return err
}
for _, res := range resources {
err = p.applyJson6902Patch(res, patch)
err = filtersutil.ApplyToJSON(patchjson6902.Filter{
Patch: p.Patch,
}, res)
if err != nil {
return err
}
@@ -152,28 +140,6 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
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)
}
}
// jsonPatchFromBytes loads a Json 6902 patch from
// a bytes input
func jsonPatchFromBytes(

View File

@@ -5,31 +5,28 @@ package builtins
import (
"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/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
// Add the given prefix and suffix to the field.
type PrefixSuffixTransformerPlugin struct {
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
FieldSpecs types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
// Not placed in a file yet due to lack of demand.
var prefixSuffixFieldSpecsToSkip = []types.FieldSpec{
{
Gvk: resid.Gvk{Kind: "CustomResourceDefinition"},
},
{
Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"},
},
// A Gvk skip list for prefix/suffix modification.
// hard coded for now - eventually should be part of config.
var prefixSuffixFieldSpecsToSkip = types.FsSlice{
{Gvk: resid.Gvk{Kind: "CustomResourceDefinition"}},
{Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"}},
{Gvk: resid.Gvk{Kind: "Namespace"}},
}
func (p *PrefixSuffixTransformerPlugin) Config(
@@ -48,29 +45,24 @@ func (p *PrefixSuffixTransformerPlugin) Config(
}
func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
// Even if both the Prefix and Suffix are empty we want
// to proceed with the transformation. This allows to add contextual
// information to the resources (AddNamePrefix and AddNameSuffix).
for _, r := range m.Resources() {
// TODO: move this test into the filter (i.e. make a better filter)
if p.shouldSkip(r.OrgId()) {
// Don't change the actual definition
// of a CRD.
continue
}
id := r.OrgId()
// current default configuration contains
// only one entry: "metadata/name" with no GVK
for _, path := range p.FieldSpecs {
if !id.IsSelected(&path.Gvk) {
// With the currrent default configuration,
// because no Gvk is specified, so a wild
// card
for _, fs := range p.FieldSpecs {
// TODO: this is redundant to filter (but needed for now)
if !id.IsSelected(&fs.Gvk) {
continue
}
if smellsLikeANameChange(&path) {
// TODO: move this test into the filter.
if smellsLikeANameChange(&fs) {
// "metadata/name" is the only field.
// this will add a prefix and a suffix
// to the resource even if those are
@@ -78,15 +70,11 @@ func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
r.AddNamePrefix(p.Prefix)
r.AddNameSuffix(p.Suffix)
}
// the addPrefixSuffix method will not
// change the name if both the prefix and suffix
// are empty.
err := transform.MutateField(
r.Map(),
path.PathSlice(),
path.CreateIfNotPresent,
p.addPrefixSuffix)
err := filtersutil.ApplyToJSON(prefixsuffix.Filter{
Prefix: p.Prefix,
Suffix: p.Suffix,
FieldSpec: fs,
}, r)
if err != nil {
return err
}
@@ -99,8 +87,7 @@ func smellsLikeANameChange(fs *types.FieldSpec) bool {
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 {
if id.IsSelected(&path.Gvk) {
return true
@@ -109,15 +96,6 @@ func (p *PrefixSuffixTransformerPlugin) shouldSkip(
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 {
return &PrefixSuffixTransformerPlugin{}
}

View File

@@ -6,7 +6,8 @@ package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/filters/replicacount"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
@@ -30,18 +31,24 @@ func (p *ReplicaCountTransformerPlugin) Config(
func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
found := false
for i, replicaSpec := range p.FieldSpecs {
matcher := p.createMatcher(i)
for _, fs := range p.FieldSpecs {
matcher := p.createMatcher(fs)
matchOriginal := m.GetMatchingResourcesByOriginalId(matcher)
matchCurrent := m.GetMatchingResourcesByCurrentId(matcher)
for _, res := range append(matchOriginal, matchCurrent...) {
resList := append(
matchOriginal, m.GetMatchingResourcesByCurrentId(matcher)...)
if len(resList) > 0 {
found = true
err := transform.MutateField(
res.Map(), replicaSpec.PathSlice(),
replicaSpec.CreateIfNotPresent, p.addReplicas)
if err != nil {
return err
for _, r := range resList {
// There are redundant checks in the filter
// that we'll live with until resolution of
// https://github.com/kubernetes-sigs/kustomize/issues/2506
err := filtersutil.ApplyToJSON(replicacount.Filter{
Replica: p.Replica,
FieldSpec: fs,
}, r)
if err != nil {
return err
}
}
}
}
@@ -59,30 +66,12 @@ func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
}
// Match Replica.Name and FieldSpec
func (p *ReplicaCountTransformerPlugin) createMatcher(i int) resmap.IdMatcher {
func (p *ReplicaCountTransformerPlugin) createMatcher(fs types.FieldSpec) resmap.IdMatcher {
return func(r resid.ResId) bool {
return r.Name == p.Replica.Name &&
r.Gvk.IsSelected(&p.FieldSpecs[i].Gvk)
return r.Name == p.Replica.Name && r.Gvk.IsSelected(&fs.Gvk)
}
}
func (p *ReplicaCountTransformerPlugin) addReplicas(in interface{}) (interface{}, error) {
switch m := in.(type) {
case int64:
// Was already in the field.
case map[string]interface{}:
if len(m) != 0 {
// A map was already in the replicas field, don't want to
// discard this data silently.
return nil, fmt.Errorf("%#v is expected to be %T", in, m)
}
// Just got added, default type is map, but we can return anything.
default:
return nil, fmt.Errorf("%#v is expected to be %T", in, m)
}
return p.Replica.Count, nil
}
func NewReplicaCountTransformerPlugin() resmap.TransformerPlugin {
return &ReplicaCountTransformerPlugin{}
}

View File

@@ -30,9 +30,9 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
for _, k := range keys {
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: fsslice.SetEntry(k, f.Annotations[k], yaml.StringTag),
SetValue: filtersutil.SetEntry(k, f.Annotations[k], yaml.StringTag),
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
CreateTag: "!!map",
CreateTag: "!!map", // TODO: change to yaml.NodeTagMap
}); err != nil {
return nil, err
}

View File

@@ -0,0 +1,6 @@
// 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

View File

@@ -0,0 +1,61 @@
// 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
}

View File

@@ -1,24 +1,27 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
package fieldspec
import (
"strings"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// fieldSpecFilter applies a single fieldSpec to a single object
// fieldSpecFilter stores internal state and should not be reused
type fieldSpecFilter struct {
var _ yaml.Filter = Filter{}
// Filter applies a single fieldSpec to a single object
// Filter stores internal state and should not be reused
type Filter struct {
// FieldSpec contains the path to the value to set.
FieldSpec types.FieldSpec `yaml:"fieldSpec"`
// Set the field using this function
SetValue SetFn
SetValue filtersutil.SetFn
// CreateKind defines the type of node to create if the field is not found
CreateKind yaml.Kind
@@ -29,7 +32,7 @@ type fieldSpecFilter struct {
path []string
}
func (fltr fieldSpecFilter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
// check if the FieldSpec applies to the object
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
return obj, errors.Wrap(err)
@@ -38,12 +41,12 @@ func (fltr fieldSpecFilter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
if err := fltr.filter(obj); err != nil {
s, _ := obj.String()
return nil, errors.WrapPrefixf(err,
"obj %v at path %v", s, fltr.FieldSpec.Path)
"obj '%s' at path '%v'", s, fltr.FieldSpec.Path)
}
return obj, nil
}
func (fltr fieldSpecFilter) filter(obj *yaml.RNode) error {
func (fltr Filter) filter(obj *yaml.RNode) error {
if len(fltr.path) == 0 {
// found the field -- set its value
return fltr.SetValue(obj)
@@ -53,24 +56,27 @@ func (fltr fieldSpecFilter) filter(obj *yaml.RNode) error {
return fltr.seq(obj)
case yaml.MappingNode:
return fltr.field(obj)
default:
return errors.Errorf("expected sequence or mapping node")
}
// not found -- this might be an error since the type doesn't match
return errors.Errorf("unsupported yaml node")
}
// field calls filter on the field matching the next path element
func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
func (fltr Filter) field(obj *yaml.RNode) error {
fieldName, isSeq := isSequenceField(fltr.path[0])
// lookup the field matching the next path element
var lookupField yaml.Filter
var kind yaml.Kind
var tag string
tag := "" // TODO: change to yaml.NodeTagEmpty
switch {
case !fltr.FieldSpec.CreateIfNotPresent || fltr.CreateKind == 0 || isSeq:
// dont' create the field if we don't find it
lookupField = yaml.Lookup(fieldName)
if isSeq {
// The query path thinks this field should be a sequence;
// accept this hint for use later if the tag is NodeTagNull.
kind = yaml.SequenceNode
}
case len(fltr.path) <= 1:
// create the field if it is missing: use the provided node kind
lookupField = yaml.LookupCreate(fltr.CreateKind, fieldName)
@@ -80,7 +86,7 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
// create the field if it is missing: must be a mapping node
lookupField = yaml.LookupCreate(yaml.MappingNode, fieldName)
kind = yaml.MappingNode
tag = "!!map"
tag = "!!map" // TODO: change to yaml.NodeTagMap
}
// locate (or maybe create) the field
@@ -91,7 +97,7 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
// if the value exists, but is null, then change it to the creation type
// TODO: update yaml.LookupCreate to support this
if field.YNode().Tag == "!!null" {
if field.YNode().Tag == "!!null" { // TODO: change to yaml.NodeTagNull
field.YNode().Kind = kind
field.YNode().Tag = tag
}
@@ -104,9 +110,9 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
}
// seq calls filter on all sequence elements
func (fltr fieldSpecFilter) seq(obj *yaml.RNode) error {
func (fltr Filter) seq(obj *yaml.RNode) error {
if err := obj.VisitElements(func(node *yaml.RNode) error {
// recurse on each element -- re-allocating a fieldSpecFilter is
// recurse on each element -- re-allocating a Filter is
// not strictly required, but is more consistent with field
// and less likely to have side effects
// keep the entire path -- it does not contain parts for sequences

View File

@@ -0,0 +1,482 @@
// 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': " +
"expected sequence or mapping 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,
},
},
{
name: "successfully set field on array entry no sequence hint",
fieldSpec: `
path: spec/containers/image
version: v1
kind: Bar
`,
input: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: foo
`,
expected: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "successfully set field on array entry with sequence hint",
fieldSpec: `
path: spec/containers[]/image
version: v1
kind: Bar
`,
input: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: foo
`,
expected: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "failure to set field on array entry with sequence hint in path",
fieldSpec: `
path: spec/containers[]/image
version: v1
kind: Bar
`,
input: `
apiVersion: v1
kind: Bar
spec:
containers:
`,
expected: `
apiVersion: v1
kind: Bar
spec:
containers: []
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "failure to set field on array entry, no sequence hint in path",
fieldSpec: `
path: spec/containers/image
version: v1
kind: Bar
`,
input: `
apiVersion: v1
kind: Bar
spec:
containers:
`,
expected: `
apiVersion: v1
kind: Bar
spec:
containers:
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
error: "obj '' at path 'spec/containers/image': expected sequence or mapping node",
},
}
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()
}
})
}
}

View File

@@ -1,6 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
package fieldspec
import (
"strings"

View File

@@ -1,6 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
package fieldspec
import (
"strings"

View File

@@ -0,0 +1,33 @@
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),
})
}
}

View File

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

View File

@@ -8,6 +8,7 @@ import (
"log"
"os"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
@@ -30,7 +31,7 @@ metadata:
}
fltr := fsslice.Filter{
CreateKind: yaml.ScalarNode,
SetValue: fsslice.SetScalar("green"),
SetValue: filtersutil.SetScalar("green"),
FsSlice: []types.FieldSpec{
{Path: "a/b", CreateIfNotPresent: true},
},

View File

@@ -4,48 +4,22 @@
package fsslice
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/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{}
// Filter uses an FsSlice to modify fields on a single object
// Filter ranges over 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 {
// FieldSpecList list of FieldSpecs to set
FsSlice types.FsSlice `yaml:"fsSlice"`
// SetValue is called on each field that matches one of the FieldSpecs
SetValue SetFn
SetValue filtersutil.SetFn
// CreateKind is used to create fields that do not exist
CreateKind yaml.Kind
@@ -59,7 +33,7 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
// apply this FieldSpec
// create a new filter for each iteration because they
// store internal state about the field paths
_, err := (&fieldSpecFilter{
_, err := (&fieldspec.Filter{
FieldSpec: fltr.FsSlice[i],
SetValue: fltr.SetValue,
CreateKind: fltr.CreateKind,

View File

@@ -9,335 +9,77 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
. "sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type TestCase struct {
name string
input string
expected string
filter fsslice.Filter
filter Filter
fsSlice string
error string
}
var tests = []TestCase{
{
name: "update",
var tests = map[string]TestCase{
"empty": {
fsSlice: `
- path: a/b
group: foo
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
apiVersion: foo/v1
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo/v1beta1
apiVersion: foo/v1
kind: Bar
a:
b: e
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "update-kind-not-match",
fsSlice: `
- path: a/b
group: foo
kind: Bar1
`,
input: `
apiVersion: foo/v1beta1
kind: Bar2
a:
b: c
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar2
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "update-group-not-match",
fsSlice: `
- path: a/b
group: foo1
kind: Bar
`,
input: `
apiVersion: foo2/v1beta1
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo2/v1beta1
kind: Bar
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "update-version-not-match",
fsSlice: `
- path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
apiVersion: foo/v1beta2
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo/v1beta2
kind: Bar
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "bad-version",
fsSlice: `
- path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
apiVersion: foo/v1beta2/something
kind: Bar
a:
b: c
`,
expected: `
apiVersion: foo/v1beta2/something
kind: Bar
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "bad-meta",
fsSlice: `
- path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
a:
b: c
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
error: "missing Resource metadata",
},
{
name: "miss-match-type",
fsSlice: `
- path: a/b/c
kind: Bar
`,
input: `
kind: Bar
a:
b: a
`,
error: "obj kind: Bar\na:\n b: a\n at path a/b/c: unsupported yaml node",
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
{
name: "add",
fsSlice: `
- path: a/b/c/d
group: foo
create: true
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a: {b: {c: {d: e}}}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
filter: Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "update-in-sequence",
fsSlice: `
- path: a/b[]/c/d
group: foo
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c:
d: a
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c:
d: e
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
},
},
// Don't create a sequence
{
name: "empty-sequence-no-create",
fsSlice: `
- path: a/b[]/c/d
group: foo
create: true
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
// Create a new field for an element in a sequence
{
name: "empty-sequence-create",
fsSlice: `
- path: a/b[]/c/d
group: foo
create: true
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c: {}
`,
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c: {d: e}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "group v1",
"two": {
fsSlice: `
- path: a/b
group: v1
group: foo
version: 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
- path: q/r[]/s/t
group: foo
version: v1
create: true
kind: Bar
`,
input: `
apiVersion: v1
apiVersion: foo/v1
kind: Bar
q:
r:
- s: {}
`,
expected: `
apiVersion: v1
apiVersion: foo/v1
kind: Bar
q:
r:
- s: {t: e}
a:
b: e
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
filter: 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) {
func TestFilter(t *testing.T) {
for name := range tests {
test := tests[name]
t.Run(name, func(t *testing.T) {
err := yaml.Unmarshal([]byte(test.fsSlice), &test.filter.FsSlice)
if !assert.NoError(t, err) {
t.FailNow()

View File

@@ -4,17 +4,24 @@
package imagetag
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Filter modifies an "image tag", the value used to specify the
// name, tag, version digest etc. of (docker) container images
// used by a pod template.
type Filter struct {
// imageTag is the tag we want to apply to the inputs
// The name of the image is used as a key, and other fields
// can specify a new name, tag, etc.
ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field
// FsSlice contains the FieldSpecs to locate an image field,
// e.g. Path: "spec/myContainers[]/image"
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
@@ -26,6 +33,12 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
}
func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
// FsSlice is an allowlist, not a denyList, so to deny
// something via configuration a new config mechanism is
// needed. Until then, hardcode it.
if f.isOnDenyList(node) {
return node, nil
}
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: updateImageTagFn(f.ImageTag),
@@ -35,7 +48,19 @@ func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
return node, nil
}
func updateImageTagFn(imageTag types.Image) fsslice.SetFn {
func (f Filter) isOnDenyList(node *yaml.RNode) bool {
meta, err := node.GetMeta()
if err != nil {
// A missing 'meta' field will cause problems elsewhere;
// ignore it here to keep the signature simple.
return false
}
// Ignore CRDs
// https://github.com/kubernetes-sigs/kustomize/issues/890
return meta.Kind == `CustomResourceDefinition`
}
func updateImageTagFn(imageTag types.Image) filtersutil.SetFn {
return func(node *yaml.RNode) error {
return node.PipeE(imageTagUpdater{
ImageTag: imageTag,

View File

@@ -19,6 +19,162 @@ func TestImageTagUpdater_Filter(t *testing.T) {
filter Filter
fsSlice types.FsSlice
}{
"ignore CustomResourceDefinition": {
input: `
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: whatever
spec:
containers:
- image: whatever
`,
expectedOutput: `
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: whatever
spec:
containers:
- image: whatever
`,
filter: Filter{
ImageTag: types.Image{
Name: "whatever",
NewName: "theImageShouldNotChangeInACrd",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/containers/image",
},
},
},
"legacy multiple images in containers": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: nginx:2.1.2
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache@12345
- image: apache@12345
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/containers/image",
},
},
},
"legacy both containers and initContainers": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: tomcat:1.2.3
initContainers:
- image: nginx:1.2.1
- image: apache:1.2.3
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache:3.2.1
- image: tomcat:1.2.3
initContainers:
- image: apache:3.2.1
- image: apache:1.2.3
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
NewTag: "3.2.1",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/containers/image",
},
{
Path: "spec/initContainers/image",
},
},
},
"legacy updates at multiple depths": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: nginx:1.2.1
- image: tomcat:1.2.3
template:
spec:
initContainers:
- image: nginx:1.2.1
- image: apache:1.2.3
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
containers:
- image: apache:3.2.1
- image: tomcat:1.2.3
template:
spec:
initContainers:
- image: apache:3.2.1
- image: apache:1.2.3
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
NewTag: "3.2.1",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/containers/image",
},
{
Path: "spec/template/spec/initContainers/image",
},
},
},
"update with digest": {
input: `
apiVersion: example.com/v1
@@ -49,6 +205,7 @@ spec:
},
},
},
"multiple matches in sequence": {
input: `
apiVersion: example.com/v1
@@ -85,6 +242,422 @@ spec:
},
},
},
"new Tag": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:latest
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx
name: nginx-notag
- image: nginx@sha256:111111111111111111
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:v2
name: nginx-tagged
- image: nginx:v2
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx:v2
name: nginx-notag
- image: nginx:v2
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewTag: "v2",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers[]/image",
},
{
Path: "spec/template/spec/initContainers[]/image",
},
},
},
"newImage": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:latest
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx
name: nginx-notag
- image: nginx@sha256:111111111111111111
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: busybox:1.7.9
name: nginx-tagged
- image: busybox:latest
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: busybox
name: nginx-notag
- image: busybox@sha256:111111111111111111
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "busybox",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers[]/image",
},
{
Path: "spec/template/spec/initContainers[]/image",
},
},
},
"newImageAndTag": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:latest
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx
name: nginx-notag
- image: nginx@sha256:111111111111111111
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: busybox:v3
name: nginx-tagged
- image: busybox:v3
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: busybox:v3
name: nginx-notag
- image: busybox:v3
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "busybox",
NewTag: "v3",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers[]/image",
},
{
Path: "spec/template/spec/initContainers[]/image",
},
},
},
"newDigest": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:latest
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx
name: nginx-notag
- image: nginx@sha256:111111111111111111
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx@sha256:222222222222222222
name: nginx-tagged
- image: nginx@sha256:222222222222222222
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx@sha256:222222222222222222
name: nginx-notag
- image: nginx@sha256:222222222222222222
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
Digest: "sha256:222222222222222222",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers/image",
},
{
Path: "spec/template/spec/initContainers/image",
},
},
},
"newImageAndDigest": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:latest
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: nginx
name: nginx-notag
- image: nginx@sha256:111111111111111111
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: busybox@sha256:222222222222222222
name: nginx-tagged
- image: busybox@sha256:222222222222222222
name: nginx-latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
initContainers:
- image: busybox@sha256:222222222222222222
name: nginx-notag
- image: busybox@sha256:222222222222222222
name: nginx-sha256
- image: alpine:1.8.0
name: init-alpine
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "busybox",
Digest: "sha256:222222222222222222",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers[]/image",
},
{
Path: "spec/template/spec/initContainers[]/image",
},
},
},
"emptyContainers": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
containers:
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
containers: []
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewTag: "v2",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/containers[]/image",
// CreateIfNotPresent: true,
},
},
},
"tagWithBraces": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: some.registry.io/my-image:{GENERATED_TAG}
name: my-image
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: some.registry.io/my-image:my-fixed-tag
name: my-image
`,
filter: Filter{
ImageTag: types.Image{
Name: "some.registry.io/my-image",
NewTag: "my-fixed-tag",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers[]/image",
},
{
Path: "spec/template/spec/initContainers[]/image",
},
},
},
}
for tn, tc := range testCases {

View File

@@ -31,9 +31,9 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
for _, k := range keys {
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: fsslice.SetEntry(k, f.Labels[k], yaml.StringTag),
SetValue: filtersutil.SetEntry(k, f.Labels[k], yaml.StringTag),
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
CreateTag: "!!map",
CreateTag: "!!map", // TODO: change to yaml.NodeTagMap
}); err != nil {
return nil, err
}

View File

@@ -4,6 +4,8 @@
package namespace
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/types"
"sigs.k8s.io/kustomize/kyaml/kio"
@@ -42,7 +44,7 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
// transformations based on data -- :)
err := node.PipeE(fsslice.Filter{
FsSlice: ns.FsSlice,
SetValue: fsslice.SetScalar(ns.Namespace),
SetValue: filtersutil.SetScalar(ns.Namespace),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
CreateTag: yaml.StringTag,
})
@@ -73,7 +75,7 @@ func (ns Filter) hacks(obj *yaml.RNode) error {
// if they are cluster scoped through either an annotation on the resources,
// or through inlined OpenAPI on the resource as a YAML comment.
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
gvk := fsslice.GetGVK(meta)
gvk := fieldspec.GetGVK(meta)
if !gvk.IsNamespaceableKind() {
return nil
}
@@ -81,7 +83,7 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) erro
FsSlice: []types.FieldSpec{
{Path: types.MetadataNamespacePath, CreateIfNotPresent: true},
},
SetValue: fsslice.SetScalar(ns.Namespace),
SetValue: filtersutil.SetScalar(ns.Namespace),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
}
_, err := f.Filter(obj)

View File

@@ -9,12 +9,11 @@ import (
"os"
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
)
func ExampleFilter() {
fss := builtinconfig.MakeDefaultConfig().NamePrefix
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.ByteReader{Reader: bytes.NewBufferString(`
apiVersion: example.com/v1
@@ -27,7 +26,8 @@ kind: Bar
metadata:
name: instance
`)}},
Filters: []kio.Filter{prefixsuffix.Filter{Prefix: "baz-", FsSlice: fss}},
Filters: []kio.Filter{prefixsuffix.Filter{
Prefix: "baz-", FieldSpec: types.FieldSpec{Path: "metadata/name"}}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
}.Execute()
if err != nil {

View File

@@ -6,7 +6,8 @@ package prefixsuffix
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"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"
@@ -17,28 +18,26 @@ type Filter struct {
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
FieldSpec types.FieldSpec `json:"fieldSpec,omitempty" yaml:"fieldSpec,omitempty"`
}
var _ kio.Filter = Filter{}
func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(ns.run)).Filter(nodes)
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(f.run)).Filter(nodes)
}
// Run runs the filter on a single node rather than a slice
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
// transformations based on data -- :)
err := node.PipeE(fsslice.Filter{
FsSlice: ns.FsSlice,
SetValue: ns.set,
func (f Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
err := node.PipeE(fieldspec.Filter{
FieldSpec: f.FieldSpec,
SetValue: f.evaluateField,
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
CreateTag: yaml.StringTag,
})
return node, err
}
func (ns Filter) set(node *yaml.RNode) error {
return fsslice.SetScalar(fmt.Sprintf(
"%s%s%s", ns.Prefix, node.YNode().Value, ns.Suffix))(node)
func (f Filter) evaluateField(node *yaml.RNode) error {
return filtersutil.SetScalar(fmt.Sprintf(
"%s%s%s", f.Prefix, node.YNode().Value, f.Suffix))(node)
}

View File

@@ -9,14 +9,12 @@ import (
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
var tests = []TestCase{
{
name: "prefix",
var tests = map[string]TestCase{
"prefix": {
input: `
apiVersion: example.com/v1
kind: Foo
@@ -40,10 +38,10 @@ metadata:
name: foo-instance
`,
filter: prefixsuffix.Filter{Prefix: "foo-"},
fs: types.FieldSpec{Path: "metadata/name"},
},
{
name: "suffix",
"suffix": {
input: `
apiVersion: example.com/v1
kind: Foo
@@ -67,10 +65,10 @@ metadata:
name: instance-foo
`,
filter: prefixsuffix.Filter{Suffix: "-foo"},
fs: types.FieldSpec{Path: "metadata/name"},
},
{
name: "prefix-suffix",
"prefix-suffix": {
input: `
apiVersion: example.com/v1
kind: Foo
@@ -94,10 +92,10 @@ metadata:
name: bar-instance-foo
`,
filter: prefixsuffix.Filter{Prefix: "bar-", Suffix: "-foo"},
fs: types.FieldSpec{Path: "metadata/name"},
},
{
name: "data-fieldspecs",
"data-fieldspecs": {
input: `
apiVersion: example.com/v1
kind: Foo
@@ -119,7 +117,7 @@ a:
apiVersion: example.com/v1
kind: Foo
metadata:
name: foo-instance
name: instance
a:
b:
c: foo-d
@@ -127,35 +125,28 @@ a:
apiVersion: example.com/v1
kind: Bar
metadata:
name: foo-instance
name: instance
a:
b:
c: foo-d
`,
filter: prefixsuffix.Filter{Prefix: "foo-"},
fsslice: []types.FieldSpec{
{
Path: "a/b/c",
},
},
fs: types.FieldSpec{Path: "a/b/c"},
},
}
type TestCase struct {
name string
input string
expected string
filter prefixsuffix.Filter
fsslice types.FsSlice
fs types.FieldSpec
}
var config = builtinconfig.MakeDefaultConfig()
func TestFilter(t *testing.T) {
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
test.filter.FsSlice = append(config.NamePrefix, test.fsslice...)
for name := range tests {
test := tests[name]
t.Run(name, func(t *testing.T) {
test.filter.FieldSpec = test.fs
if !assert.Equal(t,
strings.TrimSpace(test.expected),
strings.TrimSpace(

View File

@@ -33,10 +33,8 @@ spec:
Count: 42,
Name: "instance",
},
FsSlice: types.FsSlice{
{
Path: "spec/template/replicas",
},
FieldSpec: types.FieldSpec{
Path: "spec/template/replicas",
},
}},
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},

View File

@@ -3,7 +3,8 @@ package replicacount
import (
"strconv"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"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"
@@ -11,10 +12,8 @@ import (
// Filter updates/sets replicas fields using the fieldSpecs
type Filter struct {
Replica types.Replica `json:"replica,omitempty" yaml:"replica,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
Replica types.Replica `json:"replica,omitempty" yaml:"replica,omitempty"`
FieldSpec types.FieldSpec `json:"fieldSpec,omitempty" yaml:"fieldSpec,omitempty"`
}
var _ kio.Filter = Filter{}
@@ -23,27 +22,16 @@ func (rc Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(rc.run)).Filter(nodes)
}
// run processes each node individually.
func (rc Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
meta, err := node.GetMeta()
if err != nil {
return nil, err
}
// only update resources where the name matches the Replica name.
if meta.Name != rc.Replica.Name {
return node, nil
}
err = node.PipeE(fsslice.Filter{
FsSlice: rc.FsSlice,
err := node.PipeE(fieldspec.Filter{
FieldSpec: rc.FieldSpec,
SetValue: rc.set,
CreateKind: yaml.ScalarNode, // replicas is a ScalarNode
CreateTag: yaml.IntTag,
CreateTag: yaml.IntTag, // yaml.NodeTagInt
})
return node, err
}
func (rc Filter) set(node *yaml.RNode) error {
return fsslice.SetScalar(strconv.FormatInt(rc.Replica.Count, 10))(node)
return filtersutil.SetScalar(strconv.FormatInt(rc.Replica.Count, 10))(node)
}

View File

@@ -5,19 +5,16 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
func TestFilter(t *testing.T) {
var config = builtinconfig.MakeDefaultConfig()
testCases := map[string]struct {
input string
expected string
filter Filter
fsslice types.FsSlice
}{
"update field": {
input: `
@@ -41,11 +38,7 @@ spec:
Name: "dep",
Count: 42,
},
},
fsslice: types.FsSlice{
{
Path: "spec/replicas",
},
FieldSpec: types.FieldSpec{Path: "spec/replicas"},
},
},
"add field": {
@@ -73,9 +66,7 @@ spec:
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
FieldSpec: types.FieldSpec{
Path: "spec/template/replicas",
CreateIfNotPresent: true,
},
@@ -108,9 +99,7 @@ spec:
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
FieldSpec: types.FieldSpec{
Path: "spec/template/replicas",
CreateIfNotPresent: true,
},
@@ -140,9 +129,7 @@ spec:
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
FieldSpec: types.FieldSpec{
Path: "spec/template/replicas",
},
},
@@ -154,7 +141,6 @@ kind: Custom
metadata:
name: cus
spec:
replicas: 5
template:
replicas: 5
`,
@@ -164,7 +150,6 @@ kind: Custom
metadata:
name: cus
spec:
replicas: 42
template:
replicas: 42
`,
@@ -173,21 +158,13 @@ spec:
Name: "cus",
Count: 42,
},
},
fsslice: types.FsSlice{
{
Path: "spec/template/replicas",
},
{
Path: "spec/replicas",
},
FieldSpec: types.FieldSpec{Path: "spec/template/replicas"},
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
tc.filter.FsSlice = append(config.Replicas, tc.fsslice...)
if !assert.Equal(t,
strings.TrimSpace(tc.expected),
strings.TrimSpace(

View File

@@ -16,6 +16,8 @@ require (
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
sigs.k8s.io/kustomize/kyaml v0.3.4
sigs.k8s.io/kustomize/kyaml v0.4.2
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/kyaml v0.4.2 => ../kyaml

View File

@@ -580,8 +580,6 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/kyaml v0.3.4 h1:RhxnabYltv4mdD5+I7pIaJtae+eaTn4TiZqPT7K+C7A=
sigs.k8s.io/kustomize/kyaml v0.3.4/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw=
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.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=

View File

@@ -515,7 +515,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/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=
sigs.k8s.io/kustomize/kyaml v0.3.4/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw=
sigs.k8s.io/kustomize/kyaml v0.4.1/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@
package target
import (
"bytes"
"encoding/json"
"fmt"
"strings"
@@ -60,7 +59,7 @@ func (kt *KustTarget) Load() error {
return err
}
var k types.Kustomization
err = unmarshal(content, &k)
err = k.Unmarshal(content)
if err != nil {
return err
}
@@ -104,18 +103,8 @@ 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
// per the instructions contained in its kustomiztion instance.
// per the instructions contained in its kustomization instance.
func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
return kt.makeCustomizedResMap()
}

View File

@@ -187,7 +187,7 @@ metadata:
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "foo-ns1-bar",
"name": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},

View File

@@ -5,7 +5,6 @@ package kunstruct
import (
"encoding/json"
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -21,7 +20,7 @@ func NewKustHash() *kustHash {
return &kustHash{}
}
// Hash returns a hash of either a ConfigMap or a Secret
// Hash returns a hash of the given object
func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
u := unstructured.Unstructured{
Object: m.Map(),
@@ -36,15 +35,12 @@ func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
return configMapHash(cm)
case "Secret":
sec, err := unstructuredToSecret(u)
if err != nil {
return "", err
}
return secretHash(sec)
default:
return "", fmt.Errorf(
"type %s is not supported for hashing in %v",
kind, m.Map())
return unstructuredHash(&u)
}
}
@@ -76,6 +72,21 @@ func secretHash(sec *corev1.Secret) (string, error) {
return h, nil
}
// unstructuredHash creates a hash for an arbitrary type.
// All fields of the object are taken into account when generating the hash.
// This is a fallback for when a specalised hash for the type is unavailable.
func unstructuredHash(u *unstructured.Unstructured) (string, error) {
encoded, err := json.Marshal(u.Object)
if err != nil {
return "", err
}
h, err := hasher.Encode(hasher.Hash(string(encoded)))
if err != nil {
return "", err
}
return h, nil
}
// encodeConfigMap encodes a ConfigMap.
// Data, Kind, and Name are taken into account.
// BinaryData is included if it's not empty to avoid useless key in output.

View File

@@ -9,6 +9,7 @@ import (
"testing"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func TestConfigMapHash(t *testing.T) {
@@ -75,6 +76,39 @@ func TestSecretHash(t *testing.T) {
}
}
func TestUnstructuredHash(t *testing.T) {
cases := []struct {
desc string
unstructured *unstructured.Unstructured
hash string
err string
}{
{"minimal", &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "test/v1",
"kind": "TestResource",
"metadata": map[string]string{"name": "my-resource"}},
}, "2tt46d7f79", ""},
{"with spec", &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "test/v1",
"kind": "TestResource",
"metadata": map[string]string{"name": "my-resource"},
"spec": map[string]interface{}{"foo": 1, "bar": "abc"}},
}, "6gc62g4m6k", ""},
}
for _, c := range cases {
h, err := unstructuredHash(c.unstructured)
if SkipRest(t, c.desc, err, c.err) {
continue
}
if c.hash != h {
t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
}
}
}
func TestEncodeConfigMap(t *testing.T) {
cases := []struct {
desc string

View File

@@ -4,7 +4,15 @@
package builtinpluginconsts
const (
// imageFieldSpecs is left empty since `containers` and `initContainers`
// of *ANY* kind in *ANY* path are builtin supported in code
imagesFieldSpecs = ``
imagesFieldSpecs = `
images:
- path: spec/containers[]/image
create: true
- path: spec/initContainers[]/image
create: true
- path: spec/template/spec/containers[]/image
create: true
- path: spec/template/spec/initContainers[]/image
create: true
`
)

View File

@@ -70,7 +70,7 @@ metadata:
apiVersion: v1
kind: Namespace
metadata:
name: p-b-myNs
name: myNs
---
apiVersion: v1
kind: Role
@@ -95,7 +95,7 @@ metadata:
apiVersion: v1
kind: Namespace
metadata:
name: p-myNs2
name: myNs2
`)
}

View File

@@ -39,8 +39,8 @@ resources:
configMapGenerator:
- name: my-configmap
literals:
- testValue=1
- otherValue=10
- testValue=1
- otherValue=10
`)
th.WriteF("/app/base/deploy.yaml", `
apiVersion: v1
@@ -59,13 +59,13 @@ replicas:
- name: storefront
count: 3
resources:
- stub.yaml
- stub.yaml
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- testValue=2
- compValue=5
- testValue=2
- compValue=5
`)
th.WriteF("/app/comp/stub.yaml", `
apiVersion: v1
@@ -156,7 +156,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=9
`),
writeK("/app/prod", `
resources:
@@ -211,8 +211,8 @@ components:
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
literals:
- otherValue=9
`),
writeK("/app/prod", `
resources:
@@ -327,8 +327,8 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- compValue=5
- testValue=2
- compValue=5
- testValue=2
`),
},
runPath: "/app/direct-component",
@@ -360,7 +360,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=9
`),
},
runPath: "/app/prod",
@@ -574,7 +574,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=9
`),
},
runPath: "/app/prod",

View File

@@ -0,0 +1,48 @@
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: []
`)
}

View File

@@ -0,0 +1,215 @@
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestRoleBindingAcrossNamespace(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK("/app", `
resources:
- resource.yaml
nameSuffix: -ns2
`)
th.WriteF("/app/resource.yaml", `
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa1
namespace: ns1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa2
namespace: ns2
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa3
namespace: ns3
---
apiVersion: v1
kind: NotServiceAccount
metadata:
name: my-nsa
namespace: ns1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-role
namespace: ns2
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-role-binding
namespace: ns2
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: my-role
subjects:
- kind: ServiceAccount
name: my-sa1
namespace: ns1
- kind: ServiceAccount
name: my-sa2
namespace: ns2
- kind: ServiceAccount
name: my-sa3
namespace: ns3
- kind: NotServiceAccount
name: my-nsa
namespace: ns1
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa1-ns2
namespace: ns1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa2-ns2
namespace: ns2
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa3-ns2
namespace: ns3
---
apiVersion: v1
kind: NotServiceAccount
metadata:
name: my-nsa-ns2
namespace: ns1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-role-ns2
namespace: ns2
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-role-binding-ns2
namespace: ns2
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: my-role-ns2
subjects:
- kind: ServiceAccount
name: my-sa1-ns2
namespace: ns1
- kind: ServiceAccount
name: my-sa2-ns2
namespace: ns2
- kind: ServiceAccount
name: my-sa3-ns2
namespace: ns3
- kind: NotServiceAccount
name: my-nsa
namespace: ns1
`)
}
func TestRoleBindingAcrossNamespaceWoSubjects(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK("/app", `
resources:
- resource.yaml
nameSuffix: -ns2
`)
th.WriteF("/app/resource.yaml", `
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa1
namespace: ns1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-role
namespace: ns2
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-role-binding
namespace: ns2
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: my-role
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa1-ns2
namespace: ns1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-role-ns2
namespace: ns2
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-role-binding-ns2
namespace: ns2
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: my-role-ns2
`)
}

View File

@@ -10,24 +10,6 @@ import (
"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) {
th.WriteF(path, `
apiVersion: someteam.example.com/v1
@@ -37,53 +19,6 @@ 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) {
th := kusttest_test.MakeEnhancedHarness(t).
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer")
@@ -165,6 +100,78 @@ 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) {
th := kusttest_test.MakeEnhancedHarness(t).
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
@@ -205,3 +212,4 @@ spec:
name: whatever
`)
}
*/

View File

@@ -173,6 +173,9 @@ spec:
`)
}
// The default configuration recognizes image paths starting
// with "spec", not spec2 or spec3, so the latter two specs won't
// have their image entries changed.
func TestTransfomersImageDefaultConfig(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeTransfomersImageBase(th)
@@ -212,25 +215,25 @@ spec2:
template:
spec:
containers:
- image: nginx:v2
- image: nginx:v1
name: nginx3
- image: my-nginx:previous
- image: my-nginx:latest
name: nginx4
spec3:
template:
spec:
initContainers:
- image: my-postgres:v3
- image: postgres:alpine-9
name: postgresdb
- image: my-docker@sha256:25a0d4b4
- image: docker:17-git
name: init-docker
- image: myprivaterepohostname:1234/my/image:v1.0.1
- image: myprivaterepohostname:1234/my/image:latest
name: myImage
- image: myprivaterepohostname:1234/my/image:v1.0.1
- image: myprivaterepohostname:1234/my/image
name: myImage2
- image: my-app-image:v1
name: my-app
- image: my-cool-app:latest
- image: gcr.io:8080/my-project/my-cool-app:latest
name: my-cool-app
`)
}
@@ -299,11 +302,11 @@ spec3:
th.WriteF("/app/base/config/custom.yaml", `
images:
- kind: Custom
path: spec/template/spec/myContainers/image
path: spec/template/spec/myContainers[]/image
- kind: Custom
path: spec2/template/spec/myContainers/image
path: spec2/template/spec/myContainers[]/image
- kind: Custom
path: spec3/template/spec/myInitContainers/image
path: spec3/template/spec/myInitContainers[]/image
`)
}

View File

@@ -611,19 +611,50 @@ func (m *resWrangler) SubsetThatCouldBeReferencedByResource(
inputId := inputRes.CurId()
isInputIdNamespaceable := inputId.IsNamespaceableKind()
rctxm := inputRes.PrefixesSuffixesEquals
subjectNamespaces := getNamespacesForRoleBinding(inputRes)
for _, r := range m.Resources() {
// Need to match more accuratly both at the time of selection and transformation.
// OutmostPrefixSuffixEquals is not accurate enough since it is only using
// the outer most suffix and the last prefix. Use PrefixedSuffixesEquals instead.
resId := r.CurId()
if (!isInputIdNamespaceable || !resId.IsNamespaceableKind() || resId.IsNsEquals(inputId)) &&
r.InSameKustomizeCtx(rctxm) {
if (!isInputIdNamespaceable || !resId.IsNamespaceableKind() || resId.IsNsEquals(inputId) ||
isRoleBindingNamespace(&subjectNamespaces, r.GetNamespace())) && r.InSameKustomizeCtx(rctxm) {
result.append(r)
}
}
return result
}
// isRoleBindingNamespace returns true is the namespace `ns` is in role binding
// namespaces `m`
func isRoleBindingNamespace(m *map[string]bool, ns string) bool {
return (*m)[ns]
}
// getNamespacesForRoleBinding returns referenced ServiceAccount namespaces if the inputRes is
// a RoleBinding
func getNamespacesForRoleBinding(inputRes *resource.Resource) map[string]bool {
res := make(map[string]bool)
if inputRes.GetKind() != "RoleBinding" {
return res
}
subjects, err := inputRes.GetSlice("subjects")
if err != nil || subjects == nil {
return res
}
for _, s := range subjects {
subject := s.(map[string]interface{})
if subject["namespace"] == nil || subject["kind"] == nil ||
subject["kind"].(string) != "ServiceAccount" {
continue
}
res[subject["namespace"].(string)] = true
}
return res
}
func (m *resWrangler) append(res *resource.Resource) {
m.rList = append(m.rList, res)
}

View File

@@ -13,6 +13,178 @@ import (
"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) {
patchGood1 := types.PatchStrategicMerge("patch1.yaml")
patch1 := `

View File

@@ -4,9 +4,6 @@
package kusttest_test
import (
"bytes"
"fmt"
"strconv"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
@@ -20,8 +17,6 @@ import (
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"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.
@@ -130,42 +125,8 @@ func (th *HarnessEnhanced) LoadAndRunTransformer(
func (th *HarnessEnhanced) RunTransformerAndCheckResult(
config, input, expected string) {
for _, b := range []bool{true, false} {
th.t.Run(fmt.Sprintf("yaml-%v", b), func(t *testing.T) {
c, err := toggleYamlSupportField(config, b)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
resMap, err := th.RunTransformer(c, input)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
th.AssertActualEqualsExpected(resMap, expected)
})
}
}
func toggleYamlSupportField(config string, yamlSupport bool) (string, error) {
var out bytes.Buffer
rw := kio.ByteReadWriter{
Reader: bytes.NewBufferString(config),
Writer: &out,
}
err := kio.Pipeline{
Inputs: []kio.Reader{&rw},
Filters: []kio.Filter{
kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
return node.Pipe(yaml.FieldSetter{
Name: "yamlSupport",
StringValue: strconv.FormatBool(yamlSupport),
})
}),
),
},
Outputs: []kio.Writer{&rw},
}.Execute()
return out.String(), err
resMap := th.LoadAndRunTransformer(config, input)
th.AssertActualEqualsExpected(resMap, expected)
}
func (th *HarnessEnhanced) ErrorFromLoadAndRunTransformer(
@@ -178,16 +139,8 @@ type AssertFunc func(t *testing.T, err error)
func (th *HarnessEnhanced) RunTransformerAndCheckError(
config, input string, assertFn AssertFunc) {
for _, b := range []bool{true, false} {
th.t.Run(fmt.Sprintf("yaml-%v", b), func(t *testing.T) {
c, err := toggleYamlSupportField(config, b)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
_, err = th.RunTransformer(c, input)
assertFn(t, err)
})
}
_, err := th.RunTransformer(config, input)
assertFn(th.t, err)
}
func (th *HarnessEnhanced) RunTransformer(
@@ -203,6 +156,7 @@ func (th *HarnessEnhanced) RunTransformerFromResMap(
config string, resMap resmap.ResMap) (resmap.ResMap, error) {
transConfig, err := th.rf.RF().FromBytes([]byte(config))
if err != nil {
th.t.Logf("config: '%s'", config)
th.t.Fatalf("Err: %v", err)
}
g, err := th.pl.LoadTransformer(

View File

@@ -3,6 +3,13 @@
package types
import (
"bytes"
"encoding/json"
"sigs.k8s.io/yaml"
)
const (
KustomizationVersion = "kustomize.config.k8s.io/v1beta1"
KustomizationKind = "Kustomization"
@@ -165,3 +172,20 @@ func (k *Kustomization) EnforceFields() []string {
}
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
}

View File

@@ -0,0 +1,184 @@
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")
}
}

View File

@@ -0,0 +1,65 @@
## 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

View File

@@ -14,6 +14,6 @@ require (
k8s.io/cli-runtime v0.17.3
k8s.io/client-go v0.17.3
k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd
sigs.k8s.io/cli-utils v0.16.0
sigs.k8s.io/kustomize/kyaml v0.4.0
sigs.k8s.io/cli-utils v0.17.0
sigs.k8s.io/kustomize/kyaml v0.4.2
)

View File

@@ -616,14 +616,15 @@ 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/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
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.16.0/go.mod h1:9Jqm9K2W6ShhCxsEuaz6HSRKKOXigPUx3ZfypGgxBLY=
sigs.k8s.io/cli-utils v0.17.0 h1:iQ0nhgU8DZiRphHTErI1IHcHYp2fZaULrrFN4NF3dCc=
sigs.k8s.io/cli-utils v0.17.0/go.mod h1:9Jqm9K2W6ShhCxsEuaz6HSRKKOXigPUx3ZfypGgxBLY=
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/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/kustomize/kyaml v0.4.0 h1:jMQrJOJmiUz5Y018ki0mXWpEreEXjvad1NRfXTdi9vU=
sigs.k8s.io/kustomize/kyaml v0.4.0/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw=
sigs.k8s.io/kustomize/kyaml v0.4.2 h1:9/Tb90gnThv4vgUldZOLnrT+9Esdh7+Og2UIq024Ykg=
sigs.k8s.io/kustomize/kyaml v0.4.2/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw=
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 v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=

View File

@@ -372,6 +372,95 @@ metadata:
name: nginx-deployment
spec:
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"}
`,
},
{
name: "create setter v1",
args: []string{"hubsetter", "my-hub"},
inputOpenAPI: `
`,
input: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name"
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub
`,
expectedOpenAPI: `
`,
expectedResources: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name"
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub # {"type":"","x-kustomize":{"setter":{"name":"hubsetter","value":"my-hub"}}}
`,
},
{
name: "create partial setter v1",
args: []string{"regionsetter", "us-east1-d", "--partial"},
inputOpenAPI: `
`,
input: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name" # {"type":"","x-kustomize":{"partialSetters":[{"name":"projectsetter","value":"project-id"}]}}
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub # {"type":"","x-kustomize":{"setter":{"name":"hubsetter","value":"my-hub"}}}
`,
expectedOpenAPI: `
`,
expectedResources: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name" # {"type":"","x-kustomize":{"partialSetters":[{"name":"projectsetter","value":"project-id"},{"name":"regionsetter","value":"us-east1-d"}]}}
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub # {"type":"","x-kustomize":{"setter":{"name":"hubsetter","value":"my-hub"}}}
`,
},
}

View File

@@ -86,14 +86,17 @@ func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
// extract setter name tokens from pattern enclosed in ${}
re := regexp.MustCompile(`\$\{([^}]*)\}`)
markers := re.FindAll([]byte(r.CreateSubstitution.Pattern), -1)
markers := re.FindAllString(r.CreateSubstitution.Pattern, -1)
if len(markers) == 0 {
return errors.Errorf("unable to find setter or substitution names in pattern, " +
"setter names must be enclosed in ${}")
}
for _, marker := range markers {
name := strings.TrimSuffix(strings.TrimPrefix(string(marker), "${"), "}")
name := strings.TrimSuffix(strings.TrimPrefix(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)
if err != nil {
@@ -112,7 +115,7 @@ func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
r.CreateSubstitution.Values = append(
r.CreateSubstitution.Values,
setters2.Value{Marker: string(marker), Ref: markerRef},
setters2.Value{Marker: marker, Ref: markerRef},
)
}

View File

@@ -408,6 +408,39 @@ spec:
`,
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 {
test := tests[i]

View File

@@ -6,6 +6,7 @@ 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"
)
@@ -16,9 +17,9 @@ func NewDeleteSetterRunner(parent string) *DeleteSetterRunner {
c := &cobra.Command{
Use: "delete-setter DIR NAME",
Args: cobra.MinimumNArgs(2),
Short: "delete values on Resources fields.",
Long: "",
Example: "",
Short: commands.DeleteSetterShort,
Long: commands.DeleteSetterLong,
Example: commands.DeleteSetterExamples,
PreRunE: r.preRunE,
RunE: r.runE,
}

View File

@@ -941,6 +941,70 @@ spec:
`,
errMsg: "cyclic substitution detected with name my-nested-subst",
},
{
name: "set v1 setter asm",
args: []string{"profilesetter", "my-asm"},
out: "set 1 fields\n",
inputOpenAPI: `
`,
input: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name"
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub:
- --gcr.io/asm-testing
- --gcr.io/asm-testing2
`,
expectedOpenAPI: `
`,
expectedResources: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name"
spec:
profile: my-asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"my-asm"}}}
hub:
- --gcr.io/asm-testing
- --gcr.io/asm-testing2
`,
},
{
name: "set v1 partial setter",
args: []string{"gcloud.core.project", "my-project"},
out: "set 1 fields\n",
inputOpenAPI: `
`,
input: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name" # {"type":"string","x-kustomize":{"partialSetters":[{"name":"gcloud.core.project","value":"project-id"},{"name":"cluster-name","value":"cluster-name"},{"name":"gcloud.compute.zone","value":"us-east1-d"}]}}
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub:
- --gcr.io/asm-testing
- --gcr.io/asm-testing2
`,
expectedOpenAPI: `
`,
expectedResources: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "my-project/us-east1-d/cluster-name" # {"type":"string","x-kustomize":{"partialSetters":[{"name":"gcloud.core.project","value":"my-project"},{"name":"cluster-name","value":"cluster-name"},{"name":"gcloud.compute.zone","value":"us-east1-d"}]}}
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub:
- --gcr.io/asm-testing
- --gcr.io/asm-testing2
`,
},
}
for i := range tests {
test := tests[i]

View File

@@ -89,6 +89,22 @@ var CreateSetterExamples = `
kustomize cfg create-setter DIR/ image-tag v1.0.1 --type "string" \
--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 FmtLong = `
[Alpha] Format yaml configuration files.

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -1147,7 +1147,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 July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -812,7 +812,7 @@ ordered relative to other input resources.</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -846,7 +846,7 @@ the value will be overridden.</p>
<div class="text-muted mt-5 pt-3 border-top">Last modified June 11, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/589ddcb4faa1170e1cd549a41b11f18e146197d8">kustomize docs tweaks (589ddcb4)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -889,7 +889,7 @@ resource has been applied to a cluster.</p>
<div class="text-muted mt-5 pt-3 border-top">Last modified June 11, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/589ddcb4faa1170e1cd549a41b11f18e146197d8">kustomize docs tweaks (589ddcb4)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -873,7 +873,7 @@ configmap is created is <code>whatever.ini</code>.</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -828,7 +828,7 @@ same way.</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -818,7 +818,7 @@ generator. For details on per-resource generatorOptions usage see
<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 July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -838,7 +838,7 @@ kubernetes Deployment fragment:</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

View File

@@ -488,7 +488,7 @@ to it (regular expressions).&lt;/p&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;value&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;new&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;target&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;kind&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;MyKind&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;labelSelector&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;env=dev&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;labelSelector&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;env=dev&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;namespace&lt;/code&gt; fields of the patch target selector are
automatically anchored regular expressions. This means that the value &lt;code&gt;myapp&lt;/code&gt;
is equivalent to &lt;code&gt;^myapp$&lt;/code&gt;.&lt;/p&gt;

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -806,7 +806,7 @@
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -807,7 +807,7 @@ if it is not set on a resource.</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -807,7 +807,7 @@
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -776,7 +776,7 @@ to it (regular expressions).</p>
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">value</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span>new<span style="color:#f8f8f8;text-decoration:underline"> </span>value<span style="color:#f8f8f8;text-decoration:underline">
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">target</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline">
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span>MyKind<span style="color:#f8f8f8;text-decoration:underline">
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">labelSelector</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#34;env=dev&#34;</span><span style="color:#f8f8f8;text-decoration:underline">
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">labelSelector</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#34;env=dev&#34;</span><span style="color:#f8f8f8;text-decoration:underline">
</span></code></pre></div><p>The <code>name</code> and <code>namespace</code> fields of the patch target selector are
automatically anchored regular expressions. This means that the value <code>myapp</code>
is equivalent to <code>^myapp$</code>.</p>
@@ -835,7 +835,7 @@ is equivalent to <code>^myapp$</code>.</p>
<div class="text-muted mt-5 pt-3 border-top">Last modified June 11, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/589ddcb4faa1170e1cd549a41b11f18e146197d8">kustomize docs tweaks (589ddcb4)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -849,7 +849,7 @@ The content in this patch file can be either in JSON format as</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -840,7 +840,7 @@ patch that performs all the needed deletions.</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -828,7 +828,7 @@ that is one of:</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -833,7 +833,7 @@
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -862,7 +862,7 @@ in the Deployment.</p>
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -26,12 +26,12 @@
<meta property="og:type" content="article" />
<meta property="og:url" content="https://kubernetes-sigs.github.io/kustomize/blog/2018/05/21/v1.0.1/" />
<meta property="article:published_time" content="2018-05-21T00:00:00+00:00" />
<meta property="article:modified_time" content="2020-06-07T21:07:46-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta property="article:modified_time" content="2020-07-16T12:57:18-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta itemprop="name" content="v1.0.1">
<meta itemprop="description" content="Kustomize v1.0.1
">
<meta itemprop="datePublished" content="2018-05-21T00:00:00&#43;00:00" />
<meta itemprop="dateModified" content="2020-06-07T21:07:46-07:00" />
<meta itemprop="dateModified" content="2020-07-16T12:57:18-07:00" />
<meta itemprop="wordCount" content="45">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -26,12 +26,12 @@
<meta property="og:type" content="article" />
<meta property="og:url" content="https://kubernetes-sigs.github.io/kustomize/blog/2019/06/18/v2.1.0/" />
<meta property="article:published_time" content="2019-06-18T00:00:00+00:00" />
<meta property="article:modified_time" content="2020-06-07T21:07:46-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta property="article:modified_time" content="2020-07-16T12:57:18-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta itemprop="name" content="v2.1.0">
<meta itemprop="description" content="Kustomize v2.1.0
">
<meta itemprop="datePublished" content="2019-06-18T00:00:00&#43;00:00" />
<meta itemprop="dateModified" content="2020-06-07T21:07:46-07:00" />
<meta itemprop="dateModified" content="2020-07-16T12:57:18-07:00" />
<meta itemprop="wordCount" content="920">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -26,12 +26,12 @@
<meta property="og:type" content="article" />
<meta property="og:url" content="https://kubernetes-sigs.github.io/kustomize/blog/2019/07/03/v3.0.0/" />
<meta property="article:published_time" content="2019-07-03T00:00:00+00:00" />
<meta property="article:modified_time" content="2020-06-07T21:07:46-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta property="article:modified_time" content="2020-07-16T12:57:18-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta itemprop="name" content="v3.0.0">
<meta itemprop="description" content="Kustomize v3.0.0
">
<meta itemprop="datePublished" content="2019-07-03T00:00:00&#43;00:00" />
<meta itemprop="dateModified" content="2020-06-07T21:07:46-07:00" />
<meta itemprop="dateModified" content="2020-07-16T12:57:18-07:00" />
<meta itemprop="wordCount" content="324">
@@ -341,7 +341,7 @@ commits) and a <code>v3</code> in Go package paths.</p>
floor on a stable API for <a href="/docs/plugins">plugin</a> developers
(both <em>Go</em> plugin developers and <em>exec</em> plugin
developers who happen to use Go).</p>
<h3 id="why-so-soon-after-v210">Why so soon after v2.1.0?</h3>
<h3 id="why-so-soon-after-v210">Why so soon after v2.1.0</h3>
<p>We made a mistake - v2.1.0 should have been
v3.0.0. Per the <a href="https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher">Go modules doc</a> (which have
improved a great deal recently), a release that&rsquo;s

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -26,12 +26,12 @@
<meta property="og:type" content="article" />
<meta property="og:url" content="https://kubernetes-sigs.github.io/kustomize/blog/2019/07/26/v3.1.0/" />
<meta property="article:published_time" content="2019-07-26T00:00:00+00:00" />
<meta property="article:modified_time" content="2020-06-07T21:07:46-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta property="article:modified_time" content="2020-07-16T12:57:18-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta itemprop="name" content="v3.1.0">
<meta itemprop="description" content="Kustomize v3.1.0
">
<meta itemprop="datePublished" content="2019-07-26T00:00:00&#43;00:00" />
<meta itemprop="dateModified" content="2020-06-07T21:07:46-07:00" />
<meta itemprop="dateModified" content="2020-07-16T12:57:18-07:00" />
<meta itemprop="wordCount" content="362">
@@ -327,7 +327,7 @@
<li><a href="#patch-resolution-improvement">Patch resolution improvement</a></li>
<li><a href="#variable-resolution-improvement">Variable resolution improvement</a></li>
<li><a href="#simultaneous-change-of-names-and-namespaces">Simultaneous change of names and namespaces</a></li>
<li><a href="#resource-and-kustomize-context-matching">Resource and Kustomize Context matching.</a></li>
<li><a href="#resource-and-kustomize-context-matching">Resource and Kustomize Context matching</a></li>
</ul>
</li>
<li><a href="#other-improvements">Other improvements</a></li>
@@ -429,7 +429,7 @@ resources he needs to declare.</p>
</span><span style="color:#f8f8f8;text-decoration:underline">
</span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">resources</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline">
</span><span style="color:#f8f8f8;text-decoration:underline"></span>...<span style="color:#f8f8f8;text-decoration:underline">
</span></code></pre></div><h3 id="resource-and-kustomize-context-matching">Resource and Kustomize Context matching.</h3>
</span></code></pre></div><h3 id="resource-and-kustomize-context-matching">Resource and Kustomize Context matching</h3>
<p>Kustomize is now able to support more aggregation patterns.</p>
<p>If for instance, the top level of kustomization.yaml, is simply
combining sub-components, (as in the following example), Kustomize has improved

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -26,12 +26,12 @@
<meta property="og:type" content="article" />
<meta property="og:url" content="https://kubernetes-sigs.github.io/kustomize/blog/2019/09/17/v3.2.0/" />
<meta property="article:published_time" content="2019-09-17T00:00:00+00:00" />
<meta property="article:modified_time" content="2020-06-07T21:07:46-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta property="article:modified_time" content="2020-07-16T12:57:18-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta itemprop="name" content="v3.2.0">
<meta itemprop="description" content="Kustomize v3.2.0
">
<meta itemprop="datePublished" content="2019-09-17T00:00:00&#43;00:00" />
<meta itemprop="dateModified" content="2020-06-07T21:07:46-07:00" />
<meta itemprop="dateModified" content="2020-07-16T12:57:18-07:00" />
<meta itemprop="wordCount" content="103">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -26,12 +26,12 @@
<meta property="og:type" content="article" />
<meta property="og:url" content="https://kubernetes-sigs.github.io/kustomize/blog/2019/10/24/v3.3.0/" />
<meta property="article:published_time" content="2019-10-24T00:00:00+00:00" />
<meta property="article:modified_time" content="2020-06-07T21:07:46-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta property="article:modified_time" content="2020-07-16T12:57:18-07:00" /><meta property="og:site_name" content="Kustomize" />
<meta itemprop="name" content="v3.3.0">
<meta itemprop="description" content="Kustomize v3.3.0
">
<meta itemprop="datePublished" content="2019-10-24T00:00:00&#43;00:00" />
<meta itemprop="dateModified" content="2020-06-07T21:07:46-07:00" />
<meta itemprop="dateModified" content="2020-07-16T12:57:18-07:00" />
<meta itemprop="wordCount" content="863">
@@ -323,7 +323,7 @@
<ul>
<li><a href="#summary-of-changes">Summary of changes</a>
<ul>
<li><a href="#first-release-of-the-go-api-only-module">First release of the Go API-only module.</a></li>
<li><a href="#first-release-of-the-go-api-only-module">First release of the Go API-only module</a></li>
<li><a href="#change-log-since-v320">Change log since v3.2.0</a></li>
</ul>
</li>
@@ -346,7 +346,7 @@
<time datetime="2019-10-24" class="text-muted">Thursday, October 24, 2019</time>
</div>
<h2 id="summary-of-changes">Summary of changes</h2>
<h3 id="first-release-of-the-go-api-only-module">First release of the Go API-only module.</h3>
<h3 id="first-release-of-the-go-api-only-module">First release of the Go API-only module</h3>
<p>Many of the PRs since the last vrelease were
around restructuring the <em>sigs.k8s.io/kustomize</em>
repository into three Go modules instead of just one.</p>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -340,7 +340,7 @@
<p class="pt-0 mt-0">Summary of changes First release of the Go API-only module. Many of the PRs since the last vrelease were around restructuring the sigs.k8s.io/kustomize repository into three Go modules instead of just one.
<p class="pt-0 mt-0">Summary of changes First release of the Go API-only module Many of the PRs since the last vrelease were around restructuring the sigs.k8s.io/kustomize repository into three Go modules instead of just one.
The reasons for this are detailed in the …</p>
<p class="pt-0"><a href="/kustomize/blog/2019/10/24/v3.3.0/">Read more</a></p>
</div>

View File

@@ -23,7 +23,7 @@
&lt;h2 id=&#34;summary-of-changes&#34;&gt;Summary of changes&lt;/h2&gt;
&lt;h3 id=&#34;first-release-of-the-go-api-only-module&#34;&gt;First release of the Go API-only module.&lt;/h3&gt;
&lt;h3 id=&#34;first-release-of-the-go-api-only-module&#34;&gt;First release of the Go API-only module&lt;/h3&gt;
&lt;p&gt;Many of the PRs since the last vrelease were
around restructuring the &lt;em&gt;sigs.k8s.io/kustomize&lt;/em&gt;
repository into three Go modules instead of just one.&lt;/p&gt;
@@ -257,7 +257,7 @@ resources he needs to declare.&lt;/p&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;resources&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;...&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;resource-and-kustomize-context-matching&#34;&gt;Resource and Kustomize Context matching.&lt;/h3&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;resource-and-kustomize-context-matching&#34;&gt;Resource and Kustomize Context matching&lt;/h3&gt;
&lt;p&gt;Kustomize is now able to support more aggregation patterns.&lt;/p&gt;
&lt;p&gt;If for instance, the top level of kustomization.yaml, is simply
combining sub-components, (as in the following example), Kustomize has improved
@@ -296,7 +296,7 @@ commits) and a &lt;code&gt;v3&lt;/code&gt; in Go package paths.&lt;/p&gt;
floor on a stable API for &lt;a href=&#34;https://kubernetes-sigs.github.io/kustomize/docs/plugins&#34;&gt;plugin&lt;/a&gt; developers
(both &lt;em&gt;Go&lt;/em&gt; plugin developers and &lt;em&gt;exec&lt;/em&gt; plugin
developers who happen to use Go).&lt;/p&gt;
&lt;h3 id=&#34;why-so-soon-after-v210&#34;&gt;Why so soon after v2.1.0?&lt;/h3&gt;
&lt;h3 id=&#34;why-so-soon-after-v210&#34;&gt;Why so soon after v2.1.0&lt;/h3&gt;
&lt;p&gt;We made a mistake - v2.1.0 should have been
v3.0.0. Per the &lt;a href=&#34;https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher&#34;&gt;Go modules doc&lt;/a&gt; (which have
improved a great deal recently), a release that&amp;rsquo;s

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -340,7 +340,7 @@
<p class="pt-0 mt-0">Summary of changes First release of the Go API-only module. Many of the PRs since the last vrelease were around restructuring the sigs.k8s.io/kustomize repository into three Go modules instead of just one.
<p class="pt-0 mt-0">Summary of changes First release of the Go API-only module Many of the PRs since the last vrelease were around restructuring the sigs.k8s.io/kustomize repository into three Go modules instead of just one.
The reasons for this are detailed in the …</p>
<p class="pt-0"><a href="/kustomize/blog/2019/10/24/v3.3.0/">Read more</a></p>
</div>

View File

@@ -23,7 +23,7 @@
&lt;h2 id=&#34;summary-of-changes&#34;&gt;Summary of changes&lt;/h2&gt;
&lt;h3 id=&#34;first-release-of-the-go-api-only-module&#34;&gt;First release of the Go API-only module.&lt;/h3&gt;
&lt;h3 id=&#34;first-release-of-the-go-api-only-module&#34;&gt;First release of the Go API-only module&lt;/h3&gt;
&lt;p&gt;Many of the PRs since the last vrelease were
around restructuring the &lt;em&gt;sigs.k8s.io/kustomize&lt;/em&gt;
repository into three Go modules instead of just one.&lt;/p&gt;
@@ -257,7 +257,7 @@ resources he needs to declare.&lt;/p&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;resources&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;...&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;resource-and-kustomize-context-matching&#34;&gt;Resource and Kustomize Context matching.&lt;/h3&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;resource-and-kustomize-context-matching&#34;&gt;Resource and Kustomize Context matching&lt;/h3&gt;
&lt;p&gt;Kustomize is now able to support more aggregation patterns.&lt;/p&gt;
&lt;p&gt;If for instance, the top level of kustomization.yaml, is simply
combining sub-components, (as in the following example), Kustomize has improved
@@ -296,7 +296,7 @@ commits) and a &lt;code&gt;v3&lt;/code&gt; in Go package paths.&lt;/p&gt;
floor on a stable API for &lt;a href=&#34;https://kubernetes-sigs.github.io/kustomize/docs/plugins&#34;&gt;plugin&lt;/a&gt; developers
(both &lt;em&gt;Go&lt;/em&gt; plugin developers and &lt;em&gt;exec&lt;/em&gt; plugin
developers who happen to use Go).&lt;/p&gt;
&lt;h3 id=&#34;why-so-soon-after-v210&#34;&gt;Why so soon after v2.1.0?&lt;/h3&gt;
&lt;h3 id=&#34;why-so-soon-after-v210&#34;&gt;Why so soon after v2.1.0&lt;/h3&gt;
&lt;p&gt;We made a mistake - v2.1.0 should have been
v3.0.0. Per the &lt;a href=&#34;https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher&#34;&gt;Go modules doc&lt;/a&gt; (which have
improved a great deal recently), a release that&amp;rsquo;s

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -499,7 +499,7 @@ misunderstandings.</p>
<div class="text-muted mt-5 pt-3 border-top">Last modified June 14, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/c4518e964fd88aa4e3495ef84141c876a9500f48">Add more Kustomize contributing docs (c4518e96)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -474,7 +474,7 @@ project <a href="https://github.com/kubernetes/community/blob/master/community-m
<div class="text-muted mt-5 pt-3 border-top">Last modified June 14, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/c4518e964fd88aa4e3495ef84141c876a9500f48">Add more Kustomize contributing docs (c4518e96)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -545,7 +545,7 @@ hugo
<div class="text-muted mt-5 pt-3 border-top">Last modified June 11, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/589ddcb4faa1170e1cd549a41b11f18e146197d8">kustomize docs tweaks (589ddcb4)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -499,7 +499,7 @@ or more information is needed.</li>
<div class="text-muted mt-5 pt-3 border-top">Last modified June 14, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/c4518e964fd88aa4e3495ef84141c876a9500f48">Add more Kustomize contributing docs (c4518e96)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -560,7 +560,7 @@ the <code>kustomize/go.mod</code>.</p>
<div class="text-muted mt-5 pt-3 border-top">Last modified June 14, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/c4518e964fd88aa4e3495ef84141c876a9500f48">Add more Kustomize contributing docs (c4518e96)</a>
<div class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
@@ -503,7 +503,7 @@
<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 class="text-muted mt-5 pt-3 border-top">Last modified July 16, 2020: <a href="https://github.com/kubernetes-sigs/kustomize/commit/f9ee578aed600136133c3232fff03029cdfc526e">Docs: Auto-fix markdownlint issues (f9ee578a)</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Hugo 0.73.0" />
<meta name="generator" content="Hugo 0.73.0-DEV" />
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">

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