Compare commits

...

156 Commits

Author SHA1 Message Date
Jeff Regan
07cada36fa Merge pull request #3406 from monopole/pinToCmdConfig_v0.8.7
Pin to cmd/confg v0.8.7
2020-12-29 07:11:12 -08:00
jregan
0d6b232b49 Pin to cmd/confg v0.8.7 2020-12-29 06:55:07 -08:00
Jeff Regan
61455fe489 Merge pull request #3404 from monopole/pinKyamlv0.10.5
Pin to kyaml v0.10.5
2020-12-28 20:50:59 -08:00
jregan
c63ed033ad Pin to kyaml v0.10.5
ALLOW_MODULE_SPAN
2020-12-28 20:30:22 -08:00
Jeff Regan
455bd0c563 Merge pull request #3403 from monopole/betterPin
Unpin versioned and unversioned pins.
2020-12-28 18:11:39 -08:00
jregan
9ad4b1ddca Unpin versioned and unversioned pins. 2020-12-28 18:10:53 -08:00
Jeff Regan
d529eb8777 Merge pull request #3402 from monopole/upgradeGopkg.in_yaml.v3
Pin to gopkg.in/yaml.v3 v3.0.0-20200313102051
2020-12-28 18:02:41 -08:00
jregan
f7b2f0c067 Pin to gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
This is the last commit in yaml.v3 before

  ae27a74434

which changed the indentation of sequence.

That change has has large downstream impact on tests in the kustomize
repo.  To upgrade beyond this point in yaml.v3 means many changes to
indentation in "expected" values in tests.  That should be done in a
PR dedicated to that purpose, after specific consideration the change.

ALLOW_MODULE_SPAN
2020-12-28 17:28:01 -08:00
Jeff Regan
ff6b337ebe Update README.md 2020-12-28 14:06:43 -08:00
Jeff Regan
76f05f3a40 Update cli-utils release instructions. 2020-12-28 13:57:21 -08:00
Jeff Regan
d181a73f56 Set FlagEnableKyamlDefaultValue = false for v3.8.9
In the 3.8 branch, this is false.  In the 3.9 branch, it's true.
2020-12-28 13:32:56 -08:00
Jeff Regan
979fe3b457 Merge pull request #3401 from monopole/close3393
Regression coverage for configmap generation.
2020-12-28 13:09:37 -08:00
Kubernetes Prow Robot
bec45093e2 Merge pull request #3400 from monopole/dropClose
Drop channel close in timed call.
2020-12-28 10:06:28 -08:00
jregan
c113c41c9c Regression coverage for configmap generation. 2020-12-28 09:53:34 -08:00
jregan
99c9edfc3d Drop close in timed call. 2020-12-28 08:31:42 -08:00
Jeff Regan
cde6a5741e Merge pull request #3399 from fwolter/patch-1
Fix typo
2020-12-28 05:40:49 -08:00
Fabian Wolter
a315eb56ec Fix typo 2020-12-27 20:11:30 +01:00
Kubernetes Prow Robot
90654b39bf Merge pull request #3398 from monopole/close3343
Close 3343
2020-12-27 07:30:27 -08:00
jregan
24c4c66403 Close 3343 2020-12-26 10:43:58 -08:00
Jeff Regan
2b5029952c Merge pull request #3397 from monopole/towards3304
Drop another difference between kyaml and apimachinery
2020-12-26 10:32:50 -08:00
jregan
6a3bb5df44 Drop another difference between kyaml and apimachinery 2020-12-26 10:12:33 -08:00
Jeff Regan
d9623ab307 Merge pull request #3382 from monopole/emptyMapMania
Isolate tests related to #3396
2020-12-26 09:44:21 -08:00
jregan
dd1df5a30e Remaining problems. 2020-12-26 09:28:01 -08:00
Jeff Regan
0e13a9c02b Merge pull request #3395 from monopole/isolateEmptyDirTests
Isolate patch conflation problem to one test.
2020-12-26 08:58:52 -08:00
jregan
eb26d79fa0 Isolate patch conflation problem to one test.
See #3394
2020-12-26 08:41:48 -08:00
Jeff Regan
7f8da385c0 Merge pull request #3392 from monopole/isolateQuoting
Isolate scalar int and bool quoting oddities to one test set.
2020-12-23 18:26:52 -08:00
jregan
1426137883 Isolate scalar quoting oddities to one test set.
The apimachinery code path, in its final marshalling
for output, calls Marshall

  https://github.com/go-yaml/yaml/blob/v2/yaml.go#L199

This code path (via apimachinery Unstructured types)
has no JSON schema tags

  https://yaml.org/spec/1.2/spec.html#id2803311

so it adds quotes to values that smell like
booleans and ints (e.g. `false` becomes `"false"`).

The kyaml code path, OTOH, uses such tags,
so generally does not quote ints and booleans.

This PR isolates this difference in behavior to
one set of tests (using data fields in configmaps
in api/krusty/configmaps_test.go) so that
they don't confuse other tests that cover
completely different behaviors.
2020-12-23 17:08:25 -08:00
Kubernetes Prow Robot
d90d77cdaf Merge pull request #3366 from natasha41575/QuotedScalarValueWithColon
if setter value ends in colon, treat it as a string
2020-12-23 11:54:26 -08:00
Jeff Regan
1ffd790cfb Merge pull request #3388 from Shell32-Natsu/secret-type
Fix type ignored in secret generator
2020-12-22 17:51:07 -08:00
Jeff Regan
454906d093 Merge pull request #3389 from monopole/moreMergeTests
More merge tests, clearer method names.
2020-12-22 17:49:26 -08:00
jregan
8b97274af3 More merge tests, clearer method names. 2020-12-22 17:26:12 -08:00
Donny Xia
b1056b43cb Merge pull request #3383 from antoninbas/add-role-resourceNames-to-configMap-builtin-nameref-resolver
Add Role / ClusterRole resourceNames to ConfigMap nameref resolver
2020-12-22 14:43:19 -08:00
Donny Xia
e411942a74 Fix type ignored in secret generator 2020-12-22 14:37:13 -08:00
Kubernetes Prow Robot
6b30b72ebc Merge pull request #3385 from monopole/elimateExtraneousEmtpyMaps
Eliminate extraneous label and anno maps.
2020-12-22 08:54:26 -08:00
jregan
9ddf0fe304 Eliminate extraneous label and anno maps. 2020-12-22 08:37:40 -08:00
Jeff Regan
8a952a1b26 Merge pull request #3384 from monopole/badBlank
Fix roleref test failing under enableKyaml
2020-12-22 06:47:55 -08:00
jregan
fff484e98b Fix test failing under enableKyaml 2020-12-22 06:24:27 -08:00
Antonin Bas
e819a2ba9d Add Role / ClusterRole resourceNames to ConfigMap nameref resolver
While it is possible to use a kustomizeconfig.yml for this, with a
custom namereference, this functionality should probably be built-in.

This is similar to previous PRs, like this one:
https://github.com/kubernetes-sigs/kustomize/pull/592
2020-12-21 21:02:19 -08:00
Natasha Sarkar
4908654c09 if setter value ends in colon, treat it as a string 2020-12-21 11:54:30 -08:00
Jeff Regan
586515ebc4 Merge pull request #3379 from monopole/messingWithMerge
Fix configmap merge problem under kyaml.
2020-12-21 09:22:02 -08:00
jregan
735befef19 Add kunstruct impl of Get/SetDataMap, replace Resource.Merge 2020-12-21 07:22:03 -08:00
jregan
35087ed0cc Add RNode.Set/GetDataMap to ease configmap generation. 2020-12-21 07:18:51 -08:00
Jeff Regan
f84f8f28fd Merge pull request #3376 from monopole/oops
Drop another go.mod version replacement omission.
2020-12-20 17:07:36 -08:00
jregan
45e118458c Drop another go.mod version replacement omission. 2020-12-20 17:06:26 -08:00
Jeff Regan
1102153ae3 Merge pull request #3375 from monopole/removeVersionNumbers
In module replacements, drop specific version numbers.
2020-12-20 16:45:54 -08:00
jregan
338910d36c In module replacements, drop specific version numbers. 2020-12-20 16:23:23 -08:00
Kubernetes Prow Robot
38e9770f40 Merge pull request #3374 from monopole/deleteOldChartInflator
Delete old example helm chart inflator.
2020-12-20 11:24:25 -08:00
Kubernetes Prow Robot
20a4153893 Merge pull request #3373 from monopole/unpinKyaml
Unpin kyaml
2020-12-20 11:00:24 -08:00
jregan
51fba009b3 Delete old example helm chart inflator. 2020-12-20 10:45:43 -08:00
jregan
002215d719 Unpin kyaml 2020-12-20 10:31:17 -08:00
Kubernetes Prow Robot
f9d1e800e4 Merge pull request #3371 from mortent/UseIndexForOrderingFunctions
Multiple declarative functions in the same file should execute in order
2020-12-17 17:24:25 -08:00
Jeff Regan
82db6cd73d Merge pull request #3370 from monopole/fixAnotherNit
Fix formatting nit with enableKyaml
2020-12-17 12:49:25 -08:00
Morten Torkildsen
3c25584658 Multiple declarative functions in the same file should execute in order 2020-12-17 12:13:42 -08:00
jregan
c32a809dbd Fix formatting nit with enableKyaml 2020-12-17 11:21:46 -08:00
Jeff Regan
02be687778 Merge pull request #3369 from monopole/unpinApi
Unpin api module.
2020-12-17 10:02:20 -08:00
jregan
c0a754e7b0 Unpin api module. 2020-12-17 09:38:14 -08:00
Jeff Regan
63e441a673 Merge pull request #3368 from monopole/fixSlash
Fix apiversion slash
2020-12-17 09:20:00 -08:00
jregan
bd27d5f8bb Fix apiversion slash 2020-12-17 08:42:15 -08:00
Kubernetes Prow Robot
0aa250c6e2 Merge pull request #3359 from Shell32-Natsu/resmap-from-rnodes
Avoid error when the node has local-config
2020-12-16 11:00:30 -08:00
Jeff Regan
e269ad4a80 Merge pull request #3356 from JaredTan95/update_extension_version
upgrade admissionregistration.k8s.io/v1beta1 version to v1
2020-12-16 10:44:08 -08:00
Jeff Regan
9db6b37b88 Merge pull request #3357 from yuvalk/yuvalk/master
add curl timeout to install script
2020-12-16 10:43:13 -08:00
JaredTan95
2361b70967 fix unit test 2020-12-16 10:05:04 +08:00
Donny Xia
d016326877 avoid error when the node has local-config 2020-12-15 13:29:19 -08:00
Donny Xia
67e445c10b Merge pull request #3353 from epcim/helmValuesOnInflatorConfig-plugin
Helm values on inflator config plugin
2020-12-15 10:21:47 -08:00
Jeff Regan
76970a6b05 Merge pull request #3354 from Shell32-Natsu/set-image
describe the format of image tag that is allowed
2020-12-15 09:44:20 -08:00
Kubernetes Prow Robot
66db1df79a Merge pull request #3346 from Shell32-Natsu/ynode-iszero
Add function to check is YNode zero
2020-12-15 09:43:48 -08:00
Yuval Kashtan
6442047e52 add curl timeout to install script
This is important to improve reliency of other automations/scripts that are using this script internally. Otherwise install script might stall forever in some cases.
2020-12-15 12:01:15 +02:00
Petr Michalec
8ac6954de1 helm values on inflator config - test
Signed-off-by: Petr Michalec <epcim@apealive.net>
2020-12-15 08:39:17 +01:00
Petr Michalec
494977b9d0 helm values on inflator config - builtin
Signed-off-by: Petr Michalec <epcim@apealive.net>
2020-12-15 08:38:59 +01:00
Petr Michalec
0a0a6e1018 helm values on inflator config - plugin
Signed-off-by: Petr Michalec <epcim@apealive.net>
2020-12-15 08:38:37 +01:00
Petr Michalec
fa69d4ba9d helm values on inflator config - types
Signed-off-by: Petr Michalec <epcim@apealive.net>
2020-12-15 08:37:34 +01:00
JaredTan95
36bdcca735 update plugin api version.
Signed-off-by: JaredTan95 <jian.tan@daocloud.io>
2020-12-15 12:22:57 +08:00
JaredTan95
c71a4534a0 update kyaml api version. 2020-12-15 12:21:27 +08:00
JaredTan95
97402f1136 update crd_test.go api version. 2020-12-15 12:20:10 +08:00
JaredTan95
1329afa3ca update imagetag_test.go api version. 2020-12-15 12:19:37 +08:00
Donny Xia
60c8f4c594 Merge pull request #3350 from shibataka000/add-topologyspreadconstraints-to-builtin-common-label-field
Add topologySpreadConstraints to builtin common label field
2020-12-14 10:13:23 -08:00
Donny Xia
428e25b856 Merge pull request #3349 from montmanu/update-docker-path
add kustomize to PATH
2020-12-14 10:12:45 -08:00
Donny Xia
8dd6f2b185 describe the format of image tag that is allowed 2020-12-14 10:09:01 -08:00
Takao Shibata
a3bf3ba608 Add topologySpreadConstraints to builtin label field 2020-12-14 14:18:02 +09:00
Christopher Montoro
b97e59c57e add kustomize to PATH 2020-12-13 18:03:35 -05:00
Donny Xia
bae3228557 Add function to check is YNode zero 2020-12-11 14:55:44 -08:00
Jeff Regan
cc43a2d732 Merge pull request #3342 from Shell32-Natsu/wnode-slice
fix wnode get slice issue
2020-12-11 09:07:16 -08:00
Donny Xia
d25e1effb7 Unpin api 2020-12-10 15:13:22 -08:00
Donny Xia
485b8121d3 fix wnode get slice issue 2020-12-10 15:12:57 -08:00
Jeff Regan
401118728a Update kustomization.yaml 2020-12-10 14:20:36 -08:00
Kubernetes Prow Robot
0f45bd9583 Merge pull request #3339 from monopole/updateTests
Update tests of examples against new releases.
2020-12-10 12:58:13 -08:00
jregan
97e4353755 Update test of examples against new releases. 2020-12-10 12:37:47 -08:00
Jeff Regan
826b5d9792 Merge pull request #3338 from monopole/updateGoSum
Auto update go.sum
2020-12-10 11:27:28 -08:00
jregan
8c9da15156 Auto update go.sum 2020-12-10 11:26:51 -08:00
Kubernetes Prow Robot
e18d619c9e Merge pull request #3337 from monopole/pinToApiv0.7.0_enableKyamlByDefault
Pin kustomize to api/v0.7.0, enabling kyaml by default
2020-12-10 11:08:15 -08:00
jregan
f8a3c04286 Pin kustomize to api/v0.7.0, enabling kyaml by default
ALLOW_MODULE_SPAN
2020-12-10 10:48:52 -08:00
Kubernetes Prow Robot
1a4c82241a Merge pull request #3335 from monopole/enableKyamlByDefault
Flip default value of --enable_kyaml from false to true.
2020-12-10 10:38:14 -08:00
jregan
81ca271e62 Flip default value of --enable_kyaml from false to true. 2020-12-10 10:12:49 -08:00
Kubernetes Prow Robot
72262c5e71 Merge pull request #3334 from monopole/pinKustToApiv0.6.7
Pin kustomize to api/v0.6.7
2020-12-10 09:42:14 -08:00
jregan
125762d94d Pin kustomize to api/v0.6.7 2020-12-09 22:33:02 -08:00
Jeff Regan
0ecbd5905b Merge pull request #3332 from monopole/pinToApi0.6.7
Pin to api v0.6.7
2020-12-09 19:45:48 -08:00
jregan
cb2b376065 Pin to api v0.6.7 2020-12-09 19:20:29 -08:00
Jeff Regan
595e59b919 Merge pull request #3330 from monopole/loaderTest
Provide timeouts for all remote loads.
2020-12-09 17:33:03 -08:00
jregan
6bbc829593 Add a loader test. 2020-12-09 17:17:21 -08:00
Kubernetes Prow Robot
3dd9c6c0b5 Merge pull request #3331 from monopole/unpinKust
Unpin kustomize from api.
2020-12-09 16:04:53 -08:00
jregan
c04c13a12a Unpin kustomize from api. 2020-12-09 15:44:09 -08:00
Jeff Regan
05eccab823 Update loader.go 2020-12-09 15:17:52 -08:00
Jeff Regan
dd946e1343 Merge pull request #3328 from monopole/pin_to_api_v0.6.6
Pin to api v0.6.6
2020-12-07 17:48:32 -08:00
jregan
b4ad4b6984 Pin to api v0.6.6 2020-12-07 17:29:46 -08:00
Jeff Regan
13dee68d3b Merge pull request #3327 from monopole/pin_to_cmdConfig_v0.9.6
Pin to cmd/config v0.8.6
2020-12-07 17:22:31 -08:00
jregan
e849b160bc Pin to cmd/config v0.8.6 2020-12-07 17:02:55 -08:00
Jeff Regan
87987d3382 Merge pull request #3326 from monopole/pin_to_kyaml_v0.10.3_cliutils_v0.22.1
Pin to kyaml v0.10.3 cliutils v0.22.1
2020-12-07 16:53:35 -08:00
jregan
575b4efc18 Pin to kyaml v0.10.3 cliutils v0.22.1 2020-12-07 16:26:52 -08:00
Jeff Regan
b1a460985c Merge pull request #3325 from monopole/autoGoMo
Automated Go mod cache updates.
2020-12-07 13:44:23 -08:00
jregan
e1fd74bb61 Automated Go mod cache updates. 2020-12-07 13:23:20 -08:00
Jeff Regan
8a673b82bd Merge pull request #3287 from yujunz/getter
Upgrade go-getter
2020-12-07 13:11:26 -08:00
Jeff Regan
d2e995b3e2 Merge pull request #3306 from thatsmydoing/single-fetch
Don't fetch default branch if ref is specified
2020-12-07 13:10:26 -08:00
Jeff Regan
f2e025ea53 Update manager.go 2020-12-07 12:57:32 -08:00
Jeff Regan
dade85e40e Merge pull request #3324 from kubernetes-sigs/revert-3316-helmValuesOnInflatorConfigSpec
Revert "helm values on inflator config"
2020-12-07 12:53:49 -08:00
Jeff Regan
51ba54ad82 Revert "helm values on inflator config" 2020-12-07 12:52:31 -08:00
Jeff Regan
4144775a3b Merge pull request #3316 from epcim/helmValuesOnInflatorConfigSpec
helm values on inflator config
2020-12-07 12:51:42 -08:00
Jeff Regan
ff9b215ae7 Update taggedmodule.go 2020-12-07 12:09:09 -08:00
Jeff Regan
cd5ae17335 Merge pull request #3322 from monopole/fixModNames
Fix some plugin module names.
2020-12-07 12:08:14 -08:00
jregan
e3d022325b Fix some plugin module names. 2020-12-07 11:59:13 -08:00
Kubernetes Prow Robot
e6dc03bea4 Merge pull request #3315 from monopole/hoserface
Add more tests
2020-12-07 10:31:11 -08:00
jregan
d08b9c30ee What is this? 2020-12-07 10:16:30 -08:00
Petr Michalec
f6e5eedee2 helm values on inflator config spec. 2020-12-07 13:49:30 +01:00
Jeff Regan
212b2cff12 Merge pull request #3312 from monopole/conflicting
Extract conflict detection to its own interface.
2020-12-06 09:00:41 -08:00
jregan
f66e5bb923 Extract conflict detection to it's own interface.
This PR
 - defines a patch conflict detector interface,
 - extracts implementations of the interface from the
   merginator code, making the merginator code
   independent of --enable_kyaml.
 - injects those implementations into kustomize
   as a function of --enable_kyaml.

So, instead of using different merginators to combine
resmaps, this pr allows the use of a single patch merge
code path that uses different conflict detectors.

So instead of debating how to merge, we're now only
considering whether to warn on conflict detection
in one transformer.

This PR is in service of #3304, eliminating seven
instances where --enable_kyaml was consulted.  These
were cases where conflict detection wasn't an issue
(but merging patches was).
2020-12-06 08:38:45 -08:00
Kubernetes Prow Robot
23bc91f233 Merge pull request #3311 from drewwells/patch-1
absolute path to entrypoint
2020-12-04 18:05:25 -08:00
Drew Wells
9c421c7410 absolute path to entrypoint
Make the kustomize container tolerant of alternative working directory. 
Mounting my project and making it the working directory will now work.

ie. docker run -w /pkg -v $(shell pwd):/pkg kustomize version
2020-12-04 18:27:57 -06:00
Jeff Regan
c63dfd6772 Merge pull request #3310 from monopole/nits
Spelling nits.
2020-12-04 12:30:36 -08:00
jregan
1a5aa63d54 Spelling nits. 2020-12-04 12:29:39 -08:00
Jeff Regan
1583cef8d9 Merge pull request #3309 from monopole/autoUpdate
Automated doc update.
2020-12-04 10:51:54 -08:00
jregan
a7c91c37e9 Automated doc update. 2020-12-04 10:51:22 -08:00
Kubernetes Prow Robot
c1dca7fdb5 Merge pull request #3302 from natasha41575/TestGvknChange
tests for gvkn changing
2020-12-04 10:29:59 -08:00
Natasha Sarkar
724bbe9452 connected allowresourcesidchanges bool to allow_id_changes flag 2020-12-02 18:03:09 -08:00
Natasha Sarkar
deb2b21cbe added allowresourceidchanges bool to options struct 2020-12-02 18:02:09 -08:00
Kubernetes Prow Robot
709f499b44 Merge pull request #3305 from monopole/moreHacking
In PatchStrategicMergeTransformer's test, highlight remaining work
2020-12-02 10:38:50 -08:00
jregan
dbaa2d6092 hacking 2020-12-02 10:23:13 -08:00
Thomas Dy
6445e03d1a Don't fetch default branch if ref is specified
Currently, we always fetch the default branch with an initial git clone
and then fetch the ref after if it's specified. This changes it to only
make one fetch instead of two if a ref is specified.
2020-12-02 16:16:30 +09:00
Jeff Regan
19ff1b307e Merge pull request #3301 from rumstead/master
[Docs] Fixing README link to kubectl book.
2020-12-01 16:56:25 -08:00
Jeff Regan
55f44a29c6 Update README.md 2020-12-01 16:48:41 -08:00
Jeff Regan
1f1873a6ed Merge pull request #3299 from monopole/demoteReplacementTransformer
Move ReplacementTransformer plugin to untested folder
2020-12-01 12:45:53 -08:00
rumstead
6e3c4ecc72 Update README.md 2020-12-01 13:18:59 -05:00
jregan
c37c7b6b2c Move ReplacementTransformer plugin to untested. 2020-12-01 10:04:00 -08:00
Jeff Regan
42acdcc1d0 Merge pull request #3298 from monopole/makeUntestedPluginDir
Start directory for 'untested' plugins.
2020-12-01 09:52:59 -08:00
jregan
67db23b24b Start directory for 'untested' plugins. 2020-12-01 07:32:44 -08:00
Kubernetes Prow Robot
35a19fb8a9 Merge pull request #3296 from monopole/secretGeneratorTestKYaml
Adjust SecretGeneratorTest to pass with --enable_kyaml
2020-11-30 19:50:57 -08:00
Kubernetes Prow Robot
a6c2e982f9 Merge pull request #3292 from Shell32-Natsu/helm-extra-args
Add field extraArgs to helm generator
2020-11-30 19:50:49 -08:00
Kubernetes Prow Robot
a053ff6907 Merge pull request #3295 from monopole/addSmPatchTests
Add more tests for reswrangler ApplySmPatch
2020-11-30 19:24:50 -08:00
jregan
64201c8352 Adjust SecretGeneratorTest to pass with --enable_kyaml 2020-11-30 19:17:15 -08:00
jregan
d5ce26e423 Patchtransformers - drop copied code, improve deletion handling. 2020-11-30 18:43:35 -08:00
Kubernetes Prow Robot
09497f0830 Merge pull request #3294 from monopole/goSumCatchup
Automated go.sum updates.
2020-11-30 18:42:50 -08:00
jregan
32dd194aca Automated go.sum updates. 2020-11-30 18:16:23 -08:00
Jeff Regan
4122787bd8 Merge pull request #3293 from natasha41575/FixOpenApiInfoSpacing
Made output of `kustomize openapi info` command more readable
2020-11-30 18:15:16 -08:00
Yujun Zhang
485cb3831e Upgrade go-getter
* Provide a detector for repositories hosted on GitLab.com
* Update github.com/ulikunitz/xz@v0.5.8 for CVE-2020-16845
2020-12-01 09:39:03 +08:00
Natasha Sarkar
2ccb73a2a3 made output of kustomize openapi info command more readable 2020-11-30 14:56:20 -08:00
Kubernetes Prow Robot
83377cf597 Merge pull request #3291 from monopole/thrashing
Patchtransformers - drop copied code, improve deletion handling.
2020-11-30 14:26:50 -08:00
Donny Xia
2bf73c60c3 Add field extraArgs to helm generator 2020-11-30 14:22:25 -08:00
jregan
4a55a07c14 Patchtransformers - drop copied code, improve deletion handling. 2020-11-30 11:58:43 -08:00
179 changed files with 5547 additions and 2442 deletions

View File

@@ -26,7 +26,8 @@ verify-kustomize: \
lint-kustomize \
test-unit-kustomize-all \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.6
test-examples-kustomize-against-3.9.0 \
test-examples-kustomize-against-3.8.8
# The following target referenced by a file in
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
@@ -38,7 +39,8 @@ prow-presubmit-check: \
test-unit-cmd-all \
test-go-mod \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.6
test-examples-kustomize-against-3.9.0 \
test-examples-kustomize-against-3.8.8
.PHONY: verify-kustomize-e2e
verify-kustomize-e2e: test-examples-e2e-kustomize
@@ -274,17 +276,12 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh HEAD
.PHONY:
test-examples-kustomize-against-3.8.6: $(MYGOBIN)/mdrip
( \
set -e; \
tag=v3.8.6; \
/bin/rm -f $(MYGOBIN)/kustomize; \
echo "Installing kustomize $$tag."; \
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@$${tag}; \
./hack/testExamplesAgainstKustomize.sh $$tag; \
echo "Reinstalling kustomize from HEAD."; \
cd kustomize; go install .; \
)
test-examples-kustomize-against-3.9.0: $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh v3.9.0
.PHONY:
test-examples-kustomize-against-3.8.8: $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh v3.8.8
# linux only.
# This is for testing an example plugin that

View File

@@ -153,7 +153,7 @@ is governed by the [Kubernetes Code of Conduct].
[imageBase]: docs/images/base.jpg
[imageOverlay]: docs/images/overlay.jpg
[kubectl announcement]: https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement
[kubectl book]: https://kubectl.docs.kubernetes.io/pages/app_customization/introduction.html
[kubectl book]: https://kubectl.docs.kubernetes.io/guides/introduction/kustomize/
[kubernetes documentation]: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
[kubernetes style]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#kubernetes-style-object
[kustomization]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#kustomization

View File

@@ -6,12 +6,15 @@ package builtins
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"regexp"
"strings"
"github.com/imdario/mergo"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/resmap"
@@ -62,6 +65,9 @@ func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, conf
if p.Values == "" {
p.Values = path.Join(p.ChartHome, p.ChartName, "values.yaml")
}
if p.ValuesMerge == "" {
p.ValuesMerge = "override"
}
// runHelmCommand will run `helm` command with args provided. Return stdout
// and error if there is any.
p.runHelmCommand = func(args []string) ([]byte, error) {
@@ -88,6 +94,63 @@ func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, conf
return nil
}
// EncodeValues for writing
func (p *HelmChartInflationGeneratorPlugin) EncodeValues(w io.Writer) error {
d, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
_, err = w.Write(d)
if err != nil {
return err
}
return nil
}
// useValuesLocal process (merge) inflator config provided values with chart default values.yaml
func (p *HelmChartInflationGeneratorPlugin) useValuesLocal() error {
fn := path.Join(p.ChartHome, p.ChartName, "kustomize-values.yaml")
vf, err := os.Create(fn)
defer vf.Close()
if err != nil {
return err
}
// override, merge, none
if p.ValuesMerge == "none" || p.ValuesMerge == "no" || p.ValuesMerge == "false" {
p.Values = fn
} else {
pValues, err := ioutil.ReadFile(p.Values)
if err != nil {
return err
}
chValues := make(map[string]interface{})
err = yaml.Unmarshal(pValues, &chValues)
if err != nil {
return err
}
if p.ValuesMerge == "override" {
err = mergo.Merge(&chValues, p.ValuesLocal, mergo.WithOverride)
if err != nil {
return err
}
}
if p.ValuesMerge == "merge" {
err = mergo.Merge(&chValues, p.ValuesLocal)
if err != nil {
return err
}
}
p.ValuesLocal = chValues
p.Values = fn
}
err = p.EncodeValues(vf)
if err != nil {
return err
}
vf.Sync()
return nil
}
// Generate implements generator
func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
// cleanup
@@ -104,6 +167,15 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
return nil, err
}
}
// inflator config valuesLocal
if len(p.ValuesLocal) > 0 {
err := p.useValuesLocal()
if err != nil {
return nil, err
}
}
// render the charts
stdout, err := p.runHelmCommand(p.getTemplateCommandArgs())
if err != nil {
@@ -125,6 +197,7 @@ func (p *HelmChartInflationGeneratorPlugin) getTemplateCommandArgs() []string {
if p.Values != "" {
args = append(args, "--values", p.Values)
}
args = append(args, p.ExtraArgs...)
return args
}

View File

@@ -5,19 +5,14 @@ package builtins
import (
"fmt"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
type PatchStrategicMergeTransformerPlugin struct {
h *resmap.PluginHelpers
loadedPatches []*resource.Resource
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
@@ -25,7 +20,6 @@ type PatchStrategicMergeTransformerPlugin struct {
func (p *PatchStrategicMergeTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.h = h
err = yaml.Unmarshal(c, p)
if err != nil {
return err
@@ -35,13 +29,18 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
}
if len(p.Paths) != 0 {
for _, onePath := range p.Paths {
res, err := p.h.ResmapFactory().RF().SliceFromBytes([]byte(onePath))
// The following oddly attempts to interpret a path string as an
// actual patch (instead of as a path to a file containing a patch).
// All tests pass if this code is commented out. This code should
// be deleted; the user should use the Patches field which
// exists for this purpose (inline patch declaration).
res, err := h.ResmapFactory().RF().SliceFromBytes([]byte(onePath))
if err == nil {
p.loadedPatches = append(p.loadedPatches, res...)
continue
}
res, err = p.h.ResmapFactory().RF().SliceFromPatches(
p.h.Loader(), []types.PatchStrategicMerge{onePath})
res, err = h.ResmapFactory().RF().SliceFromPatches(
h.Loader(), []types.PatchStrategicMerge{onePath})
if err != nil {
return err
}
@@ -49,7 +48,7 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
}
}
if p.Patches != "" {
res, err := p.h.ResmapFactory().RF().SliceFromBytes([]byte(p.Patches))
res, err := h.ResmapFactory().RF().SliceFromBytes([]byte(p.Patches))
if err != nil {
return err
}
@@ -60,57 +59,25 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
return fmt.Errorf(
"patch appears to be empty; files=%v, Patch=%s", p.Paths, p.Patches)
}
return err
}
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
patches, err := p.h.ResmapFactory().Merge(p.loadedPatches)
// Merge the patches, looking for conflicts.
m, err := h.ResmapFactory().ConflatePatches(p.loadedPatches)
if err != nil {
return err
}
for _, patch := range patches.Resources() {
p.loadedPatches = m.Resources()
return nil
}
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
for _, patch := range p.loadedPatches {
target, err := m.GetById(patch.OrgId())
if err != nil {
return err
}
patchCopy := patch.DeepCopy()
patchCopy.SetName(target.GetName())
patchCopy.SetNamespace(target.GetNamespace())
patchCopy.SetGvk(target.GetGvk())
node, err := filtersutil.GetRNode(patchCopy)
if err != nil {
if err = m.ApplySmPatch(
resource.MakeIdSet([]*resource.Resource{target}), patch); err != nil {
return err
}
err = filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, target)
if err != nil {
// Check for an error string from UnmarshalJSON that's indicative
// of an object that's missing basic KRM fields, and thus may have been
// entirely deleted (an acceptable outcome). This error handling should
// be deleted along with use of ResMap and apimachinery functions like
// UnmarshalJSON.
if !strings.Contains(err.Error(), "Object 'Kind' is missing") {
// Some unknown error, let it through.
return err
}
if !target.IsEmpty() {
return errors.Wrapf(
err, "with unexpectedly non-empty object map of size %d",
len(target.Map()))
}
// Fall through to handle deleted object.
}
if target.IsEmpty() {
// This means all fields have been removed from the object.
// This can happen if a patch required deletion of the
// entire resource (not just a part of it). This means
// the overall resmap must shrink by one.
err = m.Remove(target.CurId())
if err != nil {
return err
}
}
}
return nil
}

View File

@@ -8,9 +8,7 @@ import (
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
@@ -41,7 +39,6 @@ func (p *PatchTransformerPlugin) Config(
return fmt.Errorf(
"patch and path can't be set at the same time\n%s", string(c))
}
if p.Path != "" {
loaded, loadErr := h.Loader().Load(p.Path)
if loadErr != nil {
@@ -88,66 +85,13 @@ func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch
if err != nil {
return err
}
return p.applySMPatch(target, patch)
return target.ApplySmPatch(patch)
}
resources, err := m.Select(*p.Target)
selected, err := m.Select(*p.Target)
if err != nil {
return err
}
for _, res := range resources {
patchCopy := patch.DeepCopy()
patchCopy.SetName(res.GetName())
patchCopy.SetNamespace(res.GetNamespace())
patchCopy.SetGvk(res.GetGvk())
err := p.applySMPatch(res, patchCopy)
if err != nil {
// Check for an error string from UnmarshalJSON that's indicative
// of an object that's missing basic KRM fields, and thus may have been
// entirely deleted (an acceptable outcome). This error handling should
// be deleted along with use of ResMap and apimachinery functions like
// UnmarshalJSON.
if !strings.Contains(err.Error(), "Object 'Kind' is missing") {
// Some unknown error, let it through.
return err
}
if !res.IsEmpty() {
return errors.Wrapf(
err, "with unexpectedly non-empty object map of size %d",
len(res.Map()))
}
// Fall through to handle deleted object.
}
if res.IsEmpty() {
// This means all fields have been removed from the object.
// This can happen if a patch required deletion of the
// entire resource (not just a part of it). This means
// the overall resmap must shrink by one.
err = m.Remove(res.CurId())
if err != nil {
return err
}
}
}
return nil
}
// applySMPatch applies the provided strategic merge patch to the
// given resource.
func (p *PatchTransformerPlugin) applySMPatch(resource, patch *resource.Resource) error {
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
n, ns := resource.GetName(), resource.GetNamespace()
err = filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, resource)
if !resource.IsEmpty() {
resource.SetName(n)
resource.SetNamespace(ns)
}
return err
return m.ApplySmPatch(resource.MakeIdSet(selected), patch)
}
// transformJson6902 applies the provided json6902 patch

View File

@@ -21,7 +21,7 @@ func TestImageTagUpdater_Filter(t *testing.T) {
}{
"ignore CustomResourceDefinition": {
input: `
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: whatever
@@ -30,7 +30,7 @@ spec:
- image: whatever
`,
expectedOutput: `
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: whatever

View File

@@ -15,6 +15,101 @@ func TestFilter(t *testing.T) {
patch *yaml.RNode
expected string
}{
"simple": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 1
`,
patch: yaml.MustParse(`apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`),
expected: `apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`,
},
"nullMapEntry1": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B:
C: Z
`,
patch: yaml.MustParse(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`),
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`,
},
"nullMapEntry2": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`,
patch: yaml.MustParse(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B:
C: Z
`),
expected: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`,
},
"simple patch": {
input: `
apiVersion: apps/v1

View File

@@ -10,18 +10,17 @@ require (
github.com/google/go-cmp v0.3.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/hashicorp/go-multierror v1.1.0
github.com/imdario/mergo v0.3.5
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.4.0
github.com/yujunz/go-getter v1.4.1-lite
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
sigs.k8s.io/kustomize/kyaml v0.9.4
sigs.k8s.io/kustomize/kyaml v0.10.5
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/kyaml v0.9.4 => ../kyaml

View File

@@ -158,6 +158,7 @@ github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUD
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b h1:ekuhfTjngPhisSjOJ0QWKpPQE8/rbknHaes6WVJj5Hw=
@@ -166,6 +167,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -225,6 +227,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
@@ -249,6 +252,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -287,6 +291,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
@@ -365,6 +370,7 @@ github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
@@ -406,8 +412,8 @@ github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiff
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg=
@@ -423,8 +429,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf h1:gvEmqF83GB8R5XtrMseJb6A6R0OCtNAS8f4TmZg2dGc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf/go.mod h1:bL0Pr07HEdsMZ1WBqZIxXj96r5LnFsY4LgPaPEGkw1k=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -561,12 +567,13 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
@@ -592,6 +599,8 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/kyaml v0.10.5 h1:PbJcsZsEM7O3hHtUWTR+4WkHVbQRW9crSy75or1gRbI=
sigs.k8s.io/kustomize/kyaml v0.10.5/go.mod h1:P6Oy/ah/GZMKzJMIJA2a3/bc8YrBkuL5kJji13PSIzY=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=

View File

@@ -43,12 +43,12 @@ type Kunstructured interface {
// Several uses.
Copy() Kunstructured
// Used by Resource.Replace, which in turn is used in many places, e.g.
// - resource.Resource.Merge
// - resWrangler.appendReplaceOrMerge (AbsorbAll)
// - api.internal.k8sdeps.transformer.patch.conflictdetector
// GetAnnotations returns the k8s annotations.
GetAnnotations() map[string]string
// GetData returns a top-level "data" field, as in a ConfigMap.
GetDataMap() map[string]string
// Used by ResAccumulator and ReplacementTransformer.
GetFieldValue(string) (interface{}, error)
@@ -58,7 +58,7 @@ type Kunstructured interface {
// Used by resource.Factory.SliceFromBytes
GetKind() string
// Used by Resource.Replace
// GetLabels returns the k8s labels.
GetLabels() map[string]string
// Used by Resource.CurId and resource factory.
@@ -84,19 +84,22 @@ type Kunstructured interface {
// Used by resWrangler.Select
MatchesLabelSelector(selector string) (bool, error)
// Used by Resource.Replace.
// SetAnnotations replaces the k8s annotations.
SetAnnotations(map[string]string)
// SetDataMap sets a top-level "data" field, as in a ConfigMap.
SetDataMap(map[string]string)
// Used by PatchStrategicMergeTransformer.
SetGvk(resid.Gvk)
// Used by Resource.Replace and used to remove "validated by" labels.
// SetLabels replaces the k8s labels.
SetLabels(map[string]string)
// Used by Resource.Replace.
// SetName changes the name.
SetName(string)
// Used by Resource.Replace.
// SetNamespace changes the namespace.
SetNamespace(string)
// Needed, for now, by kyaml/filtersutil.ApplyToJSON.

View File

@@ -217,6 +217,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
"secret1",
"secret1",
"secret2",
"cm1",
},
},
},
@@ -420,6 +421,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
"someprefix-secret1-somehash",
"someprefix-secret1-somehash",
"secret2",
"someprefix-cm1-somehash",
},
},
},

View File

@@ -41,13 +41,11 @@ func (ra *ResAccumulator) Vars() []types.Var {
return ra.varSet.AsSlice()
}
func (ra *ResAccumulator) AppendAll(
resources resmap.ResMap) error {
func (ra *ResAccumulator) AppendAll(resources resmap.ResMap) error {
return ra.resMap.AppendAll(resources)
}
func (ra *ResAccumulator) AbsorbAll(
resources resmap.ResMap) error {
func (ra *ResAccumulator) AbsorbAll(resources resmap.ResMap) error {
return ra.resMap.AbsorbAll(resources)
}

View File

@@ -0,0 +1,23 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package conflict
import (
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resource"
)
type cdFactory struct{}
var _ resource.ConflictDetectorFactory = &cdFactory{}
// NewFactory returns a new conflict detector factory.
func NewFactory() resource.ConflictDetectorFactory {
return &cdFactory{}
}
// New returns an instance of smPatchMergeOnlyDetector.
func (c cdFactory) New(_ resid.Gvk) (resource.ConflictDetector, error) {
return &smPatchMergeOnlyDetector{}, nil
}

View File

@@ -0,0 +1,33 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package conflict
import (
"sigs.k8s.io/kustomize/api/resource"
)
// smPatchMergeOnlyDetector ignores conflicts,
// but does real strategic merge patching.
// This is part of an effort to eliminate dependence on
// apimachinery package to allow kustomize integration
// into kubectl (#2506 and #1500)
type smPatchMergeOnlyDetector struct{}
var _ resource.ConflictDetector = &smPatchMergeOnlyDetector{}
func (c *smPatchMergeOnlyDetector) HasConflict(
_, _ *resource.Resource) (bool, error) {
return false, nil
}
// There's at least one case that doesn't work. Suppose one has a
// Deployment with a volume with the bizarre "emptyDir: {}" entry.
// If you want to get rid of this entry via a patch containing
// the entry "emptyDir: null", then the following won't work,
// because null entries are eliminated.
func (c *smPatchMergeOnlyDetector) MergePatches(
r, patch *resource.Resource) (*resource.Resource, error) {
err := r.ApplySmPatch(patch)
return r, err
}

View File

@@ -145,6 +145,7 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -219,6 +220,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@@ -253,6 +255,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -356,8 +359,8 @@ github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiff
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
@@ -370,8 +373,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf h1:gvEmqF83GB8R5XtrMseJb6A6R0OCtNAS8f4TmZg2dGc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf/go.mod h1:bL0Pr07HEdsMZ1WBqZIxXj96r5LnFsY4LgPaPEGkw1k=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -504,12 +507,13 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
@@ -530,8 +534,8 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/kyaml v0.9.4 h1:DDuzZtjIzFqp2IPy4DTyCI69Cl3bDgcJODjI6sjF9NY=
sigs.k8s.io/kustomize/kyaml v0.9.4/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
sigs.k8s.io/kustomize/kyaml v0.10.5 h1:PbJcsZsEM7O3hHtUWTR+4WkHVbQRW9crSy75or1gRbI=
sigs.k8s.io/kustomize/kyaml v0.10.5/go.mod h1:P6Oy/ah/GZMKzJMIJA2a3/bc8YrBkuL5kJji13PSIzY=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -37,10 +37,14 @@ func MakeSecret(
if err != nil {
return nil, err
}
t := "Opaque"
if args.Type != "" {
t = args.Type
}
if _, err := rn.Pipe(
yaml.FieldSetter{
Name: "type",
Value: yaml.NewStringRNode("Opaque")}); err != nil {
Value: yaml.NewStringRNode(t)}); err != nil {
return nil, err
}
m, err := makeValidatedDataMap(ldr, args.Name, args.KvPairSources)

View File

@@ -122,6 +122,34 @@ data:
b: eQ==
c: SGVsbG8gV29ybGQ=
d: dHJ1ZQ==
`,
},
},
"construct secret with type": {
args: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalSecret1",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
},
Type: "foobar",
},
exp: expected{
out: `apiVersion: v1
kind: Secret
metadata:
name: literalSecret1
labels:
foo: 'bar'
type: foobar
data:
a: eA==
`,
},
},

View File

@@ -4,10 +4,6 @@
package git
import (
"log"
"os/exec"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
)
@@ -18,70 +14,29 @@ type Cloner func(repoSpec *RepoSpec) error
// to say, some remote API, to obtain a local clone of
// a remote repo.
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
gitProgram, err := exec.LookPath("git")
if err != nil {
return errors.Wrap(err, "no 'git' program on path")
}
repoSpec.Dir, err = filesys.NewTmpConfirmedDir()
r, err := newCmdRunner()
if err != nil {
return err
}
cmd := exec.Command(
gitProgram,
"clone",
"--depth=1",
repoSpec.CloneSpec(),
repoSpec.Dir.String())
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf("Error cloning git repo: %s", out)
return errors.Wrapf(
err,
"trouble cloning git repo %v in %s",
repoSpec.CloneSpec(), repoSpec.Dir.String())
repoSpec.Dir = r.dir
if err = r.run("init"); err != nil {
return err
}
if err = r.run(
"remote", "add", "origin", repoSpec.CloneSpec()); err != nil {
return err
}
ref := "HEAD"
if repoSpec.Ref != "" {
cmd = exec.Command(
gitProgram,
"fetch",
"--depth=1",
"origin",
repoSpec.Ref)
cmd.Dir = repoSpec.Dir.String()
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("Error fetching ref: %s", out)
return errors.Wrapf(err, "trouble fetching %s", repoSpec.Ref)
}
cmd = exec.Command(
gitProgram,
"checkout",
"FETCH_HEAD")
cmd.Dir = repoSpec.Dir.String()
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("Error checking out ref: %s", out)
return errors.Wrapf(err, "trouble checking out %s", repoSpec.Ref)
}
ref = repoSpec.Ref
}
cmd = exec.Command(
gitProgram,
"submodule",
"update",
"--init",
"--recursive")
cmd.Dir = repoSpec.Dir.String()
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("Error fetching submodules: %s", out)
return errors.Wrapf(err, "trouble fetching submodules for %s", repoSpec.CloneSpec())
if err = r.run("fetch", "--depth=1", "origin", ref); err != nil {
return err
}
return nil
if err = r.run("checkout", "FETCH_HEAD"); err != nil {
return err
}
return r.run("submodule", "update", "--init", "--recursive")
}
// DoNothingCloner returns a cloner that only sets

View File

@@ -0,0 +1,58 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package git
import (
"os/exec"
"time"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/utils"
)
// Arbitrary, but non-infinite, timeout for running commands.
const defaultDuration = 27 * time.Second
// gitRunner runs the external git binary.
type gitRunner struct {
gitProgram string
duration time.Duration
dir filesys.ConfirmedDir
}
// newCmdRunner returns a gitRunner if it can find the binary.
// It also creats a temp directory for cloning repos.
func newCmdRunner() (*gitRunner, error) {
gitProgram, err := exec.LookPath("git")
if err != nil {
return nil, errors.Wrap(err, "no 'git' program on path")
}
dir, err := filesys.NewTmpConfirmedDir()
if err != nil {
return nil, err
}
return &gitRunner{
gitProgram: gitProgram,
duration: defaultDuration,
dir: dir,
}, nil
}
// run a command with a timeout.
func (r gitRunner) run(args ...string) error {
//nolint: gosec
cmd := exec.Command(r.gitProgram, args...)
cmd.Dir = r.dir.String()
return utils.TimedCall(
cmd.String(),
r.duration,
func() error {
_, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrapf(err, "git cmd = '%s'", cmd.String())
}
return err
})
}

View File

@@ -0,0 +1,43 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package conflict
import (
"encoding/json"
jsonpatch "github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/util/mergepatch"
"sigs.k8s.io/kustomize/api/resource"
)
// conflictDetectorJson detects conflicts in a list of JSON patches.
type conflictDetectorJson struct {
resourceFactory *resource.Factory
}
var _ resource.ConflictDetector = &conflictDetectorJson{}
func (cd *conflictDetectorJson) HasConflict(
p1, p2 *resource.Resource) (bool, error) {
return mergepatch.HasConflicts(p1.Map(), p2.Map())
}
func (cd *conflictDetectorJson) MergePatches(
patch1, patch2 *resource.Resource) (*resource.Resource, error) {
baseBytes, err := json.Marshal(patch1.Map())
if err != nil {
return nil, err
}
patchBytes, err := json.Marshal(patch2.Map())
if err != nil {
return nil, err
}
mergedBytes, err := jsonpatch.MergeMergePatches(baseBytes, patchBytes)
if err != nil {
return nil, err
}
mergedMap := make(map[string]interface{})
err = json.Unmarshal(mergedBytes, &mergedMap)
return cd.resourceFactory.FromMap(mergedMap), err
}

View File

@@ -0,0 +1,65 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package conflict
import (
"fmt"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"sigs.k8s.io/kustomize/api/resource"
)
// conflictDetectorSm detects conflicts in a list of strategic merge patches.
type conflictDetectorSm struct {
lookupPatchMeta strategicpatch.LookupPatchMeta
resourceFactory *resource.Factory
}
var _ resource.ConflictDetector = &conflictDetectorSm{}
func (cd *conflictDetectorSm) HasConflict(
p1, p2 *resource.Resource) (bool, error) {
return strategicpatch.MergingMapsHaveConflicts(
p1.Map(), p2.Map(), cd.lookupPatchMeta)
}
func (cd *conflictDetectorSm) MergePatches(
patch1, patch2 *resource.Resource) (*resource.Resource, error) {
if cd.hasDeleteDirectiveMarker(patch2.Map()) {
if cd.hasDeleteDirectiveMarker(patch1.Map()) {
return nil, fmt.Errorf(
"cannot merge patches both containing '$patch: delete' directives")
}
patch1, patch2 = patch2, patch1
}
mergedMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
cd.lookupPatchMeta, patch1.Map(), patch2.Map())
return cd.resourceFactory.FromMap(mergedMap), err
}
func (cd *conflictDetectorSm) hasDeleteDirectiveMarker(
patch map[string]interface{}) bool {
if v, ok := patch["$patch"]; ok && v == "delete" {
return true
}
for _, v := range patch {
switch typedV := v.(type) {
case map[string]interface{}:
if cd.hasDeleteDirectiveMarker(typedV) {
return true
}
case []interface{}:
for _, sv := range typedV {
typedE, ok := sv.(map[string]interface{})
if !ok {
break
}
if cd.hasDeleteDirectiveMarker(typedE) {
return true
}
}
}
}
return false
}

View File

@@ -0,0 +1,45 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package conflict
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
sp "k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resource"
)
type cdFactory struct {
rf *resource.Factory
}
var _ resource.ConflictDetectorFactory = &cdFactory{}
// NewFactory returns a conflict detector factory.
// The detector uses a resource factory to convert resources to/from
// json/yaml/maps representations.
func NewFactory(rf *resource.Factory) resource.ConflictDetectorFactory {
return &cdFactory{rf: rf}
}
// New returns a conflict detector that's aware of the GVK type.
func (f *cdFactory) New(gvk resid.Gvk) (resource.ConflictDetector, error) {
// Convert to apimachinery representation of object
obj, err := scheme.Scheme.New(schema.GroupVersionKind{
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
})
if err == nil {
meta, err := sp.NewPatchMetaFromStruct(obj)
return &conflictDetectorSm{
lookupPatchMeta: meta, resourceFactory: f.rf}, err
}
if runtime.IsNotRegisteredError(err) {
return &conflictDetectorJson{resourceFactory: f.rf}, nil
}
return nil, err
}

View File

@@ -1,239 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package merge
import (
"encoding/json"
"fmt"
jsonpatch "github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/mergepatch"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
)
type conflictDetector interface {
hasConflict(patch1, patch2 *resource.Resource) (bool, error)
findConflict(
conflictingPatchIdx int,
patches []*resource.Resource) (*resource.Resource, error)
mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error)
}
type jsonMergePatch struct {
resourceFactory *resource.Factory
}
var _ conflictDetector = &jsonMergePatch{}
func newJMPConflictDetector(rf *resource.Factory) conflictDetector {
return &jsonMergePatch{resourceFactory: rf}
}
func (jmp *jsonMergePatch) hasConflict(
patch1, patch2 *resource.Resource) (bool, error) {
return mergepatch.HasConflicts(patch1.Map(), patch2.Map())
}
func (jmp *jsonMergePatch) findConflict(
conflictingPatchIdx int,
patches []*resource.Resource) (*resource.Resource, error) {
for i, patch := range patches {
if i == conflictingPatchIdx {
continue
}
if !patches[conflictingPatchIdx].OrgId().Equals(patch.OrgId()) {
continue
}
conflict, err := mergepatch.HasConflicts(
patch.Map(),
patches[conflictingPatchIdx].Map())
if err != nil {
return nil, err
}
if conflict {
return patch, nil
}
}
return nil, nil
}
func (jmp *jsonMergePatch) mergePatches(
patch1, patch2 *resource.Resource) (*resource.Resource, error) {
baseBytes, err := json.Marshal(patch1.Map())
if err != nil {
return nil, err
}
patchBytes, err := json.Marshal(patch2.Map())
if err != nil {
return nil, err
}
mergedBytes, err := jsonpatch.MergeMergePatches(baseBytes, patchBytes)
if err != nil {
return nil, err
}
mergedMap := make(map[string]interface{})
err = json.Unmarshal(mergedBytes, &mergedMap)
return jmp.resourceFactory.FromMap(mergedMap), err
}
type strategicMergePatch struct {
lookupPatchMeta strategicpatch.LookupPatchMeta
rf *resource.Factory
}
var _ conflictDetector = &strategicMergePatch{}
func newSMPConflictDetector(
versionedObj runtime.Object,
rf *resource.Factory) (conflictDetector, error) {
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err
}
func (smp *strategicMergePatch) hasConflict(
p1, p2 *resource.Resource) (bool, error) {
return strategicpatch.MergingMapsHaveConflicts(
p1.Map(), p2.Map(), smp.lookupPatchMeta)
}
func (smp *strategicMergePatch) findConflict(
conflictingPatchIdx int,
patches []*resource.Resource) (*resource.Resource, error) {
for i, patch := range patches {
if i == conflictingPatchIdx {
continue
}
if !patches[conflictingPatchIdx].OrgId().Equals(patch.OrgId()) {
continue
}
conflict, err := strategicpatch.MergingMapsHaveConflicts(
patch.Map(),
patches[conflictingPatchIdx].Map(),
smp.lookupPatchMeta)
if err != nil {
return nil, err
}
if conflict {
return patch, nil
}
}
return nil, nil
}
func (smp *strategicMergePatch) mergePatches(
patch1, patch2 *resource.Resource) (*resource.Resource, error) {
if hasDeleteDirectiveMarker(patch2.Map()) {
if hasDeleteDirectiveMarker(patch1.Map()) {
return nil, fmt.Errorf(
"cannot merge patches both containing '$patch: delete' directives")
}
patch1, patch2 = patch2, patch1
}
mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
return smp.rf.FromMap(mergeJSONMap), err
}
type merginatorImpl struct {
rf *resource.Factory
}
// NewMerginator returns a new implementation of resmap.Merginator.
func NewMerginator(rf *resource.Factory) resmap.Merginator {
return &merginatorImpl{rf: rf}
}
var _ resmap.Merginator = (*merginatorImpl)(nil)
// Merge merges the incoming resources into a new resmap.ResMap.
// Returns an error on conflict.
func (m *merginatorImpl) Merge(
patches []*resource.Resource) (resmap.ResMap, error) {
rc := resmap.New()
for ix, patch := range patches {
id := patch.OrgId()
existing := rc.GetMatchingResourcesByOriginalId(id.Equals)
if len(existing) == 0 {
rc.Append(patch)
continue
}
if len(existing) > 1 {
return nil, fmt.Errorf("self conflict in patches")
}
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk))
if err != nil && !runtime.IsNotRegisteredError(err) {
return nil, err
}
var cd conflictDetector
if err != nil {
cd = newJMPConflictDetector(m.rf)
} else {
cd, err = newSMPConflictDetector(versionedObj, m.rf)
if err != nil {
return nil, err
}
}
conflict, err := cd.hasConflict(existing[0], patch)
if err != nil {
return nil, err
}
if conflict {
conflictingPatch, err := cd.findConflict(ix, patches)
if err != nil {
return nil, err
}
return nil, fmt.Errorf(
"conflict between %#v and %#v",
conflictingPatch.Map(), patch.Map())
}
merged, err := cd.mergePatches(existing[0], patch)
if err != nil {
return nil, err
}
rc.Replace(merged)
}
return rc, nil
}
// toSchemaGvk converts to a schema.GroupVersionKind.
func toSchemaGvk(x resid.Gvk) schema.GroupVersionKind {
return schema.GroupVersionKind{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}
func hasDeleteDirectiveMarker(patch map[string]interface{}) bool {
if v, ok := patch["$patch"]; ok && v == "delete" {
return true
}
for _, v := range patch {
switch typedV := v.(type) {
case map[string]interface{}:
if hasDeleteDirectiveMarker(typedV) {
return true
}
case []interface{}:
for _, sv := range typedV {
typedE, ok := sv.(map[string]interface{})
if !ok {
break
}
if hasDeleteDirectiveMarker(typedE) {
return true
}
}
}
}
return false
}

View File

@@ -1,25 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package merge
import (
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
)
// Merginator implements resmap.Merginator using kyaml libs.
type Merginator struct {
}
var _ resmap.Merginator = (*Merginator)(nil)
func NewMerginator(_ *resource.Factory) *Merginator {
return &Merginator{}
}
// Merge implements resmap.Merginator
func (m Merginator) Merge(
resources []*resource.Resource) (resmap.ResMap, error) {
panic("TODO(#Merginator): implement Merge")
}

View File

@@ -1,4 +0,0 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package merge_test

View File

@@ -32,7 +32,8 @@ s/$BAR/bar baz/g
t.Fatal(err)
}
pvd := provider.NewDefaultDepProvider()
rf := resmap.NewFactory(pvd.GetResourceFactory(), pvd.GetMerginator())
rf := resmap.NewFactory(
pvd.GetResourceFactory(), pvd.GetConflictDetectorFactory())
pluginConfig := rf.RF().FromMap(
map[string]interface{}{
"apiVersion": "someteam.example.com/v1",

View File

@@ -51,7 +51,8 @@ func TestLoader(t *testing.T) {
BuildGoPlugin("someteam.example.com", "v1", "SomeServiceGenerator")
defer th.Reset()
p := provider.NewDefaultDepProvider()
rmF := resmap.NewFactory(p.GetResourceFactory(), p.GetMerginator())
rmF := resmap.NewFactory(
p.GetResourceFactory(), p.GetConflictDetectorFactory())
fLdr, err := loader.NewLoader(
loader.RestrictionRootOnly,
filesys.Separator, filesys.MakeFsInMemory())

View File

@@ -183,8 +183,7 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
return
}
var c struct {
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
}
c.Paths = kt.kustomization.PatchesStrategicMerge
p := f()

View File

@@ -36,7 +36,8 @@ func makeKustTargetWithRf(
if err != nil {
t.Fatal(err)
}
rf := resmap.NewFactory(pvd.GetResourceFactory(), pvd.GetMerginator())
rf := resmap.NewFactory(
pvd.GetResourceFactory(), pvd.GetConflictDetectorFactory())
pc := konfig.DisabledPluginConfig()
return target.NewKustTarget(
ldr,

View File

@@ -0,0 +1,36 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import (
"fmt"
"time"
"github.com/pkg/errors"
)
type errTimeOut struct {
duration time.Duration
cmd string
}
func NewErrTimeOut(d time.Duration, c string) errTimeOut {
return errTimeOut{duration: d, cmd: c}
}
func (e errTimeOut) Error() string {
return fmt.Sprintf("hit %s timeout running '%s'", e.duration, e.cmd)
}
func IsErrTimeout(err error) bool {
if err == nil {
return false
}
_, ok := err.(errTimeOut)
if ok {
return true
}
_, ok = errors.Cause(err).(errTimeOut)
return ok
}

View File

@@ -0,0 +1,23 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import (
"time"
)
// TimedCall runs fn, failing if it doesn't complete in the given duration.
// The description is used in the timeout error message.
func TimedCall(description string, d time.Duration, fn func() error) error {
done := make(chan error)
timer := time.NewTimer(d)
defer timer.Stop()
go func() { done <- fn() }()
select {
case err := <-done:
return err
case <-timer.C:
return NewErrTimeOut(d, description)
}
}

View File

@@ -0,0 +1,64 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils_test
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/internal/utils"
)
const (
timeToWait = 10 * time.Millisecond
tooSlow = 2 * timeToWait
)
func errMsg(msg string) string {
return fmt.Sprintf("hit %s timeout running '%s'", timeToWait, msg)
}
func TestTimedCallFastNoError(t *testing.T) {
err := TimedCall(
"fast no error", timeToWait,
func() error { return nil })
if !assert.NoError(t, err) {
t.Fatal(err)
}
}
func TestTimedCallFastWithError(t *testing.T) {
err := TimedCall(
"fast with error", timeToWait,
func() error { return assert.AnError })
if assert.Error(t, err) {
assert.EqualError(t, err, assert.AnError.Error())
} else {
t.Fail()
}
}
func TestTimedCallSlowNoError(t *testing.T) {
err := TimedCall(
"slow no error", timeToWait,
func() error { time.Sleep(tooSlow); return nil })
if assert.Error(t, err) {
assert.EqualError(t, err, errMsg("slow no error"))
} else {
t.Fail()
}
}
func TestTimedCallSlowWithError(t *testing.T) {
err := TimedCall(
"slow with error", timeToWait,
func() error { time.Sleep(tooSlow); return assert.AnError })
if assert.Error(t, err) {
assert.EqualError(t, err, errMsg("slow with error"))
} else {
t.Fail()
}
}

View File

@@ -10,6 +10,10 @@ import (
// FieldValidator implements ifc.Validator to check
// the values of various KRM string fields,
// e.g. labels, annotations, names, namespaces.
//
// TODO: Have this use kyaml/yaml/internal/k8sgen/pkg/labels
// which has label and annotation validation code, but is internal
// so this impl would need to move to kyaml (a fine idea).
type FieldValidator struct {
}

View File

@@ -91,8 +91,8 @@ func (wn *WNode) GetFieldValue(path string) (interface{}, error) {
// Return value as slice for SequenceNode kind
if yn.Kind == yaml.SequenceNode {
var result []interface{}
for _, node := range yn.Content {
result = append(result, node.Value)
if err := yn.Decode(&result); err != nil {
return nil, err
}
return result, nil
}
@@ -108,6 +108,16 @@ func (wn *WNode) GetGvk() resid.Gvk {
return resid.Gvk{Group: g, Version: v, Kind: meta.Kind}
}
// GetDataMap implements ifc.Kunstructured.
func (wn *WNode) GetDataMap() map[string]string {
return wn.node.GetDataMap()
}
// SetDataMap implements ifc.Kunstructured.
func (wn *WNode) SetDataMap(m map[string]string) {
wn.node.SetDataMap(m)
}
// GetKind implements ifc.Kunstructured.
func (wn *WNode) GetKind() string {
return wn.demandMetaData("GetKind").Kind
@@ -182,9 +192,7 @@ func (wn *WNode) SetAnnotations(annotations map[string]string) {
// SetGvk implements ifc.Kunstructured.
func (wn *WNode) SetGvk(gvk resid.Gvk) {
wn.setMapField(yaml.NewScalarRNode(gvk.Kind), yaml.KindField)
wn.setMapField(
yaml.NewScalarRNode(
fmt.Sprintf("%s/%s", gvk.Group, gvk.Version)), yaml.APIVersionField)
wn.setMapField(yaml.NewScalarRNode(gvk.ApiVersion()), yaml.APIVersionField)
}
// SetLabels implements ifc.Kunstructured.

View File

@@ -377,6 +377,39 @@ func TestGetFieldValueReturnsSlice(t *testing.T) {
}
}
func TestGetFieldValueReturnsSliceOfMappings(t *testing.T) {
bytes, err := yaml.Marshal(makeBigMap())
if err != nil {
t.Fatalf("unexpected yaml.Marshal err: %v", err)
}
rNode, err := kyaml.Parse(string(bytes))
if err != nil {
t.Fatalf("unexpected yaml.Marshal err: %v", err)
}
wn := FromRNode(rNode)
expected := []interface{}{
map[string]interface{}{
"field1": "idx0foo",
"field2": "idx0bar",
},
map[string]interface{}{
"field1": "idx1foo",
"field2": "idx1bar",
},
map[string]interface{}{
"field1": "idx2foo",
"field2": "idx2bar",
},
}
actual, err := wn.GetFieldValue("those")
if err != nil {
t.Fatalf("error getting slice: %v", err)
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Fatalf("actual slice does not deep equal expected slice:\n%v", diff)
}
}
func TestGetFieldValueReturnsString(t *testing.T) {
wn := NewWNode()
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {

View File

@@ -7,6 +7,7 @@ package kunstruct
import (
"encoding/json"
"fmt"
"log"
jsonpatch "github.com/evanphx/json-patch"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -249,6 +250,29 @@ func (fs *UnstructAdapter) GetStringMap(path string) (map[string]string, error)
return nil, NoFieldError{Field: path}
}
func (fs *UnstructAdapter) GetDataMap() map[string]string {
m, err := fs.GetStringMap("data")
if err != nil {
return map[string]string{}
}
return m
}
func (fs *UnstructAdapter) SetDataMap(m map[string]string) {
if m == nil {
unstructured.RemoveNestedField(fs.Object, "data")
return
}
s := make(map[string]interface{}, len(m))
for i, v := range m {
s[i] = v
}
err := unstructured.SetNestedMap(fs.Object, s, "data")
if err != nil {
log.Fatal(err)
}
}
// GetMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)

View File

@@ -6,6 +6,8 @@ package kunstruct
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
var kunstructured = NewKunstructuredFactoryImpl().FromMap(map[string]interface{}{
@@ -557,3 +559,139 @@ func compareValues(t *testing.T, name string, pathToField string, expectedValue
t.Logf("%T value at `%s`", typedV, pathToField)
}
}
func TestKunstGetDataMap(t *testing.T) {
emptyMap := map[string]string{}
testCases := map[string]struct {
theMap map[string]interface{}
expected map[string]string
}{
"actuallyNil": {
theMap: nil,
expected: emptyMap,
},
"empty": {
theMap: map[string]interface{}{},
expected: emptyMap,
},
"mostlyEmpty": {
theMap: map[string]interface{}{
"hey": "there",
},
expected: emptyMap,
},
"noNameConfigMap": {
theMap: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
},
expected: emptyMap,
},
"configMap": {
theMap: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
},
"data": map[string]interface{}{
"wine": "cabernet",
"truck": "ford",
"rocket": "falcon9",
"planet": "mars",
"city": "brownsville",
},
},
// order irrelevant, because assert.Equals is smart about maps.
expected: map[string]string{
"city": "brownsville",
"wine": "cabernet",
"planet": "mars",
"rocket": "falcon9",
"truck": "ford",
},
},
}
for n := range testCases {
tc := testCases[n]
t.Run(n, func(t *testing.T) {
kunstr := NewKunstructuredFactoryImpl().FromMap(tc.theMap)
m := kunstr.GetDataMap()
if !assert.Equal(t, tc.expected, m) {
t.FailNow()
}
})
}
}
func TestKunstSetDataMap(t *testing.T) {
testCases := map[string]struct {
theMap map[string]interface{}
input map[string]string
expected map[string]string
}{
"empty": {
theMap: map[string]interface{}{},
input: map[string]string{
"wine": "cabernet",
"truck": "ford",
},
expected: map[string]string{
"wine": "cabernet",
"truck": "ford",
},
},
"replace": {
theMap: map[string]interface{}{
"foo": 3,
"data": map[string]string{
"rocket": "falcon9",
"planet": "mars",
},
},
input: map[string]string{
"wine": "cabernet",
"truck": "ford",
},
expected: map[string]string{
"wine": "cabernet",
"truck": "ford",
},
},
"clear1": {
theMap: map[string]interface{}{
"foo": 3,
"data": map[string]string{
"rocket": "falcon9",
"planet": "mars",
},
},
input: map[string]string{},
expected: map[string]string{},
},
"clear2": {
theMap: map[string]interface{}{
"foo": 3,
"data": map[string]string{
"rocket": "falcon9",
"planet": "mars",
},
},
input: nil,
expected: map[string]string{},
},
}
for n := range testCases {
tc := testCases[n]
t.Run(n, func(t *testing.T) {
kunstr := NewKunstructuredFactoryImpl().FromMap(tc.theMap)
kunstr.SetDataMap(tc.input)
m := kunstr.GetDataMap()
if !assert.Equal(t, tc.expected, m) {
t.FailNow()
}
})
}
}

View File

@@ -51,6 +51,11 @@ commonLabels:
group: apps
kind: Deployment
- path: spec/template/spec/topologySpreadConstraints/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/selector/matchLabels
create: true
kind: ReplicaSet
@@ -97,6 +102,11 @@ commonLabels:
group: apps
kind: StatefulSet
- path: spec/template/spec/topologySpreadConstraints/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/volumeClaimTemplates[]/metadata/labels
create: true
group: apps

View File

@@ -121,6 +121,10 @@ nameReference:
kind: CronJob
- path: spec/configSource/configMap
kind: Node
- path: rules/resourceNames
kind: Role
- path: rules/resourceNames
kind: ClusterRole
- kind: Secret
version: v1

View File

@@ -19,9 +19,30 @@ func DefaultKustomizationFileName() string {
return RecognizedKustomizationFileNames()[0]
}
// IfApiMachineryElseKyaml returns true if executing the apimachinery code
// path, else we're executing the kyaml code paths.
func IfApiMachineryElseKyaml(s1, s2 string) string {
if !FlagEnableKyamlDefaultValue {
return s1
}
return s2
}
const (
// FlagEnableKyamlDefaultValue is the default value for the --enable_kyaml
// flag. This value is also used in unit tests. See provider.DepProvider.
//
// TODO(#3304): eliminate branching on this constant.
// Details: https://github.com/kubernetes-sigs/kustomize/issues/3304
//
// All tests should pass for either true or false values
// of this constant, without having to check its value.
// In the cases where there's a different outcome, either decide
// that the difference is acceptable, or make the difference go away.
//
// Historically, tests passed for enable_kyaml == false, i.e. using
// apimachinery libs. This doesn't mean the code was better, it just
// means regression tests preserved those outcomes.
FlagEnableKyamlDefaultValue = false
// An environment variable to consult for kustomization

View File

@@ -39,8 +39,8 @@ resources:
configMapGenerator:
- name: my-configmap
literals:
- testValue=1
- otherValue=10
- testValue=purple
- otherValue=green
`)
th.WriteF("/app/base/deploy.yaml", `
apiVersion: v1
@@ -64,8 +64,8 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- testValue=2
- compValue=5
- testValue=blue
- compValue=red
`)
th.WriteF("/app/comp/stub.yaml", `
apiVersion: v1
@@ -125,14 +125,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "10"
testValue: "2"
compValue: red
otherValue: green
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-kc6k2kmkh9
name: comp-my-configmap-97647ckcmg
---
apiVersion: v1
kind: Deployment
@@ -156,7 +154,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
writeK("/app/prod", `
resources:
@@ -179,14 +177,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "9"
testValue: "2"
compValue: red
otherValue: orange
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-55249mf5kb
name: comp-my-configmap-g486mb229k
---
apiVersion: v1
kind: Deployment
@@ -212,7 +208,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
writeK("/app/prod", `
resources:
@@ -234,14 +230,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "9"
testValue: "2"
compValue: red
otherValue: orange
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-55249mf5kb
name: comp-my-configmap-g486mb229k
---
apiVersion: v1
kind: Deployment
@@ -279,11 +273,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "10"
testValue: "1"
otherValue: green
testValue: purple
kind: ConfigMap
metadata:
name: my-configmap-2g9c94mhb8
name: my-configmap-9cd648hm8f
---
apiVersion: v1
kind: Deployment
@@ -294,14 +288,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "10"
testValue: "2"
compValue: red
otherValue: green
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-kc6k2kmkh9
name: comp-my-configmap-97647ckcmg
---
apiVersion: v1
kind: Deployment
@@ -327,8 +319,8 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- compValue=5
- testValue=2
- compValue=red
- testValue=blue
`),
},
runPath: "/app/direct-component",
@@ -342,14 +334,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "10"
testValue: "2"
compValue: red
otherValue: green
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: my-configmap-kc6k2kmkh9
name: my-configmap-97647ckcmg
`,
},
"missing-optional-component-api-version": {
@@ -360,7 +350,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
},
runPath: "/app/prod",
@@ -374,13 +364,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "9"
testValue: "1"
otherValue: orange
testValue: purple
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: my-configmap-5g7gh5mgt5
name: my-configmap-6hhdg8gkdg
---
apiVersion: v1
kind: Deployment
@@ -423,11 +411,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "10"
testValue: "1"
otherValue: green
testValue: purple
kind: ConfigMap
metadata:
name: my-configmap-a-b-2g9c94mhb8
name: my-configmap-a-b-9cd648hm8f
---
apiVersion: v1
kind: Deployment
@@ -438,11 +426,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "10"
testValue: "1"
otherValue: green
testValue: purple
kind: ConfigMap
metadata:
name: my-configmap-b-2g9c94mhb8
name: my-configmap-b-9cd648hm8f
`,
},
@@ -574,7 +562,7 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
},
runPath: "/app/prod",

View File

@@ -4,11 +4,100 @@
package krusty_test
import (
"fmt"
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// Numbers and booleans are quoted
func TestGeneratorIntVsStringNoMerge(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- service.yaml
configMapGenerator:
- name: bob
literals:
- fruit=Indian Gooseberry
- year=2020
- crisis=true
`)
th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
annotations:
port: 8080
happy: true
color: green
name: demo
spec:
clusterIP: None
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(
m, `
apiVersion: v1
kind: Service
metadata:
annotations:
color: green
happy: true
port: 8080
name: demo
spec:
clusterIP: None
---
apiVersion: v1
data:
crisis: "true"
fruit: Indian Gooseberry
year: "2020"
kind: ConfigMap
metadata:
name: bob-79t79mt227
`)
}
// Observation: Numbers no longer quoted
func TestGeneratorIntVsStringWithMerge(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
configMapGenerator:
- name: bob
literals:
- fruit=Indian Gooseberry
- year=2020
- crisis=true
`)
th.WriteK("overlay", `
resources:
- ../base
configMapGenerator:
- name: bob
behavior: merge
literals:
- month=12
`)
opts := th.MakeDefaultOptions()
m := th.Run("overlay", opts)
expFmt := `apiVersion: v1
data:
crisis: %s
fruit: Indian Gooseberry
month: %s
year: %s
kind: ConfigMap
metadata:
name: bob-%s
`
th.AssertActualEqualsExpected(
m, opts.IfApiMachineryElseKyaml(
fmt.Sprintf(expFmt, `"true"`, `"12"`, `"2020"`, `bk46gm59c6`),
fmt.Sprintf(expFmt, `true`, `12`, `2020`, `bkmtk2t2fb`)))
}
// Generate a Secret and a ConfigMap from the same data
// to compare the result.
func TestGeneratorBasics(t *testing.T) {
@@ -59,10 +148,9 @@ electromagnetic
strong nuclear
weak nuclear
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
opts := th.MakeDefaultOptions()
m := th.Run("/app", opts)
expFmt := `apiVersion: v1
data:
MOUNTAIN: everest
OCEAN: pacific
@@ -95,15 +183,26 @@ apiVersion: v1
data:
MOUNTAIN: ZXZlcmVzdA==
OCEAN: cGFjaWZpYw==
forces.txt: CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbnVjbGVhcgo=
forces.txt: %s
fruit: YXBwbGU=
passphrase: CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aGUgZXZpbCBkYXlzIGNvbWUgbm90Lgo=
passphrase: %s
vegetable: YnJvY2NvbGk=
kind: Secret
metadata:
name: blah-bob-ftht6hfgmb
name: blah-bob-%s
type: Opaque
`)
`
th.AssertActualEqualsExpected(
m, opts.IfApiMachineryElseKyaml(
fmt.Sprintf(expFmt,
`CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbnVjbGVhcgo=`,
`CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aGUgZXZpbCBkYXlzIGNvbWUgbm90Lgo=`,
`ftht6hfgmb`),
fmt.Sprintf(expFmt, `|
CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbn
VjbGVhcgo=`, `|
CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aG
UgZXZpbCBkYXlzIGNvbWUgbm90Lgo=`, `9t25t44gg4`)))
}
// TODO: These should be errors instead.
@@ -159,6 +258,68 @@ metadata:
`)
}
func TestIssue3393(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- cm.yaml
configMapGenerator:
- name: project
behavior: merge
literals:
- ANOTHER_ENV_VARIABLE="bar"
`)
th.WriteF("cm.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: project
data:
A_FIRST_ENV_VARIABLE: "foo"
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
A_FIRST_ENV_VARIABLE: foo
ANOTHER_ENV_VARIABLE: bar
kind: ConfigMap
metadata:
name: project
`)
}
func TestGeneratorSimpleOverlay(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
namePrefix: p-
configMapGenerator:
- name: cm
behavior: create
literals:
- fruit=apple
`)
th.WriteK("overlay", `
resources:
- ../base
configMapGenerator:
- name: cm
behavior: merge
literals:
- veggie=broccoli
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
fruit: apple
veggie: broccoli
kind: ConfigMap
metadata:
name: p-cm-877mt5hc89
`)
}
func TestGeneratorOverlays(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base1", `
@@ -215,8 +376,6 @@ data:
from: overlay
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: p1-com1-8tc62428t2
---
apiVersion: v1
@@ -224,8 +383,6 @@ data:
from: overlay
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: p2-com2-87mcggf7d7
`)
}
@@ -272,8 +429,6 @@ data:
foo: bar
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: o1-cm-ft9mmdc8c6
---
apiVersion: v1
@@ -282,8 +437,6 @@ data:
foo: bar
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: cm-o2-5k95kd76ft
`)
}

View File

@@ -32,7 +32,7 @@ spec:
action: fly
`)
th.WriteF("/app/base/mykind.yaml", `
apiVersion: jingfang.example.com/v1beta1
apiVersion: jingfang.example.com/v1
kind: MyKind
metadata:
name: mykind
@@ -236,7 +236,7 @@ kind: Secret
metadata:
name: x-crdsecret
---
apiVersion: jingfang.example.com/v1beta1
apiVersion: jingfang.example.com/v1
kind: MyKind
metadata:
name: x-mykind
@@ -285,7 +285,7 @@ kind: Secret
metadata:
name: prod-x-crdsecret
---
apiVersion: jingfang.example.com/v1beta1
apiVersion: jingfang.example.com/v1
kind: MyKind
metadata:
name: prod-x-mykind

View File

@@ -1,6 +1,7 @@
package krusty_test
import (
"fmt"
"os/exec"
"testing"
@@ -128,8 +129,9 @@ stringData:
bootcmd:
- mkdir /mnt/vda
`)
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `
opts := th.MakeOptionsPluginsEnabled()
m := th.Run("/app", opts)
expFmt := `
apiVersion: v1
kind: Secret
metadata:
@@ -152,7 +154,7 @@ metadata:
name: demo
name: demo-budget
spec:
minAvailable: 67%
minAvailable: 67%%
selector:
matchLabels:
app: cockroachdb
@@ -185,9 +187,7 @@ metadata:
annotations:
config.kubernetes.io/path: config/demo_service.yaml
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
%s
labels:
app: cockroachdb
name: demo
@@ -244,7 +244,7 @@ spec:
- /bin/bash
- -ecx
- |
# The use of qualified `+"`hostname -f`"+` is crucial:
# The use of qualified ` + "`hostname -f`" + ` is crucial:
# Other nodes aren't able to look up the unqualified hostname.
CRARGS=("start" "--logtostderr" "--insecure" "--host" "$(hostname -f)" "--http-host" "0.0.0.0")
# We only want to initialize a new cluster (by omitting the join flag)
@@ -302,7 +302,14 @@ spec:
resources:
requests:
storage: 1Gi
`)
`
th.AssertActualEqualsExpected(m, opts.IfApiMachineryElseKyaml(
fmt.Sprintf(expFmt, ` prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"`),
fmt.Sprintf(expFmt, ` prometheus.io/port: 8080
prometheus.io/scrape: true
service.alpha.kubernetes.io/tolerate-unready-endpoints: true`)))
}
func TestFnContainerTransformer(t *testing.T) {

View File

@@ -0,0 +1,622 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
"github.com/stretchr/testify/assert"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// Regression test for https://github.com/kubernetes-sigs/kustomize/issues/3280
// GVKN shouldn't change with default options
func TestKeepOriginalGVKN(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("apps/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("apps/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: new-name
`)
th.WriteK("apps", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
m := th.Run("apps", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
// https://github.com/kubernetes-sigs/kustomize/issues/3280
// These tests document behavior that will change
func TestChangeName(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("apps/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("apps/patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: new-name
`)
th.WriteK("apps", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// name should become `new-name`
m := th.Run("apps", options)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
func TestChangeKind(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("apps/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("apps/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: old-name
`)
th.WriteK("apps", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// kind should become `StatefulSet`
m := th.Run("apps", options)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
func TestChangeNameAndKind(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("apps/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("apps/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: new-name
`)
th.WriteK("apps", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// kind should become `StatefulSet`
// name should become `new-name`
m := th.Run("apps", options)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
// https://github.com/kubernetes-sigs/kustomize/issues/3280
// Should be able to refer to a resource with either its
// original GVKN or its current one
func TestPatchOriginalName(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("base/patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: new-name
`)
th.WriteK("base", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- depPatch.yaml
`)
th.WriteF("overlay/depPatch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
replicas: 999
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// name should become `new-name`
m := th.Run("overlay", options)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
replicas: 999
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
func TestPatchNewName(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("base/patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: new-name
`)
th.WriteK("base", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- depPatch.yaml
`)
th.WriteF("overlay/depPatch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: new-name
spec:
replicas: 999
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// depPatch cannot find target with the name `new-name`
// because base/patch.yaml can't yet edit the name
assert.Error(t, th.RunWithErr("overlay", options))
}
func TestPatchOriginalNameAndKind(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("base/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: new-name
`)
th.WriteK("base", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- depPatch.yaml
`)
th.WriteF("overlay/depPatch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
replicas: 999
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// kind should become `StatefulSet`
// name should become `new-name`
m := th.Run("overlay", options)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
replicas: 999
template:
spec:
containers:
- image: nginx
name: nginx
`)
}
func TestPatchNewNameAndKind(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("base/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: new-name
`)
th.WriteK("base", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- depPatch.yaml
`)
th.WriteF("overlay/depPatch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: new-name
spec:
replicas: 999
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// depPatch cannot find target with kind `StatefulSet` and name `new-name`
// because base/patch.yaml can't yet edit the kind or name
assert.Error(t, th.RunWithErr("overlay", options))
}
// Use original name, but new kind
// Should fail, even after #3280 is done, because this ID is invalid
func TestPatchOriginalNameAndNewKind(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-name
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteF("base/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: new-name
`)
th.WriteK("base", `
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
`)
th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- depPatch.yaml
`)
th.WriteF("overlay/depPatch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: new-name
spec:
replicas: 999
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// depPatch cannot find target with kind `Deployment` and name `new-name`
// because the resource never had this GVKN
assert.Error(t, th.RunWithErr("overlay", options))
}
// Here is a structure of a kustomization of two components, component1
// and component2, that both use a shared deployment definition, which
// component2 adjusts by changing the kind via a patch. This test case
// checks that it does not have a conflicting definition.
// Currently documents broken behavior.
//
// root
// / \
// component1/overlay component2/overlay
// | |
// component1/base component2/base
// \ /
// base
//
// This is the directory layout:
//
// ├── component1
// │ ├── base
// │ │ └── kustomization.yaml
// │ └── overlay
// │ └── kustomization.yaml
// ├── component2
// │ ├── base
// │ │ └── kustomization.yaml
// │ └── overlay
// │ └── kustomization.yaml
// ├── shared
// │ ├── kustomization.yaml
// │ └── deployment.yaml
// ├── kustomization.yaml
func TestBaseReuseNameAndKindConflict(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/shared", `
resources:
- deployment.yaml
`)
th.WriteF("/app/shared/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deploy
spec:
template:
spec:
containers:
- name: nginx
image: nginx
`)
th.WriteK("/app/component1/base", `
resources:
- ../../shared
`)
th.WriteK("/app/component1/overlay", `
resources:
- ../base
namePrefix: overlay-
`)
th.WriteK("/app/component2/base", `
resources:
- ../../shared
patches:
- path: patch.yaml
target:
kind: Deployment
name: my-deploy
`)
th.WriteF("/app/component2/base/patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-stateful-set
`)
th.WriteK("/app/component2/overlay", `
resources:
- ../base
namePrefix: overlay-
`)
th.WriteK("/app", `
resources:
- component1/overlay
- component2/overlay
`)
options := th.MakeDefaultOptions()
options.AllowResourceIdChanges = true
// Error occurs when app/component2/base tries to load the shared resources
// because the kind is not (yet) allowed to change yet
// so it loads a second Deployment with the name my-deploy
// instead of a StatefulSet as specified by the patch.
// Will be fixed by #3280.
assert.Error(t, th.RunWithErr("overlay", options))
}

View File

@@ -53,7 +53,7 @@ func MakeKustomizer(fSys filesys.FileSystem, o *Options) *Kustomizer {
func (b *Kustomizer) Run(path string) (resmap.ResMap, error) {
resmapFactory := resmap.NewFactory(
b.depProvider.GetResourceFactory(),
b.depProvider.GetMerginator())
b.depProvider.GetConflictDetectorFactory())
lr := fLdr.RestrictionNone
if b.options.LoadRestrictions == types.LoadRestrictionsRootOnly {
lr = fLdr.RestrictionRootOnly

View File

@@ -4,12 +4,333 @@
package krusty_test
import (
"fmt"
"strings"
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestRemoveEmptyDirWithNullFieldInSmp(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- deployment.yaml
patchesStrategicMerge:
- patch.yaml
`)
th.WriteF("deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: fancyDisk
emptyDir: {}
`)
th.WriteF("patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: fancyDisk
emptyDir: null
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: fancyDisk
`)
}
func TestRemoveEmptyDirAddPersistentDisk(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- deployment.yaml
patchesStrategicMerge:
- patch.yaml
`)
th.WriteF("deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: fancyDisk
emptyDir: {}
`)
th.WriteF("patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: fancyDisk
emptyDir: null
gcePersistentDisk:
pdName: fancyDisk
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- gcePersistentDisk:
pdName: fancyDisk
name: fancyDisk
`)
}
func TestVolumeRemoveEmptyDirInOverlay(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
resources:
- deployment.yaml
configMapGenerator:
- name: baseCm
literals:
- foo=bar
`)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: fancyDisk
mountPath: /tmp/ps
volumes:
- name: fancyDisk
emptyDir: {}
- configMap:
name: baseCm
name: baseCm
`)
m := th.Run("base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /tmp/ps
name: fancyDisk
volumes:
- emptyDir: {}
name: fancyDisk
- configMap:
name: baseCm-798k5k7g9f
name: baseCm
---
apiVersion: v1
data:
foo: bar
kind: ConfigMap
metadata:
name: baseCm-798k5k7g9f
`)
th.WriteK("overlay", `
patchesStrategicMerge:
- patch.yaml
resources:
- ../base
configMapGenerator:
- name: overlayCm
literals:
- hello=world
`)
th.WriteF("overlay/patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: fancyDisk
emptyDir: null
gcePersistentDisk:
pdName: fancyDisk
- configMap:
name: overlayCm
name: overlayCm
`)
m = th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /tmp/ps
name: fancyDisk
volumes:
- gcePersistentDisk:
pdName: fancyDisk
name: fancyDisk
- configMap:
name: overlayCm-dc6fm46dhm
name: overlayCm
- configMap:
name: baseCm-798k5k7g9f
name: baseCm
---
apiVersion: v1
data:
foo: bar
kind: ConfigMap
metadata:
name: baseCm-798k5k7g9f
---
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
name: overlayCm-dc6fm46dhm
`)
}
func TestRemoveEmptyDirWithPatchesAtSameLevel(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
resources:
- deployment.yaml
`)
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
image: nginx
- name: sidecar
image: sidecar:latest
volumes:
- name: nginx-persistent-storage
emptyDir: {}
`)
th.WriteK("overlay", `
patchesStrategicMerge:
- deployment-patch1.yaml
- deployment-patch2.yaml
resources:
- ../base
`)
th.WriteF("overlay/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
volumes:
- name: nginx-persistent-storage
emptyDir: null
gcePersistentDisk:
pdName: nginx-persistent-storage
`)
th.WriteF("overlay/deployment-patch2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- image: nginx
name: nginx
env:
- name: ANOTHERENV
value: FOO
volumes:
- name: nginx-persistent-storage
`)
opts := th.MakeDefaultOptions()
m := th.Run("overlay", opts)
expFmt := `apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- env:
- name: ANOTHERENV
value: FOO
image: nginx
name: nginx
- image: sidecar:latest
name: sidecar
volumes:%s
name: nginx-persistent-storage
`
// TODO(#3394)
th.AssertActualEqualsExpected(
m, opts.IfApiMachineryElseKyaml(
fmt.Sprintf(expFmt, `
- gcePersistentDisk:
pdName: nginx-persistent-storage`),
fmt.Sprintf(expFmt, `
- emptyDir: {}
gcePersistentDisk:
pdName: nginx-persistent-storage`),
))
}
func TestSimpleMultiplePatches(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
@@ -41,8 +362,6 @@ spec:
- name: sidecar
image: sidecar:latest
volumes:
- name: nginx-persistent-storage
emptyDir: {}
- configMap:
name: configmap-in-base
name: configmap-in-base
@@ -86,7 +405,6 @@ spec:
value: ENVVALUE
volumes:
- name: nginx-persistent-storage
emptyDir: null
gcePersistentDisk:
pdName: nginx-persistent-storage
- configMap:
@@ -106,8 +424,6 @@ spec:
env:
- name: ANOTHERENV
value: FOO
volumes:
- name: nginx-persistent-storage
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
@@ -188,7 +504,7 @@ metadata:
`)
}
func makeCommonFileForMultiplePatchTest(th kusttest_test.Harness) {
func makeCommonFilesForMultiplePatchTests(th kusttest_test.Harness) {
th.WriteK("/app/base", `
namePrefix: team-foo-
commonLabels:
@@ -227,8 +543,6 @@ spec:
- name: sidecar
image: sidecar:latest
volumes:
- name: nginx-persistent-storage
emptyDir: {}
- configMap:
name: configmap-in-base
name: configmap-in-base
@@ -264,7 +578,7 @@ configMapGenerator:
func TestMultiplePatchesNoConflict(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
makeCommonFilesForMultiplePatchTests(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
@@ -281,7 +595,6 @@ spec:
value: ENVVALUE
volumes:
- name: nginx-persistent-storage
emptyDir: null
gcePersistentDisk:
pdName: nginx-persistent-storage
- configMap:
@@ -301,8 +614,6 @@ spec:
env:
- name: ANOTHERENV
value: FOO
volumes:
- name: nginx-persistent-storage
`)
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
@@ -405,7 +716,7 @@ metadata:
func TestMultiplePatchesWithConflict(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
makeCommonFilesForMultiplePatchTests(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
@@ -421,7 +732,6 @@ spec:
value: TRUE
volumes:
- name: nginx-persistent-storage
emptyDir: null
gcePersistentDisk:
pdName: nginx-persistent-storage
- configMap:
@@ -442,13 +752,114 @@ spec:
- name: ENABLE_FEATURE_FOO
value: FALSE
`)
err := th.RunWithErr("/app/overlay/staging", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected conflict")
}
if !strings.Contains(
err.Error(), "conflict between ") {
t.Fatalf("Unexpected err: %v", err)
opts := th.MakeDefaultOptions()
if opts.UseKyaml {
// kyaml doesn't try to detect conflicts in patches
// (so ENABLE_FEATURE_FOO FALSE wins).
m := th.Run("/app/overlay/staging", opts)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
name: staging-team-foo-nginx
spec:
selector:
matchLabels:
app: mynginx
env: staging
org: example.com
team: foo
template:
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
spec:
containers:
- env:
- name: ENABLE_FEATURE_FOO
value: false
image: nginx
name: nginx
volumeMounts:
- mountPath: /tmp/ps
name: nginx-persistent-storage
- image: sidecar:latest
name: sidecar
volumes:
- gcePersistentDisk:
pdName: nginx-persistent-storage
name: nginx-persistent-storage
- configMap:
name: staging-configmap-in-overlay-dc6fm46dhm
name: configmap-in-overlay
- configMap:
name: staging-team-foo-configmap-in-base-798k5k7g9f
name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
name: staging-team-foo-nginx
spec:
ports:
- port: 80
selector:
app: mynginx
env: staging
org: example.com
team: foo
---
apiVersion: v1
data:
foo: bar
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-798k5k7g9f
---
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
name: staging-configmap-in-overlay-dc6fm46dhm
`)
} else {
err := th.RunWithErr("/app/overlay/staging", opts)
if err == nil {
t.Fatalf("expected conflict")
}
if !strings.Contains(
err.Error(), "conflict between ") {
t.Fatalf("Unexpected err: %v", err)
}
}
}
@@ -497,8 +908,7 @@ spec:
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
makeCommonFilesForMultiplePatchTests(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", c.patch1)
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", c.patch2)
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
@@ -540,8 +950,6 @@ spec:
- mountPath: /tmp/ps
name: nginx-persistent-storage
volumes:
- emptyDir: {}
name: nginx-persistent-storage
- configMap:
name: staging-team-foo-configmap-in-base-798k5k7g9f
name: configmap-in-base
@@ -595,7 +1003,7 @@ metadata:
func TestMultiplePatchesBothWithPatchDeleteDirective(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
makeCommonFilesForMultiplePatchTests(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
@@ -620,12 +1028,98 @@ spec:
- $patch: delete
name: nginx
`)
err := th.RunWithErr("/app/overlay/staging", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected error")
}
if !strings.Contains(
err.Error(), "both containing ") {
t.Fatalf("Unexpected err: %v", err)
opt := th.MakeDefaultOptions()
if opt.UseKyaml {
// kyaml doesn't fail on conflicts in patches; both containers
// (nginx and sidecar) are deleted per this patching instruction.
m := th.Run("/app/overlay/staging", opt)
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
name: staging-team-foo-nginx
spec:
selector:
matchLabels:
app: mynginx
env: staging
org: example.com
team: foo
template:
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
spec:
containers: []
volumes:
- configMap:
name: staging-team-foo-configmap-in-base-798k5k7g9f
name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
annotations:
note: This is a test annotation
labels:
app: mynginx
env: staging
org: example.com
team: foo
name: staging-team-foo-nginx
spec:
ports:
- port: 80
selector:
app: mynginx
env: staging
org: example.com
team: foo
---
apiVersion: v1
data:
foo: bar
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-798k5k7g9f
---
apiVersion: v1
data:
hello: world
kind: ConfigMap
metadata:
labels:
env: staging
name: staging-configmap-in-overlay-dc6fm46dhm
`)
} else {
// No kyaml means error on a patch conflict.
err := th.RunWithErr("/app/overlay/staging", opt)
if err == nil {
t.Fatalf("Expected error")
}
if !strings.Contains(
err.Error(), "both containing ") {
t.Fatalf("Unexpected err: %v", err)
}
}
}

View File

@@ -38,7 +38,7 @@ configMapGenerator:
literals:
- MYSQL_USER=default
- MYSQL_DATABASE=default
- PORT=3306
- HOST=everest
`)
th.WriteK(".", `
@@ -82,15 +82,13 @@ patches:
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
HOST: everest
MYSQL_DATABASE: db
MYSQL_PASSWORD: correct horse battery staple
MYSQL_USER: my-user
PORT: "3306"
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: mysql-9792mdchtg
name: mysql-t7tt4cdbmf
---
apiVersion: apps/v1
kind: Deployment
@@ -104,10 +102,10 @@ spec:
- valueFrom:
configMapKeyRef:
key: MYSQL_DATABASE
name: mysql-9792mdchtg
name: mysql-t7tt4cdbmf
envFrom:
- configMapRef:
name: mysql-9792mdchtg
name: mysql-t7tt4cdbmf
name: handler
`)
}

View File

@@ -80,7 +80,7 @@ namespace: base
configMapGenerator:
- name: testCase
literals:
- base=true
- base=apple
`)
th.WriteK("/app/overlay", `
resources:
@@ -92,19 +92,17 @@ configMapGenerator:
- name: testCase
behavior: merge
literals:
- overlay=true
- overlay=peach
`)
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
base: "true"
overlay: "true"
base: apple
overlay: peach
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: testCase-bcbmmg48hd
name: testCase-gmfch8gkbt
namespace: overlay
`)
}

View File

@@ -307,7 +307,7 @@ metadata:
`)
}
// This serie of constants is used to prove the need of
// This series of constants is used to prove the need of
// the namespace field in the objref field of the var declaration.
// The following tests demonstrate that it creates umbiguous variable
// declaration if two entities of the kind with the same name
@@ -472,10 +472,12 @@ spec:
// not specified
func TestVariablesAmbiguous(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/namespaceNeedInVar/myapp", namespaceNeedInVarMyApp)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
err := th.RunWithErr("/namespaceNeedInVar/myapp", th.MakeDefaultOptions())
th.WriteK(".", namespaceNeedInVarMyApp)
th.WriteF("elasticsearch-dev-service.yaml",
namespaceNeedInVarDevResources)
th.WriteF("elasticsearch-test-service.yaml",
namespaceNeedInVarTestResources)
err := th.RunWithErr(".", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error")
}
@@ -529,16 +531,20 @@ vars:
// and resources into multiple kustomization context/folders instead of one.
func TestVariablesAmbiguousWorkaround(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/namespaceNeedInVar/dev", namespaceNeedInVarDevFolder)
th.WriteF("/namespaceNeedInVar/dev/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteK("/namespaceNeedInVar/test", namespaceNeedInVarTestFolder)
th.WriteF("/namespaceNeedInVar/test/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
th.WriteK("/namespaceNeedInVar/workaround", `
opts := th.MakeDefaultOptions()
if opts.UseKyaml {
t.Skip("TODO(#3396)")
}
th.WriteK("dev", namespaceNeedInVarDevFolder)
th.WriteF("dev/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteK("test", namespaceNeedInVarTestFolder)
th.WriteF("test/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
th.WriteK("workaround", `
resources:
- ../dev
- ../test
`)
m := th.Run("/namespaceNeedInVar/workaround", th.MakeDefaultOptions())
m := th.Run("workaround", opts)
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
}
@@ -585,9 +591,13 @@ vars:
// to the variable declarations allows to disambiguate the variables.
func TestVariablesDisambiguatedWithNamespace(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/namespaceNeedInVar/myapp", namespaceNeedInVarMyAppWithNamespace)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
m := th.Run("/namespaceNeedInVar/myapp", th.MakeDefaultOptions())
opts := th.MakeDefaultOptions()
if opts.UseKyaml {
t.Skip("TODO(#3396)")
}
th.WriteK(".", namespaceNeedInVarMyAppWithNamespace)
th.WriteF("elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteF("elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
}

View File

@@ -34,7 +34,7 @@ subjects:
- kind: ServiceAccount
name: default
namespace: foo
---
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:

View File

@@ -36,16 +36,28 @@ type Options struct {
// When true, use kyaml/ packages to manipulate KRM yaml.
// When false, use k8sdeps/ instead (uses k8s.io/api* packages).
UseKyaml bool
// When true, allow name and kind changing via a patch
// When false, patch name/kind don't overwrite target name/kind
AllowResourceIdChanges bool
}
// MakeDefaultOptions returns a default instance of Options.
func MakeDefaultOptions() *Options {
return &Options{
DoLegacyResourceSort: false,
AddManagedbyLabel: false,
LoadRestrictions: types.LoadRestrictionsRootOnly,
DoPrune: false,
PluginConfig: konfig.DisabledPluginConfig(),
UseKyaml: false,
DoLegacyResourceSort: false,
AddManagedbyLabel: false,
LoadRestrictions: types.LoadRestrictionsRootOnly,
DoPrune: false,
PluginConfig: konfig.DisabledPluginConfig(),
UseKyaml: konfig.FlagEnableKyamlDefaultValue,
AllowResourceIdChanges: false,
}
}
func (o Options) IfApiMachineryElseKyaml(s1, s2 string) string {
if !o.UseKyaml {
return s1
}
return s2
}

View File

@@ -0,0 +1,40 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/krusty"
)
func TestRemoteLoad(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
b := krusty.MakeKustomizer(fSys, krusty.MakeDefaultOptions())
m, err := b.Run(
"github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6")
if utils.IsErrTimeout(err) {
// Don't fail on timeouts.
t.SkipNow()
}
if !assert.NoError(t, err) {
t.FailNow()
}
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Pod
metadata:
labels:
app: myapp
name: dev-myapp-pod
spec:
containers:
- image: nginx:1.7.9
name: nginx
`, string(yml))
}

47
api/krusty/simple_test.go Normal file
View File

@@ -0,0 +1,47 @@
// 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"
)
func TestSimple1(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("/dep.yaml", `
apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 1
`)
th.WriteF("/patch.yaml", `
apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`)
th.WriteK("/", `
resources:
- dep.yaml
patchesStrategicMerge:
- patch.yaml
`)
m := th.Run("/", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`)
}

View File

@@ -74,7 +74,7 @@ kind: ConfigMap
metadata:
name: configmap-a
annotations:
kustomize.k8s.io/Generated: "false"
fruit: peach
data:
foo: $FOO
`)
@@ -87,7 +87,7 @@ data:
kind: ConfigMap
metadata:
annotations:
kustomize.k8s.io/Generated: "false"
fruit: peach
name: configmap-a
---
apiVersion: v1

View File

@@ -362,6 +362,10 @@ resources:
func TestVarRefBig(t *testing.T) {
th := kusttest_test.MakeHarness(t)
opts := th.MakeDefaultOptions()
if opts.UseKyaml {
t.Skip("TODO(#3396)")
}
th.WriteK("/app/base", `
namePrefix: base-
resources:
@@ -678,7 +682,7 @@ namePrefix: dev-
resources:
- ../../base
`)
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
m := th.Run("/app/overlay/staging", opts)
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount

View File

@@ -7,11 +7,13 @@ import (
"context"
"log"
"os"
"time"
"github.com/yujunz/go-getter"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/git"
"sigs.k8s.io/kustomize/api/internal/utils"
)
type remoteTargetSpec struct {
@@ -28,7 +30,12 @@ type remoteTargetSpec struct {
// Getter is a function that can gets resource
type remoteTargetGetter func(rs *remoteTargetSpec) error
func newLoaderAtGetter(raw string, fSys filesys.FileSystem, referrer *fileLoader, cloner git.Cloner, getter remoteTargetGetter) (ifc.Loader, error) {
func newLoaderAtGetter(
raw string,
fSys filesys.FileSystem,
referrer *fileLoader,
cloner git.Cloner,
getter remoteTargetGetter) (ifc.Loader, error) {
rs := &remoteTargetSpec{
Raw: raw,
}
@@ -80,12 +87,13 @@ func getRemoteTarget(rs *remoteTargetSpec) error {
Mode: getter.ClientModeAny,
Detectors: []getter.Detector{
new(getter.GitHubDetector),
new(getter.GitLabDetector),
new(getter.GitDetector),
new(getter.BitBucketDetector),
},
Options: opts,
}
return client.Get()
return utils.TimedCall("go-getter client.Get", 21*time.Second, client.Get)
}
func getNothing(rs *remoteTargetSpec) error {

View File

@@ -21,24 +21,22 @@ import (
func NewLoader(
lr LoadRestrictorFunc,
target string, fSys filesys.FileSystem) (ifc.Loader, error) {
ldr, errGet := newLoaderAtGetter(target, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget)
ldr, errGet := newLoaderAtGetter(
target, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget)
if errGet == nil {
return ldr, nil
}
repoSpec, errGit := git.NewRepoSpecFromUrl(target)
if errGit == nil {
// The target qualifies as a remote git target.
return newLoaderAtGitClone(
repoSpec, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget)
}
root, errDir := demandDirectoryRoot(fSys, target)
if errDir == nil {
return newLoaderAtConfirmedDir(lr, root, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget), nil
return newLoaderAtConfirmedDir(
lr, root, fSys, nil, git.ClonerUsingGitExec, getRemoteTarget), nil
}
return nil, fmt.Errorf(
"error creating new loader with git: %v, dir: %v, get: %v",
errGit, errDir, errGet)

View File

@@ -5,14 +5,13 @@ package provider
import (
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/merge"
kmerge "sigs.k8s.io/kustomize/api/internal/merge"
"sigs.k8s.io/kustomize/api/internal/conflict"
k8sconflict "sigs.k8s.io/kustomize/api/internal/k8sdeps/conflict"
"sigs.k8s.io/kustomize/api/internal/validate"
"sigs.k8s.io/kustomize/api/internal/wrappy"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/k8sdeps/validator"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
)
@@ -96,17 +95,27 @@ import (
// would really reduce the work
// (e.g. drop Vars, drop ReplacementTranformer).
//
// - resmap.Merginator
// - resource.ConflictDetector
//
// 1) api/internal/k8sdeps/merge.Merginator
// 1) api/internal/k8sdeps/conflict.conflictDetectorJson
// api/internal/k8sdeps/conflict.conflictDetectorSm
//
// Uses k8s.io/apimachinery/pkg/util/strategicpatch,
// apimachinery/pkg/util/mergepatch, etc. to merge
// resource.Resource instances.
//
// 2) api/internal/merge.Merginator
// 2) api/internal/conflict.smPatchMergeOnlyDetector
//
// At time of writing, this is unimplemented.
// At time of writing, this doesn't report conflicts,
// but it does know how to merge patches. Conflict
// reporting isn't vital to kustomize function. It's
// rare that a person would configure one transformer
// with many patches, much less so many that it became
// hard to spot conflicts. In the case of an undetected
// conflict, the last patch applied wins, likely what
// the user wants anyway. Regardless, the effect of this
// is plainly visible and usable in the output, even if
// a conflict happened but wasn't reported as an error.
//
// - ifc.Validator
//
@@ -117,6 +126,7 @@ import (
//
// 2) api/internal/validate.FieldValidator
//
// See TODO inside the validator for status.
// At time of writing, this is a do-nothing
// validator as it's not critical to kustomize function.
//
@@ -139,20 +149,20 @@ import (
// If you're reading this, plan not done.
//
type DepProvider struct {
kFactory ifc.KunstructuredFactory
resourceFactory *resource.Factory
merginator resmap.Merginator
fieldValidator ifc.Validator
kFactory ifc.KunstructuredFactory
resourceFactory *resource.Factory
conflictDectectorFactory resource.ConflictDetectorFactory
fieldValidator ifc.Validator
}
func makeK8sdepBasedInstances() *DepProvider {
kf := kunstruct.NewKunstructuredFactoryImpl()
rf := resource.NewFactory(kf)
return &DepProvider{
kFactory: kf,
resourceFactory: rf,
merginator: merge.NewMerginator(rf),
fieldValidator: validator.NewKustValidator(),
kFactory: kf,
resourceFactory: rf,
conflictDectectorFactory: k8sconflict.NewFactory(rf),
fieldValidator: validator.NewKustValidator(),
}
}
@@ -160,10 +170,10 @@ func makeKyamlBasedInstances() *DepProvider {
kf := &wrappy.WNodeFactory{}
rf := resource.NewFactory(kf)
return &DepProvider{
kFactory: kf,
resourceFactory: rf,
merginator: kmerge.NewMerginator(rf),
fieldValidator: validate.NewFieldValidator(),
kFactory: kf,
resourceFactory: rf,
conflictDectectorFactory: conflict.NewFactory(),
fieldValidator: validate.NewFieldValidator(),
}
}
@@ -186,8 +196,8 @@ func (dp *DepProvider) GetResourceFactory() *resource.Factory {
return dp.resourceFactory
}
func (dp *DepProvider) GetMerginator() resmap.Merginator {
return dp.merginator
func (dp *DepProvider) GetConflictDetectorFactory() resource.ConflictDetectorFactory {
return dp.conflictDectectorFactory
}
func (dp *DepProvider) GetFieldValidator() ifc.Validator {

View File

@@ -80,6 +80,14 @@ func (x Gvk) String() string {
return strings.Join([]string{g, v, k}, fieldSep)
}
// ApiVersion returns the combination of Group and Version
func (x Gvk) ApiVersion() string {
if x.Group == "" {
return x.Version
}
return x.Group + "/" + x.Version
}
// StringWoEmptyField returns a string representation of the GVK. Non-exist
// fields will be omitted.
func (x Gvk) StringWoEmptyField() string {

View File

@@ -1,18 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2018 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resid
@@ -112,17 +99,31 @@ var stringTests = []struct {
func TestString(t *testing.T) {
for _, hey := range stringTests {
if hey.x.String() != hey.s {
t.Fatalf("bad string for %v '%s'", hey.x, hey.s)
}
assert.Equal(t, hey.s, hey.x.String())
}
}
func TestApiVersion(t *testing.T) {
for _, hey := range []struct {
x Gvk
exp string
}{
{Gvk{}, ""},
{Gvk{Kind: "k"}, ""},
{Gvk{Version: "v"}, "v"},
{Gvk{Version: "v", Kind: "k"}, "v"},
{Gvk{Group: "g"}, "g/"},
{Gvk{Group: "g", Kind: "k"}, "g/"},
{Gvk{Group: "g", Version: "v"}, "g/v"},
{Gvk{Group: "g", Version: "v", Kind: "k"}, "g/v"},
} {
assert.Equal(t, hey.exp, hey.x.ApiVersion())
}
}
func TestStringWoEmptyField(t *testing.T) {
for _, hey := range stringTests {
if hey.x.StringWoEmptyField() != hey.r {
t.Fatalf("bad string %s for %v '%s'", hey.x.StringWoEmptyField(), hey.x, hey.r)
}
assert.Equal(t, hey.r, hey.x.StringWoEmptyField())
}
}
@@ -141,12 +142,8 @@ func TestParseGroupVersion(t *testing.T) {
}
for _, tc := range tests {
g, v := ParseGroupVersion(tc.input)
if g != tc.g {
t.Errorf("%s: expected group '%s', got '%s'", tc.input, tc.g, g)
}
if v != tc.v {
t.Errorf("%s: expected version '%s', got '%s'", tc.input, tc.v, v)
}
assert.Equal(t, tc.g, g, tc.input)
assert.Equal(t, tc.v, v, tc.input)
}
}
@@ -252,9 +249,7 @@ func TestSelectByGVK(t *testing.T) {
for _, tc := range testCases {
filtered := tc.in.IsSelected(tc.filter)
if filtered != tc.expected {
t.Fatalf("unexpected filter result for test case: %v", tc.description)
}
assert.Equal(t, tc.expected, filtered, tc.description)
}
}

View File

@@ -12,24 +12,18 @@ import (
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Merginator merges resources.
type Merginator interface {
// Merge creates a new ResMap by merging incoming resources.
// Error if conflict found.
Merge([]*resource.Resource) (ResMap, error)
}
// Factory makes instances of ResMap.
type Factory struct {
// Makes resources.
resF *resource.Factory
// Makes ResMaps via merging.
pm Merginator
// Makes ConflictDetectors.
cdf resource.ConflictDetectorFactory
}
// NewFactory returns a new resmap.Factory.
func NewFactory(rf *resource.Factory, pm Merginator) *Factory {
return &Factory{resF: rf, pm: pm}
func NewFactory(
rf *resource.Factory, cdf resource.ConflictDetectorFactory) *Factory {
return &Factory{resF: rf, cdf: cdf}
}
// RF returns a resource.Factory.
@@ -132,10 +126,11 @@ func (rmF *Factory) FromSecretArgs(
return rmF.FromResource(res), nil
}
// Merge creates a new ResMap by merging incoming resources.
// ConflatePatches creates a new ResMap containing a merger of the
// incoming patches.
// Error if conflict found.
func (rmF *Factory) Merge(patches []*resource.Resource) (ResMap, error) {
return rmF.pm.Merge(patches)
func (rmF *Factory) ConflatePatches(patches []*resource.Resource) (ResMap, error) {
return (&merginator{cdf: rmF.cdf}).ConflatePatches(patches)
}
func newResMapFromResourceSlice(
@@ -158,11 +153,11 @@ func (rmF *Factory) NewResMapFromRNodeSlice(rnodes []*yaml.RNode) (ResMap, error
if err != nil {
return nil, err
}
r, err := rmF.resF.FromBytes([]byte(s))
r, err := rmF.resF.SliceFromBytes([]byte(s))
if err != nil {
return nil, err
}
resources = append(resources, r)
resources = append(resources, r...)
}
return newResMapFromResourceSlice(resources)
}

View File

@@ -10,10 +10,11 @@ import (
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resid"
. "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
@@ -110,8 +111,6 @@ metadata:
assert.Equal(t, expYaml, mYaml)
}
var cmap = resid.Gvk{Version: "v1", Kind: "ConfigMap"}
func TestNewFromConfigMaps(t *testing.T) {
type testCase struct {
description string
@@ -278,7 +277,17 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
}
func TestFromRNodeSlice(t *testing.T) {
input := `apiVersion: rbac.authorization.k8s.io/v1
type testcase struct {
input string
expected ResMap
}
testcases := map[string]testcase{
"no resource": {
input: "---",
expected: resmaptest_test.NewRmBuilder(t, rf).ResMap(),
},
"single resource": {
input: `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
@@ -291,41 +300,119 @@ rules:
- get
- watch
- list
`
rnodes := []*yaml.RNode{
yaml.MustParse(input),
}
rm, err := rmF.NewResMapFromRNodeSlice(rnodes)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expected := resmaptest_test.NewRmBuilder(t, rf).Add(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "namespace-reader",
},
"rules": []interface{}{
`,
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
map[string]interface{}{
"apiGroups": []interface{}{
"",
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "namespace-reader",
},
"resources": []interface{}{
"namespaces",
"rules": []interface{}{
map[string]interface{}{
"apiGroups": []interface{}{
"",
},
"resources": []interface{}{
"namespaces",
},
"verbs": []interface{}{
"get",
"watch",
"list",
},
},
},
"verbs": []interface{}{
"get",
"watch",
"list",
},
},
},
}).ResMap()
if err = expected.ErrorIfNotEqualLists(rm); err != nil {
t.Fatalf("error: %s", err)
}).ResMap(),
},
"local config": {
// local config should be ignored
input: `apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
annotations:
config.kubernetes.io/local-config: 'true'
`,
expected: resmaptest_test.NewRmBuilder(t, rf).ResMap(),
},
}
for name, tc := range testcases {
rnodes := []*yaml.RNode{
yaml.MustParse(tc.input),
}
rm, err := rmF.NewResMapFromRNodeSlice(rnodes)
if err != nil {
t.Fatalf("unexpected error in test case [%s]: %v", name, err)
}
if err = tc.expected.ErrorIfNotEqualLists(rm); err != nil {
t.Fatalf("error in test case [%s]: %s", name, err)
}
}
}
func TestConflatePatches_Empty(t *testing.T) {
rm, err := rmF.ConflatePatches([]*resource.Resource{})
assert.NoError(t, err)
assert.Equal(t, 0, rm.Size())
}
func TestConflatePatches(t *testing.T) {
var (
err error
yml []byte
r1, r2 *resource.Resource
)
r1, err = rf.FromBytes([]byte(`apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B:
C: Z
`))
assert.NoError(t, err)
r2, err = rf.FromBytes([]byte(`apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`))
assert.NoError(t, err)
rm, err := rmF.ConflatePatches([]*resource.Resource{r1, r2})
assert.NoError(t, err)
yml, err = rm.AsYaml()
assert.NoError(t, err)
assert.Equal(t, konfig.IfApiMachineryElseKyaml(`apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B: null
C: Z
D: W
baz:
hello: world
`, `apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`), string(yml))
}

118
api/resmap/merginator.go Normal file
View File

@@ -0,0 +1,118 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resmap
import (
"fmt"
"sigs.k8s.io/kustomize/api/resource"
)
// merginator coordinates merging the resources in incoming to the result.
type merginator struct {
incoming []*resource.Resource
cdf resource.ConflictDetectorFactory
result ResMap
}
func (m *merginator) ConflatePatches(in []*resource.Resource) (ResMap, error) {
m.result = New()
m.incoming = in
for index := range m.incoming {
alreadyInResult, err := m.appendIfNoMatch(index)
if err != nil {
return nil, err
}
if alreadyInResult != nil {
// The resource at index has the same resId as a previously
// considered resource.
//
// If they conflict with each other (e.g. they both want to change
// the image name in a Deployment, but to different values),
// return an error.
//
// If they don't conflict, then merge them into a single resource,
// since they both target the same item, and we want cumulative
// behavior. E.g. say both patches modify a map. Without a merge,
// the last patch wins, replacing the entire map.
err = m.mergeWithExisting(index, alreadyInResult)
if err != nil {
return nil, err
}
}
}
return m.result, nil
}
func (m *merginator) appendIfNoMatch(index int) (*resource.Resource, error) {
candidate := m.incoming[index]
matchedResources := m.result.GetMatchingResourcesByOriginalId(
candidate.OrgId().Equals)
if len(matchedResources) == 0 {
m.result.Append(candidate)
return nil, nil
}
if len(matchedResources) > 1 {
return nil, fmt.Errorf("multiple resources targeted by patch")
}
return matchedResources[0], nil
}
func (m *merginator) mergeWithExisting(
index int, alreadyInResult *resource.Resource) error {
candidate := m.incoming[index]
cd, err := m.cdf.New(candidate.OrgId().Gvk)
if err != nil {
return err
}
hasConflict, err := cd.HasConflict(candidate, alreadyInResult)
if err != nil {
return err
}
if hasConflict {
return m.makeError(cd, index)
}
merged, err := cd.MergePatches(alreadyInResult, candidate)
if err != nil {
return err
}
_, err = m.result.Replace(merged)
return err
}
// Make an error message describing the conflict.
func (m *merginator) makeError(cd resource.ConflictDetector, index int) error {
conflict, err := m.findConflict(cd, index)
if err != nil {
return err
}
if conflict == nil {
return fmt.Errorf("expected conflict for %s", m.incoming[index].OrgId())
}
return fmt.Errorf(
"conflict between %#v at index %d and %#v",
m.incoming[index].Map(), index, conflict.Map())
}
// findConflict looks for a conflict in a resource slice.
// It returns the first conflict between the resource at index
// and some other resource. Two resources can only conflict if
// they have the same original ResId.
func (m *merginator) findConflict(
cd resource.ConflictDetector, index int) (*resource.Resource, error) {
targetId := m.incoming[index].OrgId()
for i, p := range m.incoming {
if i == index || !targetId.Equals(p.OrgId()) {
continue
}
conflict, err := cd.HasConflict(p, m.incoming[index])
if err != nil {
return nil, err
}
if conflict {
return p, nil
}
}
return nil, nil
}

View File

@@ -240,4 +240,9 @@ type ResMap interface {
// ToRNodeSlice converts the resources in the resmp
// to a list of RNodes
ToRNodeSlice() ([]*yaml.RNode, error)
// ApplySmPatch applies a strategic-merge patch to the
// selected set of resources.
ApplySmPatch(
selectedSet *resource.IdSet, patch *resource.Resource) error
}

View File

@@ -6,6 +6,7 @@ package resmap
import (
"bytes"
"fmt"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/resid"
@@ -455,8 +456,7 @@ func (m *resWrangler) AbsorbAll(other ResMap) error {
return nil
}
func (m *resWrangler) appendReplaceOrMerge(
res *resource.Resource) error {
func (m *resWrangler) appendReplaceOrMerge(res *resource.Resource) error {
id := res.CurId()
matches := m.GetMatchingResourcesByOriginalId(id.Equals)
if len(matches) == 0 {
@@ -470,10 +470,7 @@ func (m *resWrangler) appendReplaceOrMerge(
"id %#v does not exist; cannot merge or replace", id)
default:
// presumably types.BehaviorCreate
err := m.Append(res)
if err != nil {
return err
}
return m.Append(res)
}
case 1:
old := matches[0]
@@ -486,9 +483,10 @@ func (m *resWrangler) appendReplaceOrMerge(
}
switch res.Behavior() {
case types.BehaviorReplace:
res.Replace(old)
res.CopyMergeMetaDataFieldsFrom(old)
case types.BehaviorMerge:
res.Merge(old)
res.CopyMergeMetaDataFieldsFrom(old)
res.MergeDataMapFrom(old)
default:
return fmt.Errorf(
"id %#v exists; behavior must be merge or replace", id)
@@ -498,14 +496,14 @@ func (m *resWrangler) appendReplaceOrMerge(
return err
}
if i != index {
return fmt.Errorf("unexpected index in replacement")
return fmt.Errorf("unexpected target index in replacement")
}
return nil
default:
return fmt.Errorf(
"found multiple objects %v that could accept merge of %v",
matches, id)
}
return nil
}
// Select returns a list of resources that
@@ -578,3 +576,46 @@ func (m *resWrangler) ToRNodeSlice() ([]*kyaml_yaml.RNode, error) {
}
return rnodes, nil
}
func (m *resWrangler) ApplySmPatch(
selectedSet *resource.IdSet, patch *resource.Resource) error {
newRm := New()
for _, res := range m.Resources() {
if !selectedSet.Contains(res.CurId()) {
newRm.Append(res)
continue
}
patchCopy := patch.DeepCopy()
patchCopy.SetName(res.GetName())
patchCopy.SetNamespace(res.GetNamespace())
patchCopy.SetGvk(res.GetGvk())
err := res.ApplySmPatch(patchCopy)
if err != nil {
// Check for an error string from UnmarshalJSON that's indicative
// of an object that's missing basic KRM fields, and thus may have been
// entirely deleted (an acceptable outcome). This error handling should
// be deleted along with use of ResMap and apimachinery functions like
// UnmarshalJSON.
if !strings.Contains(err.Error(), "Object 'Kind' is missing") {
// Some unknown error, let it through.
return err
}
if !res.IsEmpty() {
return errors.Wrapf(
err, "with unexpectedly non-empty object map of size %d",
len(res.Map()))
}
// Fall through to handle deleted object.
}
if !res.IsEmpty() {
// IsEmpty means all fields have been removed from the object.
// This can happen if a patch required deletion of the
// entire resource (not just a part of it). This means
// the overall resmap must shrink by one.
newRm.Append(res)
}
}
m.Clear()
m.AppendAll(newRm)
return nil
}

View File

@@ -11,7 +11,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resid"
. "sigs.k8s.io/kustomize/api/resmap"
@@ -20,8 +19,9 @@ import (
"sigs.k8s.io/kustomize/api/types"
)
var rf = provider.NewDefaultDepProvider().GetResourceFactory()
var rmF = NewFactory(rf, nil)
var depProvider = provider.NewDefaultDepProvider()
var rf = depProvider.GetResourceFactory()
var rmF = NewFactory(rf, depProvider.GetConflictDetectorFactory())
func doAppend(t *testing.T, w ResMap, r *resource.Resource) {
err := w.Append(r)
@@ -192,6 +192,8 @@ metadata:
}
func TestGetMatchingResourcesByCurrentId(t *testing.T) {
cmap := resid.Gvk{Version: "v1", Kind: "ConfigMap"}
r1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
@@ -691,10 +693,6 @@ func TestAbsorbAll(t *testing.T) {
metadata := map[string]interface{}{
"name": "cmap",
}
if !konfig.FlagEnableKyamlDefaultValue {
metadata["annotations"] = map[string]interface{}{}
metadata["labels"] = map[string]interface{}{}
}
expected := rmF.FromResource(rf.FromMapAndOption(
map[string]interface{}{
"apiVersion": "apps/v1",
@@ -770,3 +768,452 @@ rules:
b.String(), input)
}
}
func TestApplySmPatch_General(t *testing.T) {
const (
myDeployment = "Deployment"
myCRD = "myCRD"
expectedResultSMP = `apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
image: nginx
name: nginx
`
)
tests := map[string]struct {
base []string
patches []string
expected []string
errorExpected bool
errorMsg string
}{
"clown": {
base: []string{`apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 1
`,
},
patches: []string{`apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`,
},
errorExpected: false,
expected: []string{
`apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`,
},
},
"confusion": {
base: []string{`apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
A: X
B: Y
`,
},
patches: []string{`apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B:
C: Z
`, `apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`,
},
errorExpected: false,
expected: []string{
`apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
A: X
C: Z
D: W
baz:
hello: world
`,
},
},
"withschema-ns1-ns2-one": {
base: []string{
addNamespace("ns1", baseResource(myDeployment)),
addNamespace("ns2", baseResource(myDeployment)),
},
patches: []string{
addNamespace("ns1", addLabelAndEnvPatch(myDeployment)),
addNamespace("ns2", addLabelAndEnvPatch(myDeployment)),
},
errorExpected: false,
expected: []string{
addNamespace("ns1", expectedResultSMP),
addNamespace("ns2", expectedResultSMP),
},
},
"withschema-ns1-ns2-two": {
base: []string{
addNamespace("ns1", baseResource(myDeployment)),
},
patches: []string{
addNamespace("ns2", changeImagePatch(myDeployment)),
},
expected: []string{
addNamespace("ns1", baseResource(myDeployment)),
},
},
"withschema-ns1-ns2-three": {
base: []string{
addNamespace("ns1", baseResource(myDeployment)),
},
patches: []string{
addNamespace("ns1", changeImagePatch(myDeployment)),
},
expected: []string{
`apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
namespace: ns1
spec:
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- image: nginx:1.7.9
name: nginx
`,
},
},
"withschema-nil-ns2": {
base: []string{
baseResource(myDeployment),
},
patches: []string{
addNamespace("ns2", changeImagePatch(myDeployment)),
},
expected: []string{
baseResource(myDeployment),
},
},
"withschema-ns1-nil": {
base: []string{
addNamespace("ns1", baseResource(myDeployment)),
},
patches: []string{
changeImagePatch(myDeployment),
},
expected: []string{
addNamespace("ns1", baseResource(myDeployment)),
},
},
"noschema-ns1-ns2-one": {
base: []string{
addNamespace("ns1", baseResource(myCRD)),
addNamespace("ns2", baseResource(myCRD)),
},
patches: []string{
addNamespace("ns1", addLabelAndEnvPatch(myCRD)),
addNamespace("ns2", addLabelAndEnvPatch(myCRD)),
},
errorExpected: false,
expected: []string{
addNamespace("ns1", expectedResultJMP("")),
addNamespace("ns2", expectedResultJMP("")),
},
},
"noschema-ns1-ns2-two": {
base: []string{addNamespace("ns1", baseResource(myCRD))},
patches: []string{addNamespace("ns2", changeImagePatch(myCRD))},
expected: []string{addNamespace("ns1", baseResource(myCRD))},
},
"noschema-nil-ns2": {
base: []string{baseResource(myCRD)},
patches: []string{addNamespace("ns2", changeImagePatch(myCRD))},
expected: []string{baseResource(myCRD)},
},
"noschema-ns1-nil": {
base: []string{addNamespace("ns1", baseResource(myCRD))},
patches: []string{changeImagePatch(myCRD)},
expected: []string{addNamespace("ns1", baseResource(myCRD))},
},
}
for n := range tests {
tc := tests[n]
t.Run(n, func(t *testing.T) {
m, err := rmF.NewResMapFromBytes([]byte(strings.Join(tc.base, "\n---\n")))
assert.NoError(t, err)
foundError := false
for _, patch := range tc.patches {
rp, err := rf.FromBytes([]byte(patch))
assert.NoError(t, err)
idSet := resource.MakeIdSet([]*resource.Resource{rp})
if err = m.ApplySmPatch(idSet, rp); err != nil {
foundError = true
break
}
}
if foundError {
assert.True(t, tc.errorExpected)
// compare error message?
return
}
assert.False(t, tc.errorExpected)
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, strings.Join(tc.expected, "---\n"), string(yml))
})
}
}
// simple utility function to add an namespace in a resource
// used as base, patch or expected result. Simply looks
// for specs: in order to add namespace: xxxx before this line
func addNamespace(namespace string, base string) string {
res := strings.Replace(base,
"\nspec:\n",
"\n namespace: "+namespace+"\nspec:\n",
1)
return res
}
func TestApplySmPatch_Deletion(t *testing.T) {
target := `
apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
spec:
replica: 2
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- name: nginx
image: nginx
`
tests := map[string]struct {
patch string
expected string
finalMapSize int
}{
"delete1": {
patch: `apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
spec:
replica: 2
template:
$patch: delete
metadata:
labels:
old-label: old-value
spec:
containers:
- name: nginx
image: nginx
`,
expected: `apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
spec:
replica: 2
`,
finalMapSize: 1,
},
"delete2": {
patch: `apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
spec:
$patch: delete
replica: 2
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- name: nginx
image: nginx
`,
expected: `apiVersion: apps/v1
kind: Deployment
metadata:
name: myDeploy
`,
finalMapSize: 1,
},
"delete3": {
patch: `apiVersion: apps/v1
metadata:
name: myDeploy
kind: Deployment
$patch: delete
`,
expected: "",
finalMapSize: 0,
},
}
for name, test := range tests {
m, err := rmF.NewResMapFromBytes([]byte(target))
assert.NoError(t, err, name)
idSet := resource.MakeIdSet(m.Resources())
assert.Equal(t, 1, idSet.Size(), name)
p, err := rf.FromBytes([]byte(test.patch))
assert.NoError(t, err, name)
assert.NoError(t, m.ApplySmPatch(idSet, p), name)
assert.Equal(t, test.finalMapSize, m.Size(), name)
yml, err := m.AsYaml()
assert.NoError(t, err, name)
assert.Equal(t, test.expected, string(yml), name)
}
}
// baseResource produces a base object which used to test
// patch transformation
// Also the structure is matching the Deployment syntax
// the kind can be replaced to allow testing using CRD
// without access to the schema
func baseResource(kind string) string {
return fmt.Sprintf(`apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- image: nginx
name: nginx
`, kind)
}
// addContainerAndEnvPatch produces a patch object which adds
// an entry in the env slice of the first/nginx container
// as well as adding a label in the metadata
// Note that for SMP/WithSchema merge, the name:nginx entry
// is mandatory
func addLabelAndEnvPatch(kind string) string {
return fmt.Sprintf(`apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
metadata:
labels:
some-label: some-value
spec:
containers:
- name: nginx
env:
- name: SOMEENV
value: SOMEVALUE`, kind)
}
// changeImagePatch produces a patch object which replaces
// the value of the image field in the first/nginx container
// Note that for SMP/WithSchema merge, the name:nginx entry
// is mandatory
func changeImagePatch(kind string) string {
return fmt.Sprintf(`apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
spec:
containers:
- name: nginx
image: "nginx:1.7.9"`, kind)
}
// utility method building the expected output of a JMP.
// imagename parameter allows to build a result consistent
// with the JMP behavior which basically overrides the
// entire "containers" list.
func expectedResultJMP(imagename string) string {
if imagename == "" {
return `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
name: nginx
`
}
return fmt.Sprintf(`apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- image: %s
name: nginx
`, imagename)
}

View File

@@ -0,0 +1,20 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resource
import "sigs.k8s.io/kustomize/api/resid"
// ConflictDetector detects conflicts between resources.
type ConflictDetector interface {
// HasConflict returns true if the given resources have a conflict.
HasConflict(patch1, patch2 *Resource) (bool, error)
// Merge two resources into one.
MergePatches(patch1, patch2 *Resource) (*Resource, error)
}
// ConflictDetectorFactory makes instances of ConflictDetector that know
// how to handle the given Group, Version, Kind tuple.
type ConflictDetectorFactory interface {
New(gvk resid.Gvk) (ConflictDetector, error)
}

5
api/resource/doc.go Normal file
View File

@@ -0,0 +1,5 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package resource implements representations of k8s API resources.
package resource

View File

@@ -1,7 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package resource implements representations of k8s API resources.
package resource
import (
@@ -9,9 +8,11 @@ import (
"reflect"
"strings"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -45,6 +46,10 @@ func (r *Resource) GetFieldValue(f string) (interface{}, error) {
return r.kunStr.GetFieldValue(f)
}
func (r *Resource) GetDataMap() map[string]string {
return r.kunStr.GetDataMap()
}
func (r *Resource) GetGvk() resid.Gvk {
return r.kunStr.GetGvk()
}
@@ -90,14 +95,28 @@ func (r *Resource) MatchesAnnotationSelector(selector string) (bool, error) {
}
func (r *Resource) SetAnnotations(m map[string]string) {
if len(m) == 0 {
// Force field erasure.
r.kunStr.SetAnnotations(nil)
return
}
r.kunStr.SetAnnotations(m)
}
func (r *Resource) SetDataMap(m map[string]string) {
r.kunStr.SetDataMap(m)
}
func (r *Resource) SetGvk(gvk resid.Gvk) {
r.kunStr.SetGvk(gvk)
}
func (r *Resource) SetLabels(m map[string]string) {
if len(m) == 0 {
// Force field erasure.
r.kunStr.SetLabels(nil)
return
}
r.kunStr.SetLabels(m)
}
@@ -138,10 +157,12 @@ func (r *Resource) DeepCopy() *Resource {
return rc
}
// Replace performs replace with other resource.
func (r *Resource) Replace(other *Resource) {
// CopyMergeMetaDataFields copies everything but the non-metadata in
// the ifc.Kunstructured map, merging labels and annotations.
func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) {
r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels()))
r.SetAnnotations(mergeStringMaps(other.GetAnnotations(), r.GetAnnotations()))
r.SetAnnotations(
mergeStringMaps(other.GetAnnotations(), r.GetAnnotations()))
r.SetName(other.GetName())
r.SetNamespace(other.GetNamespace())
r.copyOtherFields(other)
@@ -157,6 +178,10 @@ func (r *Resource) copyOtherFields(other *Resource) {
r.nameSuffixes = copyStringSlice(other.nameSuffixes)
}
func (r *Resource) MergeDataMapFrom(o *Resource) {
r.SetDataMap(mergeStringMaps(o.GetDataMap(), r.GetDataMap()))
}
func (r *Resource) ErrIfNotEquals(o *Resource) error {
meYaml, err := r.AsYAML()
if err != nil {
@@ -197,12 +222,6 @@ func (r *Resource) KunstructEqual(o *Resource) bool {
return reflect.DeepEqual(r.kunStr, o.kunStr)
}
// Merge performs merge with other resource.
func (r *Resource) Merge(other *Resource) {
r.Replace(other)
mergeConfigmap(r.Map(), other.Map(), r.Map())
}
func (r *Resource) copyRefBy() []resid.ResId {
if r.refBy == nil {
return nil
@@ -396,20 +415,21 @@ func (r *Resource) AppendRefVarName(variable types.Var) {
r.refVarNames = append(r.refVarNames, variable.Name)
}
// TODO: Add BinaryData once we sync to new k8s.io/api
func mergeConfigmap(
mergedTo map[string]interface{},
maps ...map[string]interface{}) {
mergedMap := map[string]interface{}{}
for _, m := range maps {
datamap, ok := m["data"].(map[string]interface{})
if ok {
for key, value := range datamap {
mergedMap[key] = value
}
}
// ApplySmPatch applies the provided strategic merge patch.
func (r *Resource) ApplySmPatch(patch *Resource) error {
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
mergedTo["data"] = mergedMap
n, ns := r.GetName(), r.GetNamespace()
err = filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, r)
if !r.IsEmpty() {
r.SetName(n)
r.SetNamespace(ns)
}
return err
}
func mergeStringMaps(maps ...map[string]string) map[string]string {

View File

@@ -4,9 +4,11 @@
package resource_test
import (
"fmt"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resid"
. "sigs.k8s.io/kustomize/api/resource"
@@ -123,3 +125,736 @@ func TestDeepCopy(t *testing.T) {
t.Errorf("expected %v\nbut got%v", r, cr)
}
}
func TestApplySmPatch_1(t *testing.T) {
resource, err := factory.FromBytes([]byte(`
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
baseAnno: This is a base annotation
labels:
app: mungebot
foo: bar
name: bingo
spec:
replicas: 1
selector:
matchLabels:
foo: bar
template:
metadata:
labels:
app: mungebot
spec:
containers:
- env:
- name: foo
value: bar
image: nginx
name: nginx
ports:
- containerPort: 80
`))
assert.NoError(t, err)
patch, err := factory.FromBytes([]byte(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: baseprefix-mungebot
spec:
template:
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 777
`))
assert.NoError(t, err)
assert.NoError(t, resource.ApplySmPatch(patch))
bytes, err := resource.AsYAML()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
baseAnno: This is a base annotation
labels:
app: mungebot
foo: bar
name: bingo
spec:
replicas: 1
selector:
matchLabels:
foo: bar
template:
metadata:
labels:
app: mungebot
spec:
containers:
- env:
- name: foo
value: bar
image: nginx
name: nginx
ports:
- containerPort: 777
- containerPort: 80
`, string(bytes))
}
func TestApplySmPatch_2(t *testing.T) {
resource, err := factory.FromBytes([]byte(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
A: X
B: Y
`))
assert.NoError(t, err)
patch, err := factory.FromBytes([]byte(`
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B:
C: Z
D: W
baz:
hello: world
`))
assert.NoError(t, err)
assert.NoError(t, resource.ApplySmPatch(patch))
bytes, err := resource.AsYAML()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
A: X
C: Z
D: W
baz:
hello: world
`, string(bytes))
}
func TestApplySmPatch_3(t *testing.T) {
resource, err := factory.FromBytes([]byte(`
apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 1
`))
assert.NoError(t, err)
patch, err := factory.FromBytes([]byte(`
apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`))
assert.NoError(t, err)
assert.NoError(t, resource.ApplySmPatch(patch))
bytes, err := resource.AsYAML()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`, string(bytes))
}
func TestMergeDataMapFrom(t *testing.T) {
resource, err := factory.FromBytes([]byte(`
apiVersion: v1
kind: BlahBlah
metadata:
name: clown
data:
fruit: pear
`))
if !assert.NoError(t, err) {
t.FailNow()
}
patch, err := factory.FromBytes([]byte(`
apiVersion: v1
kind: Whatever
metadata:
name: spaceship
data:
spaceship: enterprise
`))
if !assert.NoError(t, err) {
t.FailNow()
}
resource.MergeDataMapFrom(patch)
bytes, err := resource.AsYAML()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
data:
fruit: pear
spaceship: enterprise
kind: BlahBlah
metadata:
name: clown
`, string(bytes))
}
func TestApplySmPatch_SwapOrder(t *testing.T) {
s1 := `
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
B:
C: Z
`
s2 := `
apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`
expected := `apiVersion: example.com/v1
kind: Foo
metadata:
name: my-foo
spec:
bar:
C: Z
D: W
baz:
hello: world
`
r1, err := factory.FromBytes([]byte(s1))
assert.NoError(t, err)
r2, err := factory.FromBytes([]byte(s2))
assert.NoError(t, err)
assert.NoError(t, r1.ApplySmPatch(r2))
bytes, err := r1.AsYAML()
assert.NoError(t, err)
assert.Equal(t, expected, string(bytes))
r1, _ = factory.FromBytes([]byte(s1))
r2, _ = factory.FromBytes([]byte(s2))
assert.NoError(t, r2.ApplySmPatch(r1))
bytes, err = r2.AsYAML()
assert.NoError(t, err)
assert.Equal(t, expected, string(bytes))
}
func TestApplySmPatch(t *testing.T) {
const (
myDeployment = "Deployment"
myCRD = "myCRD"
)
tests := map[string]struct {
base string
patch []string
expected string
errorExpected bool
errorMsg string
}{
"withschema-label-image-container": {
base: baseResource(myDeployment),
patch: []string{
addLabelAndEnvPatch(myDeployment),
changeImagePatch(myDeployment, "nginx:latest"),
addContainerAndEnvPatch(myDeployment),
},
errorExpected: false,
expected: expectedResultMultiPatch(myDeployment, false),
},
"withschema-image-container-label": {
base: baseResource(myDeployment),
patch: []string{
changeImagePatch(myDeployment, "nginx:latest"),
addContainerAndEnvPatch(myDeployment),
addLabelAndEnvPatch(myDeployment),
},
errorExpected: false,
expected: expectedResultMultiPatch(myDeployment, true),
},
"withschema-container-label-image": {
base: baseResource(myDeployment),
patch: []string{
addContainerAndEnvPatch(myDeployment),
addLabelAndEnvPatch(myDeployment),
changeImagePatch(myDeployment, "nginx:latest"),
},
errorExpected: false,
expected: expectedResultMultiPatch(myDeployment, true),
},
"noschema-label-image-container": {
base: baseResource(myCRD),
patch: []string{
addLabelAndEnvPatch(myCRD),
changeImagePatch(myCRD, "nginx:latest"),
addContainerAndEnvPatch(myCRD),
},
// Might be better if this complained about patch conflict.
// See plugin/builtin/patchstrategicmergetransformer/psmt_test.go
expected: `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: ANOTHERENV
value: ANOTHERVALUE
name: nginx
- image: anotherimage
name: anothercontainer
`,
},
"noschema-image-container-label": {
base: baseResource(myCRD),
patch: []string{
changeImagePatch(myCRD, "nginx:latest"),
addContainerAndEnvPatch(myCRD),
addLabelAndEnvPatch(myCRD),
},
// Might be better if this complained about patch conflict.
expected: `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
name: nginx
`,
},
"noschema-container-label-image": {
base: baseResource(myCRD),
patch: []string{
addContainerAndEnvPatch(myCRD),
addLabelAndEnvPatch(myCRD),
changeImagePatch(myCRD, "nginx:latest"),
},
// Might be better if this complained about patch conflict.
expected: `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- image: nginx:latest
name: nginx
`,
},
"withschema-label-latest-someV-01": {
base: baseResource(myDeployment),
patch: []string{
addLabelAndEnvPatch(myDeployment),
changeImagePatch(myDeployment, "nginx:latest"),
changeImagePatch(myDeployment, "nginx:1.7.9"),
},
expected: `apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
image: nginx:1.7.9
name: nginx
`,
},
"withschema-latest-label-someV-02": {
base: baseResource(myDeployment),
patch: []string{
changeImagePatch(myDeployment, "nginx:latest"),
addLabelAndEnvPatch(myDeployment),
changeImagePatch(myDeployment, "nginx:1.7.9"),
},
expected: `apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
image: nginx:1.7.9
name: nginx
`,
},
"withschema-latest-label-someV-03": {
base: baseResource(myDeployment),
patch: []string{
changeImagePatch(myDeployment, "nginx:1.7.9"),
addLabelAndEnvPatch(myDeployment),
changeImagePatch(myDeployment, "nginx:latest"),
},
expected: `apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
image: nginx:latest
name: nginx
`,
},
"withschema-latest-label-someV-04": {
base: baseResource(myDeployment),
patch: []string{
changeImagePatch(myDeployment, "nginx:1.7.9"),
changeImagePatch(myDeployment, "nginx:latest"),
addLabelAndEnvPatch(myDeployment),
changeImagePatch(myDeployment, "nginx:nginx"),
},
expected: `apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
image: nginx:nginx
name: nginx
`,
},
"noschema-latest-label-someV-01": {
base: baseResource(myCRD),
patch: []string{
addLabelAndEnvPatch(myCRD),
changeImagePatch(myCRD, "nginx:latest"),
changeImagePatch(myCRD, "nginx:1.7.9"),
},
expected: `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- image: nginx:1.7.9
name: nginx
`,
},
"noschema-latest-label-someV-02": {
base: baseResource(myCRD),
patch: []string{
changeImagePatch(myCRD, "nginx:latest"),
addLabelAndEnvPatch(myCRD),
changeImagePatch(myCRD, "nginx:1.7.9"),
},
expected: expectedResultJMP("nginx:1.7.9"),
},
"noschema-latest-label-someV-03": {
base: baseResource(myCRD),
patch: []string{
changeImagePatch(myCRD, "nginx:1.7.9"),
addLabelAndEnvPatch(myCRD),
changeImagePatch(myCRD, "nginx:latest"),
},
expected: `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- image: nginx:latest
name: nginx
`,
},
"noschema-latest-label-someV-04": {
base: baseResource(myCRD),
patch: []string{
changeImagePatch(myCRD, "nginx:1.7.9"),
changeImagePatch(myCRD, "nginx:latest"),
addLabelAndEnvPatch(myCRD),
changeImagePatch(myCRD, "nginx:nginx"),
},
expected: `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- image: nginx:nginx
name: nginx
`,
},
}
for name, test := range tests {
resource, err := factory.FromBytes([]byte(test.base))
assert.NoError(t, err)
for _, p := range test.patch {
patch, err := factory.FromBytes([]byte(p))
assert.NoError(t, err, name)
assert.NoError(t, resource.ApplySmPatch(patch), name)
}
bytes, err := resource.AsYAML()
if test.errorExpected {
assert.Error(t, err, name)
} else {
assert.NoError(t, err, name)
assert.Equal(t, test.expected, string(bytes), name)
}
}
}
// baseResource produces a base object which used to test
// patch transformation
// Also the structure is matching the Deployment syntax
// the kind can be replaced to allow testing using CRD
// without access to the schema
func baseResource(kind string) string {
res := `
apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
spec:
containers:
- name: nginx
image: nginx`
return fmt.Sprintf(res, kind)
}
// addContainerAndEnvPatch produces a patch object which adds
// an entry in the env slice of the first/nginx container
// as well as adding a label in the metadata
// Note that for SMP/WithSchema merge, the name:nginx entry
// is mandatory
func addLabelAndEnvPatch(kind string) string {
return fmt.Sprintf(`
apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
metadata:
labels:
some-label: some-value
spec:
containers:
- name: nginx
env:
- name: SOMEENV
value: SOMEVALUE`, kind)
}
// addContainerAndEnvPatch produces a patch object which adds
// an entry in the env slice of the first/nginx container
// as well as adding a second container in the container list
// Note that for SMP/WithSchema merge, the name:nginx entry
// is mandatory
func addContainerAndEnvPatch(kind string) string {
return fmt.Sprintf(`
apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
spec:
containers:
- name: nginx
env:
- name: ANOTHERENV
value: ANOTHERVALUE
- name: anothercontainer
image: anotherimage`, kind)
}
// addContainerAndEnvPatch produces a patch object which replaces
// the value of the image field in the first/nginx container
// Note that for SMP/WithSchema merge, the name:nginx entry
// is mandatory
func changeImagePatch(kind string, newImage string) string {
return fmt.Sprintf(`
apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
spec:
containers:
- name: nginx
image: %s`, kind, newImage)
}
// utility method to build the expected result of a multipatch
// the order of the patches still have influence especially
// in the insertion location within arrays.
func expectedResultMultiPatch(kind string, reversed bool) string {
pattern := `apiVersion: apps/v1
kind: %s
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
%s
image: nginx:latest
name: nginx
- image: anotherimage
name: anothercontainer
`
if reversed {
return fmt.Sprintf(pattern, kind, `- name: SOMEENV
value: SOMEVALUE
- name: ANOTHERENV
value: ANOTHERVALUE`)
}
return fmt.Sprintf(pattern, kind, `- name: ANOTHERENV
value: ANOTHERVALUE
- name: SOMEENV
value: SOMEVALUE`)
}
// utility method building the expected output of a JMP.
// imagename parameter allows to build a result consistent
// with the JMP behavior which basically overrides the
// entire "containers" list.
func expectedResultJMP(imagename string) string {
if imagename == "" {
return `apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- env:
- name: SOMEENV
value: SOMEVALUE
name: nginx
`
}
return fmt.Sprintf(`apiVersion: apps/v1
kind: myCRD
metadata:
name: deploy1
spec:
template:
metadata:
labels:
old-label: old-value
some-label: some-value
spec:
containers:
- image: %s
name: nginx
`, imagename)
}

View File

@@ -46,7 +46,8 @@ func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
}
p := provider.NewDefaultDepProvider()
resourceFactory := p.GetResourceFactory()
resmapFactory := resmap.NewFactory(resourceFactory, p.GetMerginator())
resmapFactory := resmap.NewFactory(
resourceFactory, p.GetConflictDetectorFactory())
result := &HarnessEnhanced{
Harness: MakeHarness(t),

View File

@@ -10,10 +10,13 @@ type HelmChartArgs struct {
ChartRepoURL string `json:"chartRepoUrl,omitempty" yaml:"chartRepoUrl,omitempty"`
ChartHome string `json:"chartHome,omitempty" yaml:"chartHome,omitempty"`
// Use chartRelease to keep compatible with old exec plugin
ChartRepoName string `json:"chartRelease,omitempty" yaml:"chartRelease,omitempty"`
HelmBin string `json:"helmBin,omitempty" yaml:"helmBin,omitempty"`
HelmHome string `json:"helmHome,omitempty" yaml:"helmHome,omitempty"`
Values string `json:"values,omitempty" yaml:"values,omitempty"`
ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"`
ReleaseNamespace string `json:"releaseNamespace,omitempty" yaml:"releaseNamespace,omitempty"`
ChartRepoName string `json:"chartRelease,omitempty" yaml:"chartRelease,omitempty"`
HelmBin string `json:"helmBin,omitempty" yaml:"helmBin,omitempty"`
HelmHome string `json:"helmHome,omitempty" yaml:"helmHome,omitempty"`
Values string `json:"values,omitempty" yaml:"values,omitempty"`
ValuesLocal map[string]interface{} `json:"valuesLocal,omitempty" yaml:"valuesLocal,omitempty"`
ValuesMerge string `json:"valuesMerge,omitempty" yaml:"valuesMerge,omitempty"`
ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"`
ReleaseNamespace string `json:"releaseNamespace,omitempty" yaml:"releaseNamespace,omitempty"`
ExtraArgs []string `json:"extraArgs,omitempty" yaml:"extraArgs,omitempty"`
}

View File

@@ -15,7 +15,5 @@ require (
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
k8s.io/apimachinery v0.18.10
sigs.k8s.io/kustomize/kyaml v0.9.4
sigs.k8s.io/kustomize/kyaml v0.10.5
)
replace sigs.k8s.io/kustomize/kyaml v0.9.4 => ../../kyaml

View File

@@ -118,6 +118,7 @@ github.com/go-openapi/validate v0.19.8 h1:YFzsdWIDfVuLvIOF+ZmKjVg1MbPJ1QgY9PihMw
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
@@ -187,6 +188,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -371,12 +373,11 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -387,6 +388,8 @@ k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUc
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
sigs.k8s.io/kustomize/kyaml v0.10.5 h1:PbJcsZsEM7O3hHtUWTR+4WkHVbQRW9crSy75or1gRbI=
sigs.k8s.io/kustomize/kyaml v0.10.5/go.mod h1:P6Oy/ah/GZMKzJMIJA2a3/bc8YrBkuL5kJji13PSIzY=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=

View File

@@ -1,6 +1,3 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Code generated by "mdtogo"; DO NOT EDIT.
package api

View File

@@ -1,6 +1,3 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Code generated by "mdtogo"; DO NOT EDIT.
package commands

View File

@@ -1,6 +1,3 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Code generated by "mdtogo"; DO NOT EDIT.
package tutorials

View File

@@ -54,6 +54,7 @@ func (e *Editor) Tidy() error {
func (e *Editor) Pin(target misc.LaModule, oldV, newV semver.SemVer) error {
err := e.run(
"edit",
"-dropreplace="+target.ImportPath(),
"-dropreplace="+target.ImportPath()+"@"+oldV.String(),
"-require="+target.ImportPath()+"@"+newV.String(),
)
@@ -66,8 +67,9 @@ func (e *Editor) Pin(target misc.LaModule, oldV, newV semver.SemVer) error {
func (e *Editor) UnPin(target misc.LaModule, oldV semver.SemVer) error {
var r strings.Builder
r.WriteString(target.ImportPath())
r.WriteString("@")
r.WriteString(oldV.String())
// Don't specify the old version.
// r.WriteString("@")
// r.WriteString(oldV.String())
r.WriteString("=")
r.WriteString(upstairs(e.module.ShortName().Depth()))
r.WriteString(string(target.ShortName()))

View File

@@ -26,7 +26,7 @@ func (s TaggedModules) String() string {
// format := "%-"+strconv.Itoa(s.LenLongestString()+2)+"s"
var b strings.Builder
for i := range s {
b.WriteString(fmt.Sprintf("%-15s", s[i]))
b.WriteString(fmt.Sprintf("%-19s", s[i]))
}
return b.String()
}

View File

@@ -77,8 +77,11 @@ func (mgr *Manager) List() error {
strconv.Itoa(mgr.modules.LenLongestName()+2) +
"s%-11s%-11s%17s %s\n"
fmt.Printf(
format, "NAME", "LOCAL", "REMOTE",
format, "MODULE-NAME", "LOCAL", "REMOTE",
"HAS-UNPINNED-DEPS", "INTRA-REPO-DEPENDENCIES")
fmt.Printf(
format, "-----------", "-----", "------",
"-----------------", "-----------------------")
return mgr.modules.Apply(func(m misc.LaModule) error {
fmt.Printf(
format, m.ShortName(),

View File

@@ -6,11 +6,9 @@ require (
github.com/rakyll/statik v0.1.7
github.com/spf13/cobra v1.0.0
github.com/stretchr/testify v1.4.0
sigs.k8s.io/kustomize/api v0.6.5
sigs.k8s.io/kustomize/kyaml v0.9.4
sigs.k8s.io/kustomize/api v0.7.0
sigs.k8s.io/kustomize/kyaml v0.10.5
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/api v0.6.5 => ../../api
replace sigs.k8s.io/kustomize/kyaml v0.9.4 => ../../kyaml
replace sigs.k8s.io/kustomize/api => ../../api

View File

@@ -144,6 +144,8 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -215,6 +217,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -250,6 +253,8 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -355,8 +360,8 @@ github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiff
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
@@ -369,8 +374,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf h1:gvEmqF83GB8R5XtrMseJb6A6R0OCtNAS8f4TmZg2dGc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf/go.mod h1:bL0Pr07HEdsMZ1WBqZIxXj96r5LnFsY4LgPaPEGkw1k=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -503,11 +508,12 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
@@ -528,6 +534,8 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/kyaml v0.10.5 h1:PbJcsZsEM7O3hHtUWTR+4WkHVbQRW9crSy75or1gRbI=
sigs.k8s.io/kustomize/kyaml v0.10.5/go.mod h1:P6Oy/ah/GZMKzJMIJA2a3/bc8YrBkuL5kJji13PSIzY=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -16,7 +16,8 @@ import (
func main() {
var plugin resmap.Configurable
p := provider.NewDefaultDepProvider()
resmapFactory := resmap.NewFactory(p.GetResourceFactory(), p.GetMerginator())
resmapFactory := resmap.NewFactory(
p.GetResourceFactory(), p.GetConflictDetectorFactory())
pluginHelpers := resmap.NewPluginHelpers(
nil, p.GetFieldValidator(), resmapFactory)

View File

@@ -1,3 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: arbitrary
# Example configuration for the webserver
# at https://github.com/monopole/hello
commonLabels:

View File

@@ -172,7 +172,7 @@ resources:
EOF
```
Make a transformer configration file.
Make a transformer configuration file.
The transformer used is called `AddValueTransformer`. It's
intended to implement the 'add' operation of

View File

@@ -10,6 +10,7 @@
#
# Fails if the file already exists.
curl_timeout=600
release_url=https://api.github.com/repos/kubernetes-sigs/kustomize/releases
if [ -n "$1" ]; then
@@ -45,11 +46,11 @@ elif [[ "$OSTYPE" == darwin* ]]; then
opsys=darwin
fi
curl -s $release_url |\
curl -m $curl_timeout -s $release_url |\
grep browser_download.*${opsys}_${arch} |\
cut -d '"' -f 4 |\
sort | tail -n 1 |\
xargs curl -sLO
xargs curl -m $curl_timeout -sLO
if [ -e ./kustomize_v*_${opsys}_amd64.tar.gz ]; then
tar xzf ./kustomize_v*_${opsys}_amd64.tar.gz

View File

@@ -12,11 +12,22 @@ version=$1
# All hack scripts should run from top level.
. hack/shellHelpers.sh
echo "Installing kustomize ${version}"
# Always rebuild, never assume the installed verion is
# the right one to test.
rm -f $(go env GOPATH)/bin/kustomize
if [ "$version" == "HEAD" ]; then
(cd kustomize; go install .)
else
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@${version}
fi
# TODO: change the label?
# We test against the latest release, and HEAD, and presumably
# any branch using this label, so it should probably get
# a new value.
mdrip --mode test \
mdrip --mode test --blockTimeOut 15m \
--label testAgainstLatestRelease examples
# TODO: make work for non-linux
@@ -28,4 +39,10 @@ if onLinuxAndNotOnRemoteCI; then
mdrip --mode test --label helmtest examples/chart.md
fi
# Force outside logic to rebuild kustomize rather than
# rely on whatever this script just did. Tests should
# be order independent.
echo "Removing kustomize ${version}"
rm $(go env GOPATH)/bin/kustomize
echo "Example tests passed against ${version}."

View File

@@ -55,13 +55,9 @@ if onLinuxAndNotOnRemoteCI; then
make $(go env GOPATH)/bin/kubeval
fi
for goMod in $(find ./plugin -name 'go.mod'); do
for goMod in $(find ./plugin -name 'go.mod' -not -path "./plugin/untested/*"); do
d=$(dirname "${goMod}")
if [[ "$d" == "./plugin/someteam.example.com/v1/gogetter" ]]; then
echo "Skipping broken $d"
else
scanDir $d
fi
scanDir $d
done
if [ $rcAccumulator -ne 0 ]; then

View File

@@ -3,7 +3,7 @@ FROM golang:alpine as builder
ARG VERSION
ARG COMMIT
ARG DATE
RUN mkdir /build
RUN mkdir /build
ADD . /build/
WORKDIR /build/kustomize
RUN CGO_ENABLED=0 GO111MODULE=on go build \
@@ -17,4 +17,5 @@ FROM alpine
RUN apk add git openssh
COPY --from=builder /build/kustomize /app/
WORKDIR /app
ENTRYPOINT ["./kustomize"]
ENV PATH "$PATH:/app"
ENTRYPOINT ["/app/kustomize"]

View File

@@ -8,9 +8,9 @@ require (
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
k8s.io/client-go v0.18.10
sigs.k8s.io/kustomize/api v0.6.5
sigs.k8s.io/kustomize/cmd/config v0.8.5
sigs.k8s.io/kustomize/kyaml v0.9.4
sigs.k8s.io/kustomize/api v0.7.0
sigs.k8s.io/kustomize/cmd/config v0.8.7
sigs.k8s.io/kustomize/kyaml v0.10.5
sigs.k8s.io/yaml v1.2.0
)
@@ -20,8 +20,4 @@ exclude (
sigs.k8s.io/kustomize/cmd/config v0.2.0
)
replace sigs.k8s.io/kustomize/api v0.6.5 => ../api
replace sigs.k8s.io/kustomize/cmd/config v0.8.5 => ../cmd/config
replace sigs.k8s.io/kustomize/kyaml v0.9.4 => ../kyaml
replace sigs.k8s.io/kustomize/api => ../api

View File

@@ -169,6 +169,7 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -254,6 +255,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -294,6 +296,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -415,8 +418,8 @@ github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiff
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
@@ -429,8 +432,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf h1:gvEmqF83GB8R5XtrMseJb6A6R0OCtNAS8f4TmZg2dGc=
github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf/go.mod h1:bL0Pr07HEdsMZ1WBqZIxXj96r5LnFsY4LgPaPEGkw1k=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -584,12 +587,11 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -620,6 +622,10 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/cmd/config v0.8.7 h1:qhwnysAgGbSRD9AyLHmnybq7O8OuQkdDv7ZcEtkRWQQ=
sigs.k8s.io/kustomize/cmd/config v0.8.7/go.mod h1:TFvRemJUSkvJykqvrEErHd8GvC/TSEOKfPOpx/+f8Lc=
sigs.k8s.io/kustomize/kyaml v0.10.5 h1:PbJcsZsEM7O3hHtUWTR+4WkHVbQRW9crSy75or1gRbI=
sigs.k8s.io/kustomize/kyaml v0.10.5/go.mod h1:P6Oy/ah/GZMKzJMIJA2a3/bc8YrBkuL5kJji13PSIzY=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=

View File

@@ -99,6 +99,7 @@ func NewCmdBuild(out io.Writer) *cobra.Command {
addFlagReorderOutput(cmd.Flags())
addFlagEnableManagedbyLabel(cmd.Flags())
addFlagEnableKyaml(cmd.Flags())
addFlagAllowResourceIdChanges(cmd.Flags())
return cmd
}
@@ -137,6 +138,7 @@ func (o *Options) makeOptions() *krusty.Options {
}
opts.AddManagedbyLabel = isManagedbyLabelEnabled()
opts.UseKyaml = flagEnableKyamlValue
opts.AllowResourceIdChanges = flagAllowResourceIdChangesValue
return opts
}

View File

@@ -0,0 +1,23 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package build
import (
"github.com/spf13/pflag"
)
const (
flagAllowResourceIdChangesName = "allow_id_changes"
flagAllowResourceIdChangesHelp = `enable changes to a resourceId`
)
var (
flagAllowResourceIdChangesValue = false
)
func addFlagAllowResourceIdChanges(set *pflag.FlagSet) {
set.BoolVar(
&flagAllowResourceIdChangesValue, flagAllowResourceIdChangesName,
false, flagAllowResourceIdChangesHelp)
}

View File

@@ -73,6 +73,8 @@ images:
to the kustomization file if it doesn't exist,
and overwrite the previous ones if the image name exists.
The image tag can only contain alphanumeric, '.', '_' and '-'.
`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)

View File

@@ -19,5 +19,5 @@ require (
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
)

View File

@@ -295,6 +295,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -463,7 +463,7 @@ spec:
// TestFormatInput_service verifies a Service yaml is formatted correctly
func TestFormatInput_validatingWebhookConfiguration(t *testing.T) {
y := `
apiVersion: admissionregistration.k8s.io/v1beta1
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: <name of this configuration object>
@@ -490,7 +490,7 @@ webhooks:
- v1beta1
timeoutSeconds: 1
`
expected := `apiVersion: admissionregistration.k8s.io/v1beta1
expected := `apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: <name of this configuration object>

View File

@@ -13,7 +13,7 @@ import (
"sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi/v1191"
)
const Info = "{title:Kubernetes,version:v1.18.4},{title:Kubernetes,version:v1.18.6},{title:Kubernetes,version:v1.18.8},{title:Kubernetes,version:v1.19.0},{title:Kubernetes,version:v1.19.1}"
const Info = "{title:Kubernetes,version:v1.18.4}\n{title:Kubernetes,version:v1.18.6}\n{title:Kubernetes,version:v1.18.8}\n{title:Kubernetes,version:v1.19.0}\n{title:Kubernetes,version:v1.19.1}"
var OpenApiMustAsset = map[string]func(string) []byte{
"v1184": v1184.MustAsset,

View File

@@ -52,7 +52,7 @@ EOF
done
# add info string for `kustomize openapi info` command
OPEN_API_INFO=`echo ${info_list[@]} | tr " " ","`
OPEN_API_INFO=`echo ${info_list[@]} | sed 's/ /\\\n/g'`
cat <<EOF >>kubernetesapi/openapiinfo.go
)

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