Compare commits

...

184 Commits

Author SHA1 Message Date
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
Kubernetes Prow Robot
5279ad904b Merge pull request #3282 from pwittrock/main
Fn framework utilities for parsing templates from directories
2020-11-30 08:42:50 -08:00
Phillip Wittrock
736f110f04 Fn framework template and process options
- Refactor framework code to be simpler
- Add TemplatesFn feature
- Add PreProcessFilters feature
- Add PostProcessFilters features
- Add TemplatesFromDir
- Add PatchTemplatesFromDir
- Add PatchContainerTemplatesFromDir
2020-11-30 08:23:34 -08:00
Jeff Regan
c9ab1270fa Merge pull request #3290 from monopole/idSet
Add resource id set.
2020-11-30 05:42:26 -08:00
jregan
bb5fc9086b Add resource id set. 2020-11-30 05:37:53 -08:00
Kubernetes Prow Robot
e8c85456cc Merge pull request #3279 from monopole/addGeneratedCode
Add label and annotation selector code.
2020-11-28 22:36:48 -08:00
jregan
aa9a397808 Kyaml: disable generation on each build. 2020-11-28 05:55:16 -08:00
jregan
60ea8de5f1 Complete WNode implementation. 2020-11-26 14:48:00 -08:00
jregan
56c8df7b85 Add RNode implementation of label and annotation selectors. 2020-11-26 14:47:23 -08:00
Jeff Regan
a51e4234c4 Merge pull request #3283 from Shell32-Natsu/docker
Add git and openssh in docker image
2020-11-26 08:18:44 -08:00
Jeff Regan
50cd01e5f7 Update Makefile 2020-11-26 07:00:13 -08:00
Jeff Regan
42b082a6b1 Merge pull request #3285 from monopole/improveSelectTest
Add labels to selector test.
2020-11-26 06:57:14 -08:00
jregan
c3cdd15769 Clean up selector test. 2020-11-26 06:36:24 -08:00
Donny Xia
c3a8b6f359 Add git and openssh in docker image 2020-11-25 15:02:47 -08:00
Jeff Regan
4af4483e12 Merge pull request #3281 from Shell32-Natsu/update-go-version
update Go version to 1.15
2020-11-25 14:05:24 -08:00
Donny Xia
8f7bcb9b16 update Go version to 1.15 2020-11-25 12:41:20 -08:00
Jeff Regan
f54d904766 Merge pull request #3277 from monopole/moreRNodeSetters
More RNode setters and WNode delegation
2020-11-25 10:20:06 -08:00
Jeff Regan
ba91b6f79f Merge pull request #3278 from SyamSundarKirubakaran/doc-site-changes
Remove `zh` site contents and redirect to new site
2020-11-25 09:09:07 -08:00
Syam Sundar K
851acafe32 generate site 2020-11-25 21:42:09 +05:30
Syam Sundar K
14eac6020f remove duplicate contents and redirect 2020-11-25 21:41:27 +05:30
Jeff Regan
e45d667b4d Delete .gitattributes
Didn't work as desired.
2020-11-25 07:59:58 -08:00
Jeff Regan
cbdf4a0e43 Update .gitattributes 2020-11-25 07:53:35 -08:00
jregan
aed7e5aaf9 Delegate more from WNode to RNode.
The implementations in WNode are supposed to be thin,
as it will be removed once #2506 closes.

The change also makes some addjustments for the
upcoming flip of the enable_kyaml flag, pointing to
issue #3271.
2020-11-25 07:11:06 -08:00
jregan
ec64ef705b Add metadata getters and setters to RNode.
These setters completely remove the field if the argument
is empty, rather than setting the field to an empty value,
mimicing apimachinery behavior.
2020-11-25 07:03:12 -08:00
Jeff Regan
1e0eb58bc9 Merge pull request #3273 from Shell32-Natsu/reenable-multi-module-check
Re-enable multi-module check
2020-11-24 19:18:16 -08:00
Jeff Regan
fd2fe35863 Merge pull request #3275 from monopole/tryGitAttributes
Start a gitattributes file.
2020-11-24 19:12:23 -08:00
jregan
ebdbd81ed8 Start a gitattributes file. 2020-11-24 18:50:46 -08:00
Donny Xia
c9d2ae6b49 Re-enable multi-module check 2020-11-24 16:29:01 -08:00
Kubernetes Prow Robot
e8c212a10f Merge pull request #3272 from monopole/moreTests
Add more tests around yaml parsing.
2020-11-24 14:34:39 -08:00
jregan
1eb378254a Add more tests around yaml parsing. 2020-11-24 14:15:45 -08:00
Kubernetes Prow Robot
0d030e3095 Merge pull request #3270 from pwittrock/main
Improved fn framework support for patching
2020-11-24 12:22:39 -08:00
Phillip Wittrock
f2706dce68 Improved fn framework support for patching
- Generate patches with a func
- Generate patches for containers
2020-11-24 12:02:55 -08:00
Jeff Regan
f8194bd3c2 Merge pull request #3267 from monopole/generatedCode
Add generated code.
2020-11-23 16:51:41 -08:00
jregan
eb5227680e Add generated code. 2020-11-23 16:47:00 -08:00
Jeff Regan
27e89f271f Merge pull request #3266 from monopole/modsToMakefile
Consistently prefix make targets with clean, generate, build.
2020-11-23 16:37:34 -08:00
jregan
626f2f9d1d Another cleaning target in Makefile. 2020-11-23 16:14:47 -08:00
Jeff Regan
ffda124ca5 Update Makefile 2020-11-23 06:48:53 -08:00
Jeff Regan
fd677f635e Update README.md 2020-11-22 21:01:28 -08:00
Jeff Regan
14b1388c6a Merge pull request #3263 from monopole/useLessReflectionInTests
In some tests, replace reflection with yaml compare.
2020-11-22 20:34:38 -08:00
jregan
5248fd0cd9 In some tests, replace reflection with yaml compare. 2020-11-22 18:48:32 -08:00
Jeff Regan
b6ae9f80d3 Merge pull request #3257 from monopole/binaryData
Secrets and ConfigMaps with binary data in kyaml
2020-11-21 15:11:29 -08:00
Jeff Regan
2ad502d5a8 Merge pull request #3261 from monopole/depProviderInjection
Use DepProvider in tests to access kyaml impls.
2020-11-21 15:07:45 -08:00
jregan
a5f3d5c823 Use DepProvider in tests to access kyaml impls. 2020-11-21 14:49:44 -08:00
Jeff Regan
c65875cacc Merge pull request #3259 from pwittrock/main
fn/framework support for reading from stdin in standalone
2020-11-21 14:44:54 -08:00
Phillip Wittrock
82b2d83ede fn/framework support for reading from stdin in standalone
- speficy '-' to read from stdin when running standalone
2020-11-21 09:17:26 -08:00
Jeff Regan
7e01aec5a4 Update Makefile 2020-11-21 07:14:04 -08:00
Jeff Regan
9e8a84c5ff Merge pull request #3251 from Shell32-Natsu/krm-function-converter
[KRM function converter] Get plugin config from data field
2020-11-21 06:25:42 -08:00
Jeff Regan
849d5c4a8d Merge branch 'master' into krm-function-converter 2020-11-21 06:10:25 -08:00
Jeff Regan
00352cbc58 Merge pull request #3256 from Shell32-Natsu/pluginator-api-version
update module api version in wrapper
2020-11-21 06:09:04 -08:00
jregan
b88e770b1d binary data nope 2020-11-20 17:55:20 -08:00
Jeff Regan
eda7a9f8d6 Merge pull request #3258 from monopole/goSumAutomated
Automated go.sum change.
2020-11-20 17:55:01 -08:00
jregan
114b3f4b00 Automated go.sum change. 2020-11-20 17:18:14 -08:00
Donny Xia
6cb339142d update module api version in wrapper 2020-11-20 16:28:38 -08:00
Kubernetes Prow Robot
052a6b4e96 Merge pull request #3255 from Shell32-Natsu/rnode-format
fix rnode string format converted from resmap
2020-11-20 15:07:33 -08:00
Donny Xia
4add7eccd0 fix rnode string format converted from resmap 2020-11-20 14:34:11 -08:00
Kubernetes Prow Robot
a0a89e1adc Merge pull request #3250 from pwittrock/main
Function framework support for patching containers
2020-11-20 12:42:51 -08:00
Donny Xia
10fd4b4bbe Merge pull request #3252 from runewake2/notes
Update release notes generation
2020-11-20 10:24:03 -08:00
Donny Xia
e15ede037d Merge pull request #3253 from yujunz/remote-build
Fix test against examples
2020-11-20 09:47:47 -08:00
Yujun Zhang
32a2f5ffa9 Fix test against examples
Tests in examples.remoteBuild.md were skipped unexpectedly
2020-11-20 20:10:07 +08:00
Sam Wronski
4f74203f6c Fix variable name: "currentTag" -> "fullTag" 2020-11-19 15:37:39 -08:00
Sam Wronski
5b0cbcb5fb Update release notes generation
- Notes use tags instead commit sha
2020-11-19 14:28:05 -08:00
Donny Xia
2f4c35347e Get plugin config from data field 2020-11-19 13:11:47 -08:00
Phillip Wittrock
be5db09db1 Function framework support for patching containers 2020-11-19 10:01:12 -08:00
Jeff Regan
a6833bc4c0 Merge pull request #3211 from Shell32-Natsu/krm-plugin-tool
modify pluginator to support convert builtin plugin to krm function
2020-11-18 15:59:29 -08:00
Donny Xia
2ae323bb26 move files into internal 2020-11-18 12:21:59 -08:00
Donny Xia
7e74271071 fix script name 2020-11-18 12:21:59 -08:00
Donny Xia
260e093547 modify pluginator to add support for krm function 2020-11-18 12:21:59 -08:00
Jeff Regan
47b12fa3dc Merge pull request #3240 from Shell32-Natsu/list-builtin
Add command to list builtin plugins
2020-11-18 11:13:39 -08:00
Jeff Regan
38801cd966 Merge pull request #3238 from Shell32-Natsu/managed-by-label
fix invalid managed-by label value
2020-11-18 11:09:28 -08:00
Jeff Regan
c49e177b9c Merge pull request #3247 from monopole/secretsAndMaps
Secrets and ConfigMaps with string data in kyaml
2020-11-18 10:00:38 -08:00
jregan
486be07e22 Add WNodeFactory.MakeConfigMap,MakeSecret 2020-11-18 09:45:43 -08:00
Donny Xia
a12db91a10 mark the list-builtin command alpha 2020-11-18 09:38:03 -08:00
jregan
f7613631d1 Add some kyaml filters for k8s metadata. 2020-11-18 08:57:13 -08:00
Kubernetes Prow Robot
8a77494c7d Merge pull request #3239 from pwittrock/framework
Function framework features
2020-11-17 17:58:04 -08:00
Kubernetes Prow Robot
af25469c8b Merge pull request #3219 from phanimarupaka/RefactorOpenAPI
Refactor open api
2020-11-17 11:26:04 -08:00
Phillip Wittrock
8c4841c28f Support for framework.Selector substitutions 2020-11-17 08:52:34 -08:00
Phani Teja Marupaka
b6a4dd446a Refactor openAPI
Refactor global openapi
2020-11-16 23:03:56 -08:00
Jeff Regan
606654756d Update kfns.go 2020-11-16 21:38:25 -08:00
Jeff Regan
97c18518ea Update rnode.go 2020-11-16 21:37:28 -08:00
Jeff Regan
2dca4ab987 Merge pull request #3242 from monopole/useConst
Gather and use some of the kyaml constants.
2020-11-16 21:31:13 -08:00
jregan
712276176c Gather and use some of the kyaml constants. 2020-11-16 21:26:18 -08:00
Donny Xia
c610e3a364 Add command to list builtin plugins 2020-11-16 17:18:56 -08:00
Phillip Wittrock
02e7589323 Function framework testutil support for functions which refer to local files
Some functions may read local files using relative paths.  Update the test
framework to `cd` into the directory containing the config.yaml before
running the function.
2020-11-16 16:35:07 -08:00
Kubernetes Prow Robot
2ae180ca23 Merge pull request #3235 from pwittrock/framework
fn framework TemplatePatch support
2020-11-16 14:14:05 -08:00
Donny Xia
98900c43f7 fix invalid managed-by label value 2020-11-16 14:05:21 -08:00
Phillip Wittrock
02b14d919b fn framework -- add support for patch templates 2020-11-16 14:01:08 -08:00
Phillip Wittrock
bd0a699ff6 Refactor fn/framework tests to use a common library. 2020-11-16 14:00:55 -08:00
Jeff Regan
02b4b56c60 Merge pull request #3233 from monopole/sliceFromBytes
Implement WNodeFactory.SliceFromBytes
2020-11-16 11:57:09 -08:00
jregan
0cac05448b Implement WNodeFactory.SliceFromBytes and FromMap 2020-11-16 11:33:04 -08:00
jregan
e1c3caeba6 Introduce some RNode validation methods. 2020-11-16 11:32:23 -08:00
Jeff Regan
a25429ae3b Merge pull request #3236 from runewake2/mergeless-releases
Remove merge commits from release notes
2020-11-16 11:22:01 -08:00
Kubernetes Prow Robot
e557677fed Merge pull request #3229 from Shell32-Natsu/krm-plugin-tool-helpers
Add methods to convert ResMap to and from RNodes
2020-11-16 11:12:06 -08:00
Donny Xia
59e0b593cf Merge pull request #3232 from justinsb/hint_about_bytereader
Expand rnode function comments to point to multi-object options.
2020-11-16 10:12:54 -08:00
Sam Wronski
3fa906505c Remove merge commits from release notes 2020-11-16 09:47:57 -08:00
Justin SB
a823f3043f Expand rnode function comments to point to multi-object options.
The rnode Parse and ReadFile functions only return a single object;
suggest kio.ByteReader for the case of parsing multiple objects.
2020-11-15 13:07:28 -05:00
Jeff Regan
b2ba82a0bd Merge pull request #3231 from monopole/fromMap
Add RNode FromMap factory method.
2020-11-14 13:33:12 -08:00
jregan
a4f22cb84f Add RNode fromMap method. 2020-11-14 13:10:53 -08:00
Jeff Regan
22f41c789a Merge pull request #3230 from monopole/fmtFix
Fix go fmt.
2020-11-14 11:03:59 -08:00
jregan
966d0a054c Fix go fmt. 2020-11-14 11:02:44 -08:00
Kubernetes Prow Robot
97f3ac2da1 Merge pull request #3185 from aodinokov/streamline-fn-plugin-kyaml-part
Allowing RunFns not to stop on empty result
2020-11-13 13:47:04 -08:00
Donny Xia
536b69e5dc add methods to convert resmap to&from rnodes 2020-11-13 13:41:34 -08:00
Kubernetes Prow Robot
c7aaa18d0c Merge pull request #3227 from radTuti/master
update kustomize download script
2020-11-13 11:39:05 -08:00
tuti
a45523bb95 dry release_url 2020-11-13 11:25:35 -08:00
Kubernetes Prow Robot
376f59f0f6 Merge pull request #3222 from natasha41575/EditSetLabel
added kustomize edit set label
2020-11-13 11:15:04 -08:00
tuti
34863346b0 include arch type in grep string 2020-11-13 11:09:56 -08:00
Kubernetes Prow Robot
9569ca93d9 Merge pull request #3220 from natasha41575/OpenApiVersionField
Add multiple versions of OpenAPI schema to kyaml
2020-11-13 10:39:05 -08:00
Kubernetes Prow Robot
09377ac19c Merge pull request #3223 from sylr/azure-file
Add namereference for PersistentVolume
2020-11-13 10:25:04 -08:00
Jeff Regan
a25300dfd6 Merge pull request #3225 from Shell32-Natsu/inline-transformer
support inline transformer and generator
2020-11-13 10:05:43 -08:00
Kubernetes Prow Robot
50e9e90b17 Merge pull request #3226 from phanimarupaka/DeprecateV1Setters
Delete v1 setters code
2020-11-13 09:21:06 -08:00
tuti
e3ad472933 allow downloading older releases 2020-11-12 18:19:02 -08:00
tuti
154f894774 fix latest release download failure 2020-11-12 18:17:47 -08:00
Natasha Sarkar
4d7600d4ef updated comments and readme 2020-11-12 18:02:11 -08:00
tuti
0a0a0ccddc Merge branch 'master' from kubernetes-sigs/kustomize 2020-11-12 17:59:53 -08:00
Phani Teja Marupaka
2278e01b7f Delete v1 setters code 2020-11-12 15:29:07 -08:00
Donny Xia
abc88c56c4 support inline transformer and generator 2020-11-12 15:19:14 -08:00
Kubernetes Prow Robot
eddd872eca Merge pull request #3221 from pwittrock/framework
Function framework standalone feature
2020-11-12 13:52:25 -08:00
Sylvain Rabot
febede115e Add namereference for PersistentVolume
Signed-off-by: Sylvain Rabot <sylvain@abstraction.fr>
2020-11-12 22:47:33 +01:00
Natasha Sarkar
a2087f07d4 added kustomize edit set label 2020-11-12 13:26:52 -08:00
Phillip Wittrock
8b9d8a266d Support standalone mode for framework functions 2020-11-12 11:54:58 -08:00
Phillip Wittrock
5557e1ff3c Retain element ordering when merge resources 2020-11-12 08:54:16 -08:00
Phillip Wittrock
1c009ca217 More control over bytereadwriter options
- Override wrapping
- Override function config
2020-11-12 08:54:16 -08:00
Natasha Sarkar
bdb59d2cd2 updated releasing readme 2020-11-11 18:09:41 -08:00
Natasha Sarkar
b61a115e76 added support for multiple kubernetes openapi schemas 2020-11-11 18:09:41 -08:00
Jeff Regan
66221d17d4 Merge pull request #3217 from Shell32-Natsu/image
remove a tag from image
2020-11-11 16:22:51 -08:00
Kubernetes Prow Robot
c83f256dbe Merge pull request #3218 from monopole/unpinEverything
Unpin everything post v3.8.7 release
2020-11-11 15:58:52 -08:00
jregan
fa3caaacee Unpin everything post v3.8.7 release 2020-11-11 15:45:09 -08:00
Kubernetes Prow Robot
0a0a2ed586 Merge pull request #3209 from pwittrock/main
Remove duplicate docs content
2020-11-11 15:44:52 -08:00
Donny Xia
aff1db13e0 remove a tag from image 2020-11-11 15:41:32 -08:00
Kubernetes Prow Robot
ad092cc7a9 Merge pull request #3216 from monopole/pin_api_v0.6.5
Pin to api_v0.6.5
2020-11-11 15:08:50 -08:00
jregan
0a9fc6c8cb Pin to api_v0.6.5 2020-11-11 14:56:25 -08:00
Phillip Wittrock
afff3ce5ab update docs site 2020-11-11 08:30:00 -08:00
Phillip Wittrock
71b763888c Remove duplicate kustomize docs content 2020-11-11 08:29:43 -08:00
Alexey Odinokov
28cdcc2e46 Allowing RunFns not to stop on empty result
Introducing the additional flag
ContinueOnEmptyResult that is false by default
to keep compatibility with the previous behavior.
Based on [1]

