Compare commits

...

320 Commits

Author SHA1 Message Date
Kubernetes Prow Robot
313aacedd3 Merge pull request #6138 from dims/update-kube-openapi
bump k8s.io/kube-openapi, drop github.com/mailru/easyjson
2026-05-02 21:33:24 +05:30
Davanum Srinivas
9a61304919 bump k8s.io/kube-openapi, drop github.com/mailru/easyjson
Updates k8s.io/kube-openapi from v0.0.0-20241212222426-2c72e554b1e7 to
v0.0.0-20260502001324-b7f5293f4787 across api, kyaml, and kustomize modules,
then propagates the change across all workspace modules via make workspace-sync.

The new kube-openapi release switched from the monolithic go-openapi/swag
(v0.23.0) to the refactored split sub-modules (go-openapi/swag/* v0.25.4).
The old swag carried github.com/mailru/easyjson as a dependency; the new
sub-modules do not. After go mod tidy, easyjson and josharian/intern are
fully removed from all three module graphs.

Also upgraded: github.com/google/gnostic-models v0.6.9 → v0.7.0 (pulled
in by the same kube-openapi update).

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2026-05-02 10:47:24 -04:00
Ali jawwad
c43ab3cee1 docs: document config.kubernetes.io/local-config annotation (#6133)
* docs: document config.kubernetes.io/local-config annotation

Adds a Concepts page covering the three documented use cases:
Replacement data source, name-reference anchor across objects, and
KRM Function shared configuration. Cross-references the existing
manifest-annotations.md and the Kubernetes well-known annotations
page.

Signed-off-by: jawwad-ali <33836051+jawwad-ali@users.noreply.github.com>

* docs: drop implementation details and deprecated kustomize cfg note

Per koba1t review feedback on the local-config Concepts page:
implementation details (IsLocalConfig filter, DropLocalNodes helper,
source-file references) belong in the code rather than user docs, and
`kustomize cfg` is deprecated and should not be promoted to new users.
Removes the "How kustomize processes local-config resources" section.

Signed-off-by: jawwad-ali <33836051+jawwad-ali@users.noreply.github.com>

---------

Signed-off-by: jawwad-ali <33836051+jawwad-ali@users.noreply.github.com>
2026-05-02 01:29:24 +05:30
Kubernetes Prow Robot
7be21de377 Merge pull request #6114 from zerok/zerok/gotoolchain
chore: set minimum Go toolchain to 1.25.8
2026-05-01 17:39:24 +05:30
Horst Gutmann
d6bd9d9b08 Set minimum Go toolchain to 1.25.8 2026-05-01 11:30:18 +02:00
Kubernetes Prow Robot
0bb03d98ba Merge pull request #6137 from kubernetes-sigs/dependabot/go_modules/hack/github.com/go-jose/go-jose/v4-4.1.4
build(deps): bump github.com/go-jose/go-jose/v4 from 4.1.3 to 4.1.4 in /hack
2026-05-01 14:17:23 +05:30
dependabot[bot]
5e7858b8ea build(deps): bump github.com/go-jose/go-jose/v4 in /hack
Bumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.1.3 to 4.1.4.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Commits](https://github.com/go-jose/go-jose/compare/v4.1.3...v4.1.4)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-version: 4.1.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 00:23:45 +00:00
yugo kobayashi
1c87a5063d drop 'go-spew' dependencies and update dependencies (#6134)
* drop 'go-spew' dependencies

* update dependencies

* fix: change install method of golangci-lint
2026-05-01 05:37:24 +05:30
Kubernetes Prow Robot
2f9dbe434d Merge pull request #6135 from koba1t/fix/github-actions-sha256-error
fix: github actions require to sha 256 for external actions
2026-04-28 05:42:47 +05:30
koba1t
71a99512bd fix: github actions require to sha 256 for external actions 2026-04-28 08:54:50 +09:00
Kubernetes Prow Robot
72b0fd14d1 Merge pull request #6037 from rohithnarasimha/feat/add-configuration-command
feat: add support for 'kustomize edit add configuration' command
2026-04-07 21:45:33 +05:30
Rohith
1af74f2d9e feat(commands/edit/add): add support for 'kustomize edit add configuration' command
Add a new subcommand 'kustomize edit add configuration' to programmatically
add configuration file references to kustomization.yaml files.

This brings configurations support in line with other 'kustomize edit add'
subcommands (generators, transformers, validators).

Features:
- Support for single and multiple configuration file paths
- Glob pattern expansion (e.g., ./configs/*.yaml)
- Duplicate detection with user logging
- Idempotent operation

Related to https://github.com/kubernetes-sigs/kustomize/issues/5987
2026-04-06 07:12:10 +05:30
Agustina Barbetta
80f63ae0c3 Add labels to volumeClaimTemplates in StatefulSets if includeVolumeClaimTemplates is true (#5831) 2026-04-01 20:59:07 +05:30
Kubernetes Prow Robot
b317895057 Merge pull request #6086 from ashnehete/4338/docs
Add Kustomization file overview from kubectl.docs.kubernetes.io
2026-04-01 20:47:11 +05:30
Kubernetes Prow Robot
66af726162 Merge pull request #6111 from kubernetes-sigs/dependabot/go_modules/hack/github.com/go-git/go-git/v5-5.17.1
build(deps): bump github.com/go-git/go-git/v5 from 5.16.5 to 5.17.1 in /hack
2026-03-31 18:52:24 +05:30
dependabot[bot]
bcb4803f09 build(deps): bump github.com/go-git/go-git/v5 in /hack
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.16.5 to 5.17.1.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.16.5...v5.17.1)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-version: 5.17.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-30 17:15:35 +00:00
Kubernetes Prow Robot
4ef1cf8234 Merge pull request #6100 from kubernetes-sigs/dependabot/npm_and_yarn/site/picomatch-2.3.2
build(deps-dev): bump picomatch from 2.3.1 to 2.3.2 in /site
2026-03-27 04:48:15 +05:30
dependabot[bot]
14ed8d90e0 build(deps-dev): bump picomatch from 2.3.1 to 2.3.2 in /site
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 23:11:52 +00:00
NoNE
29bf16c673 Reject ambiguous resource paths with inner ".." to prevent silent misresolution (#6087)
* Reject paths with inner '..' in FileLoader.New to prevent silent misresolution

* Refactor hasInnerDotDot to two-phase loop eliminating mutable state

* Narrow check to embedded '..' segments to allow legitimate winding paths

* Fix gofmt alignment and trailing whitespace in new test functions

* Fix pre-existing lint errors in fileloader_test.go
2026-03-25 20:50:19 +05:30
Kubernetes Prow Robot
fb91123a1c Merge pull request #6029 from seankhliao/push-zkmktlwmzysm
Account for delimiters in structured data replacements
2026-03-19 00:08:31 +05:30
Kubernetes Prow Robot
4d331ef81a Merge pull request #5974 from VannTen/docs/sourceValue
Document `sourceValue` for replacements.
2026-03-17 17:23:39 +05:30
Sean Liao
194aac685f Account for delimiters in structured data replacements
Delimiter options were ignored for replacements targeting
structured data. Reuse the same value setting function
as replacements targeting regular values.
2026-03-17 11:09:11 +00:00
Kubernetes Prow Robot
825d1cfb8a Merge pull request #6097 from kubernetes-sigs/dependabot/github_actions/dorny/paths-filter-4
build(deps): bump dorny/paths-filter from 3 to 4
2026-03-16 23:11:39 +05:30
Kubernetes Prow Robot
811e616841 Merge pull request #6096 from sarab97/sarab/reviewer
add sarab97 to reviewers
2026-03-16 22:27:41 +05:30
dependabot[bot]
c8dfcc123f build(deps): bump dorny/paths-filter from 3 to 4
Bumps [dorny/paths-filter](https://github.com/dorny/paths-filter) from 3 to 4.
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dorny/paths-filter/compare/v3...v4)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 00:42:45 +00:00
Sarab Singh
0fb3416c16 add sarab97 to reviewers 2026-03-15 01:12:56 +05:30
Kubernetes Prow Robot
1ad9f9d96c Merge pull request #6083 from 0xMH/fix/5103-remove-component
Add kustomize edit remove component command
2026-03-05 16:20:19 +05:30
Aashish Nehete
5d2d80d41b Add Kustomization file overview 2026-03-04 19:21:29 -08:00
Kubernetes Prow Robot
0343400a36 Merge pull request #6085 from koba1t/dependencies/update_otel_to_v1.40.0
update otel lib to v1.40.0
2026-03-04 22:42:19 +05:30
Hamza
c07b901856 add kustomize edit remove component command 2026-03-04 16:28:10 +01:00
koba1t
68e507eb6f update otel lib to v1.40.0 2026-03-04 23:30:01 +09:00
Kubernetes Prow Robot
09b04840a1 Merge pull request #6080 from kubernetes-sigs/dependabot/go_modules/hack/github.com/cloudflare/circl-1.6.3
build(deps): bump github.com/cloudflare/circl from 1.6.1 to 1.6.3 in /hack
2026-02-27 17:44:55 +05:30
dependabot[bot]
0e14dbd8cd build(deps): bump github.com/cloudflare/circl in /hack
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.6.1 to 1.6.3.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.6.1...v1.6.3)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-25 21:13:01 +00:00
Max Gautier
c52ba638ea Document sourceValue for replacements.
Co-authored-by: Steven E. Harris <seh@panix.com>
2026-02-24 16:25:44 +01:00
Aashish Nehete
78ce39820d Add FAQ from kubectl.docs.kubernetes.io (#6052)
* Add FAQ from kubectl.docs.kubernetes.io

* Add title to Contributing Features

* Set sidebar_menu_compact to true

* Add glossary, fix broken links

* Update site/content/en/contribute/features/eschewedfeatures.md

Co-authored-by: Mauren <698465+stormqueen1990@users.noreply.github.com>

* Update site/content/en/contribute/features/eschewedfeatures.md

Co-authored-by: Mauren <698465+stormqueen1990@users.noreply.github.com>

* Update site/content/en/contribute/features/eschewedfeatures.md

Co-authored-by: Mauren <698465+stormqueen1990@users.noreply.github.com>

---------

Co-authored-by: Mauren <698465+stormqueen1990@users.noreply.github.com>
2026-02-19 20:13:39 +05:30
Kubernetes Prow Robot
b7ee1340a9 Merge pull request #6078 from koba1t/bump/go-git_and_crypt
bump go-git and x/crypt
2026-02-13 17:50:01 +05:30
koba1t
793f58251c remove old go build tag 2026-02-13 20:55:17 +09:00
koba1t
5231e099e5 bump go-git and x/crypt 2026-02-13 20:46:17 +09:00
Kubernetes Prow Robot
e78e03405b Merge pull request #6075 from koba1t/upgrade/go.1.25.7
update go 1.25.7
2026-02-13 10:56:00 +05:30
koba1t
8eb136f67e update go 1.25.7 2026-02-12 01:26:18 +09:00
yugo kobayashi
dc6b2b978c Merge pull request #6068 from koba1t/unpinEverything
Back to development mode; unpin the modules
2026-02-10 02:58:25 +09:00
koba1t
be8d7eb980 Back to development mode; unpin the modules 2026-02-10 01:43:07 +09:00
Kubernetes Prow Robot
9790a1c3ef Merge pull request #6067 from koba1t/pinToApi
Update api to v0.21.1
2026-02-09 21:41:22 +05:30
koba1t
4190d3dedc Update api to v0.21.1 2026-02-10 01:00:34 +09:00
Kubernetes Prow Robot
401be204e1 Merge pull request #6066 from koba1t/pinToCmdConfig
Update cmd/config to v0.21.1
2026-02-09 21:23:24 +05:30
koba1t
8073ce87f0 Update cmd/config to v0.21.1 2026-02-10 00:42:39 +09:00
Kubernetes Prow Robot
be024c92ba Merge pull request #6065 from koba1t/pinToKyaml
Update kyaml to v0.21.1
2026-02-09 21:07:25 +05:30
koba1t
bb26a70573 Update kyaml to v0.21.1 2026-02-10 00:27:48 +09:00
Kubernetes Prow Robot
798d339d10 Merge pull request #6044 from koba1t/fix/namespace_propagation_problem_at_v5.8.0
Fix namespace propagation problem at v5.8.0
2026-02-09 07:21:09 +05:30
Kubernetes Prow Robot
6c8c9cc0e8 Merge pull request #6016 from hmilkovi/fix/helm-4.0
fix: support helm v4 beside v3
2026-02-05 07:02:29 +05:30
Kubernetes Prow Robot
02d23d21f0 Merge pull request #6057 from dims/remove-pkg-errors-dep
Upgrade json-patch to v4.13.0 to remove pkg/errors dependency
2026-02-05 06:18:29 +05:30
Hrvoje Milković
c6ccb4f208 Merge branch 'kubernetes-sigs:master' into fix/helm-4.0 2026-02-04 20:40:03 +01:00
hmilkovi
54848c1049 fix: support helm v4 beside v3 and remove -c flag for helm version as it does nothing
features.
2026-02-04 20:27:15 +01:00
Davanum Srinivas
297f2b59bb Upgrade json-patch to v4.13.0 to remove pkg/errors dependency
The github.com/pkg/errors package is unmaintained and archived.
It was pulled in as a transitive dependency through json-patch v4.12.0.
Upgrading to v4.13.0 removes this dependency while maintaining API
compatibility.

json-patch commit: evanphx/json-patch@106306d

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2026-02-04 14:14:37 -05:00
koba1t
7e45799272 rename to helmRootNamespace 2026-01-13 08:13:23 +09:00
koba1t
4e75138d24 fix: apply namespace propagation for helmCharts only 2026-01-13 08:09:14 +09:00
koba1t
a397f5b491 add tests for regression 2026-01-03 03:27:12 +09:00
Kubernetes Prow Robot
008b7a0c47 Merge pull request #6038 from tsuzu/fix-test-error
Fix a failing test
2025-12-29 00:56:33 +05:30
Tsuzu
6d7267f345 Fix a failing test 2025-12-22 00:11:48 +09:00
Kubernetes Prow Robot
17a06a72be Merge pull request #6020 from koba1t/chore/parallelizing_tests
CI: parallelizing tests
2025-11-26 08:24:37 -08:00
koba1t
e6621df4d5 add aggregation job for all matrix released module tests to define a branch protection rule 2025-11-26 07:07:16 +09:00
koba1t
77cf6d6b88 CI: parallelizing tests 2025-11-26 07:07:13 +09:00
Kubernetes Prow Robot
95a6f1fec3 Merge pull request #6023 from kubernetes-sigs/dependabot/github_actions/actions/checkout-6
build(deps): bump actions/checkout from 5 to 6
2025-11-25 14:02:36 -08:00
dependabot[bot]
c79a356bb2 build(deps): bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 00:02:17 +00:00
Kubernetes Prow Robot
311dbbf975 Merge pull request #5990 from ralgozino/fix/allow-empty-strategicmerge-patches-files
fix: allow empty patches files
2025-11-19 13:12:00 -08:00
Kubernetes Prow Robot
77b3446b36 Merge pull request #6010 from koba1t/unpinEverything
Back to development mode; unpin the modules
2025-11-10 02:30:56 -08:00
koba1t
764ad39d1d Back to development mode; unpin the modules 2025-11-10 00:04:26 +09:00
Kubernetes Prow Robot
0054b5e296 Merge pull request #6009 from koba1t/pinToApi
Update api to v0.21.0
2025-11-09 06:38:52 -08:00
koba1t
16391f3dbe Update api to v0.21.0 2025-11-09 23:29:30 +09:00
Kubernetes Prow Robot
6661fefabc Merge pull request #6008 from koba1t/pinToCmdConfig
Update cmd/config to v0.21.0
2025-11-09 06:12:52 -08:00
koba1t
3c59244887 Update cmd/config to v0.21.0 2025-11-09 23:02:27 +09:00
Kubernetes Prow Robot
ade7bd609f Merge pull request #6007 from koba1t/pinToKyaml
Update kyaml to v0.21.0
2025-11-09 05:56:52 -08:00
koba1t
0fc75546f1 Update kyaml to v0.21.0 2025-11-09 22:45:40 +09:00
Joseph Cumines
87617912bf fix(kyaml/yaml): minor nil safety fix for RNode.Content etc (#5985)
* Fix kyaml/yaml field access deref nil value for methods that look "nil-safe"

This change is addressing observed panics within kustomize that obscure the
actual failure. The primary observed problem case involves RNode.Content.

* Fix test case

* Fixes from review
2025-11-02 18:34:07 -08:00
Kubernetes Prow Robot
153a37286d Merge pull request #5679 from koba1t/implements_to_replacements_value_in_the_structured_data
implements to replacements value in the structured data
2025-10-24 20:15:34 -07:00
Kubernetes Prow Robot
de011378a4 Merge pull request #5991 from isarns/fix/labels-without-selector-duplicate-key-error
Fix duplicate key error when adding multiple labels with --without-selector
2025-10-12 19:36:54 -07:00
isarns
4d37afef6f style(cmd-edit-add-label): lint multiple labels without selector test 2025-10-12 18:04:33 +03:00
isarns
f71e4d7309 style(cmd-edit-add-label): lint multiple labels without selector test 2025-10-12 12:34:00 +03:00
isarns
d427f61f84 test(cmd-edit-add-label): add multiple labels without selector test 2025-10-12 12:08:34 +03:00
isarns
9df8bbdc44 fix(cmd-edit-add-label): dubplicate key error 2025-10-05 19:33:51 +03:00
Ramiro Algozino
24ea1b951a fix(kustomize): call json6902 only when needed
Call json6902 transformer only when there are patches to apply.

Addresses #5956
2025-10-02 19:51:09 +02:00
Ramiro Algozino
68fa5177e2 chore: add test for empty patches files
Add test to validate that empty files don't produce an error when using
the `path` option of the `patches` convenience.

Add test to validate that using the deprecated patchesStrategicMerge
still produces an error and no changes have been introduced in old
features.
2025-10-02 19:15:00 +02:00
koba1t
2a1862d8b7 fix nit 2025-09-30 06:48:35 +09:00
Niklas Wagner
278dd6e55d fix: performance recession when propagating namespace to helm (#5971)
* fix: performance recession when propagating namespace to helm

* fix: handle passing namespace downstream more elegant

* Revert "fix: handle passing namespace downstream more elegant"

This reverts commit 976a7cf2aa.

* Revert "fix: performance recession when propagating namespace to helm"

This reverts commit c7612d1dba.

* fix: use annotation to identify helm chart generated resources

* fix: deduplicate code

* fix: missing import in NamespaceTransformer.go

* ci: allow manual trigger of pipeline in fork

* Revert "ci: allow manual trigger of pipeline in fork"

This reverts commit 8948788fe2.

* fix: test cases

* chore: fix code comment was on wrong line

* chore: fix code comment was on wrong line pt2
2025-09-29 14:08:19 -07:00
Kubernetes Prow Robot
b62d746b80 Merge pull request #5942 from totegamma/master
fix fnplugin storagemounts validation
2025-09-29 12:06:17 -07:00
Kubernetes Prow Robot
ab48be3747 Merge pull request #5984 from stormqueen1990/patch-2
Step down as reviewer for kustomize
2025-09-28 12:10:16 -07:00
Mauren
e5bb51847d Step down as reviewer for kustomize
Remove myself from the OWNERS_ALIASES file as I am stepping down from being a reviewer in kustomize for the time being.
2025-09-14 17:00:00 -04:00
Kubernetes Prow Robot
1a988bbed5 Merge pull request #5982 from kubernetes-sigs/dependabot/github_actions/actions/setup-go-6
build(deps): bump actions/setup-go from 5 to 6
2025-09-12 16:52:14 -07:00
totegamma
4bdc3f3f7e add test for plugin loader 2025-09-11 21:40:16 +09:00
dependabot[bot]
66c1478c1b build(deps): bump actions/setup-go from 5 to 6
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 00:02:24 +00:00
koba1t
bbe53c2c45 implements nested structure replacements 2025-09-05 19:37:24 +09:00
Kubernetes Prow Robot
cd30471046 Merge pull request #5963 from koba1t/chore/introduce_go_tool_directive
introduce go tool directive
2025-08-27 17:43:10 -07:00
koba1t
2dc0d0da8b implements to replacements value in the structured data 2025-08-28 04:44:52 +09:00
koba1t
5fd7b14fc8 update releasing/README.md to use
Helps when you have a git repository with multiple Go modules.

It handles tasks one might otherwise attempt with

'''
find ./ -name "go.mod" | xargs {some hack}
'''

Run it from a git repository root.

It walks the repository, reads 'go.mod' files, builds
a model of Go modules and intra-repo module
dependencies, then performs some operation.

Install:
'''
go get sigs.k8s.io/kustomize/cmd/gorepomod
'''

_Commands that change things (everything but 'list')
do nothing but log commands
unless you add the '--doIt' flag,
allowing the change._

_If you want to run 'gorepomod' on your fork or outside of '$GOSRC' directory, add '--local'  flag to your command._

Lists modules and intra-repo dependencies.

Use this to get module names for use in other commands.

Creates a change with mechanical updates
to 'go.mod' and 'go.sum' files.

Creates a change to 'go.mod' files.

For each module _m_ in the repository,
if _m_ depends on a _{module}_, then
_m_'s dependency on _{module} will be
replaced by a relative path to the in-repo
version of _{module}_.

If _conditionalModule_ is specified, then
the replacement of _{module}_ will happen
if _m_ depends on _{conditionalModule}_.

Creates a change to 'go.mod' files.

The opposite of 'unpin'.

The change removes replacements and pins _m_ to a
specific, previously tagged and released version of _{module}_.

The argument _{version}_ defaults to recent version of _{module}_.

_{version}_ should be in semver form, e.g. 'v1.2.3'.

Computes a new version for the module, tags the repo
with that version, and pushes the tag to the remote.

The value of the 2nd argument, either 'patch' (the default),
'minor' or 'major', determines the new version.

If the existing version is _v1.2.7_, then the new version will be:
 - 'patch' -> _v1.2.8_
 - 'minor' -> _v1.3.0_
 - 'major' -> _v2.0.0_

After establishing the version, the command looks for a branch named

> _release-{module}/-v{major}.{minor}_

If the branch doesn't exist, the command creates it and pushes it to the remote.

The command then creates a new tag in the form

> _{module}/v{major}.{minor}.{patch}_

The command pushes this tag to the remote.  This typically triggers
cloud activity to create release artifacts.

This undoes the work of 'release', by deleting the
most recent tag both locally and at the remote.

You can then fix whatever, and re-release.

This, however, must be done almost immediately.

If there's a chance someone (or some cloud robot) already
imported the module at the given tag, then don't do this,
because it will confuse module caches.

Do a new patch release instead. instead of
2025-08-28 02:54:33 +09:00
koba1t
b472396d10 introduce go tool directive 2025-08-28 02:36:10 +09:00
Kubernetes Prow Robot
39086340ad Merge pull request #5967 from seipan/fix/url-encode
Fix infinite loop in HTTP client by validating URLs before requests
2025-08-24 12:13:06 -07:00
Kubernetes Prow Robot
4468c8c9c7 Merge pull request #5970 from stormqueen1990/deps/go-viper-mapstructure
build(deps): bump github.com/go-viper/mapstructure/v2 from v2.3.0 to v2.4.0
2025-08-24 02:51:06 -07:00
Mauren Berti
05fa95ea95 build(deps): bump github.com/go-viper/mapstructure/v2 from v2.3.0 to v2.4.0 2025-08-23 14:48:29 -04:00
Kubernetes Prow Robot
1c0f1bf5ac Merge pull request #5940 from Skaronator/propagate-namespaces
fix: Propagate Namespace correctly to Helm
2025-08-21 04:07:05 -07:00
seipan
2a79ea148d fix: url.ParseRequestURI before http.Get
Signed-off-by: seipan <yamasakipann0218@gmail.com>
2025-08-21 17:18:00 +09:00
Kubernetes Prow Robot
11f9435b50 Merge pull request #5962 from koba1t/chore/update_dependencies_from_security_alert
chore: update dependencies from security alert
2025-08-18 09:45:08 -07:00
Kubernetes Prow Robot
b97b705232 Merge pull request #5964 from kubernetes-sigs/dependabot/github_actions/actions/checkout-5
build(deps): bump actions/checkout from 4 to 5
2025-08-18 06:29:12 -07:00
dependabot[bot]
efbd2a6ef1 build(deps): bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-18 00:31:49 +00:00
koba1t
e68c754cce bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 in /cmd/gorepomod 2025-08-18 06:32:36 +09:00
koba1t
c8d3d5709e bump github.com/go-git/go-git/v5 from 5.11.0 to 5.13.0 2025-08-18 06:30:17 +09:00
Kubernetes Prow Robot
ffcda0158e Merge pull request #5961 from koba1t/refactor/nested_format_string
refactor: nested format string
2025-08-17 14:27:07 -07:00
koba1t
785fce97df refactor: nested format string 2025-08-18 06:16:24 +09:00
Kubernetes Prow Robot
caa42b7125 Merge pull request #5960 from stormqueen1990/deps/golang-oauth
build(deps): bump golang.org/x/oauth2 from 0.25.0 to 0.27.0
2025-08-17 14:01:07 -07:00
Mauren Berti
c9a0d10d5a build(deps): bump golang.org/x/oauth2 from 0.25.0 to 0.27.0 2025-08-17 16:20:00 -04:00
yugo kobayashi
87d0629bd1 update go 1.24.6 (#5959)
* update go 1.24.6

* fix non-constant format string error

* update golang.org/x/tools@v0.36.0 and github.com/golangci/golangci-lint@v1.64.8 to pass execute golangci-lint

* add a verpose diff output to prow test

* remove pluginator binary version from generated files
2025-08-17 13:05:12 -07:00
Kubernetes Prow Robot
b581903858 Merge pull request #5958 from adoramshoval/resource-absorbtion-error-verbosity
fix: make AbsorbAll conflict error more verbose
2025-08-16 15:43:07 -07:00
Adoram Shoval
d54e9b2b40 fix: make AbsorbAll conflict error more verbose 2025-08-16 08:09:17 -04:00
Niklas Wagner
75839a81b3 fix: namespace is not correctly propagate with nested kustomization files 2025-08-12 22:46:22 +02:00
zepard
7c04cbb237 Add regex support for Replacement selectors (#5863)
* feat: Add regex support for Replacement selectors

* Add new tests for regex support

* Earlier exit with rejectAny, and fix linting

* Add example Use cases using regex
2025-08-12 11:13:08 -07:00
Kubernetes Prow Robot
f74736130c Merge pull request #5930 from adoramshoval/patch-args
feat: add PatchArgs API type to populate patch options
2025-08-11 13:49:07 -07:00
Adoram Shoval
9043c223d4 feat: add PatchArgs API type to populate patch options
This commit converts the Options section of a patch into an object instead of map.
This allows better clarification of the available options.
2025-08-08 07:34:20 -04:00
Kubernetes Prow Robot
2859474e3c Merge pull request #5951 from koba1t/unpinEverything
Back to development mode; unpin the modules
2025-07-23 06:06:30 -07:00
koba1t
d0d64c5bc4 Back to development mode; unpin the modules 2025-07-23 21:55:58 +09:00
Kubernetes Prow Robot
168971a501 Merge pull request #5950 from koba1t/pinToApi
Update api to v0.20.1
2025-07-23 05:44:29 -07:00
koba1t
0c3ce2c8fb Update api to v0.20.1 2025-07-23 21:34:51 +09:00
Kubernetes Prow Robot
8b42cd9918 Merge pull request #5949 from koba1t/pinToCmdConfig
Update cmd/config to v0.20.1
2025-07-23 05:30:29 -07:00
koba1t
5b313f57c4 Update cmd/config to v0.20.1 2025-07-23 21:20:57 +09:00
Kubernetes Prow Robot
792b241a4a Merge pull request #5948 from koba1t/pinToKyaml
Update kyaml to v0.20.1
2025-07-23 05:18:27 -07:00
koba1t
8192ab34ee Update kyaml to v0.20.1 2025-07-23 21:09:58 +09:00
Kubernetes Prow Robot
87f462af25 Merge pull request #5943 from koba1t/chore/drop_shlex_dependency
drop shlex dependency
2025-07-20 12:50:25 -07:00
koba1t
3866a30826 introduce one const value that indicate to no quote in ShlexSplit() 2025-07-14 20:12:00 +09:00
koba1t
5cb1b4e3f9 remove shlex dependencies 2025-07-14 03:57:51 +09:00
koba1t
b6128950c9 add ShlexSplit() as an alternative to shlex.Split() 2025-07-14 03:54:29 +09:00
koba1t
042a2cf177 add testcases for shlexsplit 2025-07-12 07:14:17 +09:00
totegamma
e115ba6240 fix fnplugin storagemounts validation 2025-07-10 22:08:22 +09:00
Niklas Wagner
9376a5c4b7 Propagate Namespace correctly to Helm 2025-07-08 19:24:46 +02:00
Kubernetes Prow Robot
f9ab532a4a Merge pull request #5937 from koba1t/unpinEverything
Back to development mode; unpin the modules
2025-06-28 00:24:29 -07:00
koba1t
76eb28bad9 Back to development mode; unpin the modules 2025-06-28 16:13:29 +09:00
Kubernetes Prow Robot
7f30f0e23a Merge pull request #5936 from koba1t/pinToApi
Update api to v0.20.0
2025-06-27 23:56:29 -07:00
koba1t
35c9d0fece Update api to v0.20.0 2025-06-28 15:46:34 +09:00
Kubernetes Prow Robot
b1bfac465f Merge pull request #5935 from koba1t/pinToCmdConfig
Update cmd/config to v0.20.0
2025-06-27 23:40:29 -07:00
koba1t
40d1f35940 Update cmd/config to v0.20.0 2025-06-28 15:29:37 +09:00
Kubernetes Prow Robot
1a515925ab Merge pull request #5934 from koba1t/pinToKyaml
Update kyaml to v0.20.0
2025-06-27 23:26:29 -07:00
koba1t
f54b2b4c59 Update kyaml to v0.20.0 2025-06-28 15:16:16 +09:00
Kubernetes Prow Robot
03ae5c93ca Merge pull request #5846 from dmvolod/issue-5845-fix-version
fix: Get version from the BuildInfo.Main.Version if not found in deps and build flag
2025-06-26 14:40:29 -07:00
Kubernetes Prow Robot
0fe722e99a Merge pull request #5931 from dims/drop-usage-of-forked-copies-of-goyaml.v2-and-goyaml.v3
Drop usage of forked copies of goyaml.v2 and goyaml.v3
2025-06-25 10:58:29 -07:00
Davanum Srinivas
a7703f685c Drop usage of forked copies of goyaml.v2 and goyaml.v3
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2025-06-25 13:13:52 -04:00
Kubernetes Prow Robot
ba617e5126 Merge pull request #5921 from ThisIsQasim/imagevolume
feat: Add suport for Image Volumes
2025-06-24 14:10:28 -07:00
Kubernetes Prow Robot
755880462f Merge pull request #5918 from kubernetes-sigs/dependabot/github_actions/joelanford/go-apidiff-0.8.3
build(deps): bump joelanford/go-apidiff from 0.8.2 to 0.8.3
2025-06-10 16:48:55 -07:00
Kubernetes Prow Robot
832f873855 Merge pull request #5927 from kubernetes-sigs/dependabot/go_modules/hack/github.com/cloudflare/circl-1.6.1
build(deps): bump github.com/cloudflare/circl from 1.3.7 to 1.6.1 in /hack
2025-06-10 16:20:56 -07:00
dependabot[bot]
731ffd3d53 build(deps): bump github.com/cloudflare/circl in /hack
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.3.7 to 1.6.1.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.3.7...v1.6.1)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 21:23:16 +00:00
ThisIsQasim
32e82514a8 feat: Add suport for Image Volume 2025-06-02 16:22:11 +05:00
dependabot[bot]
13ed4a59f5 build(deps): bump joelanford/go-apidiff from 0.8.2 to 0.8.3
Bumps [joelanford/go-apidiff](https://github.com/joelanford/go-apidiff) from 0.8.2 to 0.8.3.
- [Release notes](https://github.com/joelanford/go-apidiff/releases)
- [Commits](https://github.com/joelanford/go-apidiff/compare/v0.8.2...v0.8.3)

---
updated-dependencies:
- dependency-name: joelanford/go-apidiff
  dependency-version: 0.8.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-26 00:31:28 +00:00
Kubernetes Prow Robot
b7340bd369 Merge pull request #5882 from arthurbdiniz/set-git-messages-to-english-for-TestRemoteLoad_LocalProtocol
Set Git messages to English for TestRemoteLoad_LocalProtocol
2025-05-23 01:22:36 -07:00
Kubernetes Prow Robot
367ebb6990 Merge pull request #5888 from lcostea/master
chore: remove unused build arg and address warnings
2025-05-23 00:54:35 -07:00
Kubernetes Prow Robot
616c084805 Merge pull request #5865 from milkshake308/feat_helm_devel_arg
feat(helm): allow the use of devel alias for helmcharts
2025-05-17 12:25:16 -07:00
Kubernetes Prow Robot
dba6dee214 Merge pull request #5907 from kubernetes-sigs/dependabot/go_modules/hack/github.com/getkin/kin-openapi-0.131.0
build(deps): bump github.com/getkin/kin-openapi from 0.120.0 to 0.131.0 in /hack
2025-05-17 12:15:13 -07:00
dependabot[bot]
009369bfc9 build(deps): bump github.com/getkin/kin-openapi in /hack
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.120.0 to 0.131.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.120.0...v0.131.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-version: 0.131.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-15 16:47:35 +00:00
Kubernetes Prow Robot
65567a3733 Merge pull request #5890 from gecube/patch-2
fix indent in example yaml at generatorOptions.md
2025-04-28 23:37:54 -07:00
Kubernetes Prow Robot
d53c17b874 Merge pull request #5898 from tabbysable/typo-fix
Fix typo in documentation
2025-04-28 23:09:55 -07:00
Tabitha Sable
aa2c9ca440 Fix typo in documentation
Fix a typo in an example URL in the resources.md Kustomization file documentation
2025-04-28 15:23:15 -05:00
George Gaál
b201d97541 Update generatorOptions.md
fix indentation
2025-04-12 13:38:02 +02:00
Liviu Costea
fd97ddaca1 fix: remove unused build arg and address warnings 2025-04-07 13:18:38 +03:00
Kubernetes Prow Robot
7372f97c19 Merge pull request #5877 from tsuzu/fix-replacements-plugin-omitempty-field
fix: make private one field in replacements transformer struct that had a missing JSON tag
2025-04-03 01:50:37 -07:00
Tsuzu
e3f0349319 Make replacements private 2025-03-31 20:41:41 +09:00
Timur Demin
dd08aec23e fix: Don't panic on multiple $patch: delete strategic merge patches in a single patch file (#5859)
* chore: add test for multiple $patch: delete patches not panicking

* fix: don't panic on multiple deletion SM patches
2025-03-28 06:04:40 -07:00
Kubernetes Prow Robot
2e80cebf21 Merge pull request #5630 from cunyat/feat/5516-replacement-inline-value
Add static value source for replacement
2025-03-28 05:54:40 -07:00
Arthur Diniz
e683487ea8 Set Git messages to English for TestRemoteLoad_LocalProtocol
Ensure consistent error message matching by setting LC_ALL=C in
TestRemoteLoad_LocalProtocol, preventing locale-based variations
in Git output.

Signed-off-by: Arthur Diniz <arthurbdiniz@gmail.com>
2025-03-24 23:29:37 +00:00
Kubernetes Prow Robot
53fa7285e9 Merge pull request #5881 from kubernetes-sigs/dependabot/go_modules/hack/github.com/golang-jwt/jwt/v5-5.2.2
build(deps): bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 in /hack
2025-03-22 13:54:31 -07:00
dependabot[bot]
61b8724e87 build(deps): bump github.com/golang-jwt/jwt/v5 in /hack
Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.1 to 5.2.2.
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md)
- [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.1...v5.2.2)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt/v5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-21 22:13:49 +00:00
Julio Chana
31b37540e3 fix: Allow patches with empty files with multiple newlines or comments (#5771)
* fix: Add test, when an empty patch file is given, it should not fail

* fix: Add code so there's no error given if an empty file is given as a patch

* chore: Generate plugin with pluginator

* chore: fix tests

Signed-off-by: Julio Chana <julio.chana@lokalise.com>

* Add t.helper() at start of test function

Signed-off-by: Julio Chana <julio.chana@lokalise.com>

---------

Signed-off-by: Julio Chana <julio.chana@lokalise.com>
2025-03-16 19:15:48 -07:00
Kubernetes Prow Robot
2643c51364 Merge pull request #5873 from skitt/clean-viper
Bump to github.com/spf13/viper v1.20.0
2025-03-15 11:17:47 -07:00
Stephen Kitt
6b830658d1 Bump to github.com/spf13/viper v1.20.0
This includes the go-difflib and go-spew reverts, which means the
corresponding exclusions can be removed. cmd/gorepomod/go.mod loses a
number of indirect dependencies thanks to the spf13/viper cleanup, but
hack/go.mod gains a few.

Signed-off-by: Stephen Kitt <skitt@redhat.com>
2025-03-15 17:13:59 +01:00
milkshake308
5036c077cc fix: incorrect devel chart assertion 2025-02-23 22:33:40 +01:00
milkshake308
418f233314 feat: add test cases for helm devel 2025-02-21 01:15:33 +01:00
milkshake308
c5f69b002f feat: add devel options for helmcharts 2025-02-21 01:13:18 +01:00
Kubernetes Prow Robot
447a60903c Merge pull request #5765 from kundan2707/glossary_link_update
updated link for glossary.md
2025-02-18 19:14:26 -08:00
Kundan Kumar
06535d623a updated link for glossary.md 2025-02-18 20:08:58 +05:30
Matthias Riegler
cc7a71c288 feat: add exec-plugin argument and environment support (#5316)
* feat: add exec-plugin argument and environment support

Previously, the documentation lead to think that this is working, but
it's not been implemented.

This PR is fixing this

Signed-off-by: Matthias Riegler <matthias.riegler@ankorstore.com>

* chore: disable linting for env var split

Signed-off-by: Matthias Riegler <matthias.riegler@ankorstore.com>

---------

Signed-off-by: Matthias Riegler <matthias.riegler@ankorstore.com>
2025-02-16 13:28:21 -08:00
Kubernetes Prow Robot
3be1af6798 Merge pull request #5855 from kubernetes-sigs/dependabot/go_modules/hack/github.com/golang/glog-1.2.4
build(deps): bump github.com/golang/glog from 1.2.0 to 1.2.4 in /hack
2025-02-02 18:40:57 -08:00
dependabot[bot]
33e9361a61 build(deps): bump github.com/golang/glog from 1.2.0 to 1.2.4 in /hack
Bumps [github.com/golang/glog](https://github.com/golang/glog) from 1.2.0 to 1.2.4.
- [Release notes](https://github.com/golang/glog/releases)
- [Commits](https://github.com/golang/glog/compare/v1.2.0...v1.2.4)

---
updated-dependencies:
- dependency-name: github.com/golang/glog
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-28 17:38:48 +00:00
Kubernetes Prow Robot
160de8ce76 Merge pull request #5853 from stormqueen1990/patch-1
Step down as commands approver
2025-01-27 11:17:23 -08:00
Mauren
d339dca90c Step down as commands approver
Due to reduced time available to work on Kustomize, I decided to step down from the command approver role for the time being.
2025-01-26 11:13:08 -05:00
Kubernetes Prow Robot
e4fff94c68 Merge pull request #5656 from ah8ad3/refactor-common-labels
Update readme to remove deprecated configuration 'commonLabels'.
2025-01-19 23:22:35 -08:00
Dmitry Volodin
9c68bd2ee2 fix: Get version from the BuildInfo.Main.Version if not found in deps and build flag 2025-01-19 09:25:33 +03:00
Kubernetes Prow Robot
38eb24492a Merge pull request #5847 from koba1t/dependencies/replace_to_carapace-shlex
replace deplecated package github.com/google/shlex with github.com/carapace-sh/carapace-shlex
2025-01-17 05:56:36 -08:00
koba1t
7664c4ba38 replace github.com/google/shlex with https://github.com/carapace-sh/carapace-shlex 2025-01-16 14:54:26 +09:00
Kubernetes Prow Robot
48686ac4a3 Merge pull request #5844 from stormqueen1990/feat/bump-deps
build(deps): bump golang.org/x/net from 0.28.0 to 0.33.0 in /hack
2025-01-15 18:40:34 -08:00
Mauren Berti
f03e31389d build(deps): bump golang.org/x/net from 0.28.0 to 0.33.0 in /hack
Bump the golang.org/x/net dependency and synchronize the workspace using
make workspace-sync
2025-01-15 15:17:23 -05:00
Kubernetes Prow Robot
ba56dd28ca Merge pull request #5841 from koba1t/unpinEverything
Back to development mode; unpin the modules
2025-01-14 07:54:33 -08:00
koba1t
821aebc3b3 Back to development mode; unpin the modules 2025-01-15 00:37:09 +09:00
Kubernetes Prow Robot
95db4aa0ed Merge pull request #5840 from koba1t/pinToApi
Update api to v0.19.0
2025-01-14 07:08:34 -08:00
koba1t
07f62bd986 Update api to v0.19.0 2025-01-14 23:54:58 +09:00
Kubernetes Prow Robot
b69e76509f Merge pull request #5839 from koba1t/pinToCmdConfig
Update cmd/config to v0.19.0
2025-01-14 06:50:33 -08:00
koba1t
8a51255ea1 Update cmd/config to v0.19.0 2025-01-14 23:42:16 +09:00
Kubernetes Prow Robot
ce667b70a0 Merge pull request #5837 from koba1t/pinToKyaml
Update kyaml to v0.19.0
2025-01-14 06:22:33 -08:00
koba1t
1b33db58f2 Update kyaml to v0.19.0 2025-01-14 23:14:25 +09:00
yugo kobayashi
880a7a0187 add go work verification step for github actions (#5833)
* add go work verification step for github actions

* failure-example_this_commit_will_be_failed_to_check_go_work_sync

* Revert "failure-example_this_commit_will_be_failed_to_check_go_work_sync"

This reverts commit d8fd5020dc.
2025-01-07 10:58:29 -08:00
Sebastiaan van Stijn
2867f353c2 downgrade go-difflib and go-spew to tagged releases (#5830)
* workspace sync

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

* downgrade go-difflib and go-spew to tagged releases

commit d35edbf80d updated these dependencies
to untagged versions. The diff in both dependencies show that there's no
code changes, and it's unlikely for those modules to do new releases.

Unfortunate, because of that change all projects depending on kubernetes
or any of it's modules now had to upgrade to unreleased versions of
these.

This patch reverts those updates (but it may take some time before
all other projects can be reverted).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

---------

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-07 03:48:28 +01:00
Kubernetes Prow Robot
214aa2aae2 Merge pull request #5823 from kubernetes-sigs/dependabot/go_modules/hack/golang.org/x/crypto-0.31.0
build(deps): bump golang.org/x/crypto from 0.24.0 to 0.31.0 in /hack
2024-12-17 13:46:53 +01:00
dependabot[bot]
6f62ee7198 build(deps): bump golang.org/x/crypto from 0.24.0 to 0.31.0 in /hack
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.24.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.24.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-15 11:52:17 +00:00
Kubernetes Prow Robot
fcc95370ff Merge pull request #5825 from dims/update-to-latest-kube-api-to-drop-govalidator-dependency
Update to latest kube-opeapi to drop govalidator dependency
2024-12-15 12:50:43 +01:00
Davanum Srinivas
84e6594e9b Update golangci/golangci-lint to v1.56.2
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2024-12-14 19:28:39 -05:00
Kubernetes Prow Robot
86af799ce0 Merge pull request #5809 from fktym/fix/add-label-without-selector
fix: "edit add labels" make labels handle -f flag same as commonLabels
2024-12-13 04:26:25 +01:00
Davanum Srinivas
b79c5f652d Update to latest kube-opeapi to drop govalidator dependency
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2024-12-12 18:48:06 -05:00
fktym
70e4d2e24c fix: make labels handle -f flag same as commonLabels 2024-12-12 14:02:53 +09:00
Kubernetes Prow Robot
a8c5b10d39 Merge pull request #5810 from guettli/better-err-msg-on-undefined-loader-behavior
Better error message on undefined loader behavior.
2024-11-30 19:00:58 +00:00
Thomas Guettler
ae7ff36f1b Better error message on undefined loader behavior. 2024-11-25 08:44:36 +01:00
Kubernetes Prow Robot
bb7a280709 Merge pull request #5785 from koba1t/remove_unnecesary_install_command_from_Dockerfile
remove unnecesary install command from Dockerfile
2024-10-10 22:04:21 +01:00
koba1t
d135197eba remove unnecesary install command from Dockerfile 2024-10-09 23:26:16 +09:00
Kubernetes Prow Robot
4c5c585592 Merge pull request #5784 from koba1t/unpinEverything
Back to development mode; unpin the modules
2024-10-09 14:38:23 +01:00
koba1t
4f6e3cbe3f Back to development mode; unpin the modules 2024-10-09 22:20:42 +09:00
Kubernetes Prow Robot
afe7793676 Merge pull request #5783 from koba1t/pinToApi
Update api to v0.18.0
2024-10-09 14:08:22 +01:00
koba1t
ae98655f0f Update api to v0.18.0 2024-10-09 21:58:41 +09:00
Kubernetes Prow Robot
faccc12624 Merge pull request #5782 from koba1t/pinToCmdConfig
Update cmd/config to v0.15.0
2024-10-09 13:46:23 +01:00
koba1t
fdf9f59cb5 Update cmd/config to v0.15.0 2024-10-09 21:37:00 +09:00
Kubernetes Prow Robot
e2967cf3ce Merge pull request #5781 from koba1t/pinToKyaml
Update kyaml to v0.18.1
2024-10-09 13:30:23 +01:00
koba1t
d22fa37ae0 Update kyaml to v0.18.1 2024-10-09 21:20:17 +09:00
Kubernetes Prow Robot
01cce4f6cc Merge pull request #5756 from viniciusdc/5755-kustomize-install
chore: add bad-credentials exception for install script
2024-09-27 03:50:01 +01:00
Kubernetes Prow Robot
54cbcdc698 Merge pull request #5770 from koba1t/add_write_permission_to_run_release_CI
add write permission to run release CI
2024-09-26 23:00:04 +01:00
koba1t
b36b222b26 add write permission to run release CI 2024-09-27 01:36:10 +09:00
Kubernetes Prow Robot
2cd9a2e73a Merge pull request #5768 from dims/remove-starlark-support
Remove starlark support
2024-09-25 18:14:00 +01:00
Davanum Srinivas
d32eacf034 Remove starlark support
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2024-09-23 16:52:05 -04:00
Kubernetes Prow Robot
88f19bffa9 Merge pull request #5763 from koba1t/update_go_1.22.7
Update go 1.22.7
2024-09-16 05:41:13 +01:00
koba1t
a3c0b4add7 disable for a step to skip test when that is docs PR 2024-09-15 01:56:28 +09:00
koba1t
b67ce5bb73 go work sync && ./hack/doGoMod.sh tidy 2024-09-15 01:43:03 +09:00
koba1t
5ba8523df7 update go 1.22.7 2024-09-15 01:40:50 +09:00
Isar_NS
4034e36ee1 Add --helm-debug Flag to Kustomize for Enhanced Helm Debugging (#5751)
* feat: add helm-debug flag

* revert: go.work.sum

* test: add helm chart args helm-debug test

* test: helm debug flag

* refactor: helm debug output

* style: linting

* revert: go.work.sum
2024-09-12 23:43:12 +01:00
Kubernetes Prow Robot
c3872ce3d9 Merge pull request #5745 from isarns/master
Add Annotation to Control Inline List Conversion in Kustomize Resources"
2024-09-12 18:57:13 +01:00
Kubernetes Prow Robot
d35d21c2d0 Merge pull request #5760 from Kavinjsir/patch-docs
Docs: fix kubectl command
2024-09-10 11:39:57 +01:00
Vinicius D. Cerutti
3872752338 chore: add bad-credentials exception for install script
* fix typo at closing if statement
2024-09-09 13:08:41 -03:00
isarns
a5f43ec75a style: linting 2024-09-09 13:26:53 +03:00
isarns
e6266d4559 refactor: fix test with not 'items:' 2024-09-09 13:26:33 +03:00
Tony Jin
99efd6995a docs: fix kubectl command 2024-09-06 15:05:07 -07:00
ah8ad3
5ef10d35ee Update readme to remove deprecated configuration 'commonLabels'. 2024-09-04 18:55:00 +03:30
Daniel Wilson
b7cdd9168a Sort built-in Namespace kind before CRDs with the same name (#5458)
* add core api sort priority for NAmespace kind in gvkLessThan

* fix logic

* fix syntax

* fix syntax

* fix logic

* regenerate builtin plugins
2024-09-03 21:57:17 +01:00
Kubernetes Prow Robot
27d508fa03 Merge pull request #5716 from VannTen/cleanup/wrong_example_config_gen
Remove misleading documentation about config generation
2024-08-29 18:01:30 +01:00
Max Gautier
05339dafe5 Remove misleading documentation about config generation
ConfigMap are not garbage collected, see #3146
2024-08-26 15:00:45 +02:00
isarns
bbb0b08576 test: add empty list test 2024-08-18 14:56:54 +03:00
isarns
77daec89b8 refactor: inlineAnyEmbeddedLists 2024-08-13 14:35:46 +03:00
isarns
a1fd6efe5d feat: annotation to disable list conversion 2024-08-11 17:44:44 +03:00
Ramon Cunyat
6c27970019 Add static value source for replacement
Introduces `sourceValue` on replacement object for replacing from a
static value instead of sourcing from another object.

Solves #5516
2024-07-25 14:32:54 +02:00
John Zheng
cc9dd34216 docs: update patchMultipleObject example to filter with labelSelector (#5700)
* Update patchMultipleObjects.md

* Update patchMultipleObjects.md

* Update patchMultipleObjects.md

* Update patchMultipleObjects.md

* Update patchMultipleObjects.md

* Update patchMultipleObjects.md

* Update patchMultipleObjects.md

* Update patchMultipleObjects.md
2024-07-23 15:02:40 -07:00
Kubernetes Prow Robot
2aaa42f950 Merge pull request #5737 from koba1t/unpinEverything
Back to development mode; unpin the modules
2024-07-19 10:09:37 -07:00
koba1t
f660160a0f Back to development mode; unpin the modules 2024-07-20 01:57:28 +09:00
Varsha
d4248b1213 Merge pull request #5736 from koba1t/pinToApi
Update api to v0.17.3
2024-07-19 09:34:19 -07:00
koba1t
bd8b8a49c9 Update api to v0.17.3 2024-07-20 01:14:03 +09:00
Kubernetes Prow Robot
ddeb572a7f Merge pull request #5735 from koba1t/pinToCmdConfig
Update cmd/config to v0.14.2
2024-07-19 09:07:22 -07:00
koba1t
36d78f67fd Update cmd/config to v0.14.2 2024-07-20 00:55:30 +09:00
Kubernetes Prow Robot
4e52632bd3 Merge pull request #5734 from koba1t/pinToKyaml
Update kyaml to v0.17.2
2024-07-19 08:50:48 -07:00
koba1t
8eacab0fc6 Update kyaml to v0.17.2 2024-07-20 00:28:06 +09:00
Kubernetes Prow Robot
1a41303fbb Merge pull request #5628 from antoooks/release-helper-script
Release helper script
2024-07-16 10:53:06 -07:00
Dennis Zhou
7cbaf78b1a fix:kustomize cfg grep with no arguments causes panic (#5707)
* fix:kustomize cfg grep with no arguments causes panic

* add test for kustomize cfg grep with no arguments
2024-07-10 00:46:40 -07:00
Kubernetes Prow Robot
735ad0beef Merge pull request #5682 from kozjan/add-label-include-templates
fix: include label in templates when adding by cli
2024-07-10 00:46:33 -07:00
Kubernetes Prow Robot
c1de0301f5 Merge pull request #5413 from crenshaw-dev/patch-1
chore(docs): fix grammar error in comment
2024-06-30 11:45:02 -07:00
Kubernetes Prow Robot
5cfd3ab3e7 Merge pull request #5725 from kubernetes-sigs/dependabot/go_modules/hack/golang.org/x/image-0.18.0
build(deps): bump golang.org/x/image from 0.13.0 to 0.18.0 in /hack
2024-06-27 07:47:18 -07:00
dependabot[bot]
dfb30644f4 build(deps): bump golang.org/x/image from 0.13.0 to 0.18.0 in /hack
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.13.0 to 0.18.0.
- [Commits](https://github.com/golang/image/compare/v0.13.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-26 19:38:08 +00:00
Kubernetes Prow Robot
e3a7615ccb Merge pull request #5506 from cloud-native-team/master
fix some comments
2024-06-18 12:37:52 -07:00
Kubernetes Prow Robot
b02d02a6cd Merge pull request #5715 from kubernetes-sigs/dependabot/go_modules/hack/github.com/Azure/azure-sdk-for-go/sdk/azidentity-1.6.0
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.3.0 to 1.6.0 in /hack
2024-06-18 12:20:28 -07:00
Kubernetes Prow Robot
804f69bacf Merge pull request #5719 from kubernetes-sigs/dependabot/npm_and_yarn/site/braces-3.0.3
build(deps-dev): bump braces from 3.0.2 to 3.0.3 in /site
2024-06-18 10:11:10 -07:00
dependabot[bot]
9ab7762a40 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity
Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.3.0 to 1.6.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.3.0...sdk/azcore/v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 22:01:15 +00:00
dependabot[bot]
44a99b7284 build(deps-dev): bump braces from 3.0.2 to 3.0.3 in /site
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 21:47:44 +00:00
Kubernetes Prow Robot
692b40e515 Merge pull request #5718 from koba1t/chore/fix_lint_error_in_kustomizationfile_test.go
fix lint error in kustomizationfile_test.go
2024-06-17 14:46:47 -07:00
koba1t
bef46a1a04 fix lint error in kustomizationfile_test.go 2024-06-18 06:33:57 +09:00
Kubernetes Prow Robot
48d79c745a Merge pull request #5691 from karlkfi/karl-cockroachdb-pin-version
Pin kustomize image in cockroachdb example
2024-06-12 09:39:45 -07:00
Kubernetes Prow Robot
856662835f Merge pull request #5698 from stormqueen1990/fix/validation-name-reference
fix(namereference): add configuration for new admission API
2024-06-08 01:42:58 -07:00
jan.kozlowski
cba3688960 add validation and test case 2024-06-06 14:01:49 +02:00
Oliver F
16a7ce2b8b Fix sortOptions removal when running edit command (#5689)
* Fix sortOptions and Validators removal when running edit command

* fixed linting
2024-06-04 20:26:41 -07:00
Kubernetes Prow Robot
92e862c233 Merge pull request #5544 from sanaasy/sanaasy/add-no-verify-flag
Run kustomize build with kustomize localize and add a no-verify flag.
2024-06-04 20:10:20 -07:00
Sanaa Syed
8db4c4b062 Fix lint error message adn reduce build error message to a string concatination. 2024-06-03 22:22:03 -04:00
Kubernetes Prow Robot
cb432b0350 Merge pull request #5699 from stormqueen1990/chore/deprecation-common-labels
chore: add deprecation comment to commonLabels
2024-05-27 15:15:20 -07:00
Colin O'Dell
88c89f422a fix: always show accumulation errors (#5693)
* fix: always show accumulation errors if the resource was successfully loaded as a base

* chore: regression test

* chore: fix lint violations
2024-05-24 20:13:10 -07:00
Kubernetes Prow Robot
ce80dc9e2b Merge pull request #5705 from koba1t/unpinEverything
Back to development mode; unpin the modules
2024-05-22 08:48:38 -07:00
koba1t
226d56b5cf Back to development mode; unpin the modules 2024-05-23 00:35:50 +09:00
Kubernetes Prow Robot
f309dfc54a Merge pull request #5704 from koba1t/pinToApi
Update api to v0.17.2
2024-05-22 08:16:59 -07:00
koba1t
a34ac31a80 Update api to v0.17.2 2024-05-23 00:04:13 +09:00
Kubernetes Prow Robot
9cc25a511c Merge pull request #5703 from koba1t/pinToCmdConfig
Update cmd/config to v0.14.1
2024-05-22 07:53:44 -07:00
koba1t
f6ad718ee6 Update cmd/config to v0.14.1 2024-05-22 23:41:07 +09:00
Kubernetes Prow Robot
da14e76359 Merge pull request #5702 from koba1t/pinToKyaml
Update kyaml to v0.17.1
2024-05-22 07:37:54 -07:00
koba1t
7424956ccf Update kyaml to v0.17.1 2024-05-22 23:24:23 +09:00
Mauren Berti
77354d73b9 chore: add deprecation comment to commonLabels
`commonLabels` is deprecated, but the field did not have a deprecation comment,
like other fields do. Add the deprecation comment, as some IDEs use that as a
guideline to show a strikethrough in the field names (and to follow the pattern
of other deprecated fields).
2024-05-19 21:07:00 -04:00
Mauren Berti
3065eb36dd fix(namereference): add configuration for new admission API
Include configuration for the new `ValidatingAdmissionPolicy` and
`ValidationAdmissionPolicyBinding` APIs so that Kustomize can natively configure
the `policyName` field in `ValidatingAdmissionPolicyBinding` with the transformed
name of `ValidatingAdmissionPolicy`.
2024-05-19 20:58:03 -04:00
Sanaa Syed
b67959894e Add --no-verify flag configs along with kustomize build when kustomize localize command is run. 2024-05-15 23:45:29 -04:00
Karl Isenberg
6a829feef8 Pin kustomize image in cockroachdb example
- Pin to v5.4.1 with sha256 as example of how to ensure supply-chain
  security. Pulling the latest kustomize image or source is insecure
  without checksum validation.
- Bump example image tag to v0.1.1
2024-05-06 11:02:20 -07:00
Kubernetes Prow Robot
e244b83844 Merge pull request #5688 from emirot/refactor/indexOf
refactor: function in stdlib now
2024-05-05 19:38:34 -07:00
emirot
f9838461af refactor: function in stdlib now
Signed-off-by: emirot <emirot.nolan@gmail.com>
2024-05-03 22:45:56 +02:00
Kubernetes Prow Robot
49a645f05d Merge pull request #5294 from typeid/localize_absolute_paths
feat: localize absolute paths
2024-04-29 22:11:47 -07:00
Tiago Silva
e7a15496dd fix: use fmt.Errorf instead of non-existing errors.New (#5651)
* fix: use fmt.Errorf ubstead if non-exising `errors.New`

When https://github.com/kubernetes-sigs/kustomize/pull/5525 merged, it
referenced `errors.New` function but that function doesn't exist.
This PR replaces the call with simple `fmt.Errorf`.

* Add lint check with kustomize_disable_go_plugin_support

* move lint-api-static to /api/Makefile

* clean golangci cache
2024-04-29 18:22:26 -07:00
Kubernetes Prow Robot
0d7d830236 Merge pull request #5681 from emirot/remove-string-in-slice
chore: remove unused function
2024-04-28 23:59:56 -07:00
Kubernetes Prow Robot
e676d056b2 Merge pull request #5500 from charles-chenzz/kust-target-tc
add testcase that check yield malformed yaml errors
2024-04-28 23:45:18 -07:00
Kurnianto Trilaksono
b1a9bffd8b Update CONTRIBUTING.md
- change breaking change notes

Co-authored-by: Mauren <698465+stormqueen1990@users.noreply.github.com>
2024-04-28 23:28:48 +07:00
jan.kozlowski
a83f102cc9 fix: include label in templates when adding by cli 2024-04-26 23:21:51 +02:00
emirot
0e649599d0 chore: remove unused function
Signed-off-by: emirot <emirot.nolan@gmail.com>
2024-04-26 16:32:00 +01:00
Kubernetes Prow Robot
a68f40738a Merge pull request #5680 from koba1t/chore/restore_version_for_govalidator
chore: restore version for github.com/asaskevich/govalidator
2024-04-25 08:20:51 -07:00
koba1t
72d95b5f41 chore: restore version for github.com/asaskevich/govalidator 2024-04-25 17:21:05 +09:00
Mauren
671de1662d feat: support labels key in transformer configuration (#5556)
* feat: support labels key in transformer configuration

Allow the usage of a separate transformer configuration for the labels key,
similar to what is currently available for commonLabels and commonAnnotations.
This aims to provide the same functionality that commonLabels currently provide
for labels, since commonLabels is deprecated and slated for removal in a future
release.

* chore(transformerconfig): add nolint hint

Add a nolint hint to the new method so the returns can stay consistent with
one another.

* fix: changes from code review

* Rename methods `AddCommonLabelFieldSpec` and `AddLabelFieldSpec` to
  `AddCommonLabelsFieldSpec` and `AddLabelsFieldSpec`.
* Add extra test to verify scenarios applying labels to Custom Resource Definitions.
2024-04-25 00:40:44 -07:00
Kurnianto Trilaksono
25c7e17fb8 add pr rules, fix script 2024-04-24 20:30:34 +08:00
Kubernetes Prow Robot
2e6171a9ea Merge pull request #5671 from emirot/refactor/string_inSlice
refactor: string in slice is now part of stdlib
2024-04-23 04:36:33 -07:00
Kubernetes Prow Robot
7f99cebdc6 Merge pull request #5672 from stormqueen1990/chore/bump-deps
chore(deps): bump dependencies of kustomize + sync go workspace
2024-04-22 20:01:27 -07:00
Mauren Berti
5d127e4138 chore(deps): bump dependencies of kustomize + sync go workspace
* Bump the golang.org/x dependencies.
* Run `go work sync` to synchronize dependencies across Go workspaces.
2024-04-21 20:03:38 -04:00
nolan emirot
bcb1a367aa refactor: string in slice part of stdlib now
Signed-off-by: emirot <nolan.emirot@workday.com>
2024-04-20 18:48:40 -04:00
Yusuke Abe
ed09399cd1 fix: return error instead of log.Fatalf() (#5625)
* fix: return error instead of log.Fatalf()

* chore: add meaningful message to error output

* chore: add meaningful message to fatal function
2024-04-18 03:56:51 -07:00
Kubernetes Prow Robot
82ee768212 Merge pull request #5079 from chlunde/perf-1
perf: improve applyOrdering by avoid call to GetByCurrentId
2024-04-06 10:14:25 -07:00
Kubernetes Prow Robot
116b307b88 Merge pull request #5646 from koba1t/unpinEverything
Back to development mode; unpin the modules
2024-04-04 10:38:23 -07:00
koba1t
fb9f45ebe0 Back to development mode; unpin the modules 2024-04-05 02:24:31 +09:00
Kubernetes Prow Robot
536c1c0a8b Merge pull request #5645 from koba1t/pinToApi
Update api to v0.17.1
2024-04-04 10:11:54 -07:00
koba1t
e20e438d05 Update api to v0.17.1 2024-04-05 02:01:10 +09:00
Kubernetes Prow Robot
42873c8d2a Merge pull request #5644 from koba1t/fix/version_subcommand_is_broken
fix version subcommand is not working after release build
2024-04-04 09:53:40 -07:00
koba1t
277da9ed21 fix version subcommand is not working after release build 2024-04-05 01:37:31 +09:00
Kubernetes Prow Robot
2b00d887fd Merge pull request #5643 from koba1t/unpinEverything
unpin api
2024-04-04 08:57:57 -07:00
koba1t
08d0593c3e unpin api 2024-04-05 00:45:41 +09:00
Kurnianto Trilaksono
63329d175a fix logic and add license 2024-03-29 16:49:10 +08:00
Kurnianto Trilaksono
f63e919e3e revert untouched file 2024-03-28 00:01:40 +08:00
Kurnianto Trilaksono
3d840a6584 revert untouched files 2024-03-27 23:56:57 +08:00
Kurnianto Trilaksono
846d3c09eb fix logic 2024-03-27 00:16:03 +08:00
Kurnianto Trilaksono
fbc102dbd3 add change counter 2024-03-27 00:15:00 +08:00
Kurnianto Trilaksono
a7de0cc8cd edit printout 2024-03-27 00:11:53 +08:00
Kurnianto Trilaksono
931f924189 add helper script for releasing 2024-03-24 15:22:04 +08:00
Nick
50dc813731 Add buildMetadata task and ref (#5511)
* Add buildMetadata task and ref

Move build metadata tasks, draft buildMetadata reference

Clean up buildMetadata ref

Add managed by label task

Add local non-generated task

Add local generated resource

Add remote generator task

Clean up tasks and ref

Add local transformer annotation example

Add local and remote transformer example

* Address PR feedback and general cleanup

cherrypick updates from feature branch

fix script

fix release script
2024-03-24 14:50:19 +08:00
charles-chenzz
3f921e159b add testcase that yield malformed yaml errors 2024-01-08 19:25:04 +08:00
cui fliter
d56e1d0f46 fix some comments
Signed-off-by: cui fliter <imcusg@gmail.com>
2024-01-05 16:25:48 +08:00
Claudio Busse
7b1eaf1e4f feat: localize absolute paths 2023-11-26 12:22:15 +01:00
Carl Henrik Lunde
5c7f8b8d73 perf: improve applyOrdering by avoid call to GetByCurrentId
This shaves of 14 seconds (one third) of the execution time for a
kustomization tree with 4000 documents, from 40.68s to 27.41s

            0     0%  5.44%     18.42s 40.56%  sigs.k8s.io/kustomize/api/krusty.(*Kustomizer).applySortOrder
            0     0%  5.44%     18.40s 40.52%  sigs.k8s.io/kustomize/api/internal/builtins.applyOrdering
before

    (pprof) top20 -cum
    Showing nodes accounting for 5.85s, 12.88% of 45.41s total
    Dropped 622 nodes (cum <= 0.23s)
    Showing top 20 nodes out of 157
        flat  flat%   sum%        cum   cum%
            0     0%     0%     40.68s 89.58%  github.com/spf13/cobra.(*Command).Execute
            0     0%     0%     40.68s 89.58%  github.com/spf13/cobra.(*Command).ExecuteC
            0     0%     0%     40.68s 89.58%  github.com/spf13/cobra.(*Command).execute
            0     0%     0%     40.68s 89.58%  main.main
            0     0%     0%     40.68s 89.58%  runtime.main
            0     0%     0%     40.68s 89.58%  sigs.k8s.io/kustomize/kustomize/v5/commands/build.NewCmdBuild.func1
            0     0%     0%     40.12s 88.35%  sigs.k8s.io/kustomize/api/krusty.(*Kustomizer).Run
        0.51s  1.12%  1.12%     33.20s 73.11%  sigs.k8s.io/kustomize/api/resource.(*Resource).CurId
            0     0%  1.12%     26.95s 59.35%  sigs.k8s.io/kustomize/api/resmap.(*resWrangler).GetMatchingResourcesByCurrentId
        0.35s  0.77%  1.89%     26.95s 59.35%  sigs.k8s.io/kustomize/api/resmap.(*resWrangler).filteredById
        0.07s  0.15%  2.05%     25.53s 56.22%  sigs.k8s.io/kustomize/api/resmap.GetCurrentId
            0     0%  2.05%     21.68s 47.74%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).MakeCustomizedResMap (inline)
            0     0%  2.05%     21.68s 47.74%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).makeCustomizedResMap
        0.54s  1.19%  3.24%     19.75s 43.49%  sigs.k8s.io/kustomize/api/resource.(*Resource).GetGvk (inline)
            1s  2.20%  5.44%     19.21s 42.30%  sigs.k8s.io/kustomize/kyaml/resid.GvkFromNode
            0     0%  5.44%     18.42s 40.56%  sigs.k8s.io/kustomize/api/internal/builtins.(*SortOrderTransformerPlugin).Transform
            0     0%  5.44%     18.42s 40.56%  sigs.k8s.io/kustomize/api/krusty.(*Kustomizer).applySortOrder
            0     0%  5.44%     18.40s 40.52%  sigs.k8s.io/kustomize/api/internal/builtins.applyOrdering
        0.87s  1.92%  7.36%     16.55s 36.45%  sigs.k8s.io/kustomize/kyaml/yaml.visitMappingNodeFields
        2.51s  5.53% 12.88%     15.68s 34.53%  sigs.k8s.io/kustomize/kyaml/yaml.visitFieldsWhileTrue

after

    (pprof) top20 -cum
    Showing nodes accounting for 1.23s, 3.85% of 31.98s total
    Dropped 584 nodes (cum <= 0.16s)
    Showing top 20 nodes out of 184
        flat  flat%   sum%        cum   cum%
            0     0%     0%     27.41s 85.71%  github.com/spf13/cobra.(*Command).Execute
            0     0%     0%     27.41s 85.71%  github.com/spf13/cobra.(*Command).ExecuteC
            0     0%     0%     27.41s 85.71%  github.com/spf13/cobra.(*Command).execute
            0     0%     0%     27.41s 85.71%  main.main
            0     0%     0%     27.41s 85.71%  runtime.main
            0     0%     0%     27.41s 85.71%  sigs.k8s.io/kustomize/kustomize/v5/commands/build.NewCmdBuild.func1
            0     0%     0%     26.85s 83.96%  sigs.k8s.io/kustomize/api/krusty.(*Kustomizer).Run
            0     0%     0%     22.07s 69.01%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).MakeCustomizedResMap (inline)
            0     0%     0%     22.07s 69.01%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).makeCustomizedResMap
        0.38s  1.19%  1.19%     20.69s 64.70%  sigs.k8s.io/kustomize/api/resource.(*Resource).CurId
            0     0%  1.19%     13.64s 42.65%  sigs.k8s.io/kustomize/api/resmap.(*resWrangler).Append
            0     0%  1.19%     13.55s 42.37%  sigs.k8s.io/kustomize/api/resmap.(*resWrangler).GetMatchingResourcesByCurrentId (inline)
        0.12s  0.38%  1.56%     13.55s 42.37%  sigs.k8s.io/kustomize/api/resmap.(*resWrangler).filteredById
        0.01s 0.031%  1.59%     12.67s 39.62%  sigs.k8s.io/kustomize/api/resmap.GetCurrentId
        0.21s  0.66%  2.25%     12.49s 39.06%  sigs.k8s.io/kustomize/api/resource.(*Resource).GetGvk (inline)
        0.51s  1.59%  3.85%     12.28s 38.40%  sigs.k8s.io/kustomize/kyaml/resid.GvkFromNode
            0     0%  3.85%     11.52s 36.02%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).IgnoreLocal
            0     0%  3.85%     10.53s 32.93%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).AccumulateTarget
            0     0%  3.85%     10.53s 32.93%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).accumulateResources
            0     0%  3.85%     10.53s 32.93%  sigs.k8s.io/kustomize/api/internal/target.(*KustTarget).accumulateTarget
2023-10-30 22:31:52 +01:00
Michael Crenshaw
71546359b8 Add a comment 2023-10-24 09:22:30 -04:00
Michael Crenshaw
234ab80086 chore(docs): fix grammar error in comment 2023-10-23 14:00:29 -04:00
341 changed files with 17575 additions and 7761 deletions

View File

@@ -13,20 +13,20 @@ jobs:
if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: Clone the code
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version-file: go.work
- name: Execute go-apidiff
uses: joelanford/go-apidiff@v0.8.2
uses: joelanford/go-apidiff@60c4206be8f84348ebda2a3e0c3ac9cb54b8f685
with:
compare-imports: true
print-compatible: true
- name: Report failure
uses: nashmaniac/create-issue-action@v1.2
uses: nashmaniac/create-issue-action@6814b79f58a9e25070c226b0c847e67b0c06efdd
# Only report failures of pushes (PRs have are visible through the Checks section) to the default branch
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master'
with:

View File

@@ -2,14 +2,15 @@ name: Go
on:
push:
branches: [ master ]
branches: [master]
pull_request:
branches: [ master ]
branches: [master]
permissions:
contents: read
jobs:
## TODO: conditional-changes checker is not working
conditional-changes:
runs-on: ubuntu-latest
permissions:
@@ -17,94 +18,141 @@ jobs:
outputs:
doc: ${{ steps.filter.outputs.doc }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d
id: filter
with:
filters: |
doc:
- 'site/**'
lint:
name: Lint
needs: conditional-changes
if: needs.conditional-changes.outputs.doc == 'false'
check-modules:
name: check-synced-go-modules
# needs: conditional-changes
# if: needs.conditional-changes.outputs.doc == 'false'
runs-on: [ubuntu-latest]
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Set up Go 1.x
uses: actions/setup-go@v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version-file: go.work
cache: true
cache-dependency-path: |
**/go.sum
id: go
- name: sync go modules
run: make workspace-sync
- name: check for changes with 'make workspace-sync'
run: git diff --exit-code
lint:
name: Lint
# needs: conditional-changes
# if: needs.conditional-changes.outputs.doc == 'false'
runs-on: [ubuntu-latest]
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Set up Go 1.x
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version-file: go.work
cache: true
cache-dependency-path: |
**/go.sum
id: go
- name: Lint
run: make lint
- name: Verify boilerplate
run: make check-license
test-linux:
## Test all modules without plugins and released modules
test-non-released-modules:
name: Test Linux
needs: conditional-changes
if: needs.conditional-changes.outputs.doc == 'false'
# needs: conditional-changes
# if: needs.conditional-changes.outputs.doc == 'false'
runs-on: [ubuntu-latest]
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Go 1.x
uses: actions/setup-go@v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version-file: go.work
cache: true
cache-dependency-path: |
**/go.sum
id: go
- name: Test all modules
run: make test-unit-non-plugin
- name: Test all modules without plugins and released modules
run: make test-unit-non-plugin-and-non-released
env:
KUSTOMIZE_DOCKER_E2E: true
test-macos:
name: Test MacOS
needs: conditional-changes
if: needs.conditional-changes.outputs.doc == 'false'
runs-on: [macos-latest]
test-modules:
name: Test ${{ matrix.os }} - ${{ matrix.module }}
# needs: conditional-changes
# if: needs.conditional-changes.outputs.doc == 'false'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
module:
- kyaml
- cmd/config
- api
- kustomize
include:
- module: kyaml
test-cmd: go test -race -v -cover ./...
- module: cmd/config
test-cmd: go test -v -cover ./...
- module: api
test-cmd: go test -v -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.buildDate=2023-01-31T23:38:41Z -X sigs.k8s.io/kustomize/api/provenance.version=(test)"
- module: kustomize
test-cmd: go test -v -cover ./...
- os: ubuntu-latest
docker-e2e: true
- os: macos-latest
docker-e2e: false
- os: windows-latest
docker-e2e: false
env:
KUSTOMIZE_DOCKER_E2E: ${{ matrix.docker-e2e }}
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Go 1.x
uses: actions/setup-go@v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version-file: go.work
cache: true
cache-dependency-path: |
**/go.sum
id: go
- name: Test all modules
run: make test-unit-non-plugin
env:
KUSTOMIZE_DOCKER_E2E: false # docker not installed on mac
- name: Test ${{ matrix.module }}
run: ${{ matrix.test-cmd }}
# TODO (#4001): replace specific modules above with this once Windows tests are passing.
if: ${{ !(matrix.os == 'windows-latest' && (matrix.module == 'api' || matrix.module == 'kustomize')) }}
working-directory: ./${{ matrix.module }}
test-windows:
name: Test Windows
needs: conditional-changes
if: needs.conditional-changes.outputs.doc == 'false'
runs-on: [windows-latest]
# Aggregation matrix tests from test-modules for branch protection rules
test-modules-summary:
name: Test Summary
runs-on: ubuntu-latest
needs: test-modules
if: always()
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
- name: Set up Go 1.x
uses: actions/setup-go@v5
with:
go-version-file: go.work
id: go
- name: Test kyaml
run: go test -cover ./...
working-directory: ./kyaml
- name: Test cmd/config
run: go test -cover ./...
working-directory: ./cmd/config
env:
KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
# TODO (#4001): replace specific modules above with this once Windows tests are passing.
#- name: Test all modules
# run: make test-unit-non-plugin
# env:
# KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
- name: Check test results
run: |
if [[ "${{ needs.test-modules.result }}" != "success" ]]; then
echo "Some tests failed or were cancelled"
exit 1
fi
echo "All tests passed successfully"

View File

@@ -1,5 +1,8 @@
name: release
permissions:
contents: write # Allow actions to update dependabot PRs
on:
push:
tags:
@@ -13,11 +16,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Set up Go 1.x
uses: actions/setup-go@v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version-file: go.work
id: go

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ site/.hugo_build.lock
# goreleaser artifacts
**/dist/
/output/

View File

@@ -3,12 +3,13 @@
run:
deadline: 5m
go: '1.21'
go: "1.25"
linters:
enable-all: true
disable:
- cyclop
- depguard
- exhaustivestruct
- forbidigo
- funlen
@@ -24,7 +25,9 @@ linters:
- nlreturn
- noctx
- paralleltest
- perfsprint
- stylecheck
- testifylint
- varnamelen
- wsl
- exhaustruct
@@ -39,6 +42,11 @@ linters:
- varcheck # abandoned by author
- maligned # abandoned by author
- interfacer # archived by author
# TODO(koba1t): temporarily disabled, will be addressed after upgrading to Go 1.24
- usetesting
- mnd
- copyloopvar
- intrange
linters-settings:
dupl:
@@ -49,14 +57,14 @@ linters-settings:
min-complexity: 30
revive:
rules:
- name: var-naming
arguments:
- [ "ID", "API", "JSON" ] # AllowList
- [ ] # DenyList
- name: var-naming
arguments:
- ["ID", "API", "JSON"] # AllowList
- [] # DenyList
gomnd:
ignored-functions:
- os.WriteFile
- make
- os.WriteFile
- make
gomoddirectives:
replace-local: true
gosec:

View File

@@ -75,14 +75,39 @@ cd kustomize
git push origin myfeature
```
### Pull Request Rules
We are using [Conventional Commits v1.0.0](https://www.conventionalcommits.org/en/v1.0.0/) as the main guideline of making PR. This guideline serves to help contributor and maintainer to classify their changes, thus providing better insight on type of release will be covered on each Kustomize release cycle.
1. Please add these keywords on your PR titles accordingly
| Keyword | Description | Example |
| ------------- | ------------- | ------------- |
| fix | Patching or fixing bugs or improvements introduction from previous release. This type of change will mark a `PATCH` release. | fix: fix null value when generating yaml |
| feat | New features. This change will mark a `MINOR` release. | feat: new transformer and generator for ACME API CRD. |
| chore | Minor improvement outside main code base | chore: add exclusion for transformer test. |
| ci | CI/CD related changes (e.g. github workflow, scripts, CI steps). | ci: remove blocking tests |
| docs | Changes related to documentation. | docs: add rules documentation for PR. |
2. Add `BREAKING CHANGE:` on your commit message as footer to signify breaking changes. This will help maintainers identify `MAJOR` releases.
Example:
```
feat: change YAML parser from `yaml/v1` to `yaml/v2`
BREAKING CHANGE: parse() function now works with 2 arguments.
```
### Create a Pull Request
1. Visit your fork at `https://github.com/<user>/kustomize`
2. Click the **Compare & Pull Request** button next to your `myfeature` branch.
3. Check out the pull request [process](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md) for more details and advice.
If you ran `git push` in the previous step, GitHub will return a useful link to create a Pull Request.
### Build Kustomize
The [Kustomize Architecture] document describes the respository organization and the kustomize build process.
```bash

View File

@@ -3,7 +3,7 @@
#
# Makefile for kustomize CLI and API.
LATEST_RELEASE=v5.3.0
LATEST_RELEASE=v5.8.1
SHELL := /usr/bin/env bash
GOOS = $(shell go env GOOS)
@@ -136,11 +136,15 @@ test-unit-all: \
test-unit-non-plugin \
test-unit-kustomize-plugins
# This target is used by our Github Actions CI to run unit tests for all non-plugin modules in multiple GOOS environments.
.PHONY: test-unit-non-plugin
test-unit-non-plugin:
./hack/for-each-module.sh "make test" "./plugin/*" 20
# This target is used by our Github Actions CI to run unit tests for all non-plugin and non-released modules in multiple GOOS environments.
.PHONY: test-unit-non-plugin-and-non-released
test-unit-non-plugin-and-non-released:
./hack/for-each-module.sh "make test" "./plugin/*|./kyaml/go.mod|./cmd/config/go.mod|./api/go.mod|./kustomize/go.mod" 16
.PHONY: build-non-plugin-all
build-non-plugin-all:
./hack/for-each-module.sh "make build" "./plugin/*" 20
@@ -183,7 +187,7 @@ test-examples-kustomize-against-latest-release: $(MYGOBIN)/mdrip
workspace-sync:
go work sync
./hack/doGoMod.sh tidy
# --- Cleanup targets ---
.PHONY: clean
clean: clean-kustomize-external-go-plugin uninstall-tools

View File

@@ -99,7 +99,7 @@ generate-kustomize-builtin-plugins: $(builtplugins)
go generate .; \
done
# Check for diff by comparing current revision of generated plugins on HEAD and newly generated plugins on local branch,
# Check for diff by comparing current revision of generated plugins on HEAD and newly generated plugins on local branch,
# If diff is found, throw error code 1
.PHONY: builtin-plugins-diff
builtin-plugins-diff: $(builtplugins)
@@ -107,7 +107,9 @@ builtin-plugins-diff: $(builtplugins)
echo "Checking for diff... $${file}" ; \
set -e ; \
if [ "`git diff $${file} | wc -c`" -gt 0 ]; then\
echo "Error(1): diff found on $${file}"; exit 1; \
echo "Error(1): diff found on $${file}"; \
git diff $${file};\
exit 1;\
fi \
done

View File

@@ -10,6 +10,7 @@ endif
export PATH := $(MYGOBIN):$(PATH)
REPO_ROOT=$(shell git rev-parse --show-toplevel)
GOLANGCI_LINT_VERSION ?= $(shell cd $(REPO_ROOT)/hack && go list -m -f '{{.Version}}' github.com/golangci/golangci-lint)
# determines whether to run tests that only behave locally; can be overridden by override variable
export IS_LOCAL = false
@@ -30,9 +31,11 @@ uninstall-out-of-tree-tools:
rm -f $(MYGOBIN)/mdrip
rm -f $(MYGOBIN)/stringer
# golangci-lint is not guaranteed to use from tool directive, so we install it directly.
# https://golangci-lint.run/docs/welcome/install/local/#install-from-sources
.PHONY: $(MYGOBIN)/golangci-lint
$(MYGOBIN)/golangci-lint:
cd $(REPO_ROOT)/hack && go install github.com/golangci/golangci-lint/cmd/golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
.PHONY: $(MYGOBIN)/mdrip
$(MYGOBIN)/mdrip:

View File

@@ -11,19 +11,17 @@ aliases:
kustomize-reviewers:
- knverey
- koba1t
- stormqueen1990
- varshaprasad96
- ncapps
- sarab97
docs-approvers:
- ncapps
docs-reviewers:
- ncapps
commands-approvers:
- stormqueen1990
commands-reviewers:
- stormqueen1990
commands-approvers: []
commands-reviewers: []
# emeritus:
# - liujingfang1

View File

@@ -23,9 +23,9 @@ This tool is sponsored by [sig-cli] ([KEP]).
To find the kustomize version embedded in recent versions of kubectl, run `kubectl version`:
```sh
> kubectl version --short --client
Client Version: v1.26.0
Kustomize Version: v4.5.7
> kubectl version --client
Client Version: v1.31.0
Kustomize Version: v5.4.2
```
The kustomize build flow at [v2.0.3] was added
@@ -76,18 +76,18 @@ kustomization.yaml deployment.yaml
+---------------------------------------------+ +-------------------------------------------------------+ +-----------------------------------+
| apiVersion: kustomize.config.k8s.io/v1beta1 | | apiVersion: apps/v1 | | apiVersion: v1 |
| kind: Kustomization | | kind: Deployment | | kind: Service |
| commonLabels: | | metadata: | | metadata: |
| app: myapp | | name: myapp | | name: myapp |
| resources: | | spec: | | spec: |
| - deployment.yaml | | selector: | | selector: |
| - service.yaml | | matchLabels: | | app: myapp |
| configMapGenerator: | | app: myapp | | ports: |
| - name: myapp-map | | template: | | - port: 6060 |
| literals: | | metadata: | | targetPort: 6060 |
| - KEY=value | | labels: | +-----------------------------------+
+---------------------------------------------+ | app: myapp |
| spec: |
| containers: |
| labels: | | metadata: | | metadata: |
| - includeSelectors: true | | name: myapp | | name: myapp |
| pairs: | | spec: | | spec: |
| app: myapp | | selector: | | selector: |
| resources: | | matchLabels: | | app: myapp |
| - deployment.yaml | | app: myapp | | ports: |
| - service.yaml | | template: | | - port: 6060 |
| configMapGenerator: | | metadata: | | targetPort: 6060 |
| - name: myapp-map | | labels: | +-----------------------------------+
| literals: | | app: myapp |
| - KEY=value | | spec: |
+---------------------------------------------+ | containers: |
| - name: myapp |
| image: myapp |
| resources: |
@@ -142,16 +142,16 @@ kustomization.yaml replica_count.yaml
+-----------------------------------------------+ +-------------------------------+ +------------------------------------------+
| apiVersion: kustomize.config.k8s.io/v1beta1 | | apiVersion: apps/v1 | | apiVersion: apps/v1 |
| kind: Kustomization | | kind: Deployment | | kind: Deployment |
| commonLabels: | | metadata: | | metadata: |
| variant: prod | | name: myapp | | name: myapp |
| resources: | | spec: | | spec: |
| - ../../base | | replicas: 80 | | template: |
| patches: | +-------------------------------+ | spec: |
| - path: replica_count.yaml | | containers: |
| - path: cpu_count.yaml | | - name: myapp |
+-----------------------------------------------+ | resources: |
| limits: |
| memory: "128Mi" |
| labels: | | metadata: | | metadata: |
| - includeSelectors: true | | name: myapp | | name: myapp |
| pairs: | | spec: | | spec: |
| variant: prod | | replicas: 80 | | template: |
| resources: | +-------------------------------+ | spec: |
| - ../../base | | containers: |
| patches: | | - name: myapp |
| - path: replica_count.yaml | | resources: |
| - path: cpu_count.yaml | | limits: |
+-----------------------------------------------+ | memory: "128Mi" |
| cpu: "7000m" |
+------------------------------------------+
```

View File

@@ -11,3 +11,18 @@ build:
generate: $(MYGOBIN)/k8scopy $(MYGOBIN)/stringer
go generate ./...
lint: lint-api-static
## lint-api-static runs the linter on the API module
## with build-tag kustomize_disable_go_plugin_support
## this aims to catch any issues with the API module
## that would prevent the API module from being used
## when the go plugin support is disabled.
lint-api-static:
$(MYGOBIN)/golangci-lint cache clean # Workaround for https://github.com/golangci/golangci-lint/issues/3228
$(MYGOBIN)/golangci-lint \
-c $$KUSTOMIZE_ROOT/.golangci.yml \
--build-tags kustomize_disable_go_plugin_support \
--path-prefix api \
run ./...

View File

@@ -879,6 +879,84 @@ spec:
},
},
},
"update image volume in pod template": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: imagevolume
spec:
template:
spec:
volumes:
- name: volume
image:
reference: nginx
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: imagevolume
spec:
template:
spec:
volumes:
- name: volume
image:
reference: apache@12345
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/volumes[]/image/reference",
},
},
},
"update image volume in pod spec": {
input: `
apiVersion: v1
kind: Pod
metadata:
name: imagevolume
spec:
volumes:
- name: volume
image:
reference: nginx
`,
expectedOutput: `
apiVersion: v1
kind: Pod
metadata:
name: imagevolume
spec:
volumes:
- name: volume
image:
reference: apache@12345
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
Digest: "12345",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/volumes[]/image/reference",
},
},
},
}
for tn, tc := range testCases {

View File

@@ -205,16 +205,14 @@ func getRoleRefGvk(n *resource.Resource) (*resid.Gvk, error) {
return nil, err
}
if apiGroup.IsNil() {
return nil, fmt.Errorf(
"apiGroup cannot be found in roleRef %s", roleRef.MustString())
return nil, fmt.Errorf("apiGroup cannot be found in roleRef %s", roleRef.MustString())
}
kind, err := roleRef.Pipe(yaml.Lookup("kind"))
if err != nil {
return nil, err
}
if kind.IsNil() {
return nil, fmt.Errorf(
"kind cannot be found in roleRef %s", roleRef.MustString())
return nil, fmt.Errorf("kind cannot be found in roleRef %s", roleRef.MustString())
}
return &resid.Gvk{
Group: apiGroup.YNode().Value,

View File

@@ -4,6 +4,7 @@
package replacement
import (
"encoding/json"
"fmt"
"strings"
@@ -11,7 +12,6 @@ import (
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/resid"
kyaml_utils "sigs.k8s.io/kustomize/kyaml/utils"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
@@ -23,7 +23,7 @@ type Filter struct {
// Filter replaces values of targets with values from sources
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
for i, r := range f.Replacements {
if r.Source == nil || r.Targets == nil {
if (r.SourceValue == nil && r.Source == nil) || r.Targets == nil {
return nil, fmt.Errorf("replacements must specify a source and at least one target")
}
value, err := getReplacement(nodes, &f.Replacements[i])
@@ -39,6 +39,13 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
}
func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, error) {
if r.SourceValue != nil && r.Source != nil {
return nil, fmt.Errorf("value and resource selectors are mutually exclusive")
}
if r.SourceValue != nil {
return yaml.NewScalarRNode(*r.SourceValue), nil
}
source, err := selectSourceNode(nodes, r.Source)
if err != nil {
return nil, err
@@ -110,6 +117,10 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targetSelectors []
if len(selector.FieldPaths) == 0 {
selector.FieldPaths = []string{types.DefaultReplacementFieldPath}
}
tsr, err := types.NewTargetSelectorRegex(selector)
if err != nil {
return nil, fmt.Errorf("error creating target selector: %w", err)
}
for _, possibleTarget := range nodes {
ids, err := utils.MakeResIds(possibleTarget)
if err != nil {
@@ -125,9 +136,13 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targetSelectors []
continue
}
if tsr.RejectsAny(ids) {
continue
}
// filter targets by matching resource IDs
for _, id := range ids {
if id.IsSelectedBy(selector.Select.ResId) && !containsRejectId(selector.Reject, ids) {
if tsr.Selects(id) {
err := copyValueToTarget(possibleTarget, value, selector)
if err != nil {
return nil, err
@@ -168,43 +183,37 @@ func matchesAnnoAndLabelSelector(n *yaml.RNode, selector *types.Selector) (bool,
return annoMatch && labelMatch, nil
}
func containsRejectId(rejects []*types.Selector, ids []resid.ResId) bool {
for _, r := range rejects {
if r.ResId.IsEmpty() {
continue
}
for _, id := range ids {
if id.IsSelectedBy(r.ResId) {
return true
}
}
}
return false
}
func copyValueToTarget(target *yaml.RNode, value *yaml.RNode, selector *types.TargetSelector) error {
for _, fp := range selector.FieldPaths {
createKind := yaml.Kind(0) // do not create
if selector.Options != nil && selector.Options.Create {
createKind = value.YNode().Kind
}
// Check if this fieldPath contains structured data access
if err := setValueInStructuredData(target, value, fp, selector.Options); err == nil {
// Successfully handled as structured data
continue
}
// Fall back to normal path handling
targetFieldList, err := target.Pipe(&yaml.PathMatcher{
Path: kyaml_utils.SmarterPathSplitter(fp, "."),
Create: createKind})
if err != nil {
return errors.WrapPrefixf(err, fieldRetrievalError(fp, createKind != 0))
return errors.WrapPrefixf(err, "%s", fieldRetrievalError(fp, createKind != 0))
}
targetFields, err := targetFieldList.Elements()
if err != nil {
return errors.WrapPrefixf(err, fieldRetrievalError(fp, createKind != 0))
return errors.WrapPrefixf(err, "%s", fieldRetrievalError(fp, createKind != 0))
}
if len(targetFields) == 0 {
return errors.Errorf(fieldRetrievalError(fp, createKind != 0))
return errors.Errorf("%s", fieldRetrievalError(fp, createKind != 0))
}
for _, t := range targetFields {
if err := setFieldValue(selector.Options, t, value); err != nil {
return err
return fmt.Errorf("%w", err)
}
}
}
@@ -247,3 +256,150 @@ func setFieldValue(options *types.FieldOptions, targetField *yaml.RNode, value *
return nil
}
// setValueInStructuredData handles setting values within structured data (JSON/YAML) in scalar fields
func setValueInStructuredData(target *yaml.RNode, value *yaml.RNode, fieldPath string, options *types.FieldOptions) error {
pathParts := kyaml_utils.SmarterPathSplitter(fieldPath, ".")
if len(pathParts) < 2 {
return fmt.Errorf("not a structured data path")
}
// Find the potential scalar field that might contain structured data
var scalarFieldPath []string
var structuredDataPath []string
var foundScalar = false
// Try to find where the scalar field ends and structured data begins
for i := 1; i <= len(pathParts); i++ {
potentialScalarPath := pathParts[:i]
scalarField, err := target.Pipe(yaml.Lookup(potentialScalarPath...))
if err != nil {
continue
}
if scalarField != nil && scalarField.YNode().Kind == yaml.ScalarNode && i < len(pathParts) {
// Try to parse the scalar value as structured data
scalarValue := scalarField.YNode().Value
var parsedNode yaml.Node
if err := yaml.Unmarshal([]byte(scalarValue), &parsedNode); err == nil {
// Successfully parsed - this is structured data
scalarFieldPath = potentialScalarPath
structuredDataPath = pathParts[i:]
foundScalar = true
break
}
}
}
if !foundScalar {
return fmt.Errorf("no structured data found in path")
}
// Get the scalar field containing structured data
scalarField, err := target.Pipe(yaml.Lookup(scalarFieldPath...))
if err != nil {
return fmt.Errorf("%w", err)
}
// Parse the structured data
scalarValue := scalarField.YNode().Value
var parsedNode yaml.Node
if err := yaml.Unmarshal([]byte(scalarValue), &parsedNode); err != nil {
return fmt.Errorf("%w", err)
}
structuredData := yaml.NewRNode(&parsedNode)
createKind := yaml.Kind(0) // do not create
if options != nil && options.Create {
createKind = value.YNode().Kind
}
// Navigate to the target location within the structured data
targetInStructured, err := structuredData.Pipe(&yaml.PathMatcher{
Path: structuredDataPath,
Create: createKind,
})
if err != nil {
return fmt.Errorf("%w", err)
}
targetFields, err := targetInStructured.Elements()
if err != nil {
return fmt.Errorf("%w", err)
}
if len(targetFields) == 0 {
return fmt.Errorf("unable to find field in structured data")
}
// Set the value in the structured data
for _, t := range targetFields {
err = setFieldValue(options, t, value)
if err != nil {
return err
}
}
// Serialize the modified structured data back to the scalar field
// Try to detect if original was JSON or YAML and preserve formatting
serializedData, err := serializeStructuredData(structuredData, scalarValue)
if err != nil {
return fmt.Errorf("%w", err)
}
// Update the original scalar field
scalarField.YNode().Value = serializedData
return nil
}
// serializeStructuredData handles the serialization of structured data back to string format
// preserving the original format (JSON vs YAML) and style (pretty vs compact)
func serializeStructuredData(structuredData *yaml.RNode, originalValue string) (string, error) {
firstChar := rune(strings.TrimSpace(originalValue)[0])
if firstChar == '{' || firstChar == '[' {
return serializeAsJSON(structuredData, originalValue)
}
// Fallback to YAML format
return serializeAsYAML(structuredData)
}
// serializeAsJSON converts structured data back to JSON format
func serializeAsJSON(structuredData *yaml.RNode, originalValue string) (string, error) {
modifiedData, err := structuredData.String()
if err != nil {
return "", fmt.Errorf("failed to serialize structured data: %w", err)
}
// Parse the YAML output as JSON
var jsonData interface{}
if err := yaml.Unmarshal([]byte(modifiedData), &jsonData); err != nil {
return "", fmt.Errorf("failed to unmarshal YAML data: %w", err)
}
// Check if original was pretty-printed by looking for newlines and indentation
if strings.Contains(originalValue, "\n") && strings.Contains(originalValue, " ") {
// Pretty-print the JSON to match original formatting
if prettyJSON, err := json.MarshalIndent(jsonData, "", " "); err == nil {
return string(prettyJSON), nil
}
}
// Compact JSON
if compactJSON, err := json.Marshal(jsonData); err == nil {
return string(compactJSON), nil
}
return "", fmt.Errorf("failed to marshal JSON data")
}
// serializeAsYAML converts structured data back to YAML format
func serializeAsYAML(structuredData *yaml.RNode) (string, error) {
modifiedData, err := structuredData.String()
if err != nil {
return "", fmt.Errorf("failed to serialize YAML data: %w", err)
}
return strings.TrimSpace(modifiedData), nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,44 @@
module sigs.k8s.io/kustomize/api
go 1.21
go 1.25.0
require (
github.com/blang/semver/v4 v4.0.0
github.com/go-errors/errors v1.4.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.11.1
go.uber.org/goleak v1.3.0
gopkg.in/evanphx/json-patch.v4 v4.12.0
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
sigs.k8s.io/kustomize/kyaml v0.17.0
sigs.k8s.io/yaml v1.4.0
go.yaml.in/yaml/v2 v2.4.2
gopkg.in/evanphx/json-patch.v4 v4.13.0
k8s.io/kube-openapi v0.0.0-20260502001324-b7f5293f4787
sigs.k8s.io/kustomize/kyaml v0.21.1
sigs.k8s.io/yaml v1.5.0
)
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/go-openapi/swag v0.25.4 // indirect
github.com/go-openapi/swag/cmdutils v0.25.4 // indirect
github.com/go-openapi/swag/conv v0.25.4 // indirect
github.com/go-openapi/swag/fileutils v0.25.4 // indirect
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
github.com/go-openapi/swag/loading v0.25.4 // indirect
github.com/go-openapi/swag/mangling v0.25.4 // indirect
github.com/go-openapi/swag/netutils v0.25.4 // indirect
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/sergi/go-diff v1.4.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/sys v0.17.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/sys v0.42.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace sigs.k8s.io/kustomize/kyaml => ../kyaml

View File

@@ -1,8 +1,5 @@
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -10,27 +7,46 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU=
github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ=
github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4=
github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y=
github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk=
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM=
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48=
github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg=
github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0=
github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg=
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4=
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -40,60 +56,56 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kube-openapi v0.0.0-20260502001324-b7f5293f4787 h1:kHv8PETbPIVHfqKBYwTNNSjqChf/7xn3JOS3re+NWs8=
k8s.io/kube-openapi v0.0.0-20260502001324-b7f5293f4787/go.mod h1:Cyq7UE0QtGe+Zo+/6XFrxiS4Mq0tLyQEONkFzSkfp9o=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/kyaml v0.17.0 h1:G2bWs03V9Ur2PinHLzTUJ8Ded+30SzXZKiO92SRDs3c=
sigs.k8s.io/kustomize/kyaml v0.17.0/go.mod h1:6lxkYF1Cv9Ic8g/N7I86cvxNc5iinUo/P2vKsHNmpyE=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=

View File

@@ -144,7 +144,7 @@ func loadCrdIntoConfig(
}
_, label := property.Extensions.GetString(xLabelSelector)
if label {
err = theConfig.AddLabelFieldSpec(
err = theConfig.AddCommonLabelsFieldSpec(
makeFs(theGvk, append(path, propName)))
if err != nil {
return

View File

@@ -590,7 +590,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
rf := provider.NewDefaultDepProvider().GetResourceFactory()
v1 := rf.FromMapWithName(
v1, err := rf.FromMapWithName(
"volume1",
map[string]interface{}{
"apiVersion": "v1",
@@ -599,7 +599,10 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
"name": "someprefix-volume1",
},
})
c1 := rf.FromMapWithName(
if err != nil {
t.Fatalf("failed to get new instance with given name: %v", err)
}
c1, err := rf.FromMapWithName(
"claim1",
map[string]interface{}{
"apiVersion": "v1",
@@ -612,9 +615,11 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
"volumeName": "volume1",
},
})
if err != nil {
t.Fatalf("failed to get new instance with given name: %v", err)
}
v2 := v1.DeepCopy()
c2 := rf.FromMapWithName(
c2, err := rf.FromMapWithName(
"claim1",
map[string]interface{}{
"apiVersion": "v1",
@@ -627,6 +632,9 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
"volumeName": "someprefix-volume1",
},
})
if err != nil {
t.Fatalf("failed to get new instance with given name: %v", err)
}
m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(v1).AddR(c1).ResMap()

View File

@@ -170,7 +170,7 @@ func (ra *ResAccumulator) FixBackReferences() (err error) {
// Intersection drops the resources which "other" does not have.
func (ra *ResAccumulator) Intersection(other resmap.ResMap) error {
otherIds := other.AllIds()
otherIds := other.AllIds() //nolint:revive
for _, curId := range ra.resMap.AllIds() {
toDelete := true
for _, otherId := range otherIds {

View File

@@ -64,7 +64,7 @@ func makeResAccumulator(t *testing.T) *ResAccumulator {
"name": "backendTwo",
}}).ResMap())
if err != nil {
t.Fatalf("unexpected err: %v", err)
t.Fatalf("failed to append resources: %v", err)
}
return ra
}
@@ -143,22 +143,26 @@ func expectLog(t *testing.T, log bytes.Buffer, expect string) {
func TestResolveVarsVarNeedsDisambiguation(t *testing.T) {
ra := makeResAccumulator(t)
rm0 := resmap.New()
err := rm0.Append(
provider.NewDefaultDepProvider().GetResourceFactory().FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "backendOne",
"namespace": "fooNamespace",
},
}))
r, err := provider.NewDefaultDepProvider().GetResourceFactory().FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "backendOne",
"namespace": "fooNamespace",
},
})
if err != nil {
t.Fatalf("unexpected err: %v", err)
t.Fatalf("failed to get instance of resources: %v", err)
}
err = rm0.Append(r)
if err != nil {
t.Fatalf("failed to append a resource to ResMap: %v", err)
}
err = ra.AppendAll(rm0)
if err != nil {
t.Fatalf("unexpected err: %v", err)
t.Fatalf("failed to append a resource to ResAccumulator: %v", err)
}
err = ra.MergeVars([]types.Var{
@@ -227,7 +231,11 @@ func TestResolveVarConflicts(t *testing.T) {
// create accumulators holding apparently conflicting vars that are not
// actually in conflict because they point to the same concrete value.
rm0 := resmap.New()
err := rm0.Append(rf.FromMap(fooAws))
r0, err0 := rf.FromMap(fooAws)
if err0 != nil {
t.Fatalf("failed to get instance of resources: %v", err0)
}
err := rm0.Append(r0)
require.NoError(t, err)
ac0 := MakeEmptyAccumulator()
err = ac0.AppendAll(rm0)
@@ -236,7 +244,11 @@ func TestResolveVarConflicts(t *testing.T) {
require.NoError(t, err)
rm1 := resmap.New()
err = rm1.Append(rf.FromMap(barAws))
r1, err1 := rf.FromMap(barAws)
if err1 != nil {
t.Fatalf("failed to get instance of resources: %v", err1)
}
err = rm1.Append(r1)
require.NoError(t, err)
ac1 := MakeEmptyAccumulator()
err = ac1.AppendAll(rm1)
@@ -255,7 +267,11 @@ func TestResolveVarConflicts(t *testing.T) {
// two above (because it contains a variable whose name is used in the other
// accumulators AND whose concrete values are different).
rm2 := resmap.New()
err = rm2.Append(rf.FromMap(barGcp))
r2, err2 := rf.FromMap(barGcp)
if err2 != nil {
t.Fatalf("failed to get instance of resources: %v", err2)
}
err = rm2.Append(r2)
require.NoError(t, err)
ac2 := MakeEmptyAccumulator()
err = ac2.AppendAll(rm2)

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on AnnotationsTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on ConfigMapGenerator; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on HashTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on HelmChartInflationGenerator; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (
@@ -10,8 +8,10 @@ import (
"os/exec"
"path/filepath"
"regexp"
"slices"
"strings"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
@@ -62,6 +62,9 @@ func (p *HelmChartInflationGeneratorPlugin) Config(
if len(h.GeneralConfig().HelmConfig.ApiVersions) != 0 {
p.HelmChart.ApiVersions = h.GeneralConfig().HelmConfig.ApiVersions
}
if h.GeneralConfig().HelmConfig.Debug {
p.HelmChart.Debug = h.GeneralConfig().HelmConfig.Debug
}
p.h = h
if err = yaml.Unmarshal(config, p); err != nil {
@@ -168,13 +171,17 @@ func (p *HelmChartInflationGeneratorPlugin) runHelmCommand(
fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.ConfigHome)}
cmd.Env = append(os.Environ(), env...)
err := cmd.Run()
errorOutput := stderr.String()
if slices.Contains(args, "--debug") {
errorOutput = " Helm stack trace:\n" + errorOutput + "\nHelm template:\n" + stdout.String() + "\n"
}
if err != nil {
helm := p.h.GeneralConfig().HelmConfig.Command
err = errors.WrapPrefixf(
fmt.Errorf(
"unable to run: '%s %s' with env=%s (is '%s' installed?): %w",
helm, strings.Join(args, " "), env, helm, err),
stderr.String(),
"%s", errorOutput,
)
}
return stdout.Bytes(), err
@@ -288,11 +295,14 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err er
rm, resMapErr := p.h.ResmapFactory().NewResMapFromBytes(stdout)
if resMapErr == nil {
if err := p.markHelmGeneratedResources(rm); err != nil {
return nil, err
}
return rm, nil
}
// try to remove the contents before first "---" because
// helm may produce messages to stdout before it
r := &kio.ByteReader{Reader: bytes.NewBufferString(string(stdout)), OmitReaderAnnotations: true}
r := &kio.ByteReader{Reader: bytes.NewBuffer(stdout), OmitReaderAnnotations: true}
nodes, err := r.Read()
if err != nil {
return nil, fmt.Errorf("error reading helm output: %w", err)
@@ -303,6 +313,9 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err er
if err != nil {
return nil, fmt.Errorf("could not parse rnode slice into resource map: %w", err)
}
if err := p.markHelmGeneratedResources(rm); err != nil {
return nil, err
}
return rm, nil
}
return nil, fmt.Errorf("could not parse bytes into resource map: %w", resMapErr)
@@ -328,6 +341,9 @@ func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string {
if p.Version != "" {
args = append(args, "--version", p.Version)
}
if p.Devel {
args = append(args, "--devel")
}
return args
}
@@ -342,9 +358,18 @@ func (p *HelmChartInflationGeneratorPlugin) chartExistsLocally() (string, bool)
return path, s.IsDir()
}
// checkHelmVersion will return an error if the helm version is not V3
func (p *HelmChartInflationGeneratorPlugin) markHelmGeneratedResources(rm resmap.ResMap) error {
for _, r := range rm.Resources() {
if err := r.RNode.PipeE(kyaml.SetAnnotation(konfig.HelmGeneratedAnnotation, "true")); err != nil {
return fmt.Errorf("failed to set helm annotation: %w", err)
}
}
return nil
}
// checkHelmVersion will return an error if the helm version is not V3 or V4
func (p *HelmChartInflationGeneratorPlugin) checkHelmVersion() error {
stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"})
stdout, err := p.runHelmCommand([]string{"version", "--short"})
if err != nil {
return err
}
@@ -360,8 +385,8 @@ func (p *HelmChartInflationGeneratorPlugin) checkHelmVersion() error {
v = v[1:]
}
majorVersion := strings.Split(v, ".")[0]
if majorVersion != "3" {
return fmt.Errorf("this plugin requires helm V3 but got v%s", v)
if majorVersion != "3" && majorVersion != "4" {
return fmt.Errorf("this plugin requires helm V3 or V4 but got v%s", v)
}
return nil
}

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on IAMPolicyGenerator; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on ImageTagTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on LabelTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,12 +1,11 @@
// Code generated by pluginator on NamespaceTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
@@ -14,6 +13,8 @@ import (
)
// Change or set the namespace of non-cluster level resources.
//
//nolint:tagalign
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"`
@@ -51,6 +52,10 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
// Don't mutate empty objects?
continue
}
if annotations := r.GetAnnotations(konfig.HelmGeneratedAnnotation); annotations[konfig.HelmGeneratedAnnotation] == "true" {
// Don't apply namespace on Helm generated manifest. Helm should take care of it.
continue
}
r.StorePreviousId()
if err := r.ApplyFilter(namespace.Filter{
Namespace: p.Namespace,

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on PatchJson6902Transformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on PatchStrategicMergeTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on PatchTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (
@@ -24,10 +22,10 @@ type PatchTransformerPlugin struct {
patchText string
// patchSource is patch source message
patchSource string
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"`
Options map[string]bool `json:"options,omitempty" yaml:"options,omitempty"`
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"`
Options *types.PatchArgs `json:"options,omitempty" yaml:"options,omitempty"`
}
func (p *PatchTransformerPlugin) Config(h *resmap.PluginHelpers, c []byte) error {
@@ -56,8 +54,9 @@ func (p *PatchTransformerPlugin) Config(h *resmap.PluginHelpers, c []byte) error
patchesSM, errSM := h.ResmapFactory().RF().SliceFromBytes([]byte(p.patchText))
patchesJson, errJson := jsonPatchFromBytes([]byte(p.patchText))
if (errSM == nil && errJson == nil) ||
(patchesSM != nil && patchesJson != nil) {
if ((errSM == nil && errJson == nil) ||
(patchesSM != nil && patchesJson != nil)) &&
(len(patchesSM) > 0 && len(patchesJson) > 0) {
return fmt.Errorf(
"illegally qualifies as both an SM and JSON patch: %s",
p.patchSource)
@@ -69,10 +68,14 @@ func (p *PatchTransformerPlugin) Config(h *resmap.PluginHelpers, c []byte) error
if errSM == nil {
p.smPatches = patchesSM
for _, loadedPatch := range p.smPatches {
if p.Options["allowNameChange"] {
if p.Options == nil {
continue
}
if p.Options.AllowNameChange {
loadedPatch.AllowNameChange()
}
if p.Options["allowKindChange"] {
if p.Options.AllowKindChange {
loadedPatch.AllowKindChange()
}
}
@@ -86,7 +89,10 @@ func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
if p.smPatches != nil {
return p.transformStrategicMerge(m)
}
return p.transformJson6902(m)
if p.jsonPatches != nil {
return p.transformJson6902(m)
}
return nil
}
// transformStrategicMerge applies each loaded strategic merge patch

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on PrefixTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on ReplacementTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (
@@ -16,7 +14,7 @@ import (
// Replace values in targets with values from a source
type ReplacementTransformerPlugin struct {
ReplacementList []types.ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
Replacements []types.Replacement `json:"omitempty" yaml:"omitempty"`
replacements []types.Replacement
}
func (p *ReplacementTransformerPlugin) Config(
@@ -49,19 +47,19 @@ func (p *ReplacementTransformerPlugin) Config(
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl...)
p.replacements = append(p.replacements, repl...)
case reflect.Map:
repl := types.Replacement{}
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl)
p.replacements = append(p.replacements, repl)
default:
return fmt.Errorf("unsupported replacement type encountered within replacement path: %v", items.Kind())
}
} else {
// replacement information is already loaded
p.Replacements = append(p.Replacements, r.Replacement)
p.replacements = append(p.replacements, r.Replacement)
}
}
return nil
@@ -69,7 +67,7 @@ func (p *ReplacementTransformerPlugin) Config(
func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) {
return m.ApplyFilter(replacement.Filter{
Replacements: p.Replacements,
Replacements: p.replacements,
})
}

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on ReplicaCountTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on SecretGenerator; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on SortOrderTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (
@@ -74,34 +72,16 @@ func (p *SortOrderTransformerPlugin) Transform(m resmap.ResMap) (err error) {
// Sort
if p.SortOptions.Order == types.LegacySortOrder {
s := newLegacyIDSorter(m.AllIds(), p.SortOptions.LegacySortOptions)
s := newLegacyIDSorter(m.Resources(), p.SortOptions.LegacySortOptions)
sort.Sort(s)
err = applyOrdering(m, s.resids)
if err != nil {
return err
}
}
return nil
}
// applyOrdering takes resources (given in ResMap) and a desired ordering given
// as a sequence of ResIds, and updates the ResMap's resources to match the
// ordering.
func applyOrdering(m resmap.ResMap, ordering []resid.ResId) error {
var err error
resources := make([]*resource.Resource, m.Size())
// Clear and refill with the correct order
for i, id := range ordering {
resources[i], err = m.GetByCurrentId(id)
if err != nil {
return errors.WrapPrefixf(err, "expected match for sorting")
}
}
m.Clear()
for _, r := range resources {
err = m.Append(r)
if err != nil {
return errors.WrapPrefixf(err, "SortOrderTransformer: Failed to append to resources")
// Clear the map and re-add the resources in the sorted order.
m.Clear()
for _, r := range s.resources {
err := m.Append(r)
if err != nil {
return errors.WrapPrefixf(err, "SortOrderTransformer: Failed to append to resources")
}
}
}
return nil
@@ -117,12 +97,17 @@ func applyOrdering(m resmap.ResMap, ordering []resid.ResId) error {
type legacyIDSorter struct {
// resids only stores the metadata of the object. This is an optimization as
// it's expensive to compute these again and again during ordering.
resids []resid.ResId
resids []resid.ResId
// Initially, we sorted the metadata (ResId) of each object and then called GetByCurrentId on each to construct the final list.
// The problem is that GetByCurrentId is inefficient and does a linear scan in a list every time we do that.
// So instead, we sort resources alongside the ResIds.
resources []*resource.Resource
typeOrders map[string]int
}
func newLegacyIDSorter(
resids []resid.ResId,
resources []*resource.Resource,
options *types.LegacySortOptions) *legacyIDSorter {
// Precalculate a resource ranking based on the priority lists.
var typeOrders = func() map[string]int {
@@ -135,10 +120,13 @@ func newLegacyIDSorter(
}
return m
}()
return &legacyIDSorter{
resids: resids,
typeOrders: typeOrders,
ret := &legacyIDSorter{typeOrders: typeOrders}
for _, res := range resources {
ret.resids = append(ret.resids, res.CurId())
ret.resources = append(ret.resources, res)
}
return ret
}
var _ sort.Interface = legacyIDSorter{}
@@ -146,6 +134,7 @@ var _ sort.Interface = legacyIDSorter{}
func (a legacyIDSorter) Len() int { return len(a.resids) }
func (a legacyIDSorter) Swap(i, j int) {
a.resids[i], a.resids[j] = a.resids[j], a.resids[i]
a.resources[i], a.resources[j] = a.resources[j], a.resources[i]
}
func (a legacyIDSorter) Less(i, j int) bool {
if !a.resids[i].Gvk.Equals(a.resids[j].Gvk) {
@@ -160,6 +149,9 @@ func gvkLessThan(gvk1, gvk2 resid.Gvk, typeOrders map[string]int) bool {
if index1 != index2 {
return index1 < index2
}
if (gvk1.Kind == types.NamespaceKind && gvk2.Kind == types.NamespaceKind) && (gvk1.Group == "" || gvk2.Group == "") {
return legacyGVKSortString(gvk1) > legacyGVKSortString(gvk2)
}
return legacyGVKSortString(gvk1) < legacyGVKSortString(gvk2)
}

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on SuffixTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -1,6 +1,4 @@
// Code generated by pluginator on ValueAddTransformer; DO NOT EDIT.
// pluginator {(devel) unknown }
package builtins
import (

View File

@@ -110,4 +110,4 @@ commonLabels:
create: false
group: networking.k8s.io
kind: NetworkPolicy
` + metadataLabelsFieldSpecs
` + metadataLabelsFieldSpecs + volumeClaimTemplatesMetadataLabels

View File

@@ -14,6 +14,7 @@ func GetDefaultFieldSpecs() []byte {
[]byte(nameSuffixFieldSpecs),
[]byte(commonLabelFieldSpecs),
[]byte(templateLabelFieldSpecs),
[]byte(volumeClaimTemplateLabelFieldSpecs),
[]byte(commonAnnotationFieldSpecs),
[]byte(namespaceFieldSpecs),
[]byte(varReferenceFieldSpecs),
@@ -32,6 +33,7 @@ func GetDefaultFieldSpecsAsMap() map[string]string {
result["namesuffix"] = nameSuffixFieldSpecs
result["commonlabels"] = commonLabelFieldSpecs
result["templatelabels"] = templateLabelFieldSpecs
result["volumeclaimtemplatelabels"] = volumeClaimTemplateLabelFieldSpecs
result["commonannotations"] = commonAnnotationFieldSpecs
result["namespace"] = namespaceFieldSpecs
result["varreference"] = varReferenceFieldSpecs

View File

@@ -10,9 +10,13 @@ images:
create: true
- path: spec/initContainers[]/image
create: true
- path: spec/volumes[]/image/reference
create: true
- path: spec/template/spec/containers[]/image
create: true
- path: spec/template/spec/initContainers[]/image
create: true
- path: spec/template/spec/volumes[]/image/reference
create: true
`
)

View File

@@ -29,11 +29,6 @@ const metadataLabelsFieldSpecs = `
group: apps
kind: StatefulSet
- path: spec/volumeClaimTemplates[]/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/template/metadata/labels
create: true
group: batch

View File

@@ -421,6 +421,13 @@ nameReference:
fieldSpecs:
- path: spec/ingressClassName
kind: Ingress
- kind: ValidatingAdmissionPolicy
group: admissionregistration.k8s.io
fieldSpecs:
- path: spec/policyName
kind: ValidatingAdmissionPolicyBinding
group: admissionregistration.k8s.io
`
)

View File

@@ -0,0 +1,15 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package builtinpluginconsts
const volumeClaimTemplateLabelFieldSpecs = `
volumeClaimTemplateLabels:
` + volumeClaimTemplatesMetadataLabels
const volumeClaimTemplatesMetadataLabels = `
- path: spec/volumeClaimTemplates[]/metadata/labels
create: true
group: apps
kind: StatefulSet
`

View File

@@ -147,6 +147,26 @@ func newLoaderAtConfirmedDir(
}
}
// hasAmbiguousPathSegment reports whether path contains a segment with ".."
// embedded in it (not ".." itself). This pattern results from YAML indentation
// errors where two list entries merge into one scalar, e.g.:
//
// resources:
// - ../../base
// - ../../shared/prod
//
// YAML parses this as "../../base - ../../shared/prod", producing segment
// "base - .." which filepath.Clean absorbs, silently resolving to an
// unintended directory.
func hasAmbiguousPathSegment(path string) bool {
for _, part := range strings.Split(filepath.ToSlash(path), "/") {
if part != "" && part != "." && part != ".." && strings.Contains(part, "..") {
return true
}
}
return false
}
// New returns a new Loader, rooted relative to current loader,
// or rooted in a temp directory holding a git repo clone.
func (fl *FileLoader) New(path string) (ifc.Loader, error) {
@@ -167,9 +187,16 @@ func (fl *FileLoader) New(path string) (ifc.Loader, error) {
if filepath.IsAbs(path) {
return nil, fmt.Errorf("new root '%s' cannot be absolute", path)
}
if hasAmbiguousPathSegment(path) {
return nil, fmt.Errorf(
"path %q is ambiguous: resolves to %q after normalization, "+
"which is likely not the intended target; check for YAML "+
"indentation errors in your kustomization file",
path, filepath.Clean(path))
}
root, err := filesys.ConfirmDir(fl.fSys, fl.root.Join(path))
if err != nil {
return nil, errors.WrapPrefixf(err, ErrRtNotDir.Error())
return nil, errors.WrapPrefixf(err, "%s", ErrRtNotDir.Error())
}
if err = fl.errIfGitContainmentViolation(root); err != nil {
return nil, err
@@ -311,7 +338,11 @@ func (fl *FileLoader) httpClientGetContent(path string) ([]byte, error) {
} else {
hc = &http.Client{}
}
resp, err := hc.Get(path)
parsedURL, err := url.ParseRequestURI(path)
if err != nil {
return nil, errors.Wrap(err)
}
resp, err := hc.Get(parsedURL.String())
if err != nil {
return nil, errors.Wrap(err)
}

View File

@@ -66,7 +66,7 @@ type testData struct {
expectedContent string
}
var testCases = []testData{
var testCases = []testData{ //nolint:gochecknoglobals
{
path: "foo/project/fileA.yaml",
expectedContent: "fileA content",
@@ -88,7 +88,7 @@ var testCases = []testData{
func MakeFakeFs(td []testData) filesys.FileSystem {
fSys := filesys.MakeFsInMemory()
for _, x := range td {
fSys.WriteFile(x.path, []byte(x.expectedContent))
_ = fSys.WriteFile(x.path, []byte(x.expectedContent))
}
return fSys
}
@@ -161,31 +161,31 @@ func TestLoaderBadRelative(t *testing.T) {
require.Equal("/foo/project/subdir1", l1.Root())
// Cannot cd into a file.
l2, err := l1.New("fileB.yaml")
_, err = l1.New("fileB.yaml")
require.Error(err)
// It's not okay to stay at the same place.
l2, err = l1.New(filesys.SelfDir)
_, err = l1.New(filesys.SelfDir)
require.Error(err)
// It's not okay to go up and back down into same place.
l2, err = l1.New("../subdir1")
_, err = l1.New("../subdir1")
require.Error(err)
// It's not okay to go up via a relative path.
l2, err = l1.New("..")
_, err = l1.New("..")
require.Error(err)
// It's not okay to go up via an absolute path.
l2, err = l1.New("/foo/project")
_, err = l1.New("/foo/project")
require.Error(err)
// It's not okay to go to the root.
l2, err = l1.New("/")
_, err = l1.New("/")
require.Error(err)
// It's okay to go up and down to a sibling.
l2, err = l1.New("../subdir2")
l2, err := l1.New("../subdir2")
require.NoError(err)
require.Equal("/foo/project/subdir2", l2.Root())
@@ -198,7 +198,7 @@ func TestLoaderBadRelative(t *testing.T) {
// It's not OK to go over to a previously visited directory.
// Must disallow going back and forth in a cycle.
l1, err = l2.New("../subdir1")
_, err = l2.New("../subdir1")
require.Error(err)
}
@@ -207,6 +207,60 @@ func TestNewEmptyLoader(t *testing.T) {
require.Error(t, err)
}
func TestLoaderRejectsMalformedPath(t *testing.T) {
// A YAML indentation error can collapse two resource entries into one:
// resources:
// - ../../base
// - ../../shared/prod
// becomes the single string: "../../base - ../../shared/prod"
//
// filepath.Clean normalizes this to "../../shared/prod", silently
// dropping the "../../base" reference. The loader must reject paths
// with inner ".." components that cause this silent absorption.
// See https://github.com/kubernetes-sigs/kustomize/issues/5979
fSys := filesys.MakeFsInMemory()
require.NoError(t, fSys.MkdirAll("/base"))
require.NoError(t, fSys.MkdirAll("/shared/prod"))
require.NoError(t, fSys.MkdirAll("/overlays/prod1"))
l1 := NewLoaderOrDie(RestrictionNone, fSys, "/overlays/prod1")
// The exact bug from issue #5979.
_, err := l1.New("../../base - ../../shared/prod")
require.Error(t, err)
require.Contains(t, err.Error(), "ambiguous")
}
func TestHasAmbiguousPathSegment(t *testing.T) {
cases := map[string]bool{
// Safe: ".." only as standalone segments
"../base": false,
"../../shared/prod": false,
"..": false,
"foo/bar": false,
"foo/bar/": false,
"foo//bar": false,
"./foo/bar": false,
"https://root": false,
"foo/../bar": false,
"a/b/../../c": false,
"a/..": false,
// Winding paths are legitimate (used by localizer)
"delta/../../../../a/b/../../alpha/beta/sibling": false,
// Dangerous: segment contains embedded ".." from YAML merge errors
"../../base - ../../shared/prod": true,
"../../base ../../shared/prod": true,
"foo/bar..baz/qux": true,
"a/b/c..d/e": true,
"../../base\t- ../../shared/prod": true,
}
for path, want := range cases {
t.Run(path, func(t *testing.T) {
require.Equal(t, want, hasAmbiguousPathSegment(path), "hasAmbiguousPathSegment(%q)", path)
})
}
}
func TestNewRemoteLoaderDoesNotExist(t *testing.T) {
_, err := makeLoader().New("https://example.com/org/repo")
require.ErrorContains(t, err, "fetch")
@@ -265,23 +319,24 @@ const (
// └── exteriorData
func commonSetupForLoaderRestrictionTest(t *testing.T) (string, filesys.FileSystem) {
t.Helper()
require := require.New(t)
fSys, tmpDir := setupOnDisk(t)
dir := tmpDir.String()
fSys.Mkdir(filepath.Join(dir, "base"))
require.NoError(fSys.Mkdir(filepath.Join(dir, "base")))
fSys.WriteFile(
filepath.Join(dir, "base", "okayData"), []byte(contentOk))
require.NoError(fSys.WriteFile(
filepath.Join(dir, "base", "okayData"), []byte(contentOk)))
fSys.WriteFile(
filepath.Join(dir, "exteriorData"), []byte(contentExteriorData))
require.NoError(fSys.WriteFile(
filepath.Join(dir, "exteriorData"), []byte(contentExteriorData)))
os.Symlink(
require.NoError(os.Symlink(
filepath.Join(dir, "base", "okayData"),
filepath.Join(dir, "base", "symLinkToOkayData"))
os.Symlink(
filepath.Join(dir, "base", "symLinkToOkayData")))
require.NoError(os.Symlink(
filepath.Join(dir, "exteriorData"),
filepath.Join(dir, "base", "symLinkToExteriorData"))
filepath.Join(dir, "base", "symLinkToExteriorData")))
return dir, fSys
}
@@ -391,14 +446,14 @@ func TestNewLoaderAtGitClone(t *testing.T) {
url := rootURL + "/" + pathInRepo
coRoot := "/tmp"
fSys := filesys.MakeFsInMemory()
fSys.MkdirAll(coRoot)
fSys.MkdirAll(coRoot + "/" + pathInRepo)
fSys.WriteFile(
require.NoError(fSys.MkdirAll(coRoot))
require.NoError(fSys.MkdirAll(coRoot + "/" + pathInRepo))
require.NoError(fSys.WriteFile(
coRoot+"/"+pathInRepo+"/"+
konfig.DefaultKustomizationFileName(),
[]byte(`
whatever
`))
`)))
repoSpec, err := git.NewRepoSpecFromURL(url)
require.NoError(err)
@@ -418,7 +473,7 @@ whatever
require.Error(err)
pathInRepo = "foo/overlay"
fSys.MkdirAll(coRoot + "/" + pathInRepo)
require.NoError(fSys.MkdirAll(coRoot + "/" + pathInRepo))
url = rootURL + "/" + pathInRepo
l2, err := l.New(url)
require.NoError(err)
@@ -435,9 +490,9 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
topDir := "/whatever"
cloneRoot := topDir + "/someClone"
fSys := filesys.MakeFsInMemory()
fSys.MkdirAll(topDir + "/highBase")
fSys.MkdirAll(cloneRoot + "/foo/base")
fSys.MkdirAll(cloneRoot + "/foo/overlay")
require.NoError(fSys.MkdirAll(topDir + "/highBase"))
require.NoError(fSys.MkdirAll(cloneRoot + "/foo/base"))
require.NoError(fSys.MkdirAll(cloneRoot + "/foo/overlay"))
var l1 ifc.Loader
@@ -448,7 +503,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
require.Equal(cloneRoot+"/foo/overlay", l1.Root())
l2, err := l1.New("../base")
require.NoError(nil)
require.NoError(err)
require.Equal(cloneRoot+"/foo/base", l2.Root())
l3, err := l2.New("../../../highBase")
@@ -513,8 +568,8 @@ func TestLocalLoaderReferencingGitBase(t *testing.T) {
topDir := "/whatever"
cloneRoot := topDir + "/someClone"
fSys := filesys.MakeFsInMemory()
fSys.MkdirAll(topDir)
fSys.MkdirAll(cloneRoot + "/foo/base")
require.NoError(fSys.MkdirAll(topDir))
require.NoError(fSys.MkdirAll(cloneRoot + "/foo/base"))
l1 := newLoaderAtConfirmedDir(
RestrictionRootOnly, filesys.ConfirmedDir(topDir), fSys, nil,
@@ -534,8 +589,8 @@ func TestRepoDirectCycleDetection(t *testing.T) {
topDir := "/cycles"
cloneRoot := topDir + "/someClone"
fSys := filesys.MakeFsInMemory()
fSys.MkdirAll(topDir)
fSys.MkdirAll(cloneRoot)
require.NoError(fSys.MkdirAll(topDir))
require.NoError(fSys.MkdirAll(cloneRoot))
l1 := newLoaderAtConfirmedDir(
RestrictionRootOnly, filesys.ConfirmedDir(topDir), fSys, nil,
@@ -556,8 +611,8 @@ func TestRepoIndirectCycleDetection(t *testing.T) {
topDir := "/cycles"
cloneRoot := topDir + "/someClone"
fSys := filesys.MakeFsInMemory()
fSys.MkdirAll(topDir)
fSys.MkdirAll(cloneRoot)
require.NoError(fSys.MkdirAll(topDir))
require.NoError(fSys.MkdirAll(cloneRoot))
l0 := newLoaderAtConfirmedDir(
RestrictionRootOnly, filesys.ConfirmedDir(topDir), fSys, nil,
@@ -629,7 +684,7 @@ func TestLoaderHTTP(t *testing.T) {
u := req.URL.String()
require.Equal(x.path, u)
return &http.Response{
StatusCode: 200,
StatusCode: http.StatusOK,
Body: io.NopCloser(bytes.NewBufferString(x.expectedContent)),
Header: make(http.Header),
}
@@ -676,3 +731,15 @@ func setupOnDisk(t *testing.T) (filesys.FileSystem, filesys.ConfirmedDir) {
})
return fSys, dir
}
// TestLoaderHTTPMalformedURL tests that malformed URLs are properly handled
// to prevent infinite loops in http.Client.Get
func TestLoaderHTTPMalformedURL(t *testing.T) {
require := require.New(t)
malformedURL := "https://example.com/example?ref=main - ../../example/example.yaml"
l1 := NewLoaderOrDie(
RestrictionRootOnly, MakeFakeFs([]testData{}), filesys.Separator)
_, err := l1.Load(malformedURL)
require.Error(err)
require.Equal("HTTP Error: status code 400 (Bad Request)", err.Error())
}

View File

@@ -28,7 +28,7 @@ func NewLoader(
}
root, err := filesys.ConfirmDir(fSys, target)
if err != nil {
return nil, errors.WrapPrefixf(err, ErrRtNotDir.Error())
return nil, errors.WrapPrefixf(err, "%s", ErrRtNotDir.Error())
}
return newLoaderAtConfirmedDir(
lr, root, fSys, nil, git.ClonerUsingGitExec), nil

View File

@@ -381,7 +381,7 @@ func (lc *localizer) localizeFileWithContent(path string, content []byte) (strin
// 2. avoid paths that temporarily traverse outside the current root,
// i.e. ../../../scope/target/current-root. The localized file will be surrounded by
// different directories than its source, and so an uncleaned path may no longer be valid.
locPath = cleanFilePath(lc.fSys, lc.root, path)
locPath = cleanedRelativePath(lc.fSys, lc.root, path)
}
absPath := filepath.Join(lc.dst, locPath)
if err := lc.fSys.MkdirAll(filepath.Dir(absPath)); err != nil {

View File

@@ -296,8 +296,10 @@ func TestLocalizeFileCleaned(t *testing.T) {
kind: Kustomization
patches:
- path: ../gamma/../../../alpha/beta/./gamma/patch.yaml
- path: /alpha/beta/../beta/./gamma/patch2.yaml
`,
"patch.yaml": podConfiguration,
"patch.yaml": podConfiguration,
"patch2.yaml": podConfiguration,
}
expected, actual := makeFileSystems(t, "/alpha/beta/gamma", kustAndPatch)
@@ -307,8 +309,10 @@ patches:
kind: Kustomization
patches:
- path: patch.yaml
- path: patch2.yaml
`,
"patch.yaml": podConfiguration,
"patch.yaml": podConfiguration,
"patch2.yaml": podConfiguration,
})
checkFSys(t, expected, actual)
}
@@ -1194,19 +1198,40 @@ func TestLocalizeResources(t *testing.T) {
kind: Kustomization
resources:
- pod.yaml
- /a/b/pod2.yaml
- ../../alpha
`,
"pod.yaml": podConfiguration,
"pod.yaml": podConfiguration,
"pod2.yaml": podConfiguration,
"../../alpha/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: my-
`,
}
expected, actual := makeFileSystems(t, "/a/b", kustAndResources)
checkRun(t, actual, "/a/b", "/", "/localized-b")
addFiles(t, expected, "/localized-b/a/b", kustAndResources)
checkFSys(t, expected, actual)
// Absolute path of `/a/b/pod2.yaml` is expected to be converted to a path
// relative to the kustomization root.
expectedKustAndResources := map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- pod.yaml
- pod2.yaml
- ../../alpha
`,
"pod.yaml": podConfiguration,
"pod2.yaml": podConfiguration,
"../../alpha/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: my-
`,
}
expectedFs, actualFs := makeFileSystems(t, "/a/b", kustAndResources)
checkRun(t, actualFs, "/a/b", "/", "/localized-b")
addFiles(t, expectedFs, "/localized-b/a/b", expectedKustAndResources)
checkFSys(t, expectedFs, actualFs)
}
func TestLocalizePathError(t *testing.T) {

View File

@@ -89,11 +89,8 @@ func (ll *Loader) Load(path string) ([]byte, error) {
if err != nil {
return nil, errors.WrapPrefixf(err, "invalid file reference")
}
if filepath.IsAbs(path) {
return nil, errors.Errorf("absolute paths not yet supported in alpha: file path %q is absolute", path)
}
if !loader.IsRemoteFile(path) && ll.local {
cleanPath := cleanFilePath(ll.fSys, filesys.ConfirmedDir(ll.Root()), path)
cleanPath := cleanedRelativePath(ll.fSys, filesys.ConfirmedDir(ll.Root()), path)
cleanAbs := filepath.Join(ll.Root(), cleanPath)
dir := filesys.ConfirmedDir(filepath.Dir(cleanAbs))
// target cannot reference newDir, as this load would've failed prior to localize;

View File

@@ -276,11 +276,11 @@ func TestLoadFails(t *testing.T) {
checkNewLoader(req, ldr, &args, "/a", "/a", "/a/newDir", fSys)
cases := map[string]string{
"absolute path": "/a/pod.yaml",
"directory": "b",
"non-existent file": "kubectl.yaml",
"file outside root": "../alpha/beta/gamma/delta/deployment.yaml",
"inside dst": "newDir/pod.yaml",
"directory": "b",
"non-existent file": "kubectl.yaml",
"file outside root": "../alpha/beta/gamma/delta/deployment.yaml",
"inside dst": "newDir/pod.yaml",
"winding inside dst": "/a/test/../newDir/pod.yaml",
}
for name, file := range cases {
file := file
@@ -291,8 +291,6 @@ func TestLoadFails(t *testing.T) {
ldr, _, err := NewLoader("./a/../a", "/a/../a", "/a/newDir", fSys)
req.NoError(err)
req.NoError(fSys.WriteFile("/a/newDir/pod.yaml", []byte(podConfiguration)))
_, err = ldr.Load(file)
req.Error(err)
})

View File

@@ -112,9 +112,13 @@ func hasRef(repoURL string) bool {
return repoSpec.Ref != ""
}
// cleanFilePath returns file cleaned, where file is a relative path to root on fSys
func cleanFilePath(fSys filesys.FileSystem, root filesys.ConfirmedDir, file string) string {
abs := root.Join(file)
// cleanedRelativePath returns a cleaned relative path of file to root on fSys
func cleanedRelativePath(fSys filesys.FileSystem, root filesys.ConfirmedDir, file string) string {
abs := file
if !filepath.IsAbs(file) {
abs = root.Join(file)
}
dir, f, err := fSys.CleanedAbs(abs)
if err != nil {
log.Fatalf("cannot clean validated file path %q: %s", abs, err)

View File

@@ -301,3 +301,26 @@ func TestLocRootPath_SymlinkPath(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestCleanedRelativePath(t *testing.T) {
fSys := filesys.MakeFsInMemory()
require.NoError(t, fSys.MkdirAll("/root/test"))
require.NoError(t, fSys.WriteFile("/root/test/file.yaml", []byte("")))
require.NoError(t, fSys.WriteFile("/root/filetwo.yaml", []byte("")))
// Absolute path is cleaned to relative path
cleanedPath := cleanedRelativePath(fSys, "/root/", "/root/test/file.yaml")
require.Equal(t, "test/file.yaml", cleanedPath)
// Winding absolute path is cleaned to relative path
cleanedPath = cleanedRelativePath(fSys, "/root/", "/root/test/../filetwo.yaml")
require.Equal(t, "filetwo.yaml", cleanedPath)
// Already clean relative path stays the same
cleanedPath = cleanedRelativePath(fSys, "/root/", "test/file.yaml")
require.Equal(t, "test/file.yaml", cleanedPath)
// Winding relative path is cleaned
cleanedPath = cleanedRelativePath(fSys, "/root/", "test/../filetwo.yaml")
require.Equal(t, "filetwo.yaml", cleanedPath)
}

View File

@@ -70,30 +70,3 @@ namoPrefix:
t.Fatalf("expected error %s, but got %s", errMsg, err)
}
}
// please remove this failing test after implements the labels support
func TestLoadDefaultConfigsFromFilesWithMissingFieldsLabels(t *testing.T) {
fSys := filesys.MakeFsInMemory()
filePathContainsTypo := "config_contains_typo.yaml"
if err := fSys.WriteFile(filePathContainsTypo, []byte(`
labels:
- path: spec/podTemplate/metadata/labels
create: true
kind: FlinkDeployment
`)); err != nil {
t.Fatal(err)
}
ldr, err := loader.NewLoader(
loader.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
errMsg := "error unmarshaling JSON: while decoding JSON: json: unknown field"
_, err = loadDefaultConfig(ldr, []string{filePathContainsTypo})
if err == nil {
t.Fatalf("expected to fail unmarshal yaml, but got nil %s", filePathContainsTypo)
}
if !strings.Contains(err.Error(), errMsg) {
t.Fatalf("expected error %s, but got %s", errMsg, err)
}
}

View File

@@ -15,18 +15,22 @@ import (
)
// TransformerConfig holds the data needed to perform transformations.
//
//nolint:tagalign
type TransformerConfig struct {
// if any fields are added, update the DeepCopy implementation
NamePrefix types.FsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
NameSuffix types.FsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
NameSpace types.FsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
CommonLabels types.FsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`
TemplateLabels types.FsSlice `json:"templateLabels,omitempty" yaml:"templateLabels,omitempty"`
CommonAnnotations types.FsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
VarReference types.FsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
Images types.FsSlice `json:"images,omitempty" yaml:"images,omitempty"`
Replicas types.FsSlice `json:"replicas,omitempty" yaml:"replicas,omitempty"`
NamePrefix types.FsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
NameSuffix types.FsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
NameSpace types.FsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
CommonLabels types.FsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`
Labels types.FsSlice `json:"labels,omitempty" yaml:"labels,omitempty"`
TemplateLabels types.FsSlice `json:"templateLabels,omitempty" yaml:"templateLabels,omitempty"`
VolumeClaimTemplateLabels types.FsSlice `json:"volumeClaimTemplateLabels,omitempty" yaml:"volumeClaimTemplateLabels,omitempty"`
CommonAnnotations types.FsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
VarReference types.FsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
Images types.FsSlice `json:"images,omitempty" yaml:"images,omitempty"`
Replicas types.FsSlice `json:"replicas,omitempty" yaml:"replicas,omitempty"`
}
// MakeEmptyConfig returns an empty TransformerConfig object
@@ -37,16 +41,18 @@ func MakeEmptyConfig() *TransformerConfig {
// DeepCopy returns a new copy of TransformerConfig
func (t *TransformerConfig) DeepCopy() *TransformerConfig {
return &TransformerConfig{
NamePrefix: t.NamePrefix.DeepCopy(),
NameSuffix: t.NameSuffix.DeepCopy(),
NameSpace: t.NameSpace.DeepCopy(),
CommonLabels: t.CommonLabels.DeepCopy(),
TemplateLabels: t.TemplateLabels.DeepCopy(),
CommonAnnotations: t.CommonAnnotations.DeepCopy(),
NameReference: t.NameReference.DeepCopy(),
VarReference: t.VarReference.DeepCopy(),
Images: t.Images.DeepCopy(),
Replicas: t.Replicas.DeepCopy(),
NamePrefix: t.NamePrefix.DeepCopy(),
NameSuffix: t.NameSuffix.DeepCopy(),
NameSpace: t.NameSpace.DeepCopy(),
CommonLabels: t.CommonLabels.DeepCopy(),
Labels: t.Labels.DeepCopy(),
TemplateLabels: t.TemplateLabels.DeepCopy(),
VolumeClaimTemplateLabels: t.VolumeClaimTemplateLabels.DeepCopy(),
CommonAnnotations: t.CommonAnnotations.DeepCopy(),
NameReference: t.NameReference.DeepCopy(),
VarReference: t.VarReference.DeepCopy(),
Images: t.Images.DeepCopy(),
Replicas: t.Replicas.DeepCopy(),
}
}
@@ -94,7 +100,9 @@ func (t *TransformerConfig) sortFields() {
sort.Sort(t.NameSuffix)
sort.Sort(t.NameSpace)
sort.Sort(t.CommonLabels)
sort.Sort(t.Labels)
sort.Sort(t.TemplateLabels)
sort.Sort(t.VolumeClaimTemplateLabels)
sort.Sort(t.CommonAnnotations)
sort.Sort(t.NameReference)
sort.Sort(t.VarReference)
@@ -114,12 +122,18 @@ func (t *TransformerConfig) AddSuffixFieldSpec(fs types.FieldSpec) (err error) {
return err
}
// AddLabelFieldSpec adds a FieldSpec to CommonLabels
func (t *TransformerConfig) AddLabelFieldSpec(fs types.FieldSpec) (err error) {
// AddCommonLabelsFieldSpec adds a FieldSpec to CommonLabels
func (t *TransformerConfig) AddCommonLabelsFieldSpec(fs types.FieldSpec) (err error) {
t.CommonLabels, err = t.CommonLabels.MergeOne(fs)
return err
}
// AddLabelsFieldSpec adds a FieldSpec to Labels
func (t *TransformerConfig) AddLabelsFieldSpec(fs types.FieldSpec) (err error) {
t.Labels, err = t.Labels.MergeOne(fs)
return err //nolint:wrapcheck
}
// AddAnnotationFieldSpec adds a FieldSpec to CommonAnnotations
func (t *TransformerConfig) AddAnnotationFieldSpec(fs types.FieldSpec) (err error) {
t.CommonAnnotations, err = t.CommonAnnotations.MergeOne(fs)
@@ -162,10 +176,18 @@ func (t *TransformerConfig) Merge(input *TransformerConfig) (
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge CommonLabels fieldSpec")
}
merged.Labels, err = t.Labels.MergeAll(input.Labels)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge Labels fieldSpec")
}
merged.TemplateLabels, err = t.TemplateLabels.MergeAll(input.TemplateLabels)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge TemplateLabels fieldSpec")
}
merged.VolumeClaimTemplateLabels, err = t.VolumeClaimTemplateLabels.MergeAll(input.VolumeClaimTemplateLabels)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge VolumeClaimTemplateLabels fieldSpec")
}
merged.VarReference, err = t.VarReference.MergeAll(input.VarReference)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge VarReference fieldSpec")

View File

@@ -4,9 +4,10 @@
package builtinconfig_test
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
. "sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
@@ -35,13 +36,8 @@ func TestAddNamereferenceFieldSpec(t *testing.T) {
},
}
err := cfg.AddNamereferenceFieldSpec(nbrs)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(cfg.NameReference) != 1 {
t.Fatal("failed to add namereference FieldSpec")
}
require.NoError(t, cfg.AddNamereferenceFieldSpec(nbrs))
require.Len(t, cfg.NameReference, 1, "failed to add namereference FieldSpec")
}
func TestAddFieldSpecs(t *testing.T) {
@@ -53,34 +49,14 @@ func TestAddFieldSpecs(t *testing.T) {
CreateIfNotPresent: true,
}
err := cfg.AddPrefixFieldSpec(fieldSpec)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(cfg.NamePrefix) != 1 {
t.Fatalf("failed to add nameprefix FieldSpec")
}
err = cfg.AddSuffixFieldSpec(fieldSpec)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(cfg.NameSuffix) != 1 {
t.Fatalf("failed to add namesuffix FieldSpec")
}
err = cfg.AddLabelFieldSpec(fieldSpec)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(cfg.CommonLabels) != 1 {
t.Fatalf("failed to add nameprefix FieldSpec")
}
err = cfg.AddAnnotationFieldSpec(fieldSpec)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(cfg.CommonAnnotations) != 1 {
t.Fatalf("failed to add nameprefix FieldSpec")
}
require.NoError(t, cfg.AddPrefixFieldSpec(fieldSpec))
require.Len(t, cfg.NamePrefix, 1, "failed to add nameprefix FieldSpec")
require.NoError(t, cfg.AddSuffixFieldSpec(fieldSpec))
require.Len(t, cfg.NameSuffix, 1, "failed to add namesuffix FieldSpec")
require.NoError(t, cfg.AddCommonLabelsFieldSpec(fieldSpec))
require.Len(t, cfg.CommonLabels, 1, "failed to add labels FieldSpec")
require.NoError(t, cfg.AddAnnotationFieldSpec(fieldSpec))
require.Len(t, cfg.CommonAnnotations, 1, "failed to add nameprefix FieldSpec")
}
func TestMerge(t *testing.T) {
@@ -127,51 +103,43 @@ func TestMerge(t *testing.T) {
},
}
cfga := &TransformerConfig{}
cfga.AddNamereferenceFieldSpec(nameReference[0])
cfga.AddPrefixFieldSpec(fieldSpecs[0])
cfga.AddSuffixFieldSpec(fieldSpecs[0])
require.NoError(t, cfga.AddNamereferenceFieldSpec(nameReference[0]))
require.NoError(t, cfga.AddPrefixFieldSpec(fieldSpecs[0]))
require.NoError(t, cfga.AddSuffixFieldSpec(fieldSpecs[0]))
require.NoError(t, cfga.AddCommonLabelsFieldSpec(fieldSpecs[0]))
require.NoError(t, cfga.AddLabelsFieldSpec(fieldSpecs[0]))
cfgb := &TransformerConfig{}
cfgb.AddNamereferenceFieldSpec(nameReference[1])
cfgb.AddPrefixFieldSpec(fieldSpecs[1])
cfga.AddSuffixFieldSpec(fieldSpecs[1])
require.NoError(t, cfgb.AddNamereferenceFieldSpec(nameReference[1]))
require.NoError(t, cfgb.AddPrefixFieldSpec(fieldSpecs[1]))
require.NoError(t, cfgb.AddSuffixFieldSpec(fieldSpecs[1]))
require.NoError(t, cfgb.AddCommonLabelsFieldSpec(fieldSpecs[1]))
require.NoError(t, cfgb.AddLabelsFieldSpec(fieldSpecs[1]))
actual, err := cfga.Merge(cfgb)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(actual.NamePrefix) != 2 {
t.Fatal("merge failed for namePrefix FieldSpec")
}
if len(actual.NameSuffix) != 2 {
t.Fatal("merge failed for nameSuffix FieldSpec")
}
if len(actual.NameReference) != 1 {
t.Fatal("merge failed for namereference FieldSpec")
}
require.NoError(t, err)
require.Len(t, actual.NamePrefix, 2, "merge failed for namePrefix FieldSpec")
require.Len(t, actual.NameSuffix, 2, "merge failed for nameSuffix FieldSpec")
require.Len(t, actual.NameReference, 1, "merge failed for nameReference FieldSpec")
require.Len(t, actual.Labels, 2, "merge failed for labels FieldSpec")
require.Len(t, actual.CommonLabels, 2, "merge failed for commonLabels FieldSpec")
expected := &TransformerConfig{}
expected.AddNamereferenceFieldSpec(nameReference[0])
expected.AddNamereferenceFieldSpec(nameReference[1])
expected.AddPrefixFieldSpec(fieldSpecs[0])
expected.AddPrefixFieldSpec(fieldSpecs[1])
expected.AddSuffixFieldSpec(fieldSpecs[0])
expected.AddSuffixFieldSpec(fieldSpecs[1])
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %v\n but got: %v\n", expected, actual)
}
require.NoError(t, expected.AddNamereferenceFieldSpec(nameReference[0]))
require.NoError(t, expected.AddNamereferenceFieldSpec(nameReference[1]))
require.NoError(t, expected.AddPrefixFieldSpec(fieldSpecs[0]))
require.NoError(t, expected.AddPrefixFieldSpec(fieldSpecs[1]))
require.NoError(t, expected.AddSuffixFieldSpec(fieldSpecs[0]))
require.NoError(t, expected.AddSuffixFieldSpec(fieldSpecs[1]))
require.NoError(t, expected.AddCommonLabelsFieldSpec(fieldSpecs[0]))
require.NoError(t, expected.AddCommonLabelsFieldSpec(fieldSpecs[1]))
require.NoError(t, expected.AddLabelsFieldSpec(fieldSpecs[0]))
require.NoError(t, expected.AddLabelsFieldSpec(fieldSpecs[1]))
require.Equal(t, expected, actual)
actual, err = cfga.Merge(nil)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if !reflect.DeepEqual(actual, cfga) {
t.Fatalf("expected: %v\n but got: %v\n", cfga, actual)
}
require.NoError(t, err)
require.Equal(t, cfga, actual)
}
func TestMakeDefaultConfig_mutation(t *testing.T) {
@@ -182,9 +150,7 @@ func TestMakeDefaultConfig_mutation(t *testing.T) {
a.NameReference = a.NameReference[:1]
clean := MakeDefaultConfig()
if clean.NameReference[0].Kind == "mutated" {
t.Errorf("MakeDefaultConfig() did not return a clean copy: %+v", clean.NameReference)
}
assert.NotEqualf(t, "mutated", clean.NameReference[0].Kind, "MakeDefaultConfig() did not return a clean copy: %+v", clean.NameReference)
}
func BenchmarkMakeDefaultConfig(b *testing.B) {

View File

@@ -12,8 +12,6 @@ import (
"runtime"
"strings"
"github.com/google/shlex"
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/kyaml/errors"
@@ -95,7 +93,11 @@ func (p *ExecPlugin) processOptionalArgsFields() error {
return err
}
if c.ArgsOneLiner != "" {
p.args, _ = shlex.Split(c.ArgsOneLiner)
argsTolenSlice, err := ShlexSplit(c.ArgsOneLiner)
if err != nil {
return fmt.Errorf("failed to parse argsOneLiner: %w", err)
}
p.args = argsTolenSlice
}
if c.ArgsFromFile != "" {
content, err := p.h.Loader().Load(c.ArgsFromFile)
@@ -159,14 +161,13 @@ func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
_, err = f.Write(p.cfg)
if err != nil {
return nil, errors.WrapPrefixf(
err, "writing plugin config to "+f.Name())
err, "writing plugin config to %s", f.Name())
}
err = f.Close()
if err != nil {
return nil, errors.WrapPrefixf(
err, "closing plugin config file "+f.Name())
err, "closing plugin config file %s", f.Name())
}
//nolint:gosec
cmd := exec.Command(
p.path, append([]string{f.Name()}, p.args...)...)
cmd.Env = p.getEnv()
@@ -179,8 +180,8 @@ func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
result, err := cmd.Output()
if err != nil {
return nil, errors.WrapPrefixf(
fmt.Errorf("failure in plugin configured via %s; %w",
f.Name(), err), stdErr.String())
fmt.Errorf("failure in plugin configured via %s; %w", f.Name(), err),
"%s", stdErr.String())
}
return result, os.Remove(f.Name())
}

View File

@@ -41,7 +41,7 @@ s/$BAR/bar baz/g
}
pvd := provider.NewDefaultDepProvider()
rf := resmap.NewFactory(pvd.GetResourceFactory())
pluginConfig := rf.RF().FromMap(
pluginConfig, err := rf.RF().FromMap(
map[string]interface{}{
"apiVersion": "someteam.example.com/v1",
"kind": "SedTransformer",
@@ -51,6 +51,9 @@ s/$BAR/bar baz/g
"argsOneLiner": "one two 'foo bar'",
"argsFromFile": "sed-input.txt",
})
if err != nil {
t.Fatalf("failed to writes the data to a file: %v", err)
}
pluginConfig.RemoveBuildAnnotations()
pc := types.DisabledPluginConfig()

View File

@@ -0,0 +1,62 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package execplugin
import (
"fmt"
"strings"
"unicode"
)
// ShlexSplit splits a string into a slice of strings using shell-style rules for quoting and commenting
// Similar to Python's shlex.split with comments enabled
func ShlexSplit(s string) ([]string, error) {
return shlexSplit(s)
}
func shlexSplit(s string) ([]string, error) {
result := []string{}
// noQuote is used to track if we are not in a quoted
const noQuote = 0
var current strings.Builder
var quote rune = noQuote
var escaped bool
for _, r := range s {
switch {
case escaped:
current.WriteRune(r)
escaped = false
case r == '\\' && quote != '\'':
escaped = true
case (r == '\'' || r == '"') && quote == noQuote:
quote = r
case r == quote:
quote = noQuote
case r == '#' && quote == noQuote:
// Comment starts, ignore the rest of the line
if current.Len() > 0 {
result = append(result, current.String())
}
return result, nil
case unicode.IsSpace(r) && quote == noQuote:
if current.Len() > 0 {
result = append(result, current.String())
current.Reset()
}
default:
current.WriteRune(r)
}
}
if quote != noQuote {
return nil, fmt.Errorf("unclosed quote in string")
}
if current.Len() > 0 {
result = append(result, current.String())
}
return result, nil
}

View File

@@ -0,0 +1,183 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package execplugin
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestShlexSplit(t *testing.T) {
testCases := []struct {
name string
input string
expected []string
wantErr bool
}{
{
name: "basic space separation",
input: `hello world`,
expected: []string{"hello", "world"},
wantErr: false,
},
{
name: "double quoted string",
input: `"hello world"`,
expected: []string{"hello world"},
wantErr: false,
},
{
name: "single quoted string",
input: `'hello world'`,
expected: []string{"hello world"},
wantErr: false,
},
{
name: "mixed quotes and words",
input: `hello "world test"`,
expected: []string{"hello", "world test"},
wantErr: false,
},
{
name: "single quotes with spaces",
input: `hello 'world test'`,
expected: []string{"hello", "world test"},
wantErr: false,
},
{
name: "nested quotes - single in double",
input: `"hello 'nested' world"`,
expected: []string{"hello 'nested' world"},
wantErr: false,
},
{
name: "nested quotes - double in single",
input: `'hello "nested" world'`,
expected: []string{"hello \"nested\" world"},
wantErr: false,
},
{
name: "escaped space",
input: `hello\ world`,
expected: []string{"hello world"},
wantErr: false,
},
{
name: "escaped quotes in double quotes",
input: `"hello \"world\""`,
expected: []string{"hello \"world\""},
wantErr: false,
},
{
name: "single quote in single quotes",
input: `'can'\''t'`,
expected: []string{"can't"},
wantErr: false,
},
{
name: "complex argument list",
input: `arg1 "arg 2" 'arg 3' arg4`,
expected: []string{"arg1", "arg 2", "arg 3", "arg4"},
wantErr: false,
},
{
name: "echo command with escaped quotes",
input: `echo "Hello, \"World!\""`,
expected: []string{"echo", "Hello, \"World!\""},
wantErr: false,
},
{
name: "grep command with quoted search term",
input: `grep -r "search term" /path/to/dir`,
expected: []string{"grep", "-r", "search term", "/path/to/dir"},
wantErr: false,
},
{
name: "ls command with quoted filename",
input: `ls -la "file with spaces.txt"`,
expected: []string{"ls", "-la", "file with spaces.txt"},
wantErr: false,
},
{
name: "empty string",
input: ``,
expected: []string{},
wantErr: false,
},
{
name: "multiple spaces",
input: ` multiple spaces `,
expected: []string{"multiple", "spaces"},
wantErr: false,
},
{
name: "with comment string",
input: `echo "Hello, W#orld!" ${USER} # This is a comment`,
expected: []string{"echo", "Hello, W#orld!", "${USER}"},
wantErr: false,
},
{
name: "comment only",
input: `# this line is just a comment`,
expected: []string{},
wantErr: false,
},
// may cause an error in shlex at python3
{
name: "unclosed double quote",
input: `"unclosed quote`,
expected: nil,
wantErr: true,
},
{
name: "unclosed single quote",
input: `'unclosed quote`,
expected: nil,
wantErr: true,
},
{
name: "mixed unclosed quotes",
input: `"mixed 'quotes`,
expected: nil,
wantErr: true,
},
{
name: "single quote closed with double quote",
input: `"hello world'`,
expected: nil,
wantErr: true,
},
{
name: "double quote closed with single quote",
input: `'hello world"`,
expected: nil,
wantErr: true,
},
}
// execute each test case
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// call the ShlexSplit function
result, err := ShlexSplit(tc.input)
// check for expected error
if tc.wantErr {
if err == nil {
t.Errorf("FAIL: Expected error but got none, Expected: %q\n", tc.expected)
}
return
}
if assert.NoError(t, err, "FAIL: Unexpected error %q for input %q", err, tc.input) {
// check if the result matches the expected output
assert.Equal(t, tc.expected, result,
"FAIL: Result mismatch,Input %q, Expected %q, Got: %q\n",
tc.input, tc.expected, result,
)
}
})
}
}

View File

@@ -77,7 +77,6 @@ func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin {
runFns: runfn.RunFns{
Functions: []*yaml.RNode{},
Network: o.Network,
EnableStarlark: o.EnableStar,
EnableExec: o.EnableExec,
StorageMounts: toStorageMounts(o.Mounts),
Env: o.Env,

View File

@@ -14,11 +14,12 @@
package loader
import (
"fmt"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/resid"
)
func (l *Loader) loadGoPlugin(_ resid.ResId, _ string) (resmap.Configurable, error) {
return nil, errors.New("plugin load is disabled")
return nil, fmt.Errorf("plugin load is disabled")
}

View File

@@ -34,7 +34,8 @@ type Loader struct {
}
func NewLoader(
pc *types.PluginConfig, rf *resmap.Factory, fs filesys.FileSystem) *Loader {
pc *types.PluginConfig, rf *resmap.Factory, fs filesys.FileSystem,
) *Loader {
return &Loader{pc: pc, rf: rf, fs: fs}
}
@@ -58,7 +59,8 @@ func (l *Loader) Config() *types.PluginConfig {
func (l *Loader) LoadGenerators(
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) (
result []*resmap.GeneratorWithProperties, err error) {
result []*resmap.GeneratorWithProperties, err error,
) {
for _, res := range rm.Resources() {
g, err := l.LoadGenerator(ldr, v, res)
if err != nil {
@@ -74,7 +76,8 @@ func (l *Loader) LoadGenerators(
}
func (l *Loader) LoadGenerator(
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (resmap.Generator, error) {
ldr ifc.Loader, v ifc.Validator, res *resource.Resource,
) (resmap.Generator, error) {
c, err := l.loadAndConfigurePlugin(ldr, v, res)
if err != nil {
return nil, err
@@ -87,7 +90,8 @@ func (l *Loader) LoadGenerator(
}
func (l *Loader) LoadTransformers(
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]*resmap.TransformerWithProperties, error) {
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap,
) ([]*resmap.TransformerWithProperties, error) {
var result []*resmap.TransformerWithProperties
for _, res := range rm.Resources() {
t, err := l.LoadTransformer(ldr, v, res)
@@ -104,7 +108,8 @@ func (l *Loader) LoadTransformers(
}
func (l *Loader) LoadTransformer(
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (*resmap.TransformerWithProperties, error) {
ldr ifc.Loader, v ifc.Validator, res *resource.Resource,
) (*resmap.TransformerWithProperties, error) {
c, err := l.loadAndConfigurePlugin(ldr, v, res)
if err != nil {
return nil, err
@@ -179,7 +184,8 @@ func isBuiltinPlugin(res *resource.Resource) bool {
func (l *Loader) loadAndConfigurePlugin(
ldr ifc.Loader,
v ifc.Validator,
res *resource.Resource) (c resmap.Configurable, err error) {
res *resource.Resource,
) (c resmap.Configurable, err error) {
if isBuiltinPlugin(res) {
switch l.pc.BpLoadingOptions {
case types.BploLoadFromFileSys:
@@ -192,7 +198,7 @@ func (l *Loader) loadAndConfigurePlugin(
c, err = l.makeBuiltinPlugin(res.GetGvk())
default:
err = fmt.Errorf(
"unknown plugin loader behavior specified: %v",
"unknown plugin loader behavior specified: %s %v", res.GetGvk().String(),
l.pc.BpLoadingOptions)
}
} else {
@@ -245,7 +251,7 @@ func (l *Loader) loadPlugin(res *resource.Resource) (resmap.Configurable, error)
return nil, errors.Errorf("plugin %s with mount path '%s' is not permitted; "+
"mount paths must be relative to the current kustomization directory", res.OrgId(), mount.Src)
}
if strings.HasPrefix(filepath.Clean(mount.Src), "../") {
if strings.HasPrefix(filepath.Clean(mount.Src), "..") {
return nil, errors.Errorf("plugin %s with mount path '%s' is not permitted; "+
"mount paths must be under the current kustomization directory", res.OrgId(), mount.Src)
}
@@ -282,4 +288,3 @@ func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, err
}
return c, nil
}

View File

@@ -18,7 +18,6 @@ import (
)
const (
//nolint:gosec
secretGenerator = `
apiVersion: builtin
kind: SecretGenerator
@@ -96,3 +95,43 @@ func TestLoaderWithWorkingDir(t *testing.T) {
npLdr.Config().FnpLoadingOptions.WorkingDir,
"the plugin working dir is not updated")
}
func TestLoaderWithStorageMounts(t *testing.T) {
const storageMountTransformer = `
apiVersion: com.example.kustomize/v1
kind: Test
metadata:
name: test-transformer
annotations:
config.kubernetes.io/function: |
container:
image: test
mounts:
- type: bind
src: ../
dst: /mount
`
p := provider.NewDefaultDepProvider()
rmF := resmap.NewFactory(p.GetResourceFactory())
fsys := filesys.MakeFsInMemory()
fLdr, err := loader.NewLoader(
loader.RestrictionRootOnly,
filesys.Separator, fsys)
if err != nil {
t.Fatal(err)
}
configs, err := rmF.NewResMapFromBytes([]byte(storageMountTransformer))
if err != nil {
t.Fatal(err)
}
c := types.EnabledPluginConfig(types.BploLoadFromFileSys)
pLdr := NewLoader(c, rmF, fsys)
if pLdr == nil {
t.Fatal("expect non-nil loader")
}
_, err = pLdr.LoadTransformers(
fLdr, valtest_test.MakeFakeValidator(), configs)
if err == nil { // should fail because src specified is outside root
t.Fatal("the loader allowed a mount outside root")
}
}

View File

@@ -32,11 +32,14 @@ func TestDeterminePluginSrcRoot(t *testing.T) {
}
func makeConfigMap(rf *resource.Factory, name, behavior string, hashValue *string) *resource.Resource {
r := rf.FromMap(map[string]interface{}{
r, err := rf.FromMap(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{"name": name},
})
if err != nil {
panic(err)
}
annotations := map[string]string{}
if behavior != "" {
annotations[BehaviorAnnotation] = behavior

View File

@@ -29,13 +29,14 @@ import (
// KustTarget encapsulates the entirety of a kustomization build.
type KustTarget struct {
kustomization *types.Kustomization
kustFileName string
ldr ifc.Loader
validator ifc.Validator
rFactory *resmap.Factory
pLdr *loader.Loader
origin *resource.Origin
kustomization *types.Kustomization
kustFileName string
ldr ifc.Loader
validator ifc.Validator
rFactory *resmap.Factory
pLdr *loader.Loader
origin *resource.Origin
helmRootNamespace string // namespace inherited from parent kustomization for HelmCharts
}
// NewKustTarget returns a new instance of KustTarget.
@@ -449,9 +450,6 @@ func (kt *KustTarget) accumulateResources(
ra, err = kt.accumulateDirectory(ra, ldr, false)
}
if err != nil {
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
return nil, errF
}
return nil, errors.WrapPrefixf(
err, "accumulation err='%s'", errF.Error())
}
@@ -460,7 +458,7 @@ func (kt *KustTarget) accumulateResources(
return ra, nil
}
// accumulateResources fills the given resourceAccumulator
// accumulateComponents fills the given resourceAccumulator
// with resources read from the given list of paths.
func (kt *KustTarget) accumulateComponents(
ra *accumulator.ResAccumulator, paths []string) (*accumulator.ResAccumulator, error) {
@@ -499,6 +497,16 @@ func (kt *KustTarget) accumulateDirectory(
}
subKt.kustomization.BuildMetadata = kt.kustomization.BuildMetadata
subKt.origin = kt.origin
// Propagate namespace to child kustomization's helmRootNamespace for HelmCharts
// This ensures Helm charts in base kustomizations inherit namespace from overlays
// without affecting other transformers like patches
// Fixes https://github.com/kubernetes-sigs/kustomize/issues/6031
// Fixes https://github.com/kubernetes-sigs/kustomize/issues/6027
if kt.kustomization.Namespace != "" {
subKt.helmRootNamespace = kt.kustomization.Namespace
} else if kt.helmRootNamespace != "" {
subKt.helmRootNamespace = kt.helmRootNamespace
}
var bytes []byte
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
bytes, err = ldr.Load(openApiPath)

View File

@@ -166,6 +166,16 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
for _, chart := range kt.kustomization.HelmCharts {
c.HelmGlobals = globals
c.HelmChart = chart
// Pass kustomize namespace to helm
// Fixes https://github.com/kubernetes-sigs/kustomize/issues/5566
// Also propagate parent namespace for multi-level kustomization hierarchies
if c.HelmChart.Namespace == "" {
if kt.kustomization.Namespace != "" {
c.HelmChart.Namespace = kt.kustomization.Namespace
} else if kt.helmRootNamespace != "" {
c.HelmChart.Namespace = kt.helmRootNamespace
}
}
p := f()
if err = kt.configureBuiltinPlugin(p, c, bpt); err != nil {
return nil, err
@@ -250,10 +260,10 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
return
}
var c 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"`
Options map[string]bool `json:"options,omitempty" yaml:"options,omitempty"`
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"`
Options *types.PatchArgs `json:"options,omitempty" yaml:"options,omitempty"`
}
for _, pc := range kt.kustomization.Patches {
c.Target = pc.Target
@@ -275,13 +285,25 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
if len(kt.kustomization.Labels) == 0 && len(kt.kustomization.CommonLabels) == 0 {
return
}
type labelStruct struct {
Labels map[string]string
FieldSpecs []types.FieldSpec
}
for _, label := range kt.kustomization.Labels {
var c struct {
Labels map[string]string
FieldSpecs []types.FieldSpec
}
var c labelStruct
c.Labels = label.Pairs
fss := types.FsSlice(label.FieldSpecs)
// merge labels specified in the label section of transformer configs
// these apply to selectors and templates
fss, err := fss.MergeAll(tc.Labels)
if err != nil {
return nil, fmt.Errorf("failed to merge labels: %w", err)
}
// merge the custom fieldSpecs with the default
if label.IncludeSelectors {
fss, err = fss.MergeAll(tc.CommonLabels)
@@ -293,11 +315,18 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
return nil, errors.WrapPrefixf(err, "failed to merge template fieldSpec")
}
}
// merge spec/volumeClaimTemplates[]/metadata fieldSpecs if includeVolumeClaimTemplates flag is true
if label.IncludeVolumeClaimTemplates {
fss, err = fss.MergeAll(tc.VolumeClaimTemplateLabels)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge volumeClaimTemplate fieldSpec")
}
}
// only add to metadata by default
fss, err = fss.MergeOne(types.FieldSpec{Path: "metadata/labels", CreateIfNotPresent: true})
}
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to merge labels: %w", err)
}
c.FieldSpecs = fss
p := f()
@@ -307,10 +336,9 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
}
result = append(result, p)
}
var c struct {
Labels map[string]string
FieldSpecs []types.FieldSpec
}
var c labelStruct
c.Labels = kt.kustomization.CommonLabels
c.FieldSpecs = tc.CommonLabels
p := f()

View File

@@ -6,6 +6,8 @@ package target_test
import (
"encoding/base64"
"fmt"
"net/http"
"net/http/httptest"
"reflect"
"testing"
"time"
@@ -191,13 +193,67 @@ metadata:
pvd := provider.NewDefaultDepProvider()
resFactory := pvd.GetResourceFactory()
name0 := "dply1"
resources := []*resource.Resource{
resFactory.FromMapWithName("dply1", map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
r0, err := resFactory.FromMapWithName(name0, map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-dply1-bar",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"spec": map[string]interface{}{
"replica": "3",
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"labels": map[string]interface{}{
"app": "nginx",
},
},
},
},
})
if err != nil {
t.Fatalf("failed to get instance with given name %v: %v", name0, err)
}
name1 := "ns1"
r1, err := resFactory.FromMapWithName(name1, map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
})
if err != nil {
t.Fatalf("failed to get instance with given name %v: %v", name1, err)
}
r2, _ := resFactory.FromMapWithName("literalConfigMap",
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "foo-dply1-bar",
"name": "foo-literalConfigMap-bar-g5f6t456f5",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
@@ -206,30 +262,20 @@ metadata:
"note": "This is a test annotation",
},
},
"spec": map[string]interface{}{
"replica": "3",
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"labels": map[string]interface{}{
"app": "nginx",
},
},
},
"data": map[string]interface{}{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}),
resFactory.FromMapWithName("ns1", map[string]interface{}{
})
name2 := "secret"
r3, err := resFactory.FromMapWithName(name2,
map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "ns1",
"name": "foo-secret-bar-82c2g5f8f6",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
@@ -237,55 +283,25 @@ metadata:
"note": "This is a test annotation",
},
},
}),
resFactory.FromMapWithName("literalConfigMap",
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "foo-literalConfigMap-bar-g5f6t456f5",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"data": map[string]interface{}{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}),
resFactory.FromMapWithName("secret",
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "foo-secret-bar-82c2g5f8f6",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"type": ifc.SecretTypeOpaque,
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}),
"type": ifc.SecretTypeOpaque,
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
})
if err != nil {
t.Fatalf("failed to get instance with given name %v: %v", name2, err)
}
resources := []*resource.Resource{r0, r1, r2, r3}
expected := resmap.New()
for _, r := range resources {
if err := expected.Append(r); err != nil {
t.Fatalf("unexpected error %v", err)
}
require.NoError(t, expected.Append(r), "failed to append resource: %v")
}
expected.RemoveBuildAnnotations()
require.NoError(t, expected.RemoveTransformerAnnotations())
require.NoError(t, expected.RemoveOriginAnnotations())
expYaml, err := expected.AsYaml()
require.NoError(t, err)
@@ -294,6 +310,8 @@ metadata:
actual, err := kt.MakeCustomizedResMap()
require.NoError(t, err)
actual.RemoveBuildAnnotations()
require.NoError(t, actual.RemoveTransformerAnnotations())
require.NoError(t, actual.RemoveOriginAnnotations())
actYaml, err := actual.AsYaml()
require.NoError(t, err)
assert.Equal(t, string(expYaml), string(actYaml))
@@ -354,37 +372,51 @@ metadata:
pvd := provider.NewDefaultDepProvider()
resFactory := pvd.GetResourceFactory()
resources := []*resource.Resource{
resFactory.FromMapWithName("deployment1", map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-deployment1-bar",
"namespace": "ns1",
},
}), resFactory.FromMapWithName("config", map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "config-bar",
"namespace": "ns1",
},
}), resFactory.FromMapWithName("secret", map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "foo-secret",
"namespace": "ns1",
},
}),
name0 := "deployment1"
r0, err0 := resFactory.FromMapWithName(name0, map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-deployment1-bar",
"namespace": "ns1",
},
})
if err0 != nil {
t.Fatalf("failed to get instance with given name %v: %v", name0, err0)
}
name1 := "config"
r1, err1 := resFactory.FromMapWithName(name1, map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "config-bar",
"namespace": "ns1",
},
})
if err1 != nil {
t.Fatalf("failed to get instance with given name %v: %v", name1, err1)
}
name2 := "secret"
r2, err2 := resFactory.FromMapWithName(name2, map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "foo-secret",
"namespace": "ns1",
},
})
if err2 != nil {
t.Fatalf("failed to get instance with given name %v: %v", name2, err2)
}
var resources = []*resource.Resource{r0, r1, r2}
expected := resmap.New()
for _, r := range resources {
err := expected.Append(r)
require.NoError(t, err)
}
expected.RemoveBuildAnnotations()
require.NoError(t, expected.RemoveTransformerAnnotations())
require.NoError(t, expected.RemoveOriginAnnotations())
expYaml, err := expected.AsYaml()
require.NoError(t, err)
@@ -393,6 +425,8 @@ metadata:
actual, err := kt.MakeCustomizedResMap()
require.NoError(t, err)
actual.RemoveBuildAnnotations()
require.NoError(t, actual.RemoveTransformerAnnotations())
require.NoError(t, actual.RemoveOriginAnnotations())
actYaml, err := actual.AsYaml()
require.NoError(t, err)
require.Equal(t, string(expYaml), string(actYaml))
@@ -536,3 +570,71 @@ func (l loaderNewThrowsError) Load(location string) ([]byte, error) {
func (l loaderNewThrowsError) Cleanup() error {
return l.baseLoader.Cleanup() //nolint:wrapcheck // baseLoader's error is sufficient
}
func TestErrorMessageForMalformedYAMLAndInvalidBase(t *testing.T) {
// These testcases verify behavior for the scenario described in
// https://github.com/kubernetes-sigs/kustomize/issues/5692 .
// Use a test server to fake the remote file response
handler := http.NewServeMux()
handler.HandleFunc("/", func(out http.ResponseWriter, req *http.Request) {
// Per issue #5692, the server should return a 200 status code with a response body that fails to parse as YAML
out.WriteHeader(http.StatusOK)
_, _ = out.Write([]byte(`<!DOCTYPE html>
<html class="html-devise-layout ui-light-gray" lang="en">
<head prefix="og: http://ogp.me/ns#">`))
})
svr := httptest.NewServer(handler)
defer svr.Close()
th := kusttest_test.MakeHarness(t)
th.WriteF("/should-fail/kustomization.yml", "resources:\n- "+svr.URL)
th.WriteF("/should-fail/remote-repo/kustomization.yml", "this: is not a kustomization file!")
ldrWrapper := func(baseLoader ifc.Loader) ifc.Loader {
return &loaderWithRenamedRoots{
baseLoader: baseLoader,
fakeRootMap: map[string]string{
// Use the "remote-repo" subdir instead of the remote git repo
svr.URL: "remote-repo",
},
}
}
_, err := makeAndLoadKustTargetWithLoaderOverride(t, th.GetFSys(), "/should-fail", ldrWrapper).AccumulateTarget()
require.Error(t, err)
errString := err.Error()
assert.Contains(t, errString, "accumulating resources from '"+svr.URL+"'")
assert.Contains(t, errString, "MalformedYAMLError: yaml: line 3: mapping values are not allowed in this context")
assert.Contains(t, errString, `invalid Kustomization: json: unknown field "this"`)
}
// loaderWithRenamedRoots is a loader that can map New() roots to some other name
type loaderWithRenamedRoots struct {
baseLoader ifc.Loader
fakeRootMap map[string]string
}
func (l loaderWithRenamedRoots) Repo() string {
return l.baseLoader.Repo()
}
func (l loaderWithRenamedRoots) Root() string {
return l.baseLoader.Root()
}
func (l loaderWithRenamedRoots) New(newRoot string) (ifc.Loader, error) {
if otherRoot, ok := l.fakeRootMap[newRoot]; ok {
return l.baseLoader.New(otherRoot) //nolint:wrapcheck // baseLoader's error is sufficient
}
return l.baseLoader.New(newRoot) //nolint:wrapcheck // baseLoader's error is sufficient
}
func (l loaderWithRenamedRoots) Load(path string) ([]byte, error) {
return l.baseLoader.Load(path) //nolint:wrapcheck // baseLoader's error is sufficient
}
func (l loaderWithRenamedRoots) Cleanup() error {
return l.baseLoader.Cleanup() //nolint:wrapcheck // baseLoader's error is sufficient
}

View File

@@ -46,4 +46,7 @@ const (
// Label key that indicates the resources are validated by a validator
ValidatedByLabelKey = "validated-by"
// Annotation key for marking helm-generated resources to skip namespace transformation
HelmGeneratedAnnotation = ConfigAnnoDomain + "/helm-generated"
)

View File

@@ -31,6 +31,20 @@ spec:
- port: 7002
`
const invalidResource = `apiVersion: v1
kind: Service
metadata:
name: kapacitor
labels:
app.kubernetes.io/name: tick-kapacitor
spec:
selector:
app.kubernetes.io/name: tick-kapacitor
- name: http
port: 9092
protocol: TCP
type: ClusterIP`
func TestTargetMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("service.yaml", `
@@ -302,6 +316,14 @@ resources:
// know resource is file.
errDir: `new root '%s' cannot be absolute`,
},
{
name: "malformed yaml yields an error",
resource: "service.yaml",
files: map[string]string{
"service.yaml": invalidResource,
},
errFile: "MalformedYAMLError",
},
} {
t.Run(test.name, func(t *testing.T) {
if test.resourceFunc != nil {
@@ -338,5 +360,4 @@ resources:
// TODO(annasong): add tests that check accumulateResources errors for
// - repos
// - local directories
// - files that yield malformed yaml errors
}

View File

@@ -335,3 +335,400 @@ spec:
location: Arizona
`)
}
func TestLabelTransformerConfig(t *testing.T) {
testCases := []struct {
name string
kustomization string
transformerConfig string
expectedResult string
}{
{
name: "includeSelectors=false, includeTemplates=false, include template via transformerConfig",
kustomization: `configurations:
- config/configurations.yaml
labels:
- includeSelectors: false
includeTemplates: false
pairs:
location: planet-earth
environment: dev
resources:
- resources/deployment.yaml
`,
transformerConfig: `labels:
- path: spec/template/metadata/labels
create: true
kind: Deployment
`,
expectedResult: `apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
name: sample-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sample-deploy
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
spec:
containers:
- image: hello-world:latest
name: hello-world
`,
},
{
name: "includeSelectors=true, includeTemplates=false, include template via transformerConfig",
kustomization: `configurations:
- config/configurations.yaml
labels:
- includeSelectors: true
includeTemplates: false
pairs:
location: planet-earth
environment: dev
resources:
- resources/deployment.yaml
`,
transformerConfig: `labels:
- path: spec/template/metadata/labels
create: true
kind: Deployment
`,
expectedResult: `apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
name: sample-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sample-deploy
environment: dev
location: planet-earth
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
spec:
containers:
- image: hello-world:latest
name: hello-world
`,
},
{
name: "includeSelectors=false, includeTemplates=true, no transformerConfig",
kustomization: `labels:
- includeSelectors: false
includeTemplates: true
pairs:
location: planet-earth
environment: dev
resources:
- resources/deployment.yaml
`,
expectedResult: `apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
name: sample-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sample-deploy
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
spec:
containers:
- image: hello-world:latest
name: hello-world
`,
},
{
name: "includeSelectors=false, includeTemplates=false, no transformerConfig",
kustomization: `labels:
- includeSelectors: false
includeTemplates: false
pairs:
location: planet-earth
environment: dev
resources:
- resources/deployment.yaml
`,
expectedResult: `apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: sample-deploy
environment: dev
location: planet-earth
name: sample-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sample-deploy
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: sample-deploy
spec:
containers:
- image: hello-world:latest
name: hello-world
`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", tc.kustomization)
th.WriteF("resources/deployment.yaml",
`apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: sample-deploy
name: sample-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sample-deploy
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: sample-deploy
spec:
containers:
- image: hello-world:latest
name: hello-world
`)
if tc.transformerConfig != "" {
th.WriteF("config/configurations.yaml", tc.transformerConfig)
}
output := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(output, tc.expectedResult)
})
}
}
func TestLabelTransformerConfigWithCustomResources(t *testing.T) {
testCases := []struct {
name string
kustomization string
transformerConfig string
expectedResult string
}{
{
name: "include template via transformerConfig",
kustomization: `configurations:
- config/configurations.yaml
labels:
- includeSelectors: false
includeTemplates: false
pairs:
location: planet-earth
environment: dev
resources:
- resources/custom-resource.yaml
`,
transformerConfig: `labels:
- path: spec/template/metadata/labels
create: true
kind: SampleResource
`,
expectedResult: `apiVersion: custom.example.org/v1
kind: SampleResource
metadata:
labels:
environment: dev
location: planet-earth
name: sample-resource
namespace: sample-namespace
spec:
template:
metadata:
labels:
environment: dev
location: planet-earth
spec:
containers:
- env:
- name: VARIABLE
value: value
image: index.docker.io/library/hello-world
`,
},
{
name: "include selector via transformerConfig",
kustomization: `configurations:
- config/configurations.yaml
labels:
- includeSelectors: false
includeTemplates: false
pairs:
location: planet-earth
environment: dev
resources:
- resources/custom-resource.yaml
`,
transformerConfig: `labels:
- path: spec/selectors/labels
create: true
kind: SampleResource
`,
expectedResult: `apiVersion: custom.example.org/v1
kind: SampleResource
metadata:
labels:
environment: dev
location: planet-earth
name: sample-resource
namespace: sample-namespace
spec:
selectors:
labels:
environment: dev
location: planet-earth
template:
spec:
containers:
- env:
- name: VARIABLE
value: value
image: index.docker.io/library/hello-world
`,
},
{
name: "include selectors and labels via transformerConfig",
kustomization: `configurations:
- config/configurations.yaml
labels:
- includeSelectors: false
includeTemplates: false
pairs:
location: planet-earth
environment: dev
resources:
- resources/custom-resource.yaml
`,
transformerConfig: `
labels:
- path: spec/selectors/labels
create: true
kind: SampleResource
- path: spec/template/metadata/labels
create: true
kind: SampleResource
`,
expectedResult: `apiVersion: custom.example.org/v1
kind: SampleResource
metadata:
labels:
environment: dev
location: planet-earth
name: sample-resource
namespace: sample-namespace
spec:
selectors:
labels:
environment: dev
location: planet-earth
template:
metadata:
labels:
environment: dev
location: planet-earth
spec:
containers:
- env:
- name: VARIABLE
value: value
image: index.docker.io/library/hello-world
`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", tc.kustomization)
th.WriteF("resources/custom-resource.yaml",
`apiVersion: custom.example.org/v1
kind: SampleResource
metadata:
name: sample-resource
namespace: sample-namespace
spec:
template:
spec:
containers:
- image: index.docker.io/library/hello-world
env:
- name: VARIABLE
value: value
`)
th.WriteF("config/configurations.yaml", tc.transformerConfig)
output := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(output, tc.expectedResult)
})
}
}

View File

@@ -21,10 +21,31 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
name: test-minecraft-rcon
namespace: default
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-curseforge
namespace: default
type: Opaque
---
apiVersion: v1
@@ -32,10 +53,14 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
namespace: default
spec:
ports:
- name: minecraft
@@ -150,7 +175,7 @@ func TestHelmChartInflationGeneratorOld(t *testing.T) {
helmChartInflationGenerator:
- chartName: minecraft
chartRepoUrl: https://itzg.github.io/minecraft-server-charts
chartVersion: 3.1.3
chartVersion: 4.26.4
releaseName: test
`)
@@ -158,6 +183,54 @@ helmChartInflationGenerator:
th.AssertActualEqualsExpected(m, expectedHelm)
}
func TestHelmChartNamespacePropagation(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
chartDir := filepath.Join(th.GetRoot(), "charts", "service")
require.NoError(t, th.GetFSys().MkdirAll(filepath.Join(chartDir, "templates")))
th.WriteF(filepath.Join(chartDir, "Chart.yaml"), `
apiVersion: v2
name: service
type: application
version: 1.0.0
`)
th.WriteF(filepath.Join(chartDir, "values.yaml"), ``)
th.WriteF(filepath.Join(chartDir, "templates", "service.yaml"), `
apiVersion: v1
kind: Service
metadata:
name: the-bug
namespace: {{ .Release.Namespace }}
annotations:
this-service-is-deployed-in-namespace: {{ .Release.Namespace }}
`)
th.WriteF(filepath.Join(th.GetRoot(), "values.yaml"), ``)
th.WriteK(th.GetRoot(), `
helmGlobals:
chartHome: ./charts
namespace: the-actual-namespace
helmCharts:
- name: service
releaseName: service
valuesFile: values.yaml
`)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
this-service-is-deployed-in-namespace: the-actual-namespace
name: the-bug
namespace: the-actual-namespace
`)
}
func TestHelmChartInflationGenerator(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
@@ -169,7 +242,7 @@ func TestHelmChartInflationGenerator(t *testing.T) {
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
version: 4.26.4
releaseName: test
`)
@@ -252,7 +325,7 @@ func TestHelmChartProdVsDev(t *testing.T) {
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
version: 4.26.4
releaseName: test
`)
th.WriteK(dirProd, `
@@ -287,10 +360,30 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
name: myProd-test-minecraft-rcon
namespace: prod
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft-curseforge
namespace: prod
type: Opaque
---
@@ -299,7 +392,10 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
@@ -325,10 +421,30 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myDev-test-minecraft
name: myDev-test-minecraft-rcon
namespace: dev
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myDev-test-minecraft-curseforge
namespace: dev
type: Opaque
---
@@ -337,7 +453,10 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myDev-test-minecraft
@@ -359,10 +478,30 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
name: myProd-test-minecraft-rcon
namespace: prod
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft-curseforge
namespace: prod
type: Opaque
---
@@ -371,7 +510,10 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
@@ -586,11 +728,11 @@ helmCharts:
skipTests: true
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
version: 4.26.4
releaseName: test-1
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.4
version: 4.26.4
releaseName: test-2
`)
@@ -621,10 +763,30 @@ kind: Secret
metadata:
labels:
app: test-1-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-1-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-1
name: test-1-minecraft
name: test-1-minecraft-rcon
namespace: default
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-1-minecraft
app.kubernetes.io/instance: test-1-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-1
name: test-1-minecraft-curseforge
namespace: default
type: Opaque
---
@@ -633,7 +795,10 @@ kind: Service
metadata:
labels:
app: test-1-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-1-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-1
name: test-1-minecraft
@@ -655,10 +820,30 @@ kind: Secret
metadata:
labels:
app: test-2-minecraft
chart: minecraft-3.1.4
app.kubernetes.io/instance: test-2-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-2
name: test-2-minecraft
name: test-2-minecraft-rcon
namespace: default
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-2-minecraft
app.kubernetes.io/instance: test-2-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-2
name: test-2-minecraft-curseforge
namespace: default
type: Opaque
---
@@ -667,7 +852,10 @@ kind: Service
metadata:
labels:
app: test-2-minecraft
chart: minecraft-3.1.4
app.kubernetes.io/instance: test-2-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-2
name: test-2-minecraft
@@ -698,7 +886,7 @@ namespace: default
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 4.11.0
version: 4.26.4
releaseName: test
kubeVersion: "1.16"
valuesInline:
@@ -724,8 +912,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-rcon
@@ -741,8 +929,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-curseforge
@@ -756,8 +944,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
@@ -779,8 +967,8 @@ metadata:
app: test-minecraft-map
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-map
@@ -794,7 +982,7 @@ namespace: default
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 4.11.0
version: 4.26.4
releaseName: test
kubeVersion: "1.27"
valuesInline:
@@ -820,8 +1008,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-rcon
@@ -837,8 +1025,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-curseforge
@@ -852,8 +1040,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
@@ -875,8 +1063,8 @@ metadata:
app: test-minecraft-map
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-map
@@ -886,6 +1074,229 @@ spec:
`)
}
func TestHelmChartNamespacePropagationViaResources(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
// Create base directory with helm chart
baseDir := th.MkDir("base")
chartDir := filepath.Join(baseDir, "charts", "service")
require.NoError(t, th.GetFSys().MkdirAll(filepath.Join(chartDir, "templates")))
th.WriteF(filepath.Join(chartDir, "Chart.yaml"), `
apiVersion: v2
name: service
type: application
version: 1.0.0
`)
th.WriteF(filepath.Join(chartDir, "values.yaml"), ``)
th.WriteF(filepath.Join(chartDir, "templates", "service.yaml"), `
apiVersion: v1
kind: Service
metadata:
name: test-service
namespace: {{ .Release.Namespace }}
annotations:
deployed-in-namespace: {{ .Release.Namespace }}
`)
// Base kustomization with helmCharts
th.WriteK(baseDir, `
helmGlobals:
chartHome: ./charts
helmCharts:
- name: service
releaseName: service
`)
// Overlay that references base via resources and sets namespace
overlayDir := th.MkDir("overlay")
th.WriteK(overlayDir, `
namespace: production
resources:
- ../base
`)
m := th.Run(overlayDir, th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
deployed-in-namespace: production
name: test-service
namespace: production
`)
}
func TestHelmChartDifferentNamespaces(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
chartDir := filepath.Join(th.GetRoot(), "charts", "service")
require.NoError(t, th.GetFSys().MkdirAll(filepath.Join(chartDir, "templates")))
th.WriteF(filepath.Join(chartDir, "Chart.yaml"), `
apiVersion: v2
name: service
type: application
version: 1.0.0
`)
th.WriteF(filepath.Join(chartDir, "values.yaml"), ``)
th.WriteF(filepath.Join(chartDir, "templates", "service.yaml"), `
apiVersion: v1
kind: Service
metadata:
name: test-service
namespace: {{ .Release.Namespace }}
annotations:
helm-namespace: {{ .Release.Namespace }}
`)
// Test with different namespaces in transformer vs helmCharts.namespace
th.WriteK(th.GetRoot(), `
helmGlobals:
chartHome: ./charts
namespace: transformer-ns
helmCharts:
- name: service
releaseName: service
namespace: helm-ns
`)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
// helmCharts.namespace should take precedence
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
helm-namespace: helm-ns
name: test-service
namespace: helm-ns
`)
}
func TestHelmChartSameNamespace(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
chartDir := filepath.Join(th.GetRoot(), "charts", "service")
require.NoError(t, th.GetFSys().MkdirAll(filepath.Join(chartDir, "templates")))
th.WriteF(filepath.Join(chartDir, "Chart.yaml"), `
apiVersion: v2
name: service
type: application
version: 1.0.0
`)
th.WriteF(filepath.Join(chartDir, "values.yaml"), ``)
th.WriteF(filepath.Join(chartDir, "templates", "service.yaml"), `
apiVersion: v1
kind: Service
metadata:
name: test-service
namespace: {{ .Release.Namespace }}
annotations:
deployed-namespace: {{ .Release.Namespace }}
`)
// Test with same namespace in both places
th.WriteK(th.GetRoot(), `
helmGlobals:
chartHome: ./charts
namespace: shared-namespace
helmCharts:
- name: service
releaseName: service
namespace: shared-namespace
`)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
deployed-namespace: shared-namespace
name: test-service
namespace: shared-namespace
`)
}
// Regression test: verify that HelmCharts in base kustomizations
// still receive namespace from overlay after fixing namespace propagation issues.
// This test ensures the fix for https://github.com/kubernetes-sigs/kustomize/issues/6031
// and https://github.com/kubernetes-sigs/kustomize/issues/6027
// does not break the HelmChart namespace propagation feature from
// https://github.com/kubernetes-sigs/kustomize/issues/5566
func TestHelmChartNamespacePropagationViaResourcesThreeLevels(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
// Create base directory with helm chart (Level 1)
baseDir := th.MkDir("base")
chartDir := filepath.Join(baseDir, "charts", "service")
require.NoError(t, th.GetFSys().MkdirAll(filepath.Join(chartDir, "templates")))
th.WriteF(filepath.Join(chartDir, "Chart.yaml"), `
apiVersion: v2
name: service
type: application
version: 1.0.0
`)
th.WriteF(filepath.Join(chartDir, "values.yaml"), ``)
th.WriteF(filepath.Join(chartDir, "templates", "service.yaml"), `
apiVersion: v1
kind: Service
metadata:
name: test-service
namespace: {{ .Release.Namespace }}
annotations:
helm-namespace: {{ .Release.Namespace }}
`)
// Base kustomization with helmCharts (no namespace)
th.WriteK(baseDir, `
helmGlobals:
chartHome: ./charts
helmCharts:
- name: service
releaseName: service
`)
// Mid-layer that references base via resources (no namespace) (Level 2)
midDir := th.MkDir("mid")
th.WriteK(midDir, `
namePrefix: mid-
resources:
- ../base
`)
// Top overlay that references mid-layer and sets namespace (Level 3)
overlayDir := th.MkDir("overlay")
th.WriteK(overlayDir, `
namespace: production
resources:
- ../mid
`)
m := th.Run(overlayDir, th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
helm-namespace: production
name: mid-test-service
namespace: production
`)
}
func copyValuesFilesTestChartsIntoHarness(t *testing.T, th *kusttest_test.HarnessEnhanced) {
t.Helper()

View File

@@ -419,6 +419,389 @@ spec:
`)
}
func TestKustomizationLabelsInStatefulSetTemplateWithClaimTemplateAndIncludeVolumeClaimTemplatesFalse(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/sts.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
th.WriteK("/app", `
resources:
- sts.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
includeVolumeClaimTemplates: false
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
}
func TestKustomizationLabelsInStatefulSetTemplateWithClaimTemplateIncludeTemplateFalseAndIncludeVolumeClaimTemplatesTrue(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/sts.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
th.WriteK("/app", `
resources:
- sts.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: false
includeVolumeClaimTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
labels:
foo: bar
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
}
func TestKustomizationLabelsInStatefulSetTemplateWithClaimTemplateAndIncludeVolumeClaimTemplatesTrue(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/sts.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
th.WriteK("/app", `
resources:
- sts.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
includeVolumeClaimTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
labels:
foo: bar
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
}
func TestKustomizationLabelsInStatefulSetTemplateWithIncludeSelectorsTrue(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/sts.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
th.WriteK("/app", `
resources:
- sts.yaml
labels:
- pairs:
foo: bar
includeSelectors: true
includeTemplates: false
includeVolumeClaimTemplates: false
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
foo: bar
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
volumeMounts:
- mountPath: /usr/src/app/data
name: usrdata
volumeClaimTemplates:
- metadata:
labels:
foo: bar
name: usrdata
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
`)
}
func TestKustomizationLabelsInDeploymentWithoutClaimTemplateAndIncludeVolumeClaimTemplatesTrue(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
labels:
app: test-server
spec:
replicas: 1
selector:
matchLabels:
app: test-server
template:
metadata:
labels:
app: test-server
spec:
containers:
- name: test-server
image: test-server
`)
th.WriteK("/app", `
resources:
- deployment.yaml
labels:
- pairs:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
includeSelectors: false
includeTemplates: false
includeVolumeClaimTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test-server
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
name: deployment
spec:
replicas: 1
selector:
matchLabels:
app: test-server
template:
metadata:
labels:
app: test-server
spec:
containers:
- image: test-server
name: test-server
`)
}
func TestKustomizationLabelsInCronJobTemplate(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/cjob.yaml", `

View File

@@ -4,6 +4,7 @@
package krusty_test
import (
"strings"
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
@@ -1282,6 +1283,72 @@ metadata:
}
}
func TestSinglePatchWithMultiplePatchDeleteDirectives(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFilesForMultiplePatchTests(th)
th.WriteF("overlay/staging/deployment-patch1.yaml", `
$patch: delete
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
---
$patch: delete
apiVersion: v1
kind: Service
metadata:
name: nginx
`)
th.WriteF("overlay/staging/deployment-patch2.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-in-base
data:
foo2: bar2
`)
th.WriteK("overlay/staging", `
namePrefix: staging-
commonLabels:
env: staging
patches:
- path: deployment-patch1.yaml
- path: deployment-patch2.yaml
resources:
- ../../base
configMapGenerator:
- name: configmap-in-overlay
literals:
- hello=world
`)
m := th.Run("overlay/staging", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
foo: bar
foo2: bar2
kind: ConfigMap
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
name: staging-team-foo-configmap-in-base-8cmgkm9f44
---
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
name: staging-configmap-in-overlay-dc6fm46dhm
`)
}
func TestMultiplePatchesBothWithPatchDeleteDirective(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFilesForMultiplePatchTests(th)
@@ -1700,3 +1767,108 @@ metadata:
name: fluentd-sa-abc
`)
}
// TestEmptyPatchFilesShouldBeIgnored verifies that empty patch files are ignored.
// Tests three cases:
// 1. Completely empty file
// 2. File with only comments
// 3. File with whitespace and comments
func TestEmptyPatchFilesShouldBeIgnored(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Write a basic resource
th.WriteF("deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
// Create empty patch files of different types
th.WriteF("empty.yaml", ``)
th.WriteF("comments-only.yaml", `
# This is a comment
# Another comment
`)
th.WriteF("whitespace.yaml", `
# Comments with whitespace
# Indented comment
`)
// Reference empty patches in kustomization
th.WriteK(".", `
resources:
- deployment.yaml
patches:
- path: empty.yaml
- path: comments-only.yaml
- path: whitespace.yaml
`)
// Empty patches should be ignored, output should be unchanged
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
// TestEmptyPatchesStrategicMergeFails verifies that empty patch files are
// handled correctly with the deprecated patchesStrategicMerge field
func TestEmptyPatchesStrategicMergeFails(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Create a basic resource
th.WriteF("resource.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: dummy
data:
dummy: value
`)
// Create an empty patch file
th.WriteF("empty-patch.yaml", ``)
// Create a patch file with only comments
th.WriteF("comments-patch.yaml", `
# This is just a comment
# Another comment
`)
// Create kustomization using patchesStrategicMerge
th.WriteK(".", `
resources:
- resource.yaml
patchesStrategicMerge:
- empty-patch.yaml
- comments-patch.yaml
`)
// This fails with message
err := th.RunWithErr(".", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error for empty patchesStrategicMerge files but got none")
}
if !strings.Contains(err.Error(), "patch appears to be empty") {
t.Fatalf("unexpected error: %v", err)
}
}

View File

@@ -786,3 +786,85 @@ spec:
name: tester
`)
}
func TestBackReferenceAdmissionPolicy(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- admission.yaml
namePrefix: a-prefix-
`)
th.WriteF("admission.yaml", `---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingAdmissionPolicy
metadata:
name: sample-policy
spec:
failurePolicy: Fail
paramKind:
apiVersion: apps/v1
kind: Deployment
matchConstraints:
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
validations:
- expression: "!object.metadata.name.startsWith('test-')"
message: prefix 'test-' is not allowed
reason: Invalid
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: sample-policy-binding
spec:
policyName: sample-policy
validationActions:
- Deny
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingAdmissionPolicy
metadata:
name: a-prefix-sample-policy
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
paramKind:
apiVersion: apps/v1
kind: Deployment
validations:
- expression: '!object.metadata.name.startsWith(''test-'')'
message: prefix 'test-' is not allowed
reason: Invalid
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: a-prefix-sample-policy-binding
spec:
policyName: a-prefix-sample-policy
validationActions:
- Deny
`)
}

View File

@@ -0,0 +1,343 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// Regression test for https://github.com/kubernetes-sigs/kustomize/issues/6031
// This test verifies that namespace propagation from overlay to base does not
// break strategic merge patches when combined with nameSuffix.
//
// The issue: In v5.8.0, namespace was propagated to child kustomization early,
// causing patches to fail because they couldn't find resources with the
// propagated namespace.
func TestNamespacePropagationDoesNotBreakPatchWithNameSuffix(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Base kustomization with nameSuffix
th.WriteK("base", `
resources:
- configmap.yaml
nameSuffix: -schedule_job_1
`)
th.WriteF("base/configmap.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: hoge
data:
configs.yaml: TO_BE_SPECIFIED
`)
// Overlay with namespace and patch
// The patch targets the original name (before nameSuffix is applied)
// This is the expected behavior per kustomize documentation
th.WriteK("overlay", `
resources:
- ../base
patches:
- path: schedule_job_1.yaml
namespace: hoge-dev
`)
th.WriteF("overlay/schedule_job_1.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: hoge-schedule_job_1
data:
configs.yaml: |
case_configs:
- id: 1
name: dummy1
client: client1
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
configs.yaml: |
case_configs:
- id: 1
name: dummy1
client: client1
kind: ConfigMap
metadata:
name: hoge-schedule_job_1
namespace: hoge-dev
`)
}
// Regression test for https://github.com/kubernetes-sigs/kustomize/issues/6027
// This test verifies that namespace propagation does not break
// configMapGenerator merge behavior when the generator is in a base
// and the namespace is set in an overlay.
//
// The issue: In v5.8.0, namespace was propagated to child kustomization early,
// causing generator merge to fail because resources in the base didn't have
// namespace yet, but the overlay's generator had namespace from propagation.
func TestNamespacePropagationDoesNotBreakGeneratorMerge(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Generator config resource
th.WriteK("cm-generator", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- resources/general.yaml
`)
th.WriteF("cm-generator/resources/general.yaml", `
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: general-environment
behavior: merge
envs:
- configuration/general
`)
th.WriteF("cm-generator/configuration/general", `
COMMON_ENV=common
`)
// Base kustomization with generator
th.WriteK("base", `
generators:
- ../cm-generator
configMapGenerator:
- name: general-environment
behavior: create
`)
th.WriteF("base/configuration/general", `
BASE_LAYER_ENV=base
`)
// Overlay with namespace and same generator reference
th.WriteK("overlay", `
namespace: abc
generators:
- ../cm-generator
resources:
- ../base
`)
th.WriteF("overlay/configuration/general", `
OVERLAY_ENV=overlay
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
BASE_LAYER_ENV: base
OVERLAY_ENV: overlay
kind: ConfigMap
metadata:
name: general-environment-826bch2dh9
namespace: abc
`)
}
// Test to verify namespace propagation still works correctly for
// simple overlay/base scenarios without patches or generators.
func TestNamespaceTransformerInOverlayAppliedToBase(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Base kustomization without namespace
th.WriteK("base", `
resources:
- deployment.yaml
`)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-image:latest
`)
// Overlay with namespace
th.WriteK("overlay", `
resources:
- ../base
namespace: production
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- image: my-image:latest
name: app
`)
}
// Test for three-level kustomization hierarchy with namespace in top overlay
// This verifies namespace transformer is applied correctly across multiple levels.
func TestNamespaceTransformerWithThreeLevelHierarchy(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Level 1: Base
th.WriteK("base", `
resources:
- configmap.yaml
`)
th.WriteF("base/configmap.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: base-config
data:
key: value
`)
// Level 2: Mid-layer (no namespace)
th.WriteK("mid", `
resources:
- ../base
namePrefix: mid-
`)
// Level 3: Overlay with namespace
th.WriteK("overlay", `
resources:
- ../mid
namespace: top-ns
namePrefix: top-
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
key: value
kind: ConfigMap
metadata:
name: top-mid-base-config
namespace: top-ns
`)
}
// Test that patches in overlay can target resources from base
// when base has nameSuffix and overlay has namespace.
// This is a more complex version of TestNamespacePropagationDoesNotBreakPatchWithNameSuffix
func TestPatchTargetingWithNameSuffixAndNamespace(t *testing.T) {
th := kusttest_test.MakeHarness(t)
// Base with nameSuffix
th.WriteK("base", `
resources:
- deployment.yaml
nameSuffix: -v2
`)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myimage:v1
`)
// Overlay with namespace and patch
th.WriteK("overlay", `
resources:
- ../base
namespace: production
patches:
- target:
kind: Deployment
name: myapp-v2
patch: |
- op: replace
path: /spec/replicas
value: 3
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- image: myimage:v1
name: app
`)
}

View File

@@ -692,7 +692,6 @@ resources:
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
}
//nolint:gosec
const namespaceNeedInVarMyAppWithNamespace string = `
resources:
- elasticsearch-dev-service.yaml

View File

@@ -0,0 +1,228 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// test for https://github.com/kubernetes-sigs/kustomize/issues/4240
func TestSuffix5042(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- resource.yaml
`)
th.WriteF("resource.yaml", `
apiVersion: example.com/v1alpha1
kind: MyResource
metadata:
name: service
---
apiVersion: example.com/v1alpha1
kind: MyResourceTwo
metadata:
name: test
rules: []
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: example.com/v1alpha1
kind: MyResource
metadata:
name: service
---
apiVersion: example.com/v1alpha1
kind: MyResourceTwo
metadata:
name: test
rules: []
`)
}
func TestListSuffix5042(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- resource.yaml
`)
th.WriteF("resource.yaml", `
apiVersion: example.com/v1alpha1
kind: MyResource
metadata:
name: service
---
apiVersion: example.com/v1alpha1
kind: MyResourceList
metadata:
name: test
rules: []
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: example.com/v1alpha1
kind: MyResource
metadata:
name: service
---
apiVersion: example.com/v1alpha1
kind: MyResourceList
metadata:
name: test
rules: []
`)
}
func TestListSuffix5485(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- resource.yaml
`)
th.WriteF("resource.yaml", `
apiVersion: infra.protonbase.io/v1alpha1
kind: AccessWhiteList
metadata:
name: wlmls5769f
namespace: dc7i4hyxzw
spec:
rules:
- sourceIps: 0.0.0.0/16
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: infra.protonbase.io/v1alpha1
kind: AccessWhiteList
metadata:
name: wlmls5769f
namespace: dc7i4hyxzw
spec:
rules:
- sourceIps: 0.0.0.0/16
`)
}
func TestListToIndividualResources(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- list.yaml
`)
th.WriteF("list.yaml", `
apiVersion: v1
kind: PodList
items:
- apiVersion: v1
kind: Pod
metadata:
name: my-pod-1
namespace: default
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:1.19.10
ports:
- containerPort: 80
- apiVersion: v1
kind: Pod
metadata:
name: my-pod-2
namespace: default
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:1.19.10
ports:
- containerPort: 80
- apiVersion: v1
kind: Pod
metadata:
name: my-pod-3
namespace: default
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:1.19.10
ports:
- containerPort: 80
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Pod
metadata:
labels:
app: my-app
name: my-pod-1
namespace: default
spec:
containers:
- image: nginx:1.19.10
name: my-container
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: my-app
name: my-pod-2
namespace: default
spec:
containers:
- image: nginx:1.19.10
name: my-container
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: my-app
name: my-pod-3
namespace: default
spec:
containers:
- image: nginx:1.19.10
name: my-container
ports:
- containerPort: 80
`)
}
// Empty list should result in no resources
func TestEmptyList(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- emptyList.yaml
`)
th.WriteF("emptyList.yaml", `
apiVersion: v1
kind: PodList
items: []
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, "")
}

View File

@@ -282,6 +282,8 @@ resources:
},
}
t.Setenv("LC_ALL", "C")
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if test.skip {

View File

@@ -614,3 +614,391 @@ metadata:
name: app-config-dev-97544dk6t8
`)
}
// regex selector: append in annotation by visitor name
func TestReplacementTransformerAppendToAnnotationUsingRegex(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("base/app1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: d1
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
`)
th.WriteF("base/app2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: d2
spec:
template:
spec:
containers:
- image: app2:1.0
name: app
`)
th.WriteF("base/cm1.yaml", `
apiVersion: apps/v1
kind: ConfigMap
metadata:
name: cm1
`)
th.WriteF("base/cm2.yaml", `
apiVersion: apps/v1
kind: ConfigMap
metadata:
name: cm2
`)
th.WriteF("base/pg1.yaml", `
apiVersion: apps/v1
kind: postgresql
metadata:
name: pg1
`)
th.WriteK("base", `
resources:
- app1.yaml
- app2.yaml
- cm1.yaml
- cm2.yaml
- pg1.yaml
replacements:
- source:
kind: ConfigMap
name: cm1
targets:
- reject:
- kind: ConfigMap
name: c.1
select:
kind: Deployment|ConfigMap|postgresql
fieldPaths:
- metadata.annotations.visitedby
options:
index: -1
delimiter: ","
create: true
- source:
kind: ConfigMap
name: cm2
targets:
- reject:
- kind: ConfigMap
name: .*2
select:
kind: Deployment|ConfigMap|postgresql
fieldPaths:
- metadata.annotations.visitedby
options:
index: -1
delimiter: ","
create: true
`)
m := th.Run("base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
visitedby: cm2,cm1,
name: d1
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
visitedby: cm2,cm1,
name: d2
spec:
template:
spec:
containers:
- image: app2:1.0
name: app
---
apiVersion: apps/v1
kind: ConfigMap
metadata:
annotations:
visitedby: cm2,
name: cm1
---
apiVersion: apps/v1
kind: ConfigMap
metadata:
annotations:
visitedby: cm1,
name: cm2
---
apiVersion: apps/v1
kind: postgresql
metadata:
annotations:
visitedby: cm2,cm1,
name: pg1
`)
}
// selector regex: construct service url
func TestReplacementTransformerServiceNamespaceUrlUsingRegex(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("base/d1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: d1
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
env:
- name: APP1_SERVICE
value: "d1.app1"
`)
th.WriteF("base/d2.yaml", `
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: d2
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
env:
- name: APP1_SERVICE
value: "d2.app1"
`)
th.WriteF("base/sts1.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts1
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
env:
- name: APP1_SERVICE
value: "app1"
`)
th.WriteF("base/cm1.yaml", `
apiVersion: apps/v1
kind: ConfigMap
metadata:
name: cm1
data:
APP1_SERVICE_PORT: "8080"
`)
th.WriteF("base/svc1.yaml", `
apiVersion: v1
kind: Service
metadata:
name: svc1
namespace: svc1-namespace
spec:
selector:
app.kubernetes.io/name: app1
ports:
- protocol: TCP
port: 80
targetPort: 9376
`)
th.WriteK("base", `
resources:
- d1.yaml
- d2.yaml
- sts1.yaml
- cm1.yaml
- svc1.yaml
replacements:
- source:
kind: Service
name: svc1
fieldPath: metadata.namespace
targets:
- select:
kind: Deployment|.*Set
fieldPaths:
- spec.template.spec.containers.*.env.[name=APP1_SERVICE].value
options:
index: 99
delimiter: "."
- source:
kind: ConfigMap
name: cm1
fieldPath: data.APP1_SERVICE_PORT
targets:
- select:
kind: Deployment|.*Set
fieldPaths:
- spec.template.spec.containers.*.env.[name=APP1_SERVICE].value
options:
index: 99
delimiter: ":"
`)
m := th.Run("base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: d1
spec:
template:
spec:
containers:
- env:
- name: APP1_SERVICE
value: d1.app1.svc1-namespace:8080
image: app1:1.0
name: app
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: d2
spec:
template:
spec:
containers:
- env:
- name: APP1_SERVICE
value: d2.app1.svc1-namespace:8080
image: app1:1.0
name: app
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts1
spec:
template:
spec:
containers:
- env:
- name: APP1_SERVICE
value: app1.svc1-namespace:8080
image: app1:1.0
name: app
---
apiVersion: apps/v1
data:
APP1_SERVICE_PORT: "8080"
kind: ConfigMap
metadata:
name: cm1
---
apiVersion: v1
kind: Service
metadata:
name: svc1
namespace: svc1-namespace
spec:
ports:
- port: 80
protocol: TCP
targetPort: 9376
selector:
app.kubernetes.io/name: app1
`)
}
func TestReplacementTransformerWithSuffixTransformerAndRejectUsingRegex(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("base/app.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: original-name
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
`)
th.WriteK("base", `
resources:
- app.yaml
`)
th.WriteK("overlay", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
nameSuffix: -dev
namePrefix: pre-
resources:
- ../base
configMapGenerator:
- name: app-config
literals:
- name=something-else
replacements:
- source:
kind: ConfigMap
name: app-config
fieldPath: data.name
targets:
- reject:
- name: .*original.*
select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.0.name
- select:
kind: ConfigMap
name: app-config
fieldPaths:
- data.name-copy
options:
create: true
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: pre-original-name-dev
spec:
template:
spec:
containers:
- image: app1:1.0
name: app
---
apiVersion: v1
data:
name: something-else
name-copy: something-else
kind: ConfigMap
metadata:
name: pre-app-config-dev-7266b7f2m9
`)
}

View File

@@ -19,12 +19,21 @@ var (
// During a release, this will be set to the release tag, e.g. "kustomize/v4.5.7"
version = developmentVersion
// build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
buildDate = "unknown"
buildDate = unknown
)
// This default value, (devel), matches
// the value debug.BuildInfo uses for an unset main module version.
const developmentVersion = "(devel)"
const (
// This default value, (devel), matches
// the value debug.BuildInfo uses for an unset main module version.
developmentVersion = "(devel)"
// ModulePath is kustomize module path, defined in kustomize/go.mod
ModulePath = "sigs.k8s.io/kustomize/kustomize/v5"
// This is default value, unknown, substituted when
// the value can't be determined from debug.BuildInfo.
unknown = "unknown"
)
// Provenance holds information about the build of an executable.
type Provenance struct {
@@ -47,7 +56,7 @@ func GetProvenance() Provenance {
p := Provenance{
BuildDate: buildDate,
Version: version,
GitCommit: "unknown",
GitCommit: unknown,
GoOs: runtime.GOOS,
GoArch: runtime.GOARCH,
GoVersion: runtime.Version(),
@@ -62,19 +71,40 @@ func GetProvenance() Provenance {
// We could consider adding other info such as the commit date in the future.
if setting.Key == "vcs.revision" {
p.GitCommit = setting.Value
break
}
}
for _, dep := range info.Deps {
if dep != nil && dep.Path == "sigs.k8s.io/kustomize/kustomize/v5" {
p.Version = GetMostRecentTag(*dep)
}
}
p.Version = FindVersion(info, p.Version)
return p
}
func GetMostRecentTag(m debug.Module) string {
// FindVersion searches for a version in the depth of dependencies including replacements,
// otherwise, it tries to get version from debug.BuildInfo Main.
func FindVersion(info *debug.BuildInfo, version string) string {
for _, dep := range info.Deps {
if dep != nil && dep.Path == ModulePath {
if dep.Version == developmentVersion {
continue
}
v, err := GetMostRecentTag(*dep)
if err != nil {
fmt.Printf("failed to get most recent tag for %s: %v\n", dep.Path, err)
continue
}
return v
}
}
if version == developmentVersion && info.Main.Version != "" {
return info.Main.Version
}
return version
}
func GetMostRecentTag(m debug.Module) (string, error) {
for m.Replace != nil {
m = *m.Replace
}
@@ -83,13 +113,13 @@ func GetMostRecentTag(m debug.Module) string {
sv, err := semver.Parse(strings.TrimPrefix(split[0], "v"))
if err != nil {
return "unknown"
return "", fmt.Errorf("failed to parse version %s: %w", m.Version, err)
}
if len(split) > 1 && sv.Patch > 0 {
sv.Patch -= 1
}
return fmt.Sprintf("v%s", sv.FinalizeVersion())
return fmt.Sprintf("v%s", sv.FinalizeVersion()), nil
}
// Short returns the shortened provenance stamp.

View File

@@ -49,16 +49,65 @@ func TestProvenance_Semver(t *testing.T) {
func mockModule(version string) debug.Module {
return debug.Module{
Path: "sigs.k8s.io/kustomize/kustomize/v5",
Path: provenance.ModulePath,
Version: version,
Replace: nil,
}
}
func mockBuildInfo(mainVersion, depsVersion string) *debug.BuildInfo {
module := mockModule(depsVersion)
return &debug.BuildInfo{
Main: debug.Module{
Version: mainVersion,
},
Deps: []*debug.Module{
&module,
},
}
}
func TestFindVersion(t *testing.T) {
tests := []struct {
name string
version string
buildInfo *debug.BuildInfo
expectedVersion string
}{
{
name: "The version from LD_FLAGS is not overridden by main and dependencies versions",
version: "v2.3.4",
buildInfo: mockBuildInfo("v1.2.3", "(devel)"),
expectedVersion: "v2.3.4",
},
{
name: "The version from LD_FLAGS is overridden by the main version",
version: "(devel)",
buildInfo: mockBuildInfo("v1.2.3", "(devel)"),
expectedVersion: "v1.2.3",
},
{
name: "The version from LD_FLAGS is overridden by the version from dependencies",
version: "(devel)",
buildInfo: mockBuildInfo("v1.2.3", "v1.2.3-0.20210101010101-abcdefabcdef"),
expectedVersion: "v1.2.2",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
version := provenance.FindVersion(tt.buildInfo, tt.version)
assert.Equal(t, tt.expectedVersion, version)
})
}
}
func TestGetMostRecentTag(t *testing.T) {
tests := []struct {
name string
module debug.Module
isError bool
expectedTag string
}{
{
@@ -72,9 +121,9 @@ func TestGetMostRecentTag(t *testing.T) {
expectedTag: "v0.0.0",
},
{
name: "Invalid semver string",
module: mockModule("invalid-version"),
expectedTag: "unknown",
name: "Invalid semver string",
module: mockModule("invalid-version"),
isError: true,
},
{
name: "Valid semver with patch increment and pre-release info",
@@ -90,8 +139,14 @@ func TestGetMostRecentTag(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tag := provenance.GetMostRecentTag(tt.module)
assert.Equal(t, tt.expectedTag, tag)
tag, err := provenance.GetMostRecentTag(tt.module)
if err != nil {
if !tt.isError {
assert.NoError(t, err)
}
} else {
assert.Equal(t, tt.expectedTag, tag)
}
})
}
}

View File

@@ -181,6 +181,10 @@ func (m *resWrangler) GetMatchingResourcesByAnyId(
matches IdMatcher) []*resource.Resource {
var result []*resource.Resource
for _, r := range m.rList {
if r.RNode.IsNilOrEmpty() {
continue
}
for _, id := range append(r.PrevIds(), r.CurId()) {
if matches(id) {
result = append(result, r)
@@ -593,7 +597,7 @@ func (m *resWrangler) appendReplaceOrMerge(res *resource.Resource) error {
default:
return fmt.Errorf(
"id %#v exists; behavior must be merge or replace", id)
"id %#v exists; can not use behavior: '%s', behavior must be merge or replace", id, res.Behavior())
}
i, err := m.Replace(res)
if err != nil {

View File

@@ -73,7 +73,7 @@ func doRemove(t *testing.T, w ResMap, id resid.ResId) {
// Make a resource with a predictable name.
func makeCm(i int) *resource.Resource {
return rf.FromMap(
r, err := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -81,6 +81,10 @@ func makeCm(i int) *resource.Resource {
"name": fmt.Sprintf("cm%03d", i),
},
})
if err != nil {
panic(err)
}
return r
}
// Maintain the class invariant that no two
@@ -229,7 +233,7 @@ metadata:
func TestGetMatchingResourcesByCurrentId(t *testing.T) {
cmap := resid.NewGvk("", "v1", "ConfigMap")
r1 := rf.FromMap(
r1, err1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -237,7 +241,10 @@ func TestGetMatchingResourcesByCurrentId(t *testing.T) {
"name": "alice",
},
})
r2 := rf.FromMap(
if err1 != nil {
t.Fatalf("failed to get new instance: %v", err1)
}
r2, err2 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -245,7 +252,10 @@ func TestGetMatchingResourcesByCurrentId(t *testing.T) {
"name": "bob",
},
})
r3 := rf.FromMap(
if err2 != nil {
t.Fatalf("failed to get new instance: %v", err2)
}
r3, err3 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -254,7 +264,10 @@ func TestGetMatchingResourcesByCurrentId(t *testing.T) {
"namespace": "happy",
},
})
r4 := rf.FromMap(
if err3 != nil {
t.Fatalf("failed to get new instance: %v", err3)
}
r4, err4 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -263,7 +276,10 @@ func TestGetMatchingResourcesByCurrentId(t *testing.T) {
"namespace": "happy",
},
})
r5 := rf.FromMap(
if err4 != nil {
t.Fatalf("failed to get new instance: %v", err4)
}
r5, err5 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Deployment",
@@ -272,6 +288,9 @@ func TestGetMatchingResourcesByCurrentId(t *testing.T) {
"namespace": "happy",
},
})
if err5 != nil {
t.Fatalf("failed to get new instance: %v", err5)
}
m := resmaptest_test.NewRmBuilder(t, rf).
AddR(r1).AddR(r2).AddR(r3).AddR(r4).AddR(r5).ResMap()
@@ -367,7 +386,7 @@ func TestGetMatchingResourcesByCurrentId(t *testing.T) {
}
func TestGetMatchingResourcesByAnyId(t *testing.T) {
r1 := rf.FromMap(
r1, err1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -380,7 +399,10 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
},
},
})
r2 := rf.FromMap(
if err1 != nil {
t.Fatalf("failed to get new instance: %v", err1)
}
r2, err2 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -393,7 +415,10 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
},
},
})
r3 := rf.FromMap(
if err2 != nil {
t.Fatalf("failed to get new instance: %v", err2)
}
r3, err3 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -407,7 +432,10 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
},
},
})
r4 := rf.FromMap(
if err3 != nil {
t.Fatalf("failed to get new instance: %v", err3)
}
r4, err4 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -421,7 +449,10 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
},
},
})
r5 := rf.FromMap(
if err4 != nil {
t.Fatalf("failed to get new instance: %v", err4)
}
r5, err5 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Deployment",
@@ -430,6 +461,9 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
"namespace": "happy",
},
})
if err5 != nil {
t.Fatalf("failed to get new instance: %v", err5)
}
m := resmaptest_test.NewRmBuilder(t, rf).
AddR(r1).AddR(r2).AddR(r3).AddR(r4).AddR(r5).ResMap()
@@ -498,7 +532,7 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
}
func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
r1 := rf.FromMap(
r1, err1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -506,7 +540,10 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"name": "alice",
},
})
r2 := rf.FromMap(
if err1 != nil {
t.Fatalf("failed to get new instance: %v", err1)
}
r2, err2 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -514,7 +551,10 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"name": "bob",
},
})
r3 := rf.FromMap(
if err2 != nil {
t.Fatalf("failed to get new instance: %v", err2)
}
r3, err3 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -523,7 +563,10 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"namespace": "happy",
},
})
r4 := rf.FromMap(
if err3 != nil {
t.Fatalf("failed to get new instance: %v", err3)
}
r4, err4 := rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
@@ -532,7 +575,10 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"namespace": "happy",
},
})
r5 := rf.FromMap(
if err4 != nil {
t.Fatalf("failed to get new instance: %v", err4)
}
r5, err5 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -541,8 +587,11 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"namespace": "happy",
},
})
if err5 != nil {
t.Fatalf("failed to get new instance: %v", err5)
}
r5.AddNamePrefix("little-")
r6 := rf.FromMap(
r6, err6 := rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
@@ -551,8 +600,11 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"namespace": "happy",
},
})
if err6 != nil {
t.Fatalf("failed to get new instance: %v", err6)
}
r6.AddNamePrefix("little-")
r7 := rf.FromMap(
r7, err7 := rf.FromMap(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleBinding",
@@ -560,6 +612,9 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
"name": "meh",
},
})
if err7 != nil {
t.Fatalf("failed to get new instance: %v", err7)
}
tests := map[string]struct {
filter *resource.Resource
@@ -639,7 +694,7 @@ func TestDeepCopy(t *testing.T) {
}
func TestErrorIfNotEqualSets(t *testing.T) {
r1 := rf.FromMap(
r1, err1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -647,7 +702,10 @@ func TestErrorIfNotEqualSets(t *testing.T) {
"name": "cm1",
},
})
r2 := rf.FromMap(
if err1 != nil {
t.Fatalf("failed to get new instance: %v", err1)
}
r2, err2 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -655,7 +713,10 @@ func TestErrorIfNotEqualSets(t *testing.T) {
"name": "cm2",
},
})
r3 := rf.FromMap(
if err2 != nil {
t.Fatalf("failed to get new instance: %v", err2)
}
r3, err3 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -664,6 +725,9 @@ func TestErrorIfNotEqualSets(t *testing.T) {
"namespace": "system",
},
})
if err3 != nil {
t.Fatalf("failed to get new instance: %v", err3)
}
m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).AddR(r2).AddR(r3).ResMap()
if err := m1.ErrorIfNotEqualSets(m1); err != nil {
@@ -712,7 +776,7 @@ func TestErrorIfNotEqualSets(t *testing.T) {
}
func TestErrorIfNotEqualLists(t *testing.T) {
r1 := rf.FromMap(
r1, err1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -720,7 +784,10 @@ func TestErrorIfNotEqualLists(t *testing.T) {
"name": "cm1",
},
})
r2 := rf.FromMap(
if err1 != nil {
t.Fatalf("failed to get new instance: %v", err1)
}
r2, err2 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -728,7 +795,10 @@ func TestErrorIfNotEqualLists(t *testing.T) {
"name": "cm2",
},
})
r3 := rf.FromMap(
if err2 != nil {
t.Fatalf("failed to get new instance: %v", err2)
}
r3, err3 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -737,6 +807,9 @@ func TestErrorIfNotEqualLists(t *testing.T) {
"namespace": "system",
},
})
if err3 != nil {
t.Fatalf("failed to get new instance: %v", err3)
}
m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).AddR(r2).AddR(r3).ResMap()
if err := m1.ErrorIfNotEqualLists(m1); err != nil {
@@ -780,7 +853,7 @@ func TestErrorIfNotEqualLists(t *testing.T) {
}
func TestAppendAll(t *testing.T) {
r1 := rf.FromMap(
r1, err1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
@@ -788,8 +861,11 @@ func TestAppendAll(t *testing.T) {
"name": "foo-deploy1",
},
})
if err1 != nil {
t.Fatalf("failed to get new instance: %v", err1)
}
input1 := rmF.FromResource(r1)
r2 := rf.FromMap(
r2, err2 := rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "StatefulSet",
@@ -797,6 +873,9 @@ func TestAppendAll(t *testing.T) {
"name": "bar-stateful",
},
})
if err2 != nil {
t.Fatalf("failed to get new instance: %v", err2)
}
input2 := rmF.FromResource(r2)
expected := New()

View File

@@ -41,28 +41,26 @@ func (rf *Factory) Hasher() ifc.KustHasher {
}
// FromMap returns a new instance of Resource.
func (rf *Factory) FromMap(m map[string]interface{}) *Resource {
func (rf *Factory) FromMap(m map[string]interface{}) (*Resource, error) {
res, err := rf.FromMapAndOption(m, nil)
if err != nil {
// TODO: return err instead of log.
log.Fatalf("failed to create resource from map: %v", err)
return nil, fmt.Errorf("failed to create resource from map: %w", err)
}
return res
return res, nil
}
// FromMapWithName returns a new instance with the given "original" name.
func (rf *Factory) FromMapWithName(n string, m map[string]interface{}) *Resource {
func (rf *Factory) FromMapWithName(n string, m map[string]interface{}) (*Resource, error) {
return rf.FromMapWithNamespaceAndName(resid.DefaultNamespace, n, m)
}
// FromMapWithNamespaceAndName returns a new instance with the given "original" namespace.
func (rf *Factory) FromMapWithNamespaceAndName(ns string, n string, m map[string]interface{}) *Resource {
func (rf *Factory) FromMapWithNamespaceAndName(ns string, n string, m map[string]interface{}) (*Resource, error) {
r, err := rf.FromMapAndOption(m, nil)
if err != nil {
// TODO: return err instead of log.
log.Fatalf("failed to create resource from map: %v", err)
return nil, fmt.Errorf("failed to create resource from map: %w", err)
}
return r.setPreviousId(ns, n, r.GetKind())
return r.setPreviousId(ns, n, r.GetKind()), nil
}
// FromMapAndOption returns a new instance of Resource with given options.
@@ -204,7 +202,10 @@ func (rf *Factory) inlineAnyEmbeddedLists(
}
items, ok := m["items"]
if !ok {
// treat as an empty list
// Items field is not present.
// This is not a collections resource.
// read more https://kubernetes.io/docs/reference/using-api/api-concepts/#collections
result = append(result, n0)
continue
}
slice, ok := items.([]interface{})

View File

@@ -274,24 +274,43 @@ kind: List
},
},
}
testDeploymentA := factory.FromMap(
deploymentA := "deployment-a"
testDeploymentA, errA := factory.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deployment-a",
"name": deploymentA,
},
"spec": testDeploymentSpec,
})
testDeploymentB := factory.FromMap(
if errA != nil {
t.Fatalf("failed to create new instance with %v: %v", deploymentA, errA)
}
deploymentB := "deployment-b"
testDeploymentB, errB := factory.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deployment-b",
"name": deploymentB,
},
"spec": testDeploymentSpec,
})
if errB != nil {
t.Fatalf("failed to create new instance with %v: %v", deploymentB, errB)
}
deploymentNoItems := "deployment-no-items"
testDeploymentNoItems, errNoItems := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "List",
},
)
if errNoItems != nil {
t.Fatalf("failed to create new instance with %v: %v", deploymentNoItems, testDeploymentNoItems)
}
fSys := filesys.MakeFsInMemory()
fSys.WriteFile(string(patchGood1), []byte(patch1))
@@ -308,6 +327,16 @@ kind: List
t.Fatal(err)
}
td, err := createTestDeployment()
if err != nil {
t.Fatalf("failed to create test deployment: %v", err)
}
tc, err := createTestConfigMap()
if err != nil {
t.Fatalf("failed to create test config: %v", err)
}
tests := map[string]struct {
input []types.PatchStrategicMerge
expectedOut []*Resource
@@ -315,7 +344,7 @@ kind: List
}{
"happy": {
input: []types.PatchStrategicMerge{patchGood1, patchGood2},
expectedOut: []*Resource{testDeployment, testConfigMap},
expectedOut: []*Resource{td, tc},
expectedErr: false,
},
"badFileName": {
@@ -330,7 +359,7 @@ kind: List
},
"listOfPatches": {
input: []types.PatchStrategicMerge{patchList},
expectedOut: []*Resource{testDeployment, testConfigMap},
expectedOut: []*Resource{td, tc},
expectedErr: false,
},
"listWithAnchorReference": {
@@ -345,7 +374,7 @@ kind: List
},
"listWithNoItems": {
input: []types.PatchStrategicMerge{patchList4},
expectedOut: []*Resource{},
expectedOut: []*Resource{testDeploymentNoItems},
expectedErr: false,
},
}

View File

@@ -12,21 +12,45 @@ import (
func TestIdSet_Empty(t *testing.T) {
s := MakeIdSet([]*Resource{})
td, err := createTestDeployment()
if err != nil {
t.Fatalf("Failed to create test deployment: %v", err)
}
tc, err := createTestConfigMap()
if err != nil {
t.Fatalf("Failed to create test config: %v", err)
}
assert.Equal(t, 0, s.Size())
assert.False(t, s.Contains(testDeployment.CurId()))
assert.False(t, s.Contains(testConfigMap.CurId()))
assert.False(t, s.Contains(td.CurId()))
assert.False(t, s.Contains(tc.CurId()))
}
func TestIdSet_One(t *testing.T) {
s := MakeIdSet([]*Resource{testDeployment})
td, err := createTestDeployment()
if err != nil {
t.Fatalf("failed to create test deployment: %v", err)
}
tc, err := createTestConfigMap()
if err != nil {
t.Fatalf("failed to create test config: %v", err)
}
s := MakeIdSet([]*Resource{td})
assert.Equal(t, 1, s.Size())
assert.True(t, s.Contains(testDeployment.CurId()))
assert.False(t, s.Contains(testConfigMap.CurId()))
assert.True(t, s.Contains(td.CurId()))
assert.False(t, s.Contains(tc.CurId()))
}
func TestIdSet_Two(t *testing.T) {
s := MakeIdSet([]*Resource{testDeployment, testConfigMap})
td, err := createTestDeployment()
if err != nil {
t.Fatalf("failed to create test Deployment: %v", err)
}
tc, err := createTestConfigMap()
if err != nil {
t.Fatalf("failed to create test Config: %v", err)
}
s := MakeIdSet([]*Resource{td, tc})
assert.Equal(t, 2, s.Size())
assert.True(t, s.Contains(testDeployment.CurId()))
assert.True(t, s.Contains(testConfigMap.CurId()))
assert.True(t, s.Contains(td.CurId()))
assert.True(t, s.Contains(tc.CurId()))
}

View File

@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
@@ -47,6 +48,8 @@ var BuildAnnotations = []string{
kioutil.LegacyPathAnnotation,
kioutil.LegacyIndexAnnotation,
kioutil.LegacyIdAnnotation,
konfig.HelmGeneratedAnnotation,
}
func (r *Resource) ResetRNode(incoming *Resource) {

View File

@@ -20,27 +20,38 @@ import (
var factory = provider.NewDefaultDepProvider().GetResourceFactory()
var testConfigMap = factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
"namespace": "hundred-acre-wood",
},
})
func createTestConfigMap() (*Resource, error) {
res, err := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
"namespace": "hundred-acre-wood",
},
})
if err != nil {
return nil, fmt.Errorf("failed to create test config: %w", err)
}
return res, nil
}
//nolint:gosec
const configMapAsString = `{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie","namespace":"hundred-acre-wood"}}`
var testDeployment = factory.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "pooh",
},
})
func createTestDeployment() (*Resource, error) {
res, err := factory.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "pooh",
},
})
if err != nil {
return nil, fmt.Errorf("failed to create Deployment: %w", err)
}
return res, nil
}
const deploymentAsString = `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"pooh"}}`
@@ -50,9 +61,13 @@ kind: Deployment
metadata:
name: pooh
`
yaml, err := testDeployment.AsYAML()
td, err := createTestDeployment()
if err != nil {
t.Fatal(err)
t.Fatalf("failed to create test deployment: %s", err)
}
yaml, err := td.AsYAML()
if err != nil {
t.Fatalf("failed to get yaml: %s", err)
}
if string(yaml) != expected {
t.Fatalf("--- expected\n%s\n--- got\n%s\n", expected, string(yaml))
@@ -60,16 +75,24 @@ metadata:
}
func TestResourceString(t *testing.T) {
td, err := createTestDeployment()
if err != nil {
t.Fatalf("failed to create test deployment: %v", err)
}
tc, err := createTestConfigMap()
if err != nil {
t.Fatalf("failed to create test config: %v", err)
}
tests := []struct {
in *Resource
s string
}{
{
in: testConfigMap,
in: tc,
s: configMapAsString,
},
{
in: testDeployment,
in: td,
s: deploymentAsString,
},
}
@@ -79,18 +102,26 @@ func TestResourceString(t *testing.T) {
}
func TestResourceId(t *testing.T) {
td, err := createTestDeployment()
if err != nil {
t.Fatalf("failed to create test deployment: %v", err)
}
tc, err := createTestConfigMap()
if err != nil {
t.Fatalf("failed to create test config: %v", err)
}
tests := []struct {
in *Resource
id resid.ResId
}{
{
in: testConfigMap,
in: tc,
id: resid.NewResIdWithNamespace(
resid.NewGvk("", "v1", "ConfigMap"),
"winnie", "hundred-acre-wood"),
},
{
in: testDeployment,
in: td,
id: resid.NewResId(
resid.NewGvk("apps", "v1", "Deployment"), "pooh"),
},
@@ -103,7 +134,7 @@ func TestResourceId(t *testing.T) {
}
func TestDeepCopy(t *testing.T) {
r := factory.FromMap(
r, err := factory.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
@@ -111,6 +142,9 @@ func TestDeepCopy(t *testing.T) {
"name": "pooh",
},
})
if err != nil {
t.Fatalf("failed to create test config: %v", err)
}
r.AppendRefBy(resid.NewResId(resid.Gvk{Group: "somegroup", Kind: "MyKind"}, "random"))
var1 := types.Var{

View File

@@ -41,7 +41,11 @@ func NewSeededRmBuilderDefault(t *testing.T, m resmap.ResMap) *rmBuilder {
}
func (rm *rmBuilder) Add(m map[string]interface{}) *rmBuilder {
return rm.AddR(rm.rf.FromMap(m))
r, err := rm.rf.FromMap(m)
if err != nil {
rm.t.Fatalf("test setup failure: %v", err)
}
return rm.AddR(r)
}
func (rm *rmBuilder) AddR(r *resource.Resource) *rmBuilder {
@@ -53,7 +57,11 @@ func (rm *rmBuilder) AddR(r *resource.Resource) *rmBuilder {
}
func (rm *rmBuilder) AddWithName(n string, m map[string]interface{}) *rmBuilder {
err := rm.m.Append(rm.rf.FromMapWithNamespaceAndName(resid.DefaultNamespace, n, m))
r, err := rm.rf.FromMapWithNamespaceAndName(resid.DefaultNamespace, n, m)
if err != nil {
rm.t.Fatalf("test setup failure: %v", err)
}
err = rm.m.Append(r)
if err != nil {
rm.t.Fatalf("test setup failure: %v", err)
}
@@ -61,7 +69,11 @@ func (rm *rmBuilder) AddWithName(n string, m map[string]interface{}) *rmBuilder
}
func (rm *rmBuilder) AddWithNsAndName(ns string, n string, m map[string]interface{}) *rmBuilder {
err := rm.m.Append(rm.rf.FromMapWithNamespaceAndName(ns, n, m))
r, err := rm.rf.FromMapWithNamespaceAndName(ns, n, m)
if err != nil {
rm.t.Fatalf("test setup failure: %v", err)
}
err = rm.m.Append(r)
if err != nil {
rm.t.Fatalf("test setup failure: %v", err)
}
@@ -69,7 +81,7 @@ func (rm *rmBuilder) AddWithNsAndName(ns string, n string, m map[string]interfac
}
func (rm *rmBuilder) ReplaceResource(m map[string]interface{}) *rmBuilder {
r := rm.rf.FromMap(m)
r, _ := rm.rf.FromMap(m)
_, err := rm.m.Replace(r)
if err != nil {
rm.t.Fatalf("test setup failure: %v", err)

View File

@@ -96,6 +96,12 @@ type HelmChart struct {
// SkipTests skips tests from templated output.
SkipTests bool `json:"skipTests,omitempty" yaml:"skipTests,omitempty"`
// debug enables debug output from the Helm chart inflator generator.
Debug bool `json:"debug,omitempty" yaml:"debug,omitempty"`
// allow for devel release to be used.
Devel bool `json:"devel,omitempty" yaml:"devel,omitempty"`
}
// HelmChartArgs contains arguments to helm.
@@ -188,5 +194,11 @@ func (h HelmChart) AsHelmArgs(absChartHome string) []string {
if h.SkipHooks {
args = append(args, "--no-hooks")
}
if h.Debug {
args = append(args, "--debug")
}
if h.Devel {
args = append(args, "--devel")
}
return args
}

View File

@@ -60,4 +60,45 @@ func TestAsHelmArgs(t *testing.T) {
"-f", "values1", "-f", "values2",
"--api-versions", "foo", "--api-versions", "bar"})
})
t.Run("use helm-debug", func(t *testing.T) {
p := types.HelmChart{
Name: "chart-name",
Version: "1.0.0",
Repo: "https://helm.releases.hashicorp.com",
ValuesFile: "values",
AdditionalValuesFiles: []string{"values1", "values2"},
Debug: true,
}
require.Equal(t, p.AsHelmArgs("/home/charts"),
[]string{"template", "--generate-name", "/home/charts/chart-name",
"-f", "values",
"-f", "values1",
"-f", "values2",
"--debug"})
})
t.Run("use helm-devel", func(t *testing.T) {
// We first test that the devel flag is only appended when specified
p := types.HelmChart{
Name: "chart-name",
Version: "1.0.0",
Repo: "https://helm.releases.hashicorp.com",
ValuesFile: "values",
AdditionalValuesFiles: []string{"values1", "values2"},
}
require.Equal(t, p.AsHelmArgs("/home/charts"),
[]string{"template", "--generate-name", "/home/charts/chart-name",
"-f", "values",
"-f", "values1",
"-f", "values2"})
p.Devel = true
require.Equal(t, p.AsHelmArgs("/home/charts"),
[]string{"template", "--generate-name", "/home/charts/chart-name",
"-f", "values",
"-f", "values1",
"-f", "values2",
"--devel"})
})
}

View File

@@ -22,6 +22,7 @@ const (
MetadataNamespacePath = "metadata/namespace"
MetadataNamespaceApiVersion = "v1"
MetadataNamePath = "metadata/name"
NamespaceKind = "Namespace"
OriginAnnotations = "originAnnotations"
TransformerAnnotations = "transformerAnnotations"
@@ -55,6 +56,7 @@ type Kustomization struct {
// Namespace to add to all objects.
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
// Deprecated: Use the Labels field instead, which provides a superset of the functionality of CommonLabels.
// CommonLabels to add to all objects and selectors.
CommonLabels map[string]string `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`

View File

@@ -6,17 +6,22 @@ package types
type Label struct {
// Pairs contains the key-value pairs for labels to add
Pairs map[string]string `json:"pairs,omitempty" yaml:"pairs,omitempty"`
// IncludeSelectors inidicates should transformer include the
// IncludeSelectors indicates whether the transformer should include the
// fieldSpecs for selectors. Custom fieldSpecs specified by
// FieldSpecs will be merged with builtin fieldSpecs if this
// is true.
IncludeSelectors bool `json:"includeSelectors,omitempty" yaml:"includeSelectors,omitempty"`
// IncludeTemplates inidicates should transformer include the
// IncludeTemplates indicates whether the transformer should include the
// spec/template/metadata fieldSpec. Custom fieldSpecs specified by
// FieldSpecs will be merged with spec/template/metadata fieldSpec if this
// is true. If IncludeSelectors is true, IncludeTemplates is not needed.
IncludeTemplates bool `json:"includeTemplates,omitempty" yaml:"includeTemplates,omitempty"`
FieldSpecs []FieldSpec `json:"fields,omitempty" yaml:"fields,omitempty"`
IncludeTemplates bool `json:"includeTemplates,omitempty" yaml:"includeTemplates,omitempty"`
// IncludeVolumeClaimTemplates indicates whether the transformer should include the
// spec/volumeClaimTemplates[]/metadata fieldSpec. Custom fieldSpecs specified by
// FieldSpecs will be merged with spec/volumeClaimTemplates[]/metadata fieldSpec if this
// is true. If IncludeSelectors is true, IncludeVolumeClaimTemplates is not needed.
IncludeVolumeClaimTemplates bool `json:"includeVolumeClaimTemplates,omitempty" yaml:"includeVolumeClaimTemplates,omitempty"`
FieldSpecs []FieldSpec `json:"fields,omitempty" yaml:"fields,omitempty"`
}
func labelFromCommonLabels(commonLabels map[string]string) *Label {

View File

@@ -3,8 +3,6 @@
package types
import "reflect"
// Patch represent either a Strategic Merge Patch or a JSON patch
// and its targets.
// The content of the patch can either be from a file
@@ -20,15 +18,17 @@ type Patch struct {
Target *Selector `json:"target,omitempty" yaml:"target,omitempty"`
// Options is a list of options for the patch
Options map[string]bool `json:"options,omitempty" yaml:"options,omitempty"`
Options *PatchArgs `json:"options,omitempty" yaml:"options,omitempty"`
}
// Equals return true if p equals o.
func (p *Patch) Equals(o Patch) bool {
targetEqual := (p.Target == o.Target) ||
(p.Target != nil && o.Target != nil && *p.Target == *o.Target)
optionsEqual := (p.Options == o.Options) ||
(p.Options != nil && o.Options != nil && *p.Options == *o.Options)
return p.Path == o.Path &&
p.Patch == o.Patch &&
targetEqual &&
reflect.DeepEqual(p.Options, o.Options)
optionsEqual
}

View File

@@ -101,6 +101,28 @@ func TestPatchEquals(t *testing.T) {
},
expect: true,
},
{
name: "same options",
patch1: Patch{
Path: "foo",
Patch: "bar",
Target: &selector,
Options: &PatchArgs{
AllowNameChange: true,
AllowKindChange: true,
},
},
patch2: Patch{
Path: "foo",
Patch: "bar",
Target: &selector,
Options: &PatchArgs{
AllowNameChange: true,
AllowKindChange: true,
},
},
expect: true,
},
{
name: "one nil target",
patch1: Patch{
@@ -124,6 +146,28 @@ func TestPatchEquals(t *testing.T) {
},
expect: false,
},
{
name: "different options",
patch1: Patch{
Path: "foo",
Patch: "bar",
Target: &selector,
Options: &PatchArgs{
AllowNameChange: false,
AllowKindChange: true,
},
},
patch2: Patch{
Path: "foo",
Patch: "bar",
Target: &selector,
Options: &PatchArgs{
AllowNameChange: true,
AllowKindChange: true,
},
},
expect: false,
},
}
for _, tc := range testcases {

13
api/types/patchargs.go Normal file
View File

@@ -0,0 +1,13 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package types
// PatchArgs represent set of options on resources of a patch.
type PatchArgs struct {
// AllowNameChange allows name changes to the resource.
AllowNameChange bool `json:"allowNameChange,omitempty" yaml:"allowNameChange,omitempty"`
// AllowKindChange allows kind changes to the resource.
AllowKindChange bool `json:"allowKindChange,omitempty" yaml:"allowKindChange,omitempty"`
}

View File

@@ -8,6 +8,7 @@ type HelmConfig struct {
Command string
ApiVersions []string
KubeVersion string
Debug bool
}
// PluginConfig holds plugin configuration.
@@ -27,7 +28,6 @@ type PluginConfig struct {
func EnabledPluginConfig(b BuiltinPluginLoadingOptions) (pc *PluginConfig) {
pc = MakePluginConfig(PluginRestrictionsNone, b)
pc.FnpLoadingOptions.EnableStar = true
pc.HelmConfig.Enabled = true
// If this command is not on PATH, tests needing it should skip.
pc.HelmConfig.Command = "helmV3"

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