[1]
https://github.com/kubernetes-sigs/kustomize/pull/3112
2020-11-05 07:19:20 +00:00
560 changed files with 375058 additions and 27229 deletions

View File

@@ -33,16 +33,13 @@ verify-kustomize: \
.PHONY: prow-presubmit-check
prow-presubmit-check: \
lint-kustomize \
test-multi-module \
test-unit-kustomize-all \
test-unit-cmd-all \
test-go-mod \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.6
# test-multi-module \
# Temporarily removed from prow-presubmit-check
# See https://github.com/kubernetes-sigs/kustomize/issues/3191
.PHONY: verify-kustomize-e2e
verify-kustomize-e2e: test-examples-e2e-kustomize
@@ -193,24 +190,27 @@ $(pGen)/%.go: $(MYGOBIN)/pluginator
.PHONY: generate-kustomize-builtin-plugins
generate-kustomize-builtin-plugins: $(builtinplugins)
.PHONY: kustomize-external-go-plugin-build
kustomize-external-go-plugin-build:
.PHONY: build-kustomize-external-go-plugin
build-kustomize-external-go-plugin:
./hack/buildExternalGoPlugins.sh ./plugin
.PHONY: kustomize-external-go-plugin-clean
kustomize-external-go-plugin-clean:
.PHONY: clean-kustomize-external-go-plugin
clean-kustomize-external-go-plugin:
./hack/buildExternalGoPlugins.sh ./plugin clean
### End kustomize plugin rules.
.PHONY: lint-kustomize
lint-kustomize: install-tools $(builtinplugins)
cd api; \
$(MYGOBIN)/golangci-lint-kustomize -c ../.golangci-kustomize.yml run ./...
cd kustomize; \
$(MYGOBIN)/golangci-lint-kustomize -c ../.golangci-kustomize.yml run ./...
cd cmd/pluginator; \
$(MYGOBIN)/golangci-lint-kustomize -c ../../.golangci-kustomize.yml run ./...
cd api; $(MYGOBIN)/golangci-lint-kustomize \
-c ../.golangci-kustomize.yml \
run ./...
cd kustomize; $(MYGOBIN)/golangci-lint-kustomize \
-c ../.golangci-kustomize.yml \
run ./...
cd cmd/pluginator; $(MYGOBIN)/golangci-lint-kustomize \
-c ../../.golangci-kustomize.yml \
run ./...
# Used to add non-default compilation flags when experimenting with
# plugin-to-api compatibility checks.
@@ -218,6 +218,10 @@ lint-kustomize: install-tools $(builtinplugins)
build-kustomize-api: $(builtinplugins)
cd api; go build ./...
.PHONY: generate-kustomize-api
generate-kustomize-api:
cd api; go generate ./...
.PHONY: test-unit-kustomize-api
test-unit-kustomize-api: build-kustomize-api
cd api; go test ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
@@ -354,13 +358,15 @@ $(MYGOBIN)/gh:
)
.PHONY: clean
clean: kustomize-external-go-plugin-clean
clean: clean-kustomize-external-go-plugin
go clean --cache
rm -f $(builtinplugins)
rm -f $(MYGOBIN)/pluginator
rm -f $(MYGOBIN)/kustomize
rm -f $(MYGOBIN)/golangci-lint-kustomize
# Handle pluginator manually.
# rm -f $(MYGOBIN)/pluginator
# Nuke the site from orbit. It's the only way to be sure.
.PHONY: nuke
nuke: clean

View File

@@ -20,15 +20,20 @@ This tool is sponsored by [sig-cli] ([KEP]).
## kubectl integration
Since [v1.14][kubectl announcement] the kustomize build system has been included in kubectl.
The kustomize build flow at [v2.0.3] was added
to [kubectl v1.14][kubectl announcement]. The kustomize
flow in kubectl has remained frozen at v2.0.3 while work
to extract kubectl from the k/k repo, and work to remove
kustomize's dependence on core k/k code ([#2506]) has proceeded.
The reintegration effort is tracked in [#1500] (and its blocking
issues).
| kubectl version | kustomize version |
|---------|--------|
| v1.16.0 | [v2.0.3](/../../tree/v2.0.3) |
| v1.15.x | [v2.0.3](/../../tree/v2.0.3) |
| v1.14.x | [v2.0.3](/../../tree/v2.0.3) |
[v2.0.3]: /../../tree/v2.0.3
[#2506]: https://github.com/kubernetes-sigs/kustomize/issues/2506
[#1500]: https://github.com/kubernetes-sigs/kustomize/issues/1500
For examples and guides for using the kubectl integration please see the [kubectl book] or the [kubernetes documentation].
For examples and guides for using the kubectl integration please
see the [kubectl book] or the [kubernetes documentation].
## Usage
@@ -148,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

@@ -125,6 +125,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,14 +5,10 @@ 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"
)
@@ -35,6 +31,11 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
}
if len(p.Paths) != 0 {
for _, onePath := range p.Paths {
// 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 := p.h.ResmapFactory().RF().SliceFromBytes([]byte(onePath))
if err == nil {
p.loadedPatches = append(p.loadedPatches, res...)
@@ -73,44 +74,10 @@ func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error
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

@@ -5,10 +5,9 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
@@ -220,7 +219,7 @@ map:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
factory := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
factory := provider.NewDefaultDepProvider().GetResourceFactory()
referrer, err := factory.FromBytes([]byte(tc.input))
if err != nil {
t.Fatal(err)
@@ -321,7 +320,7 @@ metadata:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
factory := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
factory := provider.NewDefaultDepProvider().GetResourceFactory()
referrer, err := factory.FromBytes([]byte(tc.input))
if err != nil {
t.Fatal(err)
@@ -732,7 +731,7 @@ ref:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
factory := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
factory := provider.NewDefaultDepProvider().GetResourceFactory()
referrer, err := factory.FromBytes([]byte(tc.input))
if err != nil {
t.Fatal(err)

View File

@@ -15,6 +15,78 @@ func TestFilter(t *testing.T) {
patch *yaml.RNode
expected string
}{
"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

@@ -1,9 +1,10 @@
module sigs.k8s.io/kustomize/api
go 1.14
go 1.15
require (
github.com/evanphx/json-patch v4.5.0+incompatible
github.com/go-errors/errors v1.0.1
github.com/go-openapi/spec v0.19.5
github.com/golangci/golangci-lint v1.21.0
github.com/google/go-cmp v0.3.0
@@ -11,7 +12,7 @@ require (
github.com/hashicorp/go-multierror v1.1.0
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
@@ -19,6 +20,6 @@ require (
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
sigs.k8s.io/kustomize/kyaml v0.9.4
sigs.k8s.io/kustomize/kyaml v0.10.3
sigs.k8s.io/yaml v1.2.0
)

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=
@@ -287,6 +290,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 +369,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 +411,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 +428,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,6 +566,7 @@ 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=
@@ -592,8 +598,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.9.4 h1:DDuzZtjIzFqp2IPy4DTyCI69Cl3bDgcJODjI6sjF9NY=
sigs.k8s.io/kustomize/kyaml v0.9.4/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
sigs.k8s.io/kustomize/kyaml v0.10.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj908I=
sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
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

@@ -8,17 +8,14 @@ import (
"testing"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/provider"
"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"
)
func TestNameReferenceHappyRun(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).AddWithName(
m := resmaptest_test.NewRmBuilderDefault(t).AddWithName(
"cm1",
map[string]interface{}{
"apiVersion": "v1",
@@ -261,7 +258,8 @@ func TestNameReferenceHappyRun(t *testing.T) {
},
}).ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).ReplaceResource(
expected := resmaptest_test.NewSeededRmBuilderDefault(
t, m.ShallowCopy()).ReplaceResource(
map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
@@ -475,14 +473,12 @@ func TestNameReferenceHappyRun(t *testing.T) {
}
func TestNameReferenceUnhappyRun(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
tests := []struct {
resMap resmap.ResMap
expectedErr string
}{
{
resMap: resmaptest_test.NewRmBuilder(t, rf).Add(
resMap: resmaptest_test.NewRmBuilderDefault(t).Add(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
@@ -502,7 +498,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
}).ResMap(),
expectedErr: "is expected to be"},
{
resMap: resmaptest_test.NewRmBuilder(t, rf).Add(
resMap: resmaptest_test.NewRmBuilderDefault(t).Add(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
@@ -538,8 +534,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
}
func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
rf := provider.NewDefaultDepProvider().GetResourceFactory()
v1 := rf.FromMapWithName(
"volume1",
@@ -664,9 +659,7 @@ const (
// object with the same original names (uniquename) in different namespaces
// and with different current Id.
func TestNameReferenceNamespace(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).
m := resmaptest_test.NewRmBuilderDefault(t).
// Add ConfigMap with the same org name in noNs, "ns1" and "ns2" namespaces
AddWithName(orgname, map[string]interface{}{
"apiVersion": "v1",
@@ -715,7 +708,7 @@ func TestNameReferenceNamespace(t *testing.T) {
AddWithNsAndName(ns1, orgname, deploymentMap(ns1, prefixedname, orgname, orgname)).
AddWithNsAndName(ns2, orgname, deploymentMap(ns2, suffixedname, orgname, orgname)).ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
expected := resmaptest_test.NewSeededRmBuilderDefault(t, m.ShallowCopy()).
ReplaceResource(deploymentMap(defaultNs, modifiedname, modifiedname, modifiedname)).
ReplaceResource(deploymentMap(ns1, prefixedname, prefixedname, prefixedname)).
ReplaceResource(deploymentMap(ns2, suffixedname, suffixedname, suffixedname)).ResMap()
@@ -735,9 +728,7 @@ func TestNameReferenceNamespace(t *testing.T) {
// object with the same original names (uniquename) in different namespaces
// and with different current Id.
func TestNameReferenceClusterWide(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).
m := resmaptest_test.NewRmBuilderDefault(t).
// Add ServiceAccount with the same org name in noNs, "ns1" and "ns2" namespaces
AddWithName(orgname, map[string]interface{}{
"apiVersion": "v1",
@@ -816,7 +807,7 @@ func TestNameReferenceClusterWide(t *testing.T) {
},
}}).ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
expected := resmaptest_test.NewSeededRmBuilderDefault(t, m.ShallowCopy()).
ReplaceResource(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
@@ -898,9 +889,7 @@ func TestNameReferenceClusterWide(t *testing.T) {
// object with the same original names (uniquename) in different namespaces
// and with different current Id.
func TestNameReferenceNamespaceTransformation(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).
m := resmaptest_test.NewRmBuilderDefault(t).
AddWithNsAndName(ns4, orgname, map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
@@ -964,7 +953,7 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
},
}}).ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
expected := resmaptest_test.NewSeededRmBuilderDefault(t, m.ShallowCopy()).
ReplaceResource(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
@@ -1026,9 +1015,7 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
// It validates the change done is IsSameFuzzyNamespace which
// uses the IsNsEquals method instead of the simple == operator.
func TestNameReferenceCandidateSelection(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmaptest_test.NewRmBuilder(t, rf).
m := resmaptest_test.NewRmBuilderDefault(t).
AddWithName("cm1", map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -1045,7 +1032,7 @@ func TestNameReferenceCandidateSelection(t *testing.T) {
AddWithName("deploy1", deploymentMap("", "p1-deploy1", "cm1", "secret1")).
ResMap()
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
expected := resmaptest_test.NewSeededRmBuilderDefault(t, m.ShallowCopy()).
ReplaceResource(deploymentMap("", "p1-deploy1", "p1-cm1-hash", "p1-secret1-hash")).
ResMap()

View File

@@ -7,10 +7,8 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"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"
"sigs.k8s.io/kustomize/api/types"
)
@@ -46,8 +44,7 @@ func TestRefVarTransformer(t *testing.T) {
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/interface"},
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/num"},
},
res: resmaptest_test.NewRmBuilder(
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
res: resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -77,8 +74,7 @@ func TestRefVarTransformer(t *testing.T) {
}}).ResMap(),
},
expected: expected{
res: resmaptest_test.NewRmBuilder(
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
res: resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -116,8 +112,7 @@ func TestRefVarTransformer(t *testing.T) {
fs: []types.FieldSpec{
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/slice"},
},
res: resmaptest_test.NewRmBuilder(
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
res: resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -138,8 +133,7 @@ func TestRefVarTransformer(t *testing.T) {
fs: []types.FieldSpec{
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/nil"},
},
res: resmaptest_test.NewRmBuilder(
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
res: resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -151,8 +145,7 @@ func TestRefVarTransformer(t *testing.T) {
}}).ResMap(),
},
expected: expected{
res: resmaptest_test.NewRmBuilder(
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
res: resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",

View File

@@ -12,7 +12,7 @@ import (
. "sigs.k8s.io/kustomize/api/internal/accumulator"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
@@ -20,16 +20,14 @@ import (
"sigs.k8s.io/kustomize/api/types"
)
func makeResAccumulator(t *testing.T) (*ResAccumulator, *resource.Factory) {
func makeResAccumulator(t *testing.T) *ResAccumulator {
ra := MakeEmptyAccumulator()
err := ra.MergeConfig(builtinconfig.MakeDefaultConfig())
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
err = ra.AppendAll(
resmaptest_test.NewRmBuilder(t, rf).
resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
@@ -66,11 +64,11 @@ func makeResAccumulator(t *testing.T) (*ResAccumulator, *resource.Factory) {
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
return ra, rf
return ra
}
func TestResolveVarsHappy(t *testing.T) {
ra, _ := makeResAccumulator(t)
ra := makeResAccumulator(t)
err := ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
@@ -99,7 +97,7 @@ func TestResolveVarsHappy(t *testing.T) {
}
func TestResolveVarsOneUnused(t *testing.T) {
ra, _ := makeResAccumulator(t)
ra := makeResAccumulator(t)
err := ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
@@ -140,11 +138,10 @@ func expectLog(t *testing.T, log bytes.Buffer, expect string) {
}
func TestResolveVarsVarNeedsDisambiguation(t *testing.T) {
ra, rf := makeResAccumulator(t)
ra := makeResAccumulator(t)
rm0 := resmap.New()
err := rm0.Append(
rf.FromMap(
provider.NewDefaultDepProvider().GetResourceFactory().FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
@@ -213,8 +210,7 @@ func makeVarToNamepaceAndPath(
}
func TestResolveVarConflicts(t *testing.T) {
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
rf := provider.NewDefaultDepProvider().GetResourceFactory()
// create configmaps in foo and bar namespaces with `data.provider` values.
fooAws := makeNamespacedConfigMapWithDataProviderValue("foo", "aws")
barAws := makeNamespacedConfigMapWithDataProviderValue("bar", "aws")
@@ -261,7 +257,7 @@ func TestResolveVarConflicts(t *testing.T) {
}
func TestResolveVarsGoodResIdBadField(t *testing.T) {
ra, _ := makeResAccumulator(t)
ra := makeResAccumulator(t)
err := ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
@@ -286,7 +282,7 @@ func TestResolveVarsGoodResIdBadField(t *testing.T) {
}
func TestResolveVarsUnmappableVar(t *testing.T) {
ra, _ := makeResAccumulator(t)
ra := makeResAccumulator(t)
err := ra.MergeVars([]types.Var{
{
Name: "SERVICE_THREE",
@@ -310,7 +306,7 @@ func TestResolveVarsUnmappableVar(t *testing.T) {
}
func TestResolveVarsWithNoambiguation(t *testing.T) {
ra1, rf := makeResAccumulator(t)
ra1 := makeResAccumulator(t)
err := ra1.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
@@ -327,7 +323,7 @@ func TestResolveVarsWithNoambiguation(t *testing.T) {
// Create another accumulator having a resource with different prefix
ra2 := MakeEmptyAccumulator()
m := resmaptest_test.NewRmBuilder(t, rf).
m := resmaptest_test.NewRmBuilderDefault(t).
Add(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",

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,28 @@
// 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
}
func (c *smPatchMergeOnlyDetector) MergePatches(
r, patch *resource.Resource) (*resource.Resource, error) {
err := r.ApplySmPatch(patch)
return r, err
}

View File

@@ -7,14 +7,13 @@ import (
"sort"
"strings"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
var fileReader = kunstruct.NewKunstructuredFactoryImpl()
// This document is meant to be used at the elasticsearch document type.
// Fields are serialized as-is to elasticsearch, where indices are built
// to facilitate text search queries. Identifiers, Values, FilePath,
@@ -42,6 +41,7 @@ type KustomizationDocument struct {
Kinds []string `json:"kinds,omitempty"`
Identifiers []string `json:"identifiers,omitempty"`
Values []string `json:"values,omitempty"`
resFactory *resource.Factory
}
type set map[string]struct{}
@@ -52,6 +52,7 @@ func (doc *KustomizationDocument) Copy() *KustomizationDocument {
Kinds: doc.Kinds,
Identifiers: doc.Identifiers,
Values: doc.Values,
resFactory: provider.NewDefaultDepProvider().GetResourceFactory(),
}
}
@@ -150,7 +151,7 @@ func (doc *KustomizationDocument) readBytes() ([]map[string]interface{}, error)
}
configs := make([]map[string]interface{}, 0)
ks, err := fileReader.SliceFromBytes(data)
ks, err := doc.resFactory.SliceFromBytes(data)
if err != nil {
return nil, fmt.Errorf("unable to parse resource: %v", err)
}

View File

@@ -1,6 +1,6 @@
module sigs.k8s.io/kustomize/api/internal/crawl
go 1.14
go 1.15
require (
github.com/elastic/go-elasticsearch/v6 v6.8.5

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=
@@ -253,6 +254,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=
@@ -317,6 +319,7 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
@@ -355,8 +358,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 +372,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,6 +506,7 @@ 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=
@@ -529,8 +533,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.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj908I=
sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
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

@@ -0,0 +1,51 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package generators
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// MakeConfigMap makes a configmap.
//
// ConfigMap: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#configmap-v1-core
//
// ConfigMaps and Secrets are similar.
//
// Both objects have a `data` field, which contains a map from keys to
// values that must be UTF-8 valid strings. Such data might be simple text,
// or whoever made the data may have done so by performing a base64 encoding
// on binary data. Regardless, k8s has no means to know this, so it treats
// the data field as a string.
//
// The ConfigMap has an additional field `binaryData`, also a map, but its
// values are _intended_ to be interpreted as a base64 encoding of []byte,
// by whatever makes use of the ConfigMap.
//
// In a ConfigMap, any key used in `data` cannot also be used in `binaryData`
// and vice-versa. A key must be unique across both maps.
func MakeConfigMap(
ldr ifc.KvLoader, args *types.ConfigMapArgs) (rn *yaml.RNode, err error) {
rn, err = makeBaseNode("ConfigMap", args.Name, args.Namespace)
if err != nil {
return nil, err
}
m, err := makeValidatedDataMap(ldr, args.Name, args.KvPairSources)
if err != nil {
return nil, err
}
for _, k := range filtersutil.SortedMapKeys(m) {
fldName, vrN := makeConfigMapValueRNode(m[k])
if _, err = rn.Pipe(
yaml.LookupCreate(yaml.MappingNode, fldName),
yaml.SetField(k, vrN)); err != nil {
return nil, err
}
}
copyLabelsAndAnnotations(rn, args.Options)
return rn, err
}

View File

@@ -0,0 +1,223 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package generators_test
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filesys"
. "sigs.k8s.io/kustomize/api/internal/generators"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/loader"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
var binaryHello = []byte{
0xff, // non-utf8
0x68, // h
0x65, // e
0x6c, // l
0x6c, // l
0x6f, // o
}
func manyHellos(count int) (result []byte) {
for i := 0; i < count; i++ {
result = append(result, binaryHello...)
}
return
}
func TestMakeConfigMap(t *testing.T) {
type expected struct {
out string
errMsg string
}
testCases := map[string]struct {
args types.ConfigMapArgs
exp expected
}{
"construct config map from env": {
args: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "envConfigMap",
KvPairSources: types.KvPairSources{
EnvSources: []string{
filepath.Join("configmap", "app.env"),
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: ConfigMap
metadata:
name: envConfigMap
data:
DB_PASSWORD: qwerty
DB_USERNAME: admin
`,
},
},
"construct config map from text file": {
args: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileConfigMap1",
KvPairSources: types.KvPairSources{
FileSources: []string{
filepath.Join("configmap", "app-init.ini"),
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: ConfigMap
metadata:
name: fileConfigMap1
data:
app-init.ini: |
FOO=bar
BAR=baz
`,
},
},
"construct config map from text and binary file": {
args: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileConfigMap2",
KvPairSources: types.KvPairSources{
FileSources: []string{
filepath.Join("configmap", "app-init.ini"),
filepath.Join("configmap", "app.bin"),
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: ConfigMap
metadata:
name: fileConfigMap2
data:
app-init.ini: |
FOO=bar
BAR=baz
binaryData:
app.bin: |
/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbG
xv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hl
bGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2
hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv
`,
},
},
"construct config map from literal": {
args: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalConfigMap1",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: ConfigMap
metadata:
name: literalConfigMap1
labels:
foo: 'bar'
data:
a: x
b: y
c: Hello World
d: "true"
`,
},
},
"construct config map from literal with GeneratorOptions in ConfigMapArgs": {
args: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalConfigMap2",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"veggie": "celery",
"dog": "beagle",
"cat": "annoying",
},
Annotations: map[string]string{
"river": "Missouri",
"city": "Iowa City",
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: ConfigMap
metadata:
name: literalConfigMap2
labels:
cat: 'annoying'
dog: 'beagle'
veggie: 'celery'
annotations:
city: 'Iowa City'
river: 'Missouri'
data:
a: x
b: y
c: Hello World
d: "true"
`,
},
},
}
fSys := filesys.MakeFsInMemory()
fSys.WriteFile(
filesys.RootedPath("configmap", "app.env"),
[]byte("DB_USERNAME=admin\nDB_PASSWORD=qwerty\n"))
fSys.WriteFile(
filesys.RootedPath("configmap", "app-init.ini"),
[]byte("FOO=bar\nBAR=baz\n"))
fSys.WriteFile(
filesys.RootedPath("configmap", "app.bin"),
manyHellos(30))
kvLdr := kv.NewLoader(
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for n := range testCases {
tc := testCases[n]
t.Run(n, func(t *testing.T) {
rn, err := MakeConfigMap(kvLdr, &tc.args)
if err != nil {
if !assert.EqualError(t, err, tc.exp.errMsg) {
t.FailNow()
}
return
}
if tc.exp.errMsg != "" {
t.Fatalf("%s: should return error '%s'", n, tc.exp.errMsg)
}
output := rn.MustString()
if !assert.Equal(t, tc.exp.out, output) {
t.FailNow()
}
})
}
}

View File

@@ -0,0 +1,60 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package generators
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// MakeSecret makes a kubernetes Secret.
//
// Secret: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#secret-v1-core
//
// ConfigMaps and Secrets are similar.
//
// Like a ConfigMap, a Secret has a `data` field, but unlike a ConfigMap it has
// no `binaryData` field.
//
// All of a Secret's data is assumed to be opaque in nature, and assumed to be
// base64 encoded from its original representation, regardless of whether the
// original data was UTF-8 text or binary.
//
// This encoding provides no secrecy. It's just a neutral, common means to
// represent opaque text and binary data. Beneath the base64 encoding
// is presumably further encoding under control of the Secret's consumer.
//
// A Secret has string field `type` which holds an identifier, used by the
// client, to choose the algorithm to interpret the `data` field. Kubernetes
// cannot make use of this data; it's up to a controller or some pod's service
// to interpret the value, using `type` as a clue as to how to do this.
func MakeSecret(
ldr ifc.KvLoader, args *types.SecretArgs) (rn *yaml.RNode, err error) {
rn, err = makeBaseNode("Secret", args.Name, args.Namespace)
if err != nil {
return nil, err
}
if _, err := rn.Pipe(
yaml.FieldSetter{
Name: "type",
Value: yaml.NewStringRNode("Opaque")}); err != nil {
return nil, err
}
m, err := makeValidatedDataMap(ldr, args.Name, args.KvPairSources)
if err != nil {
return nil, err
}
for _, k := range filtersutil.SortedMapKeys(m) {
vrN := makeSecretValueRNode(m[k])
if _, err = rn.Pipe(
yaml.LookupCreate(yaml.MappingNode, yaml.DataField),
yaml.SetField(k, vrN)); err != nil {
return nil, err
}
}
copyLabelsAndAnnotations(rn, args.Options)
return rn, err
}

View File

@@ -0,0 +1,203 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package generators_test
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filesys"
. "sigs.k8s.io/kustomize/api/internal/generators"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/loader"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
func TestMakeSecret(t *testing.T) {
type expected struct {
out string
errMsg string
}
testCases := map[string]struct {
args types.SecretArgs
exp expected
}{
"construct secret from env": {
args: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "envSecret",
KvPairSources: types.KvPairSources{
EnvSources: []string{
filepath.Join("secret", "app.env"),
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: Secret
metadata:
name: envSecret
type: Opaque
data:
DB_PASSWORD: cXdlcnR5
DB_USERNAME: YWRtaW4=
`,
},
},
"construct secret from text file": {
args: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileSecret1",
KvPairSources: types.KvPairSources{
FileSources: []string{
filepath.Join("secret", "app-init.ini"),
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: Secret
metadata:
name: fileSecret1
type: Opaque
data:
app-init.ini: Rk9PPWJhcgpCQVI9YmF6Cg==
`,
},
},
"construct secret from text and binary file": {
args: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileSecret2",
KvPairSources: types.KvPairSources{
FileSources: []string{
filepath.Join("secret", "app-init.ini"),
filepath.Join("secret", "app.bin"),
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: Secret
metadata:
name: fileSecret2
type: Opaque
data:
app-init.ini: Rk9PPWJhcgpCQVI9YmF6Cg==
app.bin: //0=
`,
},
},
"construct secret from literal": {
args: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalSecret1",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: Secret
metadata:
name: literalSecret1
labels:
foo: 'bar'
type: Opaque
data:
a: eA==
b: eQ==
c: SGVsbG8gV29ybGQ=
d: dHJ1ZQ==
`,
},
},
"construct secret from literal with GeneratorOptions in SecretArgs": {
args: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalSecret2",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"veggie": "celery",
"dog": "beagle",
"cat": "annoying",
},
Annotations: map[string]string{
"river": "Missouri",
"city": "Iowa City",
},
},
},
},
exp: expected{
out: `apiVersion: v1
kind: Secret
metadata:
name: literalSecret2
labels:
cat: 'annoying'
dog: 'beagle'
veggie: 'celery'
annotations:
city: 'Iowa City'
river: 'Missouri'
type: Opaque
data:
a: eA==
b: eQ==
c: SGVsbG8gV29ybGQ=
d: dHJ1ZQ==
`,
},
},
}
fSys := filesys.MakeFsInMemory()
fSys.WriteFile(
filesys.RootedPath("secret", "app.env"),
[]byte("DB_USERNAME=admin\nDB_PASSWORD=qwerty\n"))
fSys.WriteFile(
filesys.RootedPath("secret", "app-init.ini"),
[]byte("FOO=bar\nBAR=baz\n"))
fSys.WriteFile(
filesys.RootedPath("secret", "app.bin"),
[]byte{0xff, 0xfd})
kvLdr := kv.NewLoader(
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for n := range testCases {
tc := testCases[n]
t.Run(n, func(t *testing.T) {
rn, err := MakeSecret(kvLdr, &tc.args)
if err != nil {
if !assert.EqualError(t, err, tc.exp.errMsg) {
t.FailNow()
}
return
}
if tc.exp.errMsg != "" {
t.Fatalf("%s: should return error '%s'", n, tc.exp.errMsg)
}
output := rn.MustString()
if !assert.Equal(t, tc.exp.out, output) {
t.FailNow()
}
})
}
}

View File

@@ -0,0 +1,139 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package generators
import (
"encoding/base64"
"fmt"
"strings"
"unicode/utf8"
"github.com/go-errors/errors"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func makeBaseNode(kind, name, namespace string) (*yaml.RNode, error) {
rn, err := yaml.Parse(fmt.Sprintf(`
apiVersion: v1
kind: %s
`, kind))
if err != nil {
return nil, err
}
if name == "" {
return nil, errors.Errorf("a configmap must have a name")
}
if _, err := rn.Pipe(yaml.SetK8sName(name)); err != nil {
return nil, err
}
if namespace != "" {
if _, err := rn.Pipe(yaml.SetK8sNamespace(namespace)); err != nil {
return nil, err
}
}
return rn, nil
}
func makeValidatedDataMap(
ldr ifc.KvLoader, name string, sources types.KvPairSources) (map[string]string, error) {
pairs, err := ldr.Load(sources)
if err != nil {
return nil, errors.WrapPrefix(err, "loading KV pairs", 0)
}
knownKeys := make(map[string]string)
for _, p := range pairs {
// legal key: alphanumeric characters, '-', '_' or '.'
if err := ldr.Validator().ErrIfInvalidKey(p.Key); err != nil {
return nil, err
}
if _, ok := knownKeys[p.Key]; ok {
return nil, errors.Errorf(
"configmap %s illegally repeats the key `%s`", name, p.Key)
}
knownKeys[p.Key] = p.Value
}
return knownKeys, nil
}
// copyLabelsAndAnnotations copies labels and annotations from
// GeneratorOptions into the given object.
func copyLabelsAndAnnotations(
rn *yaml.RNode, opts *types.GeneratorOptions) error {
if opts == nil {
return nil
}
for _, k := range filtersutil.SortedMapKeys(opts.Labels) {
v := opts.Labels[k]
if _, err := rn.Pipe(yaml.SetLabel(k, v)); err != nil {
return err
}
}
for _, k := range filtersutil.SortedMapKeys(opts.Annotations) {
v := opts.Annotations[k]
if _, err := rn.Pipe(yaml.SetAnnotation(k, v)); err != nil {
return err
}
}
return nil
}
// In a secret, all data is base64 encoded, regardless of its conformance
// or lack thereof to UTF-8.
func makeSecretValueRNode(s string) *yaml.RNode {
yN := &yaml.Node{Kind: yaml.ScalarNode}
// Purposely don't use YAML tags to identify the data as being plain text or
// binary. It kubernetes Secrets the values in the `data` map are expected
// to be base64 encoded, and in ConfigMaps that same can be said for the
// values in the `binaryData` field.
yN.Tag = yaml.NodeTagString
yN.Value = encodeBase64(s)
if strings.Contains(yN.Value, "\n") {
yN.Style = yaml.LiteralStyle
}
return yaml.NewRNode(yN)
}
func makeConfigMapValueRNode(s string) (field string, rN *yaml.RNode) {
yN := &yaml.Node{Kind: yaml.ScalarNode}
yN.Tag = yaml.NodeTagString
if utf8.ValidString(s) {
field = yaml.DataField
yN.Value = s
} else {
field = yaml.BinaryDataField
yN.Value = encodeBase64(s)
}
if strings.Contains(yN.Value, "\n") {
yN.Style = yaml.LiteralStyle
}
return field, yaml.NewRNode(yN)
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines
// as appropriate for the resulting length.
func encodeBase64(s string) string {
const lineLen = 70
encLen := base64.StdEncoding.EncodedLen(len(s))
lines := encLen/lineLen + 1
buf := make([]byte, encLen*2+lines)
in := buf[0:encLen]
out := buf[encLen:]
base64.StdEncoding.Encode(in, []byte(s))
k := 0
for i := 0; i < len(in); i += lineLen {
j := i + lineLen
if j > len(in) {
j = len(in)
}
k += copy(out[k:], in[i:j])
if lines > 1 {
out[k] = '\n'
k++
}
}
return string(out[:k])
}

View File

@@ -29,43 +29,57 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
cmd := exec.Command(
gitProgram,
"clone",
"--depth=1",
repoSpec.CloneSpec(),
"init",
repoSpec.Dir.String())
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf("Error cloning git repo: %s", out)
log.Printf("Error initializing git repo: %s", out)
return errors.Wrapf(
err,
"trouble cloning git repo %v in %s",
repoSpec.CloneSpec(), repoSpec.Dir.String())
"trouble initializing git repo in %s",
repoSpec.Dir.String())
}
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,
"remote",
"add",
"origin",
repoSpec.CloneSpec())
cmd.Dir = repoSpec.Dir.String()
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("Error adding remote: %s", out)
return errors.Wrapf(err, "trouble adding remote %s", repoSpec.CloneSpec())
}
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 := "HEAD"
if repoSpec.Ref != "" {
ref = repoSpec.Ref
}
cmd = exec.Command(
gitProgram,
"fetch",
"--depth=1",
"origin",
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", 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", ref)
}
cmd = exec.Command(

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

@@ -13,12 +13,10 @@ import (
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
)
func TestExecPluginConfig(t *testing.T) {
@@ -33,10 +31,9 @@ s/$BAR/bar baz/g
if err != nil {
t.Fatal(err)
}
pvd := provider.NewDefaultDepProvider()
rf := resmap.NewFactory(
resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), nil)
v := valtest_test.MakeFakeValidator()
pvd.GetResourceFactory(), pvd.GetConflictDetectorFactory())
pluginConfig := rf.RF().FromMap(
map[string]interface{}{
"apiVersion": "someteam.example.com/v1",
@@ -62,7 +59,7 @@ s/$BAR/bar baz/g
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
p.Config(resmap.NewPluginHelpers(ldr, v, rf), yaml)
p.Config(resmap.NewPluginHelpers(ldr, pvd.GetFieldValidator(), rf), yaml)
expected := "someteam.example.com/v1/sedtransformer/SedTransformer"
if !strings.HasSuffix(p.Path(), expected) {

View File

@@ -8,11 +8,10 @@ import (
"sigs.k8s.io/kustomize/api/filesys"
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
@@ -51,8 +50,9 @@ func TestLoader(t *testing.T) {
BuildGoPlugin("builtin", "", "SecretGenerator").
BuildGoPlugin("someteam.example.com", "v1", "SomeServiceGenerator")
defer th.Reset()
rmF := resmap.NewFactory(resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), nil)
p := provider.NewDefaultDepProvider()
rmF := resmap.NewFactory(
p.GetResourceFactory(), p.GetConflictDetectorFactory())
fLdr, err := loader.NewLoader(
loader.RestrictionRootOnly,
filesys.Separator, filesys.MakeFsInMemory())

View File

@@ -9,9 +9,10 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
@@ -64,7 +65,7 @@ func strptr(s string) *string {
}
func TestUpdateResourceOptions(t *testing.T) {
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
rf := provider.NewDefaultDepProvider().GetResourceFactory()
in := resmap.New()
expected := resmap.New()
cases := []struct {
@@ -87,28 +88,12 @@ func TestUpdateResourceOptions(t *testing.T) {
expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
}
actual, err := UpdateResourceOptions(in)
if err != nil {
t.Fatalf("unexpected error: %v", err.Error())
}
for i, a := range expected.Resources() {
b := actual.GetByIndex(i)
if b == nil {
t.Fatalf("resource %d missing from processed map", i)
}
if !a.Equals(b) {
t.Errorf("expected %v got %v", a, b)
}
if a.NeedHashSuffix() != b.NeedHashSuffix() {
t.Errorf("")
}
if a.Behavior() != b.Behavior() {
t.Errorf("expected %v got %v", a.Behavior(), b.Behavior())
}
}
assert.NoError(t, err)
assert.NoError(t, expected.ErrorIfNotEqualLists(actual))
}
func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
rf := provider.NewDefaultDepProvider().GetResourceFactory()
cases := []string{
"",
"FaLsE",

View File

@@ -235,7 +235,18 @@ func (kt *KustTarget) runGenerators(
func (kt *KustTarget) configureExternalGenerators() ([]resmap.Generator, error) {
ra := accumulator.MakeEmptyAccumulator()
ra, err := kt.accumulateResources(ra, kt.kustomization.Generators)
var generatorPaths []string
for _, p := range kt.kustomization.Generators {
// handle inline generators
rm, err := kt.rFactory.NewResMapFromBytes([]byte(p))
if err != nil {
// not an inline config
generatorPaths = append(generatorPaths, p)
continue
}
ra.AppendAll(rm)
}
ra, err := kt.accumulateResources(ra, generatorPaths)
if err != nil {
return nil, err
}
@@ -260,7 +271,18 @@ func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]resmap.Transformer, error) {
ra := accumulator.MakeEmptyAccumulator()
ra, err := kt.accumulateResources(ra, transformers)
var transformerPaths []string
for _, p := range transformers {
// handle inline transformers
rm, err := kt.rFactory.NewResMapFromBytes([]byte(p))
if err != nil {
// not an inline config
transformerPaths = append(transformerPaths, p)
continue
}
ra.AppendAll(rm)
}
ra, err := kt.accumulateResources(ra, transformerPaths)
if err != nil {
return nil, err

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

@@ -8,9 +8,10 @@ import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
@@ -76,8 +77,7 @@ commonLabels:
}
kt := makeKustTargetWithRf(
t, th.GetFSys(), "/",
resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()))
t, th.GetFSys(), "/", provider.NewDefaultDepProvider())
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
th.WriteK("/", tc.content)
@@ -148,7 +148,8 @@ metadata:
{"op": "add", "path": "/spec/replica", "value": "3"}
]`)
resFactory := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
pvd := provider.NewDefaultDepProvider()
resFactory := pvd.GetResourceFactory()
resources := []*resource.Resource{
resFactory.FromMapWithName("dply1", map[string]interface{}{
@@ -243,19 +244,14 @@ metadata:
t.Fatalf("unexpected error %v", err)
}
}
expYaml, err := expected.AsYaml()
assert.NoError(t, err)
kt := makeKustTargetWithRf(
t, th.GetFSys(), "/whatever", resFactory)
err := kt.Load()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}
kt := makeKustTargetWithRf(t, th.GetFSys(), "/whatever", pvd)
assert.NoError(t, kt.Load())
actual, err := kt.MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}
if err = expected.ErrorIfNotEqualLists(actual); err != nil {
t.Fatalf("unexpected inequality: %v", err)
}
assert.NoError(t, err)
actYaml, err := actual.AsYaml()
assert.NoError(t, err)
assert.Equal(t, expYaml, actYaml)
}

View File

@@ -7,14 +7,12 @@ import (
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/merge"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
)
@@ -22,9 +20,7 @@ func makeAndLoadKustTarget(
t *testing.T,
fSys filesys.FileSystem,
root string) *target.KustTarget {
kt := makeKustTargetWithRf(
t, fSys, root,
resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()))
kt := makeKustTargetWithRf(t, fSys, root, provider.NewDefaultDepProvider())
if err := kt.Load(); err != nil {
t.Fatalf("Unexpected load error %v", err)
}
@@ -35,13 +31,13 @@ func makeKustTargetWithRf(
t *testing.T,
fSys filesys.FileSystem,
root string,
resourceFactory *resource.Factory) *target.KustTarget {
pvd *provider.DepProvider) *target.KustTarget {
ldr, err := fLdr.NewLoader(fLdr.RestrictionRootOnly, root, fSys)
if err != nil {
t.Fatal(err)
}
rf := resmap.NewFactory(
resourceFactory, merge.NewMerginator(resourceFactory))
pvd.GetResourceFactory(), pvd.GetConflictDetectorFactory())
pc := konfig.DisabledPluginConfig()
return target.NewKustTarget(
ldr,

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

@@ -4,38 +4,105 @@
package wrappy
import (
"fmt"
"sigs.k8s.io/kustomize/api/hasher"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/generators"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// WNodeFactory makes instances of WNode.
//
// These instances in turn adapt
// sigs.k8s.io/kustomize/kyaml/yaml.RNode
// to implement ifc.Unstructured.
// This factory is meant to implement ifc.KunstructuredFactory.
//
// This implementation should be thin, as both WNode and WNodeFactory must be
// factored away (deleted) along with ifc.Kunstructured in favor of direct use
// of RNode methods upon completion of
// https://github.com/kubernetes-sigs/kustomize/issues/2506.
//
// See also api/krusty/internal/provider/depprovider.go
type WNodeFactory struct {
}
var _ ifc.KunstructuredFactory = (*WNodeFactory)(nil)
func (k *WNodeFactory) SliceFromBytes(bs []byte) ([]ifc.Kunstructured, error) {
panic("TODO(#WNodeFactory): implement SliceFromBytes")
yamlRNodes, err := kio.FromBytes(bs)
if err != nil {
return nil, err
}
var result []ifc.Kunstructured
for i := range yamlRNodes {
rn := yamlRNodes[i]
meta, err := rn.GetValidatedMetadata()
if err != nil {
return nil, err
}
if !shouldDropObject(meta) {
if foundNil, path := rn.HasNilEntryInList(); foundNil {
return nil, fmt.Errorf("empty item at %v in object %v", path, rn)
}
result = append(result, FromRNode(rn))
}
}
return result, nil
}
// shouldDropObject returns true if the resource should not be accumulated.
func shouldDropObject(m yaml.ResourceMeta) bool {
_, y := m.ObjectMeta.Annotations[konfig.IgnoredByKustomizeResourceAnnotation]
return y
}
func (k *WNodeFactory) FromMap(m map[string]interface{}) ifc.Kunstructured {
panic("TODO(#WNodeFactory): implement FromMap")
rn, err := FromMap(m)
if err != nil {
// TODO(#WNodeFactory): handle or bubble error"
panic(err)
}
return rn
}
// kustHash computes a hash of an unstructured object.
type kustHash struct{}
// Hash returns a hash of the given object
func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
node, err := filtersutil.GetRNode(m)
if err != nil {
return "", err
}
return hasher.HashRNode(node)
}
func (k *WNodeFactory) Hasher() ifc.KunstructuredHasher {
panic("TODO(#WNodeFactory): implement Hasher")
return &kustHash{}
}
// MakeConfigMap makes a wrapped configmap.
func (k *WNodeFactory) MakeConfigMap(
kvLdr ifc.KvLoader, args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
panic("TODO(#WNodeFactory): implement MakeConfigMap")
ldr ifc.KvLoader, args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
rn, err := generators.MakeConfigMap(ldr, args)
if err != nil {
return nil, err
}
return FromRNode(rn), nil
}
// MakeSecret makes a wrapped secret.
func (k *WNodeFactory) MakeSecret(
kvLdr ifc.KvLoader, args *types.SecretArgs) (ifc.Kunstructured, error) {
panic("TODO(#WNodeFactory): implement MakeSecret")
ldr ifc.KvLoader, args *types.SecretArgs) (ifc.Kunstructured, error) {
rn, err := generators.MakeSecret(ldr, args)
if err != nil {
return nil, err
}
return FromRNode(rn), nil
}

View File

@@ -1,4 +1,321 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package wrappy
package wrappy_test
import (
"fmt"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/internal/wrappy"
)
func TestHasher(t *testing.T) {
input := `
apiVersion: v1
kind: ConfigMap
metadata:
name: foo
data:
one: ""
binaryData:
two: ""
`
expect := "698h7c7t9m"
factory := &WNodeFactory{}
k, err := factory.SliceFromBytes([]byte(input))
if err != nil {
t.Fatal(err)
}
hasher := factory.Hasher()
result, err := hasher.Hash(k[0])
if err != nil {
t.Fatal(err)
}
if result != expect {
t.Fatalf("expect %s but got %s", expect, result)
}
}
func TestSliceFromBytes(t *testing.T) {
factory := &WNodeFactory{}
testConfigMap :=
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
},
}
testConfigMapList :=
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMapList",
"items": []interface{}{
testConfigMap,
testConfigMap,
},
}
testDeploymentSpec := map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"hostAliases": []interface{}{
map[string]interface{}{
"hostnames": []interface{}{
"a.example.com",
},
"ip": "8.8.8.8",
},
},
},
},
}
testDeploymentA := map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deployment-a",
},
"spec": testDeploymentSpec,
}
testDeploymentB := map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deployment-b",
},
"spec": testDeploymentSpec,
}
testDeploymentList :=
map[string]interface{}{
"apiVersion": "v1",
"kind": "DeploymentList",
"items": []interface{}{
testDeploymentA,
testDeploymentB,
},
}
type expected struct {
out []map[string]interface{}
isErr bool
}
testCases := map[string]struct {
input []byte
exp expected
}{
"garbage": {
input: []byte("garbageIn: garbageOut"),
exp: expected{
isErr: true,
},
},
"noBytes": {
input: []byte{},
exp: expected{
out: []map[string]interface{}{},
},
},
"goodJson": {
input: []byte(`
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
`),
exp: expected{
out: []map[string]interface{}{testConfigMap},
},
},
"goodYaml1": {
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
exp: expected{
out: []map[string]interface{}{testConfigMap},
},
},
"goodYaml2": {
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
exp: expected{
out: []map[string]interface{}{testConfigMap, testConfigMap},
},
},
"localConfigYaml": {
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie-skip
annotations:
# this annotation causes the Resource to be ignored by kustomize
config.kubernetes.io/local-config: ""
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
exp: expected{
out: []map[string]interface{}{testConfigMap},
},
},
"garbageInOneOfTwoObjects": {
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
`),
exp: expected{
isErr: true,
},
},
"emptyObjects": {
input: []byte(`
---
#a comment
---
`),
exp: expected{
out: []map[string]interface{}{},
},
},
"Missing .metadata.name in object": {
input: []byte(`
apiVersion: v1
kind: Namespace
metadata:
annotations:
foo: bar
`),
exp: expected{
isErr: true,
},
},
"nil value in list": {
input: []byte(`
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: kube100-site
labels:
app: web
testList:
- testA
-
`),
exp: expected{
isErr: true,
},
},
"List": {
input: []byte(`
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
exp: expected{
out: []map[string]interface{}{
testConfigMap,
testConfigMap},
},
},
"ConfigMapList": {
input: []byte(`
apiVersion: v1
kind: ConfigMapList
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
exp: expected{
out: []map[string]interface{}{testConfigMapList},
},
},
"listWithAnchors": {
input: []byte(`
apiVersion: v1
kind: DeploymentList
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-a
spec: &hostAliases
template:
spec:
hostAliases:
- hostnames:
- a.example.com
ip: 8.8.8.8
- apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-b
spec:
<<: *hostAliases
`),
exp: expected{
out: []map[string]interface{}{testDeploymentList},
},
},
}
for n := range testCases {
tc := testCases[n]
t.Run(n, func(t *testing.T) {
rs, err := factory.SliceFromBytes(tc.input)
if err != nil {
assert.True(t, tc.exp.isErr)
return
}
assert.False(t, tc.exp.isErr)
assert.Equal(t, len(tc.exp.out), len(rs))
for i := range rs {
assert.Equal(
t, fmt.Sprintf("%v", tc.exp.out[i]), fmt.Sprintf("%v", rs[i].Map()))
if n != "listWithAnchors" {
// https://github.com/kubernetes-sigs/kustomize/issues/3271
if !reflect.DeepEqual(tc.exp.out[i], rs[i].Map()) {
t.Fatalf("%s:\nexpected: %v\n actual: %v",
n, tc.exp.out[i], rs[i].Map())
}
}
}
})
}
}

View File

@@ -31,6 +31,14 @@ func NewWNode() *WNode {
return FromRNode(yaml.NewRNode(nil))
}
func FromMap(m map[string]interface{}) (*WNode, error) {
n, err := yaml.FromMap(m)
if err != nil {
return nil, err
}
return FromRNode(n), nil
}
func FromRNode(node *yaml.RNode) *WNode {
return &WNode{node: node}
}
@@ -155,47 +163,51 @@ func (wn *WNode) MarshalJSON() ([]byte, error) {
}
// MatchesAnnotationSelector implements ifc.Kunstructured.
func (wn *WNode) MatchesAnnotationSelector(string) (bool, error) {
panic("TODO(#WNode) MatchesAnnotationSelector; implement or drop from API")
func (wn *WNode) MatchesAnnotationSelector(selector string) (bool, error) {
return wn.node.MatchesAnnotationSelector(selector)
}
// MatchesLabelSelector implements ifc.Kunstructured.
func (wn *WNode) MatchesLabelSelector(string) (bool, error) {
panic("TODO(#WNode) MatchesLabelSelector; implement or drop from API")
func (wn *WNode) MatchesLabelSelector(selector string) (bool, error) {
return wn.node.MatchesLabelSelector(selector)
}
// SetAnnotations implements ifc.Kunstructured.
func (wn *WNode) SetAnnotations(annotations map[string]string) {
wn.setField(yaml.NewMapRNode(&annotations), yaml.MetadataField, yaml.AnnotationsField)
if err := wn.node.SetAnnotations(annotations); err != nil {
log.Fatal(err) // interface doesn't allow error.
}
}
// SetGvk implements ifc.Kunstructured.
func (wn *WNode) SetGvk(gvk resid.Gvk) {
wn.setField(yaml.NewScalarRNode(gvk.Kind), yaml.KindField)
wn.setField(yaml.NewScalarRNode(fmt.Sprintf("%s/%s", gvk.Group, gvk.Version)), yaml.APIVersionField)
wn.setMapField(yaml.NewScalarRNode(gvk.Kind), yaml.KindField)
wn.setMapField(
yaml.NewScalarRNode(
fmt.Sprintf("%s/%s", gvk.Group, gvk.Version)), yaml.APIVersionField)
}
// SetLabels implements ifc.Kunstructured.
func (wn *WNode) SetLabels(labels map[string]string) {
wn.setField(yaml.NewMapRNode(&labels), yaml.MetadataField, yaml.LabelsField)
if err := wn.node.SetLabels(labels); err != nil {
log.Fatal(err) // interface doesn't allow error.
}
}
// SetName implements ifc.Kunstructured.
func (wn *WNode) SetName(name string) {
wn.setField(yaml.NewScalarRNode(name), yaml.MetadataField, yaml.NameField)
wn.setMapField(yaml.NewScalarRNode(name), yaml.MetadataField, yaml.NameField)
}
// SetNamespace implements ifc.Kunstructured.
func (wn *WNode) SetNamespace(ns string) {
wn.setField(yaml.NewScalarRNode(ns), yaml.MetadataField, yaml.NamespaceField)
if err := wn.node.SetNamespace(ns); err != nil {
log.Fatal(err) // interface doesn't allow error.
}
}
func (wn *WNode) setField(value *yaml.RNode, path ...string) {
err := wn.node.PipeE(
yaml.LookupCreate(yaml.MappingNode, path[0:len(path)-1]...),
yaml.SetField(path[len(path)-1], value),
)
if err != nil {
func (wn *WNode) setMapField(value *yaml.RNode, path ...string) {
if err := wn.node.SetMapField(value, path...); err != nil {
// Log and die since interface doesn't allow error.
log.Fatalf("failed to set field %v: %v", path, err)
}

View File

@@ -8,9 +8,8 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"sigs.k8s.io/kustomize/api/resid"
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/api/resid"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
)

View File

@@ -14,6 +14,7 @@ import (
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/configmapandsecret"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types"
)
@@ -116,10 +117,6 @@ func (kf *KunstructuredFactoryImpl) validate(u unstructured.Unstructured) error
return nil
}
// nonKustomizableResourceAnnotation if set on a Resource will cause Kustomize to
// ignore the Resource rather than Kustomize it.
const ignoredByKustomizeResourceAnnotation = "config.kubernetes.io/local-config"
// skipResource returns true if the Resource should not be accumulated
func (kf *KunstructuredFactoryImpl) skipResource(u unstructured.Unstructured) bool {
an := u.GetAnnotations()
@@ -128,7 +125,7 @@ func (kf *KunstructuredFactoryImpl) skipResource(u unstructured.Unstructured) bo
return false
}
// check if the Resource has opt-ed out of kustomize
_, found := an[ignoredByKustomizeResourceAnnotation]
_, found := an[konfig.IgnoredByKustomizeResourceAnnotation]
return found
}

View File

@@ -258,6 +258,8 @@ nameReference:
kind: Service
group: serving.knative.dev
version: v1
- path: spec/azureFile/secretName
kind: PersistentVolume
- kind: Service
version: v1

View File

@@ -19,7 +19,32 @@ 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
// configuration data. See:
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
@@ -31,6 +56,9 @@ const (
// A program name, for use in help, finding the XDG_CONFIG_DIR, etc.
ProgramName = "kustomize"
// If a resource has this annotation, kustomize will drop it.
IgnoredByKustomizeResourceAnnotation = "config.kubernetes.io/local-config"
// Label key that indicates the resources are built from Kustomize
ManagedbyLabelKey = "app.kubernetes.io/managed-by"

View File

@@ -9,6 +9,7 @@ import (
"runtime"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
"sigs.k8s.io/kustomize/api/types"
)
@@ -157,3 +158,15 @@ func pwdEnv() string {
}
return "PWD"
}
// GetBuiltinPluginNames returns a list of builtin plugin names
func GetBuiltinPluginNames() []string {
var ret []string
for k := range builtinhelpers.GeneratorFactories {
ret = append(ret, k.String())
}
for k := range builtinhelpers.TransformerFactories {
ret = append(ret, k.String())
}
return ret
}

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

@@ -0,0 +1,79 @@
// 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 TestInlineTransformer(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("/app/resource.yaml", `
apiVersion: apps/v1
kind: ConfigMap
metadata:
name: whatever
data: {}
`)
th.WriteK("/app", `
resources:
- resource.yaml
transformers:
- |-
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: not-important-to-example
namespace: test
fieldSpecs:
- path: metadata/namespace
create: true
`)
expected := `
apiVersion: apps/v1
data: {}
kind: ConfigMap
metadata:
name: whatever
namespace: test
`
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
}
func TestInlineGenerator(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK("/app", `
generators:
- |-
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: mymap
literals:
- FRUIT=apple
- VEGETABLE=carrot
`)
expected := `
apiVersion: v1
data:
FRUIT: apple
VEGETABLE: carrot
kind: ConfigMap
metadata:
name: mymap-kfd8tf729k
`
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
}

View File

@@ -11,9 +11,9 @@ import (
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/krusty/internal/provider"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provenance"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
)
@@ -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
@@ -85,7 +85,7 @@ func (b *Kustomizer) Run(path string) (resmap.ResMap, error) {
t := builtins.LabelTransformerPlugin{
Labels: map[string]string{
konfig.ManagedbyLabelKey: fmt.Sprintf(
"kustomize-%s", provenance.GetProvenance().Version)},
"kustomize-%s", provenance.GetProvenance().Semver())},
FieldSpecs: []types.FieldSpec{{
Path: "metadata/labels",
CreateIfNotPresent: true,

View File

@@ -36,16 +36,21 @@ 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: false,
AllowResourceIdChanges: false,
}
}

View File

@@ -80,6 +80,7 @@ func getRemoteTarget(rs *remoteTargetSpec) error {
Mode: getter.ClientModeAny,
Detectors: []getter.Detector{
new(getter.GitHubDetector),
new(getter.GitLabDetector),
new(getter.GitDetector),
new(getter.BitBucketDetector),
},

View File

@@ -6,6 +6,7 @@ package provenance
import (
"fmt"
"runtime"
"strings"
)
var (
@@ -57,3 +58,11 @@ func (v Provenance) Short() string {
BuildDate: v.BuildDate,
})
}
// Semver returns the semantic version of kustomize.
// kustomize version is set in format "kustomize/vX.X.X" in every release.
// X.X.X is a semver. If the version string is not in this format,
// return the original version string
func (v Provenance) Semver() string {
return strings.TrimPrefix(v.Version, "kustomize/")
}

View File

@@ -5,13 +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/resmap"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resource"
)
@@ -95,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
//
@@ -116,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.
//
@@ -138,18 +149,20 @@ import (
// If you're reading this, plan not done.
//
type DepProvider struct {
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{
resourceFactory: rf,
merginator: merge.NewMerginator(rf),
fieldValidator: validator.NewKustValidator(),
kFactory: kf,
resourceFactory: rf,
conflictDectectorFactory: k8sconflict.NewFactory(rf),
fieldValidator: validator.NewKustValidator(),
}
}
@@ -157,9 +170,10 @@ func makeKyamlBasedInstances() *DepProvider {
kf := &wrappy.WNodeFactory{}
rf := resource.NewFactory(kf)
return &DepProvider{
resourceFactory: rf,
merginator: kmerge.NewMerginator(rf),
fieldValidator: validate.NewFieldValidator(),
kFactory: kf,
resourceFactory: rf,
conflictDectectorFactory: conflict.NewFactory(),
fieldValidator: validate.NewFieldValidator(),
}
}
@@ -170,12 +184,20 @@ func NewDepProvider(useKyaml bool) *DepProvider {
return makeK8sdepBasedInstances()
}
func NewDefaultDepProvider() *DepProvider {
return NewDepProvider(konfig.FlagEnableKyamlDefaultValue)
}
func (dp *DepProvider) GetKunstructuredFactory() ifc.KunstructuredFactory {
return dp.kFactory
}
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

@@ -9,26 +9,21 @@ import (
"sigs.k8s.io/kustomize/api/internal/kusterr"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"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.
@@ -133,8 +128,8 @@ func (rmF *Factory) FromSecretArgs(
// Merge creates a new ResMap by merging incoming resources.
// Error if conflict found.
func (rmF *Factory) Merge(patches []*resource.Resource) (ResMap, error) {
return rmF.pm.Merge(patches)
func (rmF *Factory) Merge(incoming []*resource.Resource) (ResMap, error) {
return (&merginator{cdf: rmF.cdf}).Merge(incoming)
}
func newResMapFromResourceSlice(
@@ -148,3 +143,20 @@ func newResMapFromResourceSlice(
}
return result, nil
}
// NewResMapFromRNodeSlice returns a ResMap from a slice of RNodes
func (rmF *Factory) NewResMapFromRNodeSlice(rnodes []*yaml.RNode) (ResMap, error) {
var resources []*resource.Resource
for _, rnode := range rnodes {
s, err := rnode.String()
if err != nil {
return nil, err
}
r, err := rmF.resF.FromBytes([]byte(s))
if err != nil {
return nil, err
}
resources = append(resources, r)
}
return newResMapFromResourceSlice(resources)
}

View File

@@ -5,18 +5,20 @@ package resmap_test
import (
"encoding/base64"
"reflect"
"testing"
"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"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func TestFromFile(t *testing.T) {
@@ -59,29 +61,21 @@ metadata:
"name": "dply2",
"namespace": "test",
}}).ResMap()
expYaml, err := expected.AsYaml()
assert.NoError(t, err)
fSys := filesys.MakeFsInMemory()
err := fSys.WriteFile("deployment.yaml", []byte(resourceStr))
if err != nil {
t.Fatal(err)
}
assert.NoError(t, fSys.WriteFile("deployment.yaml", []byte(resourceStr)))
ldr, err := loader.NewLoader(
loader.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
assert.NoError(t, err)
m, err := rmF.FromFile(ldr, "deployment.yaml")
if err != nil {
t.Fatal(err)
}
if m.Size() != 3 {
t.Fatalf("result should contain 3, but got %d", m.Size())
}
if err := expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
assert.NoError(t, err)
mYaml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, expYaml, mYaml)
}
func TestFromBytes(t *testing.T) {
@@ -108,17 +102,15 @@ metadata:
"metadata": map[string]interface{}{
"name": "cm2",
}}).ResMap()
expYaml, err := expected.AsYaml()
assert.NoError(t, err)
m, err := rmF.NewResMapFromBytes(encoded)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(m, expected) {
t.Fatalf("%#v doesn't match expected %#v", m, expected)
}
assert.NoError(t, err)
mYaml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, expYaml, mYaml)
}
var cmap = resid.Gvk{Version: "v1", Kind: "ConfigMap"}
func TestNewFromConfigMaps(t *testing.T) {
type testCase struct {
description string
@@ -228,12 +220,12 @@ BAR=baz
}
}
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = tc.expected.ErrorIfNotEqualLists(r); err != nil {
t.Fatalf("testcase: %q, err: %v", tc.description, err)
}
assert.NoError(t, err, tc.description)
rYaml, err := r.AsYaml()
assert.NoError(t, err, tc.description)
expYaml, err := tc.expected.AsYaml()
assert.NoError(t, err, tc.description)
assert.Equal(t, expYaml, rYaml)
}
}
@@ -262,6 +254,8 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
actYaml, err := actual.AsYaml()
assert.NoError(t, err)
expected := resmaptest_test.NewRmBuilder(t, rf).Add(
map[string]interface{}{
@@ -276,7 +270,127 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).ResMap()
if err = expected.ErrorIfNotEqualLists(actual); err != nil {
expYaml, err := expected.AsYaml()
assert.NoError(t, err)
assert.Equal(t, string(expYaml), string(actYaml))
}
func TestFromRNodeSlice(t *testing.T) {
input := `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- 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{}{
map[string]interface{}{
"apiGroups": []interface{}{
"",
},
"resources": []interface{}{
"namespaces",
},
"verbs": []interface{}{
"get",
"watch",
"list",
},
},
},
}).ResMap()
if err = expected.ErrorIfNotEqualLists(rm); err != nil {
t.Fatalf("error: %s", err)
}
}
func TestMerge_Empty(t *testing.T) {
rm, err := rmF.Merge([]*resource.Resource{})
assert.NoError(t, err)
assert.Equal(t, 0, rm.Size())
}
func TestMerge(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.Merge([]*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) Merge(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

@@ -10,6 +10,7 @@ import (
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// A Transformer modifies an instance of ResMap.
@@ -235,4 +236,13 @@ type ResMap interface {
// Select returns a list of resources that
// are selected by a Selector
Select(types.Selector) ([]*resource.Resource, error)
// 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,11 +6,13 @@ package resmap
import (
"bytes"
"fmt"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
kyaml_yaml "sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/yaml"
)
@@ -338,10 +340,8 @@ func (m *resWrangler) ErrorIfNotEqualLists(other ResMap) error {
}
for i, r1 := range m.rList {
r2 := m2.rList[i]
if !r1.Equals(r2) {
return fmt.Errorf(
"Item i=%d differs:\n n1 = %s\n n2 = %s\n o1 = %s\n o2 = %s\n",
i, r1.OrgId(), r2.OrgId(), r1, r2)
if err := r1.ErrIfNotEquals(r2); err != nil {
return err
}
}
return nil
@@ -561,3 +561,64 @@ func (m *resWrangler) Select(s types.Selector) ([]*resource.Resource, error) {
}
return result, nil
}
// ToRNodeSlice converts the resources in the resmp
// to a list of RNodes
func (m *resWrangler) ToRNodeSlice() ([]*kyaml_yaml.RNode, error) {
var rnodes []*kyaml_yaml.RNode
for _, r := range m.Resources() {
s, err := r.AsYAML()
if err != nil {
return nil, err
}
rnode, err := kyaml_yaml.Parse(string(s))
if err != nil {
return nil, err
}
rnodes = append(rnodes, rnode)
}
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

@@ -4,12 +4,15 @@
package resmap_test
import (
"bytes"
"fmt"
"reflect"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"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"
"sigs.k8s.io/kustomize/api/resource"
@@ -17,9 +20,9 @@ import (
"sigs.k8s.io/kustomize/api/types"
)
var rf = resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
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)
@@ -190,6 +193,8 @@ metadata:
}
func TestGetMatchingResourcesByCurrentId(t *testing.T) {
cmap := resid.Gvk{Version: "v1", Kind: "ConfigMap"}
r1 := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
@@ -686,49 +691,506 @@ func makeMap2(b types.GenerationBehavior) ResMap {
}
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",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{},
"labels": map[string]interface{}{},
"name": "cmap",
},
"metadata": metadata,
"data": map[string]interface{}{
"a": "u",
"b": "v",
"c": "w",
},
}, &types.GeneratorArgs{
},
&types.GeneratorArgs{
Behavior: "create",
}))
w := makeMap1()
if err := w.AbsorbAll(makeMap2(types.BehaviorMerge)); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := expected.ErrorIfNotEqualLists(w); err != nil {
t.Fatal(err)
}
assert.NoError(t, w.AbsorbAll(makeMap2(types.BehaviorMerge)))
assert.NoError(t, expected.ErrorIfNotEqualLists(w))
w = makeMap1()
if err := w.AbsorbAll(nil); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := w.ErrorIfNotEqualLists(makeMap1()); err != nil {
t.Fatal(err)
}
assert.NoError(t, w.AbsorbAll(nil))
assert.NoError(t, w.ErrorIfNotEqualLists(makeMap1()))
w = makeMap1()
w2 := makeMap2(types.BehaviorReplace)
if err := w.AbsorbAll(w2); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := w2.ErrorIfNotEqualLists(w); err != nil {
t.Fatal(err)
}
assert.NoError(t, w.AbsorbAll(w2))
assert.NoError(t, w2.ErrorIfNotEqualLists(w))
w = makeMap1()
w2 = makeMap2(types.BehaviorUnspecified)
err := w.AbsorbAll(w2)
if err == nil {
t.Fatalf("expected error with unspecified behavior")
assert.Error(t, err)
assert.True(
t, strings.Contains(err.Error(), "behavior must be merge or replace"))
}
func TestToRNodeSlice(t *testing.T) {
input := `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- watch
- list
`
rm, err := rmF.NewResMapFromBytes([]byte(input))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
rnodes, err := rm.ToRNodeSlice()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
b := bytes.NewBufferString("")
for i, n := range rnodes {
if i != 0 {
b.WriteString("---\n")
}
s, err := n.String()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
b.WriteString(s)
}
if !reflect.DeepEqual(input, b.String()) {
t.Fatalf("actual doesn't match expected.\nActual:\n%s\n===\nExpected:\n%s\n",
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
}{
"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

@@ -6,6 +6,7 @@ package resmap_test
import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/resid"
. "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
@@ -48,38 +49,36 @@ metadata:
name: x-name1
namespace: x-default
`))
if err != nil {
t.Fatalf("unexpected error %v", err)
}
assert.NoError(t, err)
return result
}
func TestFindPatchTargets(t *testing.T) {
rm := setupRMForPatchTargets(t)
testcases := []struct {
testcases := map[string]struct {
target types.Selector
count int
}{
{
"select_01": {
target: types.Selector{
Name: "name.*",
},
count: 3,
},
{
"select_02": {
target: types.Selector{
Name: "name.*",
AnnotationSelector: "foo=bar",
},
count: 2,
},
{
"select_03": {
target: types.Selector{
LabelSelector: "app=name1",
},
count: 1,
},
{
"select_04": {
target: types.Selector{
Gvk: resid.Gvk{
Kind: "Kind1",
@@ -88,31 +87,31 @@ func TestFindPatchTargets(t *testing.T) {
},
count: 2,
},
{
"select_05": {
target: types.Selector{
Name: "NotMatched",
},
count: 0,
},
{
"select_06": {
target: types.Selector{
Name: "",
},
count: 4,
},
{
"select_07": {
target: types.Selector{
Namespace: "default",
},
count: 2,
},
{
"select_08": {
target: types.Selector{
Namespace: "",
},
count: 4,
},
{
"select_09": {
target: types.Selector{
Namespace: "default",
Name: "name.*",
@@ -122,69 +121,65 @@ func TestFindPatchTargets(t *testing.T) {
},
count: 1,
},
{
"select_10": {
target: types.Selector{
Name: "^name.*",
},
count: 3,
},
{
"select_11": {
target: types.Selector{
Name: "name.*$",
},
count: 3,
},
{
"select_12": {
target: types.Selector{
Name: "^name.*$",
},
count: 3,
},
{
"select_13": {
target: types.Selector{
Namespace: "^def.*",
},
count: 2,
},
{
"select_14": {
target: types.Selector{
Namespace: "def.*$",
},
count: 2,
},
{
"select_15": {
target: types.Selector{
Namespace: "^def.*$",
},
count: 2,
},
{
"select_16": {
target: types.Selector{
Namespace: "default",
},
count: 2,
},
{
"select_17": {
target: types.Selector{
Namespace: "NotMatched",
},
count: 0,
},
{
"select_18": {
target: types.Selector{
Namespace: "ns1",
},
count: 1,
},
}
for _, testcase := range testcases {
for n, testcase := range testcases {
actual, err := rm.Select(testcase.target)
if err != nil {
t.Errorf("unexpected error %v", err)
}
if len(actual) != testcase.count {
t.Errorf("expected %d objects, but got %d:\n%v", testcase.count, len(actual), actual)
}
assert.NoError(t, err)
assert.Equalf(
t, testcase.count, len(actual), "test=%s target=%v", n, testcase.target)
}
}

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

@@ -94,7 +94,7 @@ func (rf *Factory) SliceFromPatches(
return result, nil
}
// FromBytes unmarshals bytes into one Resource.
// FromBytes unmarshalls bytes into one Resource.
func (rf *Factory) FromBytes(in []byte) (*Resource, error) {
result, err := rf.SliceFromBytes(in)
if err != nil {

View File

@@ -4,9 +4,12 @@
package resource_test
import (
"reflect"
"fmt"
"testing"
"sigs.k8s.io/kustomize/api/konfig"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/loader"
. "sigs.k8s.io/kustomize/api/resource"
@@ -340,7 +343,15 @@ kind: List
name: "listWithAnchorReference",
input: []types.PatchStrategicMerge{patchList2},
expectedOut: []*Resource{testDeploymentA, testDeploymentB},
expectedErr: false,
// See https://github.com/kubernetes-sigs/kustomize/issues/3271
// This test should not have an error, but does when kyaml is used.
// The error using kyaml is:
// json: unsupported type: map[interface {}]interface {}
// probably arising from too many conversions between
// yaml, json, Resource, RNode, Unstructured etc.
// These conversions can be removed after closing
// https://github.com/kubernetes-sigs/kustomize/issues/2506
expectedErr: konfig.FlagEnableKyamlDefaultValue,
},
{
name: "listWithNoEntries",
@@ -349,7 +360,7 @@ kind: List
expectedErr: false,
},
{
name: "listWithNo'items:'",
name: "listWithNoItems",
input: []types.PatchStrategicMerge{patchList4},
expectedOut: []*Resource{},
expectedErr: false,
@@ -357,21 +368,19 @@ kind: List
}
for _, test := range tests {
rs, err := factory.SliceFromPatches(ldr, test.input)
if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name)
}
if !test.expectedErr && err != nil {
t.Fatalf("%v: unexpected error: %s", test.name, err)
}
if len(rs) != len(test.expectedOut) {
t.Fatalf("%s: length mismatch %d != %d",
test.name, len(rs), len(test.expectedOut))
if err != nil {
assert.True(t, test.expectedErr,
fmt.Sprintf("in test %s, got unexpected error: %v", test.name, err))
continue
}
assert.False(t, test.expectedErr, "expected no error in "+test.name)
assert.Equal(t, len(test.expectedOut), len(rs))
for i := range rs {
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
t.Fatalf("%s: Got: %v\nexpected:%v",
test.name, test.expectedOut[i], rs[i])
}
expYaml, err := test.expectedOut[i].AsYAML()
assert.NoError(t, err)
actYaml, err := rs[i].AsYAML()
assert.NoError(t, err)
assert.Equal(t, expYaml, actYaml)
}
}
}

30
api/resource/idset.go Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resource
import "sigs.k8s.io/kustomize/api/resid"
type IdSet struct {
ids map[resid.ResId]bool
}
func MakeIdSet(slice []*Resource) *IdSet {
set := make(map[resid.ResId]bool)
for _, r := range slice {
id := r.CurId()
if _, ok := set[id]; !ok {
set[id] = true
}
}
return &IdSet{ids: set}
}
func (s IdSet) Contains(id resid.ResId) bool {
_, ok := s.ids[id]
return ok
}
func (s IdSet) Size() int {
return len(s.ids)
}

View File

@@ -0,0 +1,32 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resource_test
import (
"testing"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/resource"
)
func TestIdSet_Empty(t *testing.T) {
s := MakeIdSet([]*Resource{})
assert.Equal(t, 0, s.Size())
assert.False(t, s.Contains(testDeployment.CurId()))
assert.False(t, s.Contains(testConfigMap.CurId()))
}
func TestIdSet_One(t *testing.T) {
s := MakeIdSet([]*Resource{testDeployment})
assert.Equal(t, 1, s.Size())
assert.True(t, s.Contains(testDeployment.CurId()))
assert.False(t, s.Contains(testConfigMap.CurId()))
}
func TestIdSet_Two(t *testing.T) {
s := MakeIdSet([]*Resource{testDeployment, testConfigMap})
assert.Equal(t, 2, s.Size())
assert.True(t, s.Contains(testDeployment.CurId()))
assert.True(t, s.Contains(testConfigMap.CurId()))
}

View File

@@ -1,16 +1,18 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package resource implements representations of k8s API resources.
package resource
import (
"fmt"
"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"
)
@@ -156,9 +158,25 @@ func (r *Resource) copyOtherFields(other *Resource) {
r.nameSuffixes = copyStringSlice(other.nameSuffixes)
}
func (r *Resource) Equals(o *Resource) bool {
return r.ReferencesEqual(o) &&
reflect.DeepEqual(r.kunStr, o.kunStr)
func (r *Resource) ErrIfNotEquals(o *Resource) error {
meYaml, err := r.AsYAML()
if err != nil {
return err
}
otherYaml, err := o.AsYAML()
if err != nil {
return err
}
if !r.ReferencesEqual(o) {
return fmt.Errorf("references unequal")
}
if string(meYaml) != string(otherYaml) {
return fmt.Errorf("--- self:\n"+
"%s\n"+
"--- other:\n"+
"%s\n", meYaml, otherYaml)
}
return nil
}
func (r *Resource) ReferencesEqual(o *Resource) bool {
@@ -379,6 +397,23 @@ func (r *Resource) AppendRefVarName(variable types.Var) {
r.refVarNames = append(r.refVarNames, variable.Name)
}
// ApplySmPatch applies the provided strategic merge patch.
func (r *Resource) ApplySmPatch(patch *Resource) error {
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
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
}
// TODO: Add BinaryData once we sync to new k8s.io/api
func mergeConfigmap(
mergedTo map[string]interface{},

View File

@@ -1,33 +1,21 @@
/*
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 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resource_test
import (
"fmt"
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resid"
. "sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
)
var factory = NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
var factory = provider.NewDefaultDepProvider().GetResourceFactory()
var testConfigMap = factory.FromMap(
map[string]interface{}{
@@ -137,3 +125,669 @@ 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_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

@@ -8,13 +8,11 @@ import (
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/merge"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
@@ -46,11 +44,10 @@ func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
if err != nil {
t.Fatal(err)
}
resourceFactory := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
p := provider.NewDefaultDepProvider()
resourceFactory := p.GetResourceFactory()
resmapFactory := resmap.NewFactory(
resourceFactory,
merge.NewMerginator(resourceFactory))
resourceFactory, p.GetConflictDetectorFactory())
result := &HarnessEnhanced{
Harness: MakeHarness(t),

View File

@@ -6,6 +6,7 @@ package resmaptest_test
import (
"testing"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
)
@@ -25,6 +26,15 @@ func NewRmBuilder(t *testing.T, rf *resource.Factory) *rmBuilder {
return NewSeededRmBuilder(t, rf, resmap.New())
}
func NewRmBuilderDefault(t *testing.T) *rmBuilder {
return NewSeededRmBuilderDefault(t, resmap.New())
}
func NewSeededRmBuilderDefault(t *testing.T, m resmap.ResMap) *rmBuilder {
return NewSeededRmBuilder(
t, provider.NewDefaultDepProvider().GetResourceFactory(), m)
}
func (rm *rmBuilder) Add(m map[string]interface{}) *rmBuilder {
return rm.AddR(rm.rf.FromMap(m))
}

View File

@@ -0,0 +1,25 @@
// Code generated by "stringer -type=BuiltinPluginLoadingOptions"; DO NOT EDIT.
package types
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[BploUndefined-0]
_ = x[BploUseStaticallyLinked-1]
_ = x[BploLoadFromFileSys-2]
}
const _BuiltinPluginLoadingOptions_name = "BploUndefinedBploUseStaticallyLinkedBploLoadFromFileSys"
var _BuiltinPluginLoadingOptions_index = [...]uint8{0, 13, 36, 55}
func (i BuiltinPluginLoadingOptions) String() string {
if i < 0 || i >= BuiltinPluginLoadingOptions(len(_BuiltinPluginLoadingOptions_index)-1) {
return "BuiltinPluginLoadingOptions(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _BuiltinPluginLoadingOptions_name[_BuiltinPluginLoadingOptions_index[i]:_BuiltinPluginLoadingOptions_index[i+1]]
}

View File

@@ -10,10 +10,11 @@ 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"`
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

@@ -1,6 +1,6 @@
module sigs.k8s.io/kustomize/cmd/config
go 1.14
go 1.15
require (
github.com/go-errors/errors v1.0.1
@@ -15,5 +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.3
)

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,6 +373,7 @@ 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=
@@ -387,8 +390,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.9.4 h1:DDuzZtjIzFqp2IPy4DTyCI69Cl3bDgcJODjI6sjF9NY=
sigs.k8s.io/kustomize/kyaml v0.9.4/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
sigs.k8s.io/kustomize/kyaml v0.10.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj908I=
sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
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

@@ -17,8 +17,7 @@ import (
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/cmd/config/runner"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/setters"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -34,34 +33,23 @@ func NewCreateSetterRunner(parent string) *CreateSetterRunner {
PreRunE: r.preRunE,
RunE: r.runE,
}
set.Flags().StringVar(&r.Set.SetPartialField.Setter.Value, "value", "",
set.Flags().StringVar(&r.FieldValue, "value", "",
"optional flag, alternative to specifying the value as an argument. e.g. used to specify values that start with '-'")
set.Flags().StringVar(&r.Set.SetPartialField.SetBy, "set-by", "",
set.Flags().StringVar(&r.SetBy, "set-by", "",
"record who the field was default by.")
set.Flags().StringVar(&r.Set.SetPartialField.Description, "description", "",
set.Flags().StringVar(&r.Description, "description", "",
"record a description for the current setter value.")
set.Flags().StringVar(&r.Set.SetPartialField.Field, "field", "",
set.Flags().StringVar(&r.FieldName, "field", "",
"name of the field to set, a suffix of the path to the field, or the full"+
" path to the field. Default is to match all fields.")
set.Flags().StringVar(&r.Set.ResourceMeta.Name, "name", "",
"name of the Resource on which to create the setter.")
set.Flags().MarkHidden("name")
set.Flags().StringVar(&r.Set.ResourceMeta.Kind, "kind", "",
"kind of the Resource on which to create the setter.")
set.Flags().MarkHidden("kind")
set.Flags().StringVar(&r.Set.SetPartialField.Type, "type", "",
set.Flags().StringVar(&r.Type, "type", "",
"OpenAPI field type for the setter -- e.g. integer,boolean,string.")
set.Flags().BoolVar(&r.Set.SetPartialField.Partial, "partial", false,
"create a partial setter for only part of the field value.")
set.Flags().MarkHidden("partial")
set.Flags().StringVar(&setterVersion, "version", "",
"use this version of the setter format")
set.Flags().BoolVar(&r.CreateSetter.Required, "required", false,
set.Flags().BoolVar(&r.Required, "required", false,
"indicates that this setter must be set by package consumer before live apply/preview")
set.Flags().StringVar(&r.SchemaPath, "schema-path", "",
`openAPI schema file path for setter constraints -- file content `+
`e.g. {"type": "string", "maxLength": 15, "enum": ["allowedValue1", "allowedValue2"]}`)
set.Flags().BoolVarP(&r.CreateSetter.RecurseSubPackages, "recurse-subpackages", "R", false,
set.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
"creates setter recursively in all the nested subpackages")
set.Flags().MarkHidden("version")
runner.FixDocs(parent, set)
@@ -74,11 +62,19 @@ func CreateSetterCommand(parent string) *cobra.Command {
}
type CreateSetterRunner struct {
Command *cobra.Command
Set setters.CreateSetter
CreateSetter settersutil.SetterCreator
OpenAPIFile string
SchemaPath string
Command *cobra.Command
CreateSetter settersutil.SetterCreator
OpenAPIFile string
SchemaPath string
FieldValue string
SetBy string
Description string
SetterName string
Type string
FieldName string
Schema string
Required bool
RecurseSubPackages bool
}
func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error {
@@ -86,48 +82,29 @@ func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error {
}
func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error {
valueSetFromFlag := c.Flag("value").Changed
var err error
r.Set.SetPartialField.Setter.Name = args[1]
r.CreateSetter.Name = args[1]
if valueSetFromFlag {
r.CreateSetter.FieldValue = r.Set.SetPartialField.Setter.Value
} else if len(args) > 2 {
r.Set.SetPartialField.Setter.Value = args[2]
r.CreateSetter.FieldValue = args[2]
r.SetterName = args[1]
if len(args) > 2 {
r.FieldValue = args[2]
}
r.CreateSetter.FieldName, err = c.Flags().GetString("field")
r.FieldName, err = c.Flags().GetString("field")
if err != nil {
return err
}
if setterVersion == "" {
if len(args) == 2 && r.Set.SetPartialField.Type == "array" && c.Flag("field").Changed {
setterVersion = "v2"
} else if err := initSetterVersion(c, args); err != nil {
return err
}
}
if r.Set.SetPartialField.Type != "array" && !c.Flag("value").Changed && len(args) < 3 {
if r.Type != "array" && !c.Flag("value").Changed && len(args) < 3 {
return errors.Errorf("setter name and value must be provided, " +
"value can either be an argument or can be passed as a flag --value")
}
if setterVersion == "v2" {
r.CreateSetter.Description = r.Set.SetPartialField.Description
r.CreateSetter.SetBy = r.Set.SetPartialField.SetBy
r.CreateSetter.Type = r.Set.SetPartialField.Type
err = r.processSchema()
if err != nil {
return err
}
err = r.processSchema()
if err != nil {
return err
}
if r.CreateSetter.Type == "array" {
if !c.Flag("field").Changed {
return errors.Errorf("field flag must be set for array type setters")
}
if r.Type == "array" {
if !c.Flag("field").Changed {
return errors.Errorf("field flag must be set for array type setters")
}
}
return nil
@@ -139,7 +116,7 @@ func (r *CreateSetterRunner) processSchema() error {
return err
}
flagType := r.CreateSetter.Type
flagType := r.Type
var schemaType string
switch {
// json schema allows more than one type to be specified, but openapi
@@ -156,13 +133,13 @@ func (r *CreateSetterRunner) processSchema() error {
// are both set with different values, we return an error.
switch {
case flagType == "" && schemaType != "":
r.CreateSetter.Type = schemaType
r.Type = schemaType
case flagType != "" && schemaType == "":
sc.Type = []string{flagType}
case flagType != "" && schemaType != "":
if flagType != schemaType {
return errors.Errorf("type provided in type flag (%s) and in schema (%s) doesn't match",
r.CreateSetter.Type, sc.Type[0])
r.Type, sc.Type[0])
}
}
@@ -174,54 +151,47 @@ func (r *CreateSetterRunner) processSchema() error {
if err != nil {
return errors.Errorf("error marshalling schema: %v", err)
}
r.CreateSetter.Schema = string(b)
r.Schema = string(b)
return nil
}
func (r *CreateSetterRunner) createSetter(c *cobra.Command, args []string) error {
if setterVersion == "v2" {
e := runner.ExecuteCmdOnPkgs{
NeedOpenAPI: true,
Writer: c.OutOrStdout(),
RootPkgPath: args[0],
RecurseSubPackages: r.CreateSetter.RecurseSubPackages,
CmdRunner: r,
}
err := e.Execute()
if err != nil {
return runner.HandleError(c, err)
}
return nil
e := runner.ExecuteCmdOnPkgs{
NeedOpenAPI: true,
Writer: c.OutOrStdout(),
RootPkgPath: args[0],
RecurseSubPackages: r.RecurseSubPackages,
CmdRunner: r,
}
rw := &kio.LocalPackageReadWriter{PackagePath: args[0]}
err := kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{&r.Set},
Outputs: []kio.Writer{rw}}.Execute()
err := e.Execute()
if err != nil {
return err
return runner.HandleError(c, err)
}
return nil
}
func (r *CreateSetterRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
sc, err := openapi.SchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName()))
if err != nil {
return err
}
r.CreateSetter = settersutil.SetterCreator{
Name: r.CreateSetter.Name,
SetBy: r.CreateSetter.SetBy,
Description: r.CreateSetter.Description,
Type: r.CreateSetter.Type,
Schema: r.CreateSetter.Schema,
FieldName: r.CreateSetter.FieldName,
FieldValue: r.CreateSetter.FieldValue,
Required: r.CreateSetter.Required,
RecurseSubPackages: r.CreateSetter.RecurseSubPackages,
Name: r.SetterName,
SetBy: r.SetBy,
Description: r.Description,
Type: r.Type,
Schema: r.Schema,
FieldName: r.FieldName,
FieldValue: r.FieldValue,
Required: r.Required,
RecurseSubPackages: r.RecurseSubPackages,
OpenAPIFileName: ext.KRMFileName(),
OpenAPIPath: filepath.Join(pkgPath, ext.KRMFileName()),
ResourcesPath: pkgPath,
SettersSchema: sc,
}
err := r.CreateSetter.Create()
err = r.CreateSetter.Create()
if err != nil {
// return err if RecurseSubPackages is false
if !r.CreateSetter.RecurseSubPackages {

View File

@@ -466,60 +466,6 @@ spec:
replicas: 3 # {"$openapi":"foo.bar"}
`,
},
{
name: "create setter v1",
args: []string{"hubsetter", "my-hub"},
inputOpenAPI: `
`,
input: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name"
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub
`,
expectedOpenAPI: `
`,
expectedResources: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name"
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub # {"type":"","x-kustomize":{"setter":{"name":"hubsetter","value":"my-hub"}}}
`,
},
{
name: "create partial setter v1",
args: []string{"regionsetter", "us-east1-d", "--partial"},
inputOpenAPI: `
`,
input: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name" # {"type":"","x-kustomize":{"partialSetters":[{"name":"projectsetter","value":"project-id"}]}}
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub # {"type":"","x-kustomize":{"setter":{"name":"hubsetter","value":"my-hub"}}}
`,
expectedOpenAPI: `
`,
expectedResources: `
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
metadata:
clusterName: "project-id/us-east1-d/cluster-name" # {"type":"","x-kustomize":{"partialSetters":[{"name":"projectsetter","value":"project-id"},{"name":"regionsetter","value":"us-east1-d"}]}}
spec:
profile: asm # {"type":"string","x-kustomize":{"setter":{"name":"profilesetter","value":"asm"}}}
hub: my-hub # {"type":"","x-kustomize":{"setter":{"name":"hubsetter","value":"my-hub"}}}
`,
},
{
name: "provide different type values in schema and with flag",
args: []string{"replicas", "3", "--description", "hello world", "--type", "string"},

View File

@@ -11,6 +11,7 @@ import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/cmd/config/runner"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -66,6 +67,10 @@ func (r *CreateSubstitutionRunner) runE(c *cobra.Command, args []string) error {
}
func (r *CreateSubstitutionRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
sc, err := openapi.SchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName()))
if err != nil {
return err
}
r.CreateSubstitution = settersutil.SubstitutionCreator{
Name: r.CreateSubstitution.Name,
FieldName: r.CreateSubstitution.FieldName,
@@ -75,9 +80,10 @@ func (r *CreateSubstitutionRunner) ExecuteCmd(w io.Writer, pkgPath string) error
OpenAPIFileName: ext.KRMFileName(),
OpenAPIPath: filepath.Join(pkgPath, ext.KRMFileName()),
ResourcesPath: pkgPath,
SettersSchema: sc,
}
err := r.CreateSubstitution.Create()
err = r.CreateSubstitution.Create()
if err != nil {
// return err if RecurseSubPackages is false
if !r.CreateSubstitution.RecurseSubPackages {

View File

@@ -13,6 +13,7 @@ import (
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/cmd/config/runner"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -72,6 +73,10 @@ func (r *DeleteSetterRunner) runE(c *cobra.Command, args []string) error {
}
func (r *DeleteSetterRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
sc, err := openapi.SchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName()))
if err != nil {
return err
}
r.DeleteSetter = settersutil.DeleterCreator{
Name: r.DeleteSetter.Name,
DefinitionPrefix: fieldmeta.SetterDefinitionPrefix,
@@ -79,9 +84,10 @@ func (r *DeleteSetterRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
OpenAPIFileName: ext.KRMFileName(),
OpenAPIPath: filepath.Join(pkgPath, ext.KRMFileName()),
ResourcesPath: pkgPath,
SettersSchema: sc,
}
err := r.DeleteSetter.Delete()
err = r.DeleteSetter.Delete()
if err != nil {
// return err if RecurseSubPackages is false
if !r.DeleteSetter.RecurseSubPackages {

View File

@@ -12,6 +12,7 @@ import (
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/cmd/config/runner"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -68,6 +69,10 @@ func (r *DeleteSubstitutionRunner) runE(c *cobra.Command, args []string) error {
}
func (r *DeleteSubstitutionRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
sc, err := openapi.SchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName()))
if err != nil {
return err
}
r.DeleteSubstitution = settersutil.DeleterCreator{
Name: r.DeleteSubstitution.Name,
DefinitionPrefix: fieldmeta.SubstitutionDefinitionPrefix,
@@ -75,9 +80,10 @@ func (r *DeleteSubstitutionRunner) ExecuteCmd(w io.Writer, pkgPath string) error
OpenAPIFileName: ext.KRMFileName(),
OpenAPIPath: filepath.Join(pkgPath, ext.KRMFileName()),
ResourcesPath: pkgPath,
SettersSchema: sc,
}
err := r.DeleteSubstitution.Delete()
err = r.DeleteSubstitution.Delete()
if err != nil {
// return err if RecurseSubPackages is false
if !r.DeleteSubstitution.RecurseSubPackages {

View File

@@ -16,7 +16,7 @@ import (
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/cmd/config/runner"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/setters"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters2"
)
@@ -49,46 +49,46 @@ func ListSettersCommand(parent string) *cobra.Command {
type ListSettersRunner struct {
Command *cobra.Command
Lookup setters.LookupSetters
List setters2.List
Markdown bool
IncludeSubst bool
RecurseSubPackages bool
Name string
}
func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
if len(args) > 1 {
r.Lookup.Name = args[1]
r.List.Name = args[1]
r.Name = args[1]
}
initSetterVersion(c, args)
return nil
}
func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
if setterVersion == "v2" {
e := runner.ExecuteCmdOnPkgs{
NeedOpenAPI: true,
Writer: c.OutOrStdout(),
RootPkgPath: args[0],
RecurseSubPackages: r.RecurseSubPackages,
CmdRunner: r,
}
err := e.Execute()
if err != nil {
return runner.HandleError(c, err)
}
return nil
e := runner.ExecuteCmdOnPkgs{
NeedOpenAPI: true,
Writer: c.OutOrStdout(),
RootPkgPath: args[0],
RecurseSubPackages: r.RecurseSubPackages,
CmdRunner: r,
}
return runner.HandleError(c, lookup(r.Lookup, c, args))
err := e.Execute()
if err != nil {
return runner.HandleError(c, err)
}
return nil
}
func (r *ListSettersRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
sc, err := openapi.SchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName()))
if err != nil {
return err
}
r.List = setters2.List{
Name: r.List.Name,
Name: r.Name,
OpenAPIFileName: ext.KRMFileName(),
SettersSchema: sc,
}
openAPIPath := filepath.Join(pkgPath, ext.KRMFileName())
if err := r.ListSetters(w, openAPIPath, pkgPath); err != nil {

View File

@@ -6,17 +6,13 @@ package commands
import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/cmd/config/runner"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/setters"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -36,13 +32,13 @@ func NewSetRunner(parent string) *SetRunner {
r.Command = c
c.Flags().StringArrayVar(&r.Values, "values", []string{},
"optional flag, the values of the setter to be set to")
c.Flags().StringVar(&r.Perform.SetBy, "set-by", "",
c.Flags().StringVar(&r.SetBy, "set-by", "",
"annotate the field with who set it")
c.Flags().StringVar(&r.Perform.Description, "description", "",
c.Flags().StringVar(&r.Description, "description", "",
"annotate the field with a description of its value")
c.Flags().StringVar(&setterVersion, "version", "",
"use this version of the setter format")
c.Flags().BoolVarP(&r.Set.RecurseSubPackages, "recurse-subpackages", "R", false,
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
"sets recursively in all the nested subpackages")
c.Flags().MarkHidden("version")
@@ -56,31 +52,16 @@ func SetCommand(parent string) *cobra.Command {
}
type SetRunner struct {
Command *cobra.Command
Lookup setters.LookupSetters
Perform setters.PerformSetters
Set settersutil.FieldSetter
OpenAPIFile string
Values []string
}
func initSetterVersion(c *cobra.Command, args []string) error {
setterVersion = "v2"
l := setters.LookupSetters{}
// backwards compatibility for resources with setter v1
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.LocalPackageReader{PackagePath: args[0]}},
Filters: []kio.Filter{&l},
}.Execute()
if err != nil {
return err
}
if len(l.SetterCounts) > 0 {
setterVersion = "v1"
}
return nil
Command *cobra.Command
Set settersutil.FieldSetter
OpenAPIFile string
Values []string
SetBy string
Description string
Name string
Value string
ListValues []string
RecurseSubPackages bool
}
func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
@@ -90,79 +71,51 @@ func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
return errors.Errorf("value should set either from flag or arg")
}
if len(args) > 1 {
r.Perform.Name = args[1]
r.Lookup.Name = args[1]
}
r.Name = args[1]
if valueFlagSet {
r.Perform.Value = r.Values[0]
} else if len(args) > 2 {
r.Perform.Value = args[2]
r.Value = r.Values[0]
} else {
r.Value = args[2]
}
if setterVersion == "" {
if len(args) < 2 || len(args) < 3 && !valueFlagSet {
setterVersion = "v1"
} else if err := initSetterVersion(c, args); err != nil {
return err
}
// set remaining values as list values
if valueFlagSet && len(r.Values) > 1 {
r.ListValues = r.Values[1:]
} else if !valueFlagSet && len(args) > 3 {
r.ListValues = args[3:]
}
if setterVersion == "v2" {
r.Set.Name = args[1]
if valueFlagSet {
r.Set.Value = r.Values[0]
} else {
r.Set.Value = args[2]
}
// set remaining values as list values
if valueFlagSet && len(r.Values) > 1 {
r.Set.ListValues = r.Values[1:]
} else if !valueFlagSet && len(args) > 3 {
r.Set.ListValues = args[3:]
}
r.Set.Description = r.Perform.Description
r.Set.SetBy = r.Perform.SetBy
r.OpenAPIFile = filepath.Join(args[0], ext.KRMFileName())
}
r.OpenAPIFile = filepath.Join(args[0], ext.KRMFileName())
return nil
}
func (r *SetRunner) runE(c *cobra.Command, args []string) error {
if setterVersion == "v2" {
e := runner.ExecuteCmdOnPkgs{
NeedOpenAPI: true,
Writer: c.OutOrStdout(),
RootPkgPath: args[0],
RecurseSubPackages: r.Set.RecurseSubPackages,
CmdRunner: r,
}
err := e.Execute()
if err != nil {
return runner.HandleError(c, err)
}
return nil
e := runner.ExecuteCmdOnPkgs{
NeedOpenAPI: true,
Writer: c.OutOrStdout(),
RootPkgPath: args[0],
RecurseSubPackages: r.RecurseSubPackages,
CmdRunner: r,
}
if len(args) > 2 || c.Flag("values").Changed {
return runner.HandleError(c, r.perform(c, args))
err := e.Execute()
if err != nil {
return runner.HandleError(c, err)
}
return runner.HandleError(c, lookup(r.Lookup, c, args))
return nil
}
func (r *SetRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
r.Set = settersutil.FieldSetter{
Name: r.Set.Name,
Value: r.Set.Value,
ListValues: r.Set.ListValues,
Description: r.Set.Description,
SetBy: r.Set.SetBy,
Name: r.Name,
Value: r.Value,
ListValues: r.ListValues,
Description: r.Description,
SetBy: r.SetBy,
Count: 0,
OpenAPIPath: filepath.Join(pkgPath, ext.KRMFileName()),
OpenAPIFileName: ext.KRMFileName(),
ResourcesPath: pkgPath,
RecurseSubPackages: r.Set.RecurseSubPackages,
RecurseSubPackages: r.RecurseSubPackages,
IsSet: true,
}
count, err := r.Set.Set()
@@ -179,65 +132,3 @@ func (r *SetRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
}
return nil
}
func lookup(l setters.LookupSetters, c *cobra.Command, args []string) error {
// lookup the setters
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.LocalPackageReader{PackagePath: args[0]}},
Filters: []kio.Filter{&l},
}.Execute()
if err != nil {
return err
}
table := tablewriter.NewWriter(c.OutOrStdout())
table.SetRowLine(false)
table.SetBorder(false)
table.SetHeaderLine(false)
table.SetColumnSeparator(" ")
table.SetCenterSeparator(" ")
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetHeader([]string{
"NAME", "DESCRIPTION", "VALUE", "TYPE", "COUNT", "SETBY",
})
for i := range l.SetterCounts {
s := l.SetterCounts[i]
v := s.Value
if s.Value == "" {
v = s.Value
}
table.Append([]string{
s.Name,
"'" + s.Description + "'",
v,
fmt.Sprintf("%v", s.Type),
fmt.Sprintf("%d", s.Count),
s.SetBy,
})
}
table.Render()
if len(l.SetterCounts) == 0 {
// exit non-0 if no matching setters are found
os.Exit(1)
}
return nil
}
// perform the setters
func (r *SetRunner) perform(c *cobra.Command, args []string) error {
rw := &kio.LocalPackageReadWriter{
PackagePath: args[0],
}
// perform the setters in the package
err := kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{&r.Perform},
Outputs: []kio.Writer{rw},
}.Execute()
if err != nil {
return err
}
fmt.Fprintf(c.OutOrStdout(), "set %d fields\n", r.Perform.Count)
return nil
}

View File

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

View File

@@ -1,5 +1,5 @@
module sigs.k8s.io/kustomize/cmd/config/internal/commands/e2e/e2econtainerconfig
go 1.14
go 1.15
require sigs.k8s.io/kustomize/kyaml v0.1.10

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

@@ -7,13 +7,11 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/go-errors/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/pathutil"
)
@@ -73,14 +71,6 @@ func (e ExecuteCmdOnPkgs) Execute() error {
func (e ExecuteCmdOnPkgs) processPkg(pkgPath string) error {
// Add schema present in openAPI file for current package
if e.NeedOpenAPI {
clean, err := openapi.AddSchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName()))
if err != nil {
return err
}
defer clean()
}
if !e.SkipPkgPathPrint {
fmt.Fprintf(e.Writer, "%s/\n", pkgPath)
}

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

@@ -1,3 +1,3 @@
module sigs.k8s.io/kustomize/cmd/mdtogo
go 1.14
go 1.15

30
cmd/pluginator/Makefile Normal file
View File

@@ -0,0 +1,30 @@
.PHONY: statik test all clean generate run
FUNC_WRAPPER_SRC_DIR = funcwrappersrc
FUNC_WRAPPER_DST_DIR = funcwrapper
all: test build
statik:
go get github.com/rakyll/statik
test: generate
go test ./...
generate: statik
( \
cd internal/krmfunction; \
statik -src=$(FUNC_WRAPPER_SRC_DIR) -f -p $(FUNC_WRAPPER_DST_DIR) -include=main.go,go.mod.src \
)
build: generate
go build -o pluginator main.go
install: generate
go install .
run: generate
go run . $(ARGS)
clean:
rm -f pluginator

View File

@@ -1,7 +1,14 @@
module sigs.k8s.io/kustomize/cmd/pluginator/v2
go 1.14
go 1.15
require sigs.k8s.io/kustomize/api v0.6.4
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.10.3
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/api v0.6.4 => ../../api
replace sigs.k8s.io/kustomize/api v0.6.5 => ../../api

View File

@@ -32,6 +32,7 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -59,10 +60,13 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -140,10 +144,13 @@ 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=
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/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -153,6 +160,7 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
@@ -172,16 +180,20 @@ github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
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/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@@ -190,19 +202,27 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/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/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=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@@ -232,22 +252,29 @@ 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=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
@@ -257,8 +284,10 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96d
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
@@ -279,14 +308,18 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
@@ -302,6 +335,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -312,6 +346,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -324,7 +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/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=
@@ -334,15 +370,18 @@ github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOV
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite/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=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@@ -408,6 +447,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c h1:Vco5b+cuG5NNfORVxZy6bYZQ7rsigisU1WQFkvQ0L5E=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -455,15 +495,19 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
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=
@@ -472,20 +516,25 @@ gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C
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=
k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg=
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
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-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
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.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj908I=
sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
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

@@ -0,0 +1,176 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package builtinplugin
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provenance"
)
//go:generate stringer -type=pluginType
type pluginType int
const packageForGeneratedCode = "builtins"
const (
unknown pluginType = iota
Transformer
Generator
)
// ConvertToBuiltInPlugin converts the input plugin file to
// kustomize builtin plugin and writes it to proper directory
func ConvertToBuiltInPlugin() error {
root, err := inputFileRoot()
if err != nil {
return err
}
file, err := os.Open(root + ".go")
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
err = readToPackageMain(scanner, file.Name())
if err != nil {
return err
}
w, err := newWriter(root)
if err != nil {
return err
}
defer w.close()
// This particular phrasing is required.
w.write(
fmt.Sprintf(
"// Code generated by pluginator on %s; DO NOT EDIT.",
root))
w.write(
fmt.Sprintf(
"// pluginator %s\n", provenance.GetProvenance().Short()))
w.write("\n")
w.write("package " + packageForGeneratedCode)
pType := unknown
for scanner.Scan() {
l := scanner.Text()
if strings.HasPrefix(l, "//go:generate") {
continue
}
if strings.HasPrefix(l, "//noinspection") {
continue
}
if l == "var "+konfig.PluginSymbol+" plugin" {
continue
}
if strings.Contains(l, " Transform(") {
if pType != unknown {
return fmt.Errorf("unexpected Transform(")
}
pType = Transformer
} else if strings.Contains(l, " Generate(") {
if pType != unknown {
return fmt.Errorf("unexpected Generate(")
}
pType = Generator
}
w.write(l)
}
if err := scanner.Err(); err != nil {
return err
}
w.write("")
w.write("func New" + root + "Plugin() resmap." + pType.String() + "Plugin {")
w.write(" return &" + root + "Plugin{}")
w.write("}")
return nil
}
func inputFileRoot() (string, error) {
n := os.Getenv("GOFILE")
if !strings.HasSuffix(n, ".go") {
return "", fmt.Errorf("%+v, expecting .go suffix on %s", provenance.GetProvenance(), n)
}
return n[:len(n)-len(".go")], nil
}
func readToPackageMain(s *bufio.Scanner, f string) error {
gotMain := false
for !gotMain && s.Scan() {
gotMain = strings.HasPrefix(s.Text(), "package main")
}
if !gotMain {
return fmt.Errorf("%s missing package main", f)
}
return nil
}
type writer struct {
root string
f *os.File
}
func newWriter(r string) (*writer, error) {
n := makeOutputFileName(r)
f, err := os.Create(n)
if err != nil {
return nil, fmt.Errorf("unable to create `%s`; %v", n, err)
}
return &writer{root: r, f: f}, nil
}
// Assume that this command is running with a $PWD of
// $HOME/kustomize/plugin/builtin/secretGenerator
// (for example). Then we want to write to
// $HOME/kustomize/api/builtins
func makeOutputFileName(root string) string {
return filepath.Join(
"..", "..", "..", "api", packageForGeneratedCode, root+".go")
}
func (w *writer) close() {
// Do this for debugging.
// fmt.Println("Generated " + makeOutputFileName(w.root))
w.f.Close()
}
func (w *writer) write(line string) {
_, err := w.f.WriteString(w.filter(line) + "\n")
if err != nil {
fmt.Printf("Trouble writing: %s", line)
fmt.Printf("Error: %s", err)
os.Exit(1)
}
}
func (w *writer) filter(in string) string {
if ok, newer := w.replace(in, "type plugin struct"); ok {
return newer
}
if ok, newer := w.replace(in, "*plugin)"); ok {
return newer
}
return in
}
// replace 'plugin' with 'FooPlugin' in context
// sensitive manner.
func (w *writer) replace(in, target string) (bool, string) {
if !strings.Contains(in, target) {
return false, ""
}
newer := strings.Replace(
target, "plugin", w.root+"Plugin", 1)
return true, strings.Replace(in, target, newer, 1)
}

View File

@@ -1,6 +1,6 @@
// Code generated by "stringer -type=pluginType"; DO NOT EDIT.
package main
package builtinplugin
import "strconv"

View File

@@ -0,0 +1,30 @@
package krmfunction
import (
"github.com/spf13/cobra"
)
// NewKrmFunctionCmd returns a pointer to a command
func NewKrmFunctionCmd() *cobra.Command {
var outputDir string
var inputFile string
cmd := &cobra.Command{
Use: "krm -i FILE -o DIR",
Short: "Convert the plugin to KRM function instead of builtin function",
RunE: func(cmd *cobra.Command, args []string) error {
c := NewConverter(outputDir, inputFile)
return c.Convert()
},
}
cmd.Flags().StringVarP(&outputDir, "output", "o", "",
"Path to the directory which will contain the KRM function")
cmd.Flags().StringVarP(&inputFile, "input", "i", "",
"Path to the input file")
cmd.MarkFlagRequired("output")
cmd.MarkFlagRequired("input")
return cmd
}

View File

@@ -0,0 +1,165 @@
package krmfunction
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/rakyll/statik/fs"
// load embedded func wrapper
_ "sigs.k8s.io/kustomize/cmd/pluginator/v2/internal/krmfunction/funcwrapper"
)
// Converter is a converter to convert the
// plugin file to KRM function
type Converter struct {
// Path to the output directory
outputDir string
// Path to the input file
inputFile string
wrapperFileName string
pluginFileName string
goModFileName string
dockerFileName string
}
// NewConverter return a pointer to a new converter
func NewConverter(outputDir, inputFile string) *Converter {
return &Converter{
outputDir: outputDir,
inputFile: inputFile,
wrapperFileName: "main.go",
pluginFileName: "plugin.go",
goModFileName: "go.mod",
dockerFileName: "Dockerfile",
}
}
// Convert converts the input file to a executable
// KRM function and writes to destination directory
func (c *Converter) Convert() error {
// read and process executable wrapper
wrapper, err := c.readEmbeddedFile(c.wrapperFileName)
if err != nil {
return err
}
wrapper = c.prepareWrapper(wrapper)
if !strings.HasSuffix(c.inputFile, ".go") {
return fmt.Errorf("input file %s is not a Go file", c.inputFile)
}
// read and process plugin code
pluginCode, err := c.readDiskFile(c.inputFile)
if err != nil {
return err
}
_, c.pluginFileName = filepath.Split(c.inputFile)
// go.mod file
goMod, err := c.readEmbeddedFile(c.goModFileName + ".src")
if err != nil {
return err
}
// prepare destination directory
err = c.mkDstDir()
if err != nil {
return err
}
// write
return c.write(map[string]string{
c.wrapperFileName: wrapper,
c.pluginFileName: pluginCode,
c.goModFileName: goMod,
c.dockerFileName: c.getDockerfile(),
})
}
func (c *Converter) getDockerfile() string {
return `FROM golang:1.13-stretch
ENV CGO_ENABLED=0
WORKDIR /go/src/
COPY . .
RUN go build -v -o /usr/local/bin/function ./
FROM alpine:latest
COPY --from=0 /usr/local/bin/function /usr/local/bin/function
CMD ["function"]
`
}
func (c *Converter) prepareWrapper(content string) string {
b := bytes.NewBufferString(content)
o := &bytes.Buffer{}
scanner := bufio.NewScanner(b)
for scanner.Scan() {
line := scanner.Text()
// Set the package name to main
if strings.TrimSpace(line) == "package funcwrappersrc" {
line = "package main"
}
// assign to plugin variable
if strings.TrimSpace(line) == "var plugin resmap.Configurable" {
line = line + `
// KustomizePlugin is a global variable defined in every plugin
plugin = &KustomizePlugin
`
}
o.WriteString(line + "\n")
}
return o.String()
}
// readEmbeddedFile read the file from embedded files with filename
// name. Return the file content if it's successful.
func (c *Converter) readEmbeddedFile(name string) (string, error) {
statikFS, err := fs.New()
if err != nil {
return "", err
}
r, err := statikFS.Open("/" + name)
if err != nil {
return "", err
}
defer r.Close()
contents, err := ioutil.ReadAll(r)
if err != nil {
return "", err
}
return string(contents), nil
}
func (c *Converter) readDiskFile(path string) (string, error) {
f, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
return string(f), nil
}
func (c *Converter) mkDstDir() error {
p := c.outputDir
f, err := os.Open(p)
if err == nil || f != nil {
return fmt.Errorf("directory %s has already existed", p)
}
return os.MkdirAll(p, 0755)
}
func (c *Converter) write(m map[string]string) error {
for k, v := range m {
p := filepath.Join(c.outputDir, k)
err := ioutil.WriteFile(p, []byte(v), 0644)
if err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,247 @@
package krmfunction
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func makeTempDir(t *testing.T) string {
s, err := ioutil.TempDir("", "pluginator-*")
assert.NoError(t, err)
return s
}
func getTransformerCode() []byte {
// a simple namespace transformer
return []byte(`
package main
import (
"fmt"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/yaml"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/api/types"
)
type plugin struct{
Namespace string ` + "`json:\"namespace,omitempty\" yaml:\"namespace,omitempty\"`" + `
FieldSpecs []types.FieldSpec ` + "`json:\"fieldSpecs,omitempty\" yaml:\"fieldSpecs,omitempty\"`" + `
}
//noinspection GoUnusedGlobalVariable
var KustomizePlugin plugin
func (p *plugin) Config(
_ *resmap.PluginHelpers, config []byte) (err error) {
return yaml.Unmarshal(config, p)
}
func (p *plugin) Transform(rm resmap.ResMap) error {
if len(p.Namespace) == 0 {
return nil
}
for _, r := range rm.Resources() {
if r.IsEmpty() {
// Don't mutate empty objects?
continue
}
err := filtersutil.ApplyToJSON(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
}, r)
if err != nil {
return err
}
matches := rm.GetMatchingResourcesByCurrentId(r.CurId().Equals)
if len(matches) != 1 {
return fmt.Errorf(
"namespace transformation produces ID conflict: %+v", matches)
}
}
return nil
}
`)
}
func getTransformerInputResource() []byte {
return []byte(`
apiVersion: config.kubernetes.io/v1beta1
kind: ResourceList
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/example/foo:v1.0.0
data:
namespace: foo
fieldSpecs:
- path: metadata/namespace
create: true
items:
- apiVersion: apps/v1
kind: foobar
metadata:
name: whatever
`)
}
func runKrmFunction(t *testing.T, input []byte, dir string) []byte {
cmd := exec.Command("go", "run", ".")
ib := bytes.NewReader(input)
cmd.Stdin = ib
ob := bytes.NewBuffer([]byte{})
cmd.Stdout = ob
eb := bytes.NewBuffer([]byte{})
cmd.Stderr = eb
cmd.Dir = dir
err := cmd.Run()
if !assert.NoErrorf(t, err, "Stdout:\n%s\nStderr:\n%s\n", ob.String(), eb.String()) {
t.FailNow()
}
return ob.Bytes()
}
func TestTransformerConverter(t *testing.T) {
dir := makeTempDir(t)
defer os.RemoveAll(dir)
ioutil.WriteFile(filepath.Join(dir, "Plugin.go"),
getTransformerCode(), 0644)
c := NewConverter(filepath.Join(dir, "output"),
filepath.Join(dir, "Plugin.go"))
err := c.Convert()
assert.NoError(t, err)
output := runKrmFunction(t, getTransformerInputResource(), filepath.Join(dir, "output"))
assert.Equal(t, `apiVersion: config.kubernetes.io/v1beta1
kind: ResourceList
items:
- apiVersion: apps/v1
kind: foobar
metadata:
name: whatever
namespace: foo
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/example/foo:v1.0.0
data:
namespace: foo
fieldSpecs:
- path: metadata/namespace
create: true
`, string(output))
}
func getGeneratorCode() []byte {
return []byte(`package main
import (
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
type plugin struct {
h *resmap.PluginHelpers
types.ObjectMeta ` + "`json:\"metadata,omitempty\" yaml:\"metadata,omitempty\"`" + `
types.ConfigMapArgs
}
//noinspection GoUnusedGlobalVariable
var KustomizePlugin plugin
func (p *plugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.ConfigMapArgs = types.ConfigMapArgs{}
err = yaml.Unmarshal(config, p)
if p.ConfigMapArgs.Name == "" {
p.ConfigMapArgs.Name = p.Name
}
if p.ConfigMapArgs.Namespace == "" {
p.ConfigMapArgs.Namespace = p.Namespace
}
p.h = h
return
}
func (p *plugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromConfigMapArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.ConfigMapArgs)
}`)
}
func getGeneratorInputResource() []byte {
return []byte(`
apiVersion: config.kubernetes.io/v1beta1
kind: ResourceList
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/example/foo:v1.0.0
data:
metadata:
name: staging
items: []
`)
}
func TestGeneratorConverter(t *testing.T) {
dir := makeTempDir(t)
defer os.RemoveAll(dir)
ioutil.WriteFile(filepath.Join(dir, "Plugin.go"),
getGeneratorCode(), 0644)
c := NewConverter(filepath.Join(dir, "output"),
filepath.Join(dir, "Plugin.go"))
err := c.Convert()
assert.NoError(t, err)
output := runKrmFunction(t, getGeneratorInputResource(), filepath.Join(dir, "output"))
assert.Equal(t, `apiVersion: config.kubernetes.io/v1beta1
kind: ResourceList
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: staging
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/example/foo:v1.0.0
data:
metadata:
name: staging
`, string(output))
}

View File

@@ -0,0 +1,14 @@
// Code generated by statik. DO NOT EDIT.
package funcwrapper
import (
"github.com/rakyll/statik/fs"
)
func init() {
data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\xc9\xa3yQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00go.mod.srcUT\x05\x00\x01\xda\xbe\xbe_\x84\xce=\x8e\xc20\x10\xc5\xf1:s\n\x97\xbbE\xc6c;\x1f\x9bb\xb9\x8b\x1dL\x18%\xc6!\x8e#\xc1\xe9QDE\x01\xd4\xef'\xbd\x7f\x88\xc7<y\x11,_\x00\x86(\x14\xaa\x1a`\xf1\xd7\xcc\x8b\x17?P\x0c\xbc\x9e\xb3\xc3>\x06\x99\xe6\x932\xb2\x8fn\xb1bSHHP$\x1e\x12\x8e\x7f 9\xca1\xa75\x06\xbe{ig\x16\x1ba\x83\xd5;1\xdel\x98v\xd3\xa1y5\xcfA\xa1F\x82\xdf=e\x9el\xef\xc5\xb7#\xf1\x7f\xf8l\x08\xa9\xd4\xa4I)M\xdaPkLI\xb5\xb6\x8d\xab|\xd7\xb4\x0e\x1e\x01\x00\x00\xff\xffPK\x07\x08\xf6G\x8e3\x9e\x00\x00\x00\n\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xe5\x8ewQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00 \x00main.goUT\x05\x00\x01\x7f\xf7\xbb_\x94TMo\xdc6\x14<\x93\xbf\xe2EE\x0b\n\x10$\xf4V$\xd8Sl\xa7\x05j\xc3\xd8\x1a\xb9\x049\xd0\xd4\xa3B,?\x84Gj7\xe9B\xff\xbd\xa0\xa4\xfdl\x1c8\xc7}\x1a\xce\xcc\x9b\x1d\xb2i\xe0\xe9\x8b\x89\xa0\x8dE\xd8\x19k\xe1\x19\xa1\xa7\xa00FlA\xfa\x16\xd0=c\xdbb\x0b)@o\x87\xcex\x99\x02\xd5\x9c\xf7Rmd\x87\xa0\x07\xafv$\xfb\x1e)\x92\xe2\xdc\xb8>P\x02\xc1Y\xa1]*8+B,8gE4]\xac7\x7f\xc4\xda\x84f3\xc4\x14\x9c\xf9\x17\x1b\xd9\x9b\xa6\xa7\xb05-R\xf1C\x14at\xb2\x7f\x19\xb3\xf9&\x9dm\xb4o4I\x87\xbb@\x9bkl\x06\x14\xbc\xe4\xbci|\xb0\xc6'\x9e\xcd\x83\x93\xc6\x8b\x12\xf6\x9cm%-K\xc2\xacV\xbf\x0f^\x9bn \xf9l\x91\xb3\x1e\xde\xae\xe0\xe0\xb6~\xc0\xdd\x0dj9\xd8t\x83\xfd\xe32\x15%g\xf3\xd9;\xa9R\xa0o\xf9\xc8B\xf6\x80\xbbe(\xfa\xfa\x03\xa65\xc60\x90\xc2\xc3\xb0\xac`\x9a\xdf#-9\x8b\xb2\xe4lv\xf4'\xda\x1c\xf1%\xdd\xe3\xf9'\xc1\x19\xf3\xc6.$w\x06m\xfbQZ\xd3\xceD\x15\\\xd8*\xf9\xe4s\xd2\xff\xdb\xc4\x94y\x7f;&W\xaf\xcf>\xed\xc7Kh}7x\x95L\xf0s8\xb0\x02'\xfbO1\x91\xf1\xddg\xe3\x13\x92\x96\n\xf7\xe3~\xe4\x9c)\xd7f\xea\x13\xf3\xfb\xe0\x9c\xf4\xad8g\xac\xa6\x16\x89\x12\x90(P\xfe'\xb2\xe0\xbd\xec\xab<9\xad\xbcx\xcf\x9b\xaf\xa7\xefw\x14\xdc\xfa!\xb4\xf8\x8f5\n/8\xeb\xbf\x12\xbaXr\xc6\x8c\x9eX\xde\xac\xc0\x1b;\x913\xc24\x90\xcfc\xce\xd8\xc8\x19ke\x92SbG\xc5\x0e\xd3M\x1eRp\x97\xfb\x8a\x1fd\xf13r\x1f\xa5\x1d\xf0(\x97\xbbY\xdfK\x8a_\xa4\x15G7\xaf\xe3\xe3\x8ce\xc4j\xe9\xeeRZq\xd1\x9b\n\x8e\x9a\xaf#\x9d0\xa9\x82\xb0\x99J?3\x8b\xa5zO$}\xd4\x81\x1c\xd2\\\xc1\xf2]\x06N<\xb3\x95t\xc2\x88\xf9\xbf\xcc\xb2\xdf\xd3\xbd\x14\x9e\x94G@\x1b\x11\x8c\x86\xee\x05\x03\x1f\xd0#\xe5b\xffO\xfe\xbc8+\xe8\x0eH\x14?\xa3\xcf\xe7\x06^\x95\xe9@:K\xd4O\xe1\xacz\xaf\x0du\x19xc9\x1bK~8\xf3v\x05\xca\xb5\xf5\xedWTC\xf6\xfa\xee\x9aI\xbbT?\x92\xf1\xc9z\x81DY.\xc4\xfa\xf6\xabI\xe2\xf7\x92\xb3\x91\x8f\xd7\xcf\xda\xcb\x05\xd6\n\xce\xaei \xe2\xecW5\xdf\xc1\xe99\xd4\x87\xf0\xb5\xaa\xc5\xf7\xef\xf8\xbc\xc1\x9b%\xfc\xd3r\x15d\xc3\xb7\x99J\x8bB/\xfa\xa0\xe6\x17\xe3\xd7_\xb6`\"\xf8\x90`\x9b_\xa8\xa2\x02\xad\xa6-\x0e\x14\xfaS\x91\xfbZ|\xae\xa6\xa8F\xfe_\x00\x00\x00\xff\xffPK\x07\x08\xb5\xa26N\xb6\x02\x00\x00\xab\x06\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xc9\xa3yQ\xf6G\x8e3\x9e\x00\x00\x00\n\x01\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x00\x00\x00\x00go.mod.srcUT\x05\x00\x01\xda\xbe\xbe_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xe5\x8ewQ\xb5\xa26N\xb6\x02\x00\x00\xab\x06\x00\x00\x07\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdf\x00\x00\x00main.goUT\x05\x00\x01\x7f\xf7\xbb_PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x7f\x00\x00\x00\xd3\x03\x00\x00\x00\x00"
fs.Register(data)
}

View File

@@ -0,0 +1,20 @@
//nolint
package funcwrappersrc
import (
"sigs.k8s.io/kustomize/api/resmap"
)
type plugin struct{}
//noinspection GoUnusedGlobalVariable
var KustomizePlugin plugin
func (p *plugin) Config(
_ *resmap.PluginHelpers, _ []byte) (err error) {
return nil
}
func (p *plugin) Transform(_ resmap.ResMap) error {
return nil
}

View File

@@ -0,0 +1,12 @@
module main
go 1.15
require (
github.com/spf13/cobra v1.0.0
sigs.k8s.io/kustomize/api v0.6.4
sigs.k8s.io/kustomize/kyaml v0.9.3
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/api v0.6.4 => sigs.k8s.io/kustomize/api v0.0.0-20201120230733-052a6b4e967b

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