Compare commits

...

337 Commits

Author SHA1 Message Date
Natasha Sarkar
62f0dab2ac Merge pull request #4876 from KnVerey/new_token
Regenerate token and encrypt without newline (attempt 4)
2022-11-16 13:46:19 -06:00
Katrina Verey
d642b959cf Regenerate token and encrypt without newline 2022-11-16 14:36:33 -05:00
Natasha Sarkar
d49f6e17ad Merge pull request #4875 from KnVerey/new_token
Third try new token without newline
2022-11-16 13:25:32 -06:00
Katrina Verey
0de4e0ba11 Third try new token without newline 2022-11-16 14:24:20 -05:00
Natasha Sarkar
54569e4591 Merge pull request #4874 from KnVerey/token_again
New token, hopefully without trailing whitespace error
2022-11-16 13:12:49 -06:00
Katrina Verey
b2dc88447e New token, hopefully without trailing whitespace error 2022-11-16 14:11:40 -05:00
Anna Song
314b8fbefa Implement localizeFile() skeleton for patches (#4865)
* Implement localizeFile()

* Fix lint

* Address code review feedback

* Remove unnecessary String(), Error() with string formatters
* Remove processing of un-implemented methods
* Improve readability

* Remove unimplemented addLocalizeDir, hitsLocalizeDir

* Improve documentation

* Remove deprecated patchesJson6902 logic
2022-11-16 10:24:48 -08:00
Natasha Sarkar
c0840b6804 Merge pull request #4873 from KnVerey/new_token
Rotate token for cloud build
2022-11-16 10:58:14 -06:00
Katrina Verey
1eccbc4e30 Rotate token for cloud build 2022-11-16 11:54:33 -05:00
Anna Song
f79e16b352 Improve localizer readability (#4860)
* Replace '%s' with %q

* Change ambiguous cli-"Arg" suffix in func arg names

* Remove repetitive "loc" in names

* Apply readability changes to localizer

* Fix comment
2022-11-16 08:42:49 -08:00
Kubernetes Prow Robot
b20e611413 Merge pull request #4723 from koba1t/emit_a_warning_when_deprecated_fields_are_used
Emit a warning on build when deprecated fields are used
2022-11-16 08:32:50 -08:00
Kubernetes Prow Robot
e638e408b0 Merge pull request #4802 from oscr/the-the
grammar: replace all occurrences of "the the" with "the"
2022-11-16 08:22:48 -08:00
Anna Song
84bd402cc0 Fix RepoSpec query extraction (#4863)
* Clean query processing

* Improve readability

* Remove redundant code
* Add comment

* Return path literal when not parsable

* Handle url.Parse() error in future
2022-11-14 09:38:41 -08:00
Kubernetes Prow Robot
e724e25fec Merge pull request #4855 from koba1t/chore/add_koba1t_to_reviews
add koba1t to reviews
2022-11-10 14:22:09 -08:00
Anna Song
50e731a1d9 Implement localizer skeleton for kustomize localize (#4859)
* Add localizer outline

* Add localizer unit tests

* include previous change

* Add proper NewLocalizer, Localize unit tests

mock processKust

* Address code review feedback

* Make processKustFn public

* Remove mock testing
2022-11-10 09:24:54 -08:00
Anna Song
beb2825f82 Improve readability of ifc.Loader's Repo() method (#4857)
* Improve ldr Repo() method readability

* Change Repo() implementations and calls

* Improve readability of conditions in ldr.New()

* Fix details
2022-11-08 14:48:14 -08:00
Anna Song
6d9b54004e Address TODO in PR #4652 (#4856)
* Address TODO in PR #4652

* Improve readability
2022-11-08 13:51:01 -08:00
yugo kobayashi
1f04fd2f23 add koba1t to reviews 2022-11-07 18:40:54 +00:00
Kubernetes Prow Robot
6ffd22a1f1 Merge pull request #4854 from koba1t/fix/failed_lint_on_master
fix: failed lint on master
2022-11-07 10:16:18 -08:00
yugo kobayashi
3e6ede9645 fix_failed_lint_on_master 2022-11-04 07:12:46 +00:00
Kubernetes Prow Robot
14f3cea24f Merge pull request #4830 from summer-dev/update-swagto-v0.22.3
update kyaml's dependency swag to v0.22.3
2022-11-03 21:06:14 -07:00
sun min
f0f414d53a e2econtainerconfig test failure 2022-11-04 10:34:37 +08:00
sun min
f9d553689e update dependencies of libs using go workspace mode 2022-11-02 13:44:23 +08:00
summer-dev
69435e059a Merge branch 'kubernetes-sigs:master' into update-swagto-v0.22.3 2022-11-02 09:46:51 +08:00
Natasha Sarkar
997e6fcc63 fix TestRemoteLoad_LocalProtocol (#4844)
* remote load test fix

* fix spacing
2022-10-31 10:58:44 -07:00
Kubernetes Prow Robot
daf81df437 Merge pull request #4654 from aabouzaid/fix-krm-exec-function
fix: krm exec function working dir
2022-10-26 11:30:36 -07:00
Ahmed AbouZaid
3e447da6ef proposal v2.1 2022-10-22 03:16:41 +02:00
Ahmed AbouZaid
ea21b37d67 proposal v2 2022-10-22 03:16:41 +02:00
Ahmed AbouZaid
d29febecb7 Fix krm exec function working dir 2022-10-22 03:16:41 +02:00
Ahmed AbouZaid
1b1e6ccab0 Test transformers krm exec function 2022-10-22 03:16:41 +02:00
Kubernetes Prow Robot
7ee6dd551d Merge pull request #4733 from koba1t/feat/add_edit-fix_for_patchesStrategicMerge_to_patches
add `edit fix` for patchesStrategicMerge to patches
2022-10-21 14:57:57 -07:00
Kubernetes Prow Robot
ccb68aa881 Merge pull request #4820 from florianl/flo-preallocate
preallocate memory
2022-10-21 14:35:57 -07:00
sun min
1252e45576 update kyaml's go.mod and go.sum 2022-10-13 09:34:45 +08:00
summer-dev
19d163ca0f update kyaml's dependency swag to v0.22.3 2022-10-12 21:30:12 +08:00
Kubernetes Prow Robot
bf7a0f9004 Merge pull request #4805 from aibarbetta/fix-4717
[address #4717] Re-do create template/metadata when using includeTemplates if not present
2022-10-11 09:23:02 -07:00
Kubernetes Prow Robot
3b1a711cee Merge pull request #4826 from dvrkps/patch-1
update actions/checkout
2022-10-11 09:13:01 -07:00
Davor Kapsa
cd35e95560 update actions/checkout 2022-10-11 11:41:21 +02:00
Kubernetes Prow Robot
0a16b6cf40 Merge pull request #4808 from larsks/feature/no-hooks
Add support for helm --no-hooks flag
2022-10-10 11:51:22 -07:00
Agustina Barbetta
7b84613ad1 Use fewer labels to ease reading 2022-10-08 20:38:44 -03:00
Agustina Barbetta
d14dfb604c Use WrapPrefixf 2022-10-08 20:37:24 -03:00
Agustina Barbetta
acba8fff62 Update api/krusty/inlinelabels_test.go
Co-authored-by: Katrina Verey <kn.verey@gmail.com>
2022-10-08 20:18:57 -03:00
Lars Kellogg-Stedman
38da7ca15c Add support for helm --no-hooks flag
This commit adds the `skipHooks` option to the helm chart support in order
to  expose the --no-hooks flag introduced to Helm in [1].

Using Kustomize to inflate a Helm chart would in some situations result in
different results than using `helm install`. This is because `helm
template`, by default, will render chart tests in the `templates/test`
directory, which can lead to undesired resources in the output.

See [2] for additional discussion.

[1]: https://github.com/helm/helm/pull/6444
[2]: https://github.com/helm/helm/issues/6443

Signed-off-by: Lars Kellogg-Stedman <lars@oddbit.com>
2022-10-07 17:14:06 -04:00
Kubernetes Prow Robot
9ef7ba9c95 Merge pull request #4663 from johnmanjiro13/handle-error-of-remove-annotation
fix: handle error of remove annotations
2022-10-07 08:19:53 -07:00
johnmanjiro13
4e7f4bce7b feat: Wrap error 2022-10-07 18:14:59 +09:00
Kubernetes Prow Robot
f8f444d92a Merge pull request #4819 from annasong20/add-reviewer
Add annasong20@ to reviewers list
2022-10-06 09:23:54 -07:00
Florian Lehner
c2312c4018 kyaml/yaml: preallocate memory
Signed-off-by: Florian Lehner <dev@der-flo.net>
2022-10-06 05:38:18 +02:00
Florian Lehner
0fbaa2d0e8 kyaml/sets: preallocate memory
Signed-off-by: Florian Lehner <dev@der-flo.net>
2022-10-06 05:37:41 +02:00
Anna Song
ae20497fd3 Add myself to reviewers list 2022-10-05 16:16:10 -07:00
Dani Santos
506dc4f9fe migrate site content: contributing docs (#4709)
* migrate contributing docs

* modifies weight for ordering

* updates links and info based on feedback

* removes broken powershell link

* Update site/content/en/contribute/windows/_index.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* Update site/content/en/contribute/windows/_index.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* Update site/content/en/contribute/mac/_index.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* Update site/content/en/contribute/howitworks/_index.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* Update site/content/en/contribute/howitworks/_index.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* simplify build explanation

* removes windows docs

* removes community - duplicate

* update the tooling instructions

* point to proposal docs

* Update site/content/en/contribute/howitworks/_index.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>
2022-09-29 10:20:39 -07:00
Kubernetes Prow Robot
482e8930fc Merge pull request #4809 from ephesused/issue-4793
convert PrevIds to use apiVersion instead meta
2022-09-27 14:21:50 -07:00
Ed Overton
d37fabf876 convert PrevIds to use apiVersion instead meta
Since PrevIds uses only the apiVersion information from the metadata,
change the retrieval from the full meta to just the apiVersion.
2022-09-27 14:03:59 -04:00
Agustina Barbetta
eb1529b516 use %w to format errors 2022-09-25 09:19:31 -03:00
Agustina Barbetta
c750c0089d use fmt instead of errors 2022-09-25 09:07:47 -03:00
Agustina Barbetta
2b9ef61f88 error wraps for linter 2022-09-23 18:30:00 -03:00
Agustina Barbetta
344b257c1f add tests for other kinds 2022-09-23 15:54:25 -03:00
Agustina Barbetta
e2196d9bd1 separate template specific field specs and use in includeTemplates 2022-09-23 15:11:59 -03:00
Kubernetes Prow Robot
65aeefd281 Merge pull request #4806 from koba1t/chore/update_golangci-lint_v1.49.0
update golangci-lint version to v1.49.0
2022-09-23 10:00:26 -07:00
yugo kobayashi
6ce230f2b2 fix testcases on runfn_test.go 2022-09-23 07:26:19 +00:00
yugo kobayashi
401cf9579c update golangci-lint v1.49.0 2022-09-22 13:24:40 +00:00
Agustina Barbetta
4dcc040ec1 create template/metadata in includeTemplates if not present 2022-09-20 13:33:07 -03:00
Agustina Barbetta
662ccf1915 add test for resources with no template 2022-09-20 13:29:38 -03:00
Yunchi Luo
e62480d11c Rewrite remoteload_test integration tests (#4783)
* Better error message when git clone fails

* support file:// URLs

* rewrite remoteload_test

* lint and test fix

* fixes for kverey's comments

* document file:// remote load

* replace assert with require where appropriate

* add tests for file:// without git suffix

* fixes plus pr review from natasha

* fixes for review, lint

* revert changes to error handling

* fix skipped test
2022-09-19 09:13:18 -07:00
Oscar Utbult
88cf251ef7 grammar: replace all occurrences of "the the" with "the" 2022-09-17 22:28:56 +02:00
Kubernetes Prow Robot
d6e40a3f6c Merge pull request #4798 from annasong20/patch-1
Fix flaky
2022-09-16 10:23:21 -07:00
Anna Song
eb51117adf Fix flaky
Disable submodules and increase timeout to prevent `localize` test that uses testdata from flaking.
2022-09-15 18:05:25 -07:00
yugo kobayashi
0d68e0c7be add newline for fix.go 2022-09-12 17:56:11 +00:00
yugo kobayashi
7c2e8845ad fix test with t.Run() 2022-09-12 17:47:33 +00:00
Kubernetes Prow Robot
ce18530656 Merge pull request #4791 from caproven/fix-4790
Performance fix for fetching previous resource IDs
2022-09-12 09:51:25 -07:00
Christian Provenzano
ca71736140 Wrap error in exported func 2022-09-09 20:27:28 -04:00
Christian Provenzano
e7d5f665b8 Fix redundant rnode metadata parsing 2022-09-09 19:25:59 -04:00
Kubernetes Prow Robot
6c587c9542 Merge pull request #4770 from jihoon-seo/220824_Fix_broken_links
Fix broken links
2022-09-09 08:49:22 -07:00
Kubernetes Prow Robot
56a47bd901 Merge pull request #4758 from koba1t/feature/emit_a_warning_to_ignore_plugin
Emit a warning when using missing field in FunctionSpec
2022-09-09 08:35:23 -07:00
johnmanjiro13
a8c0be49ae fix: handle error of remove annotations 2022-09-05 16:27:59 +09:00
yugo kobayashi
e49bf52928 fix tests 2022-09-03 00:29:10 +00:00
yugo kobayashi
a54226e0a9 fix error handling 2022-09-03 00:29:10 +00:00
yugo kobayashi
f086269d6e be build fail when parse failed to FunctionSpec 2022-09-03 00:29:10 +00:00
yugo kobayashi
e2e9181bed add a warning to missing field in FunctionSpec 2022-09-03 00:29:10 +00:00
yugo kobayashi
21ee7f7125 Emit a warning when deprecated fields are used 2022-09-01 23:02:50 +00:00
yugo kobayashi
cbb61fc668 fix yaml in test 2022-09-01 22:41:24 +00:00
Kubernetes Prow Robot
23de1499c2 Merge pull request #4719 from oscr/remove-dot-from-short
Remove dots from short descriptions
2022-08-30 09:54:55 -07:00
Kubernetes Prow Robot
cb2636335f Merge pull request #4779 from annasong20/locloader
Reinstate #4652 without url-related code
2022-08-30 08:13:01 -07:00
Kubernetes Prow Robot
c266537b27 Merge pull request #4777 from mightyguava/repospec-unit-tests
expand and clean up repospec_test
2022-08-29 18:11:03 -07:00
Anna Song
f80cf9f433 Reinstate #4652 without url-related code
Remove code that changes remotes-loading code path, as mandated by #4756
2022-08-29 16:57:15 +00:00
yugo kobayashi
032bf3338e update checker code in patchStrategicMerge 2022-08-28 17:20:21 +00:00
yugo kobayashi
b4d25b1b26 add testcases 2022-08-28 15:45:47 +00:00
Yunchi Luo
d917876949 expand and clean up repospec_test 2022-08-27 14:30:10 -04:00
Kubernetes Prow Robot
14b7282ed8 Merge pull request #4775 from kubernetes-sigs/revert-4652-localize-file
Revert "Load and calculate Destination of files for `kustomize localize`"
2022-08-26 11:48:16 -07:00
Natasha Sarkar
8868d91670 Revert "Load and calculate Destination of files for kustomize localize (#4652)"
This reverts commit bf17fe1d8f.
2022-08-26 13:26:23 -05:00
Kubernetes Prow Robot
b6fae2a959 Merge pull request #4759 from mightyguava/enable-ssh-tests
Enable SSH tests
2022-08-26 09:14:25 -07:00
Kubernetes Prow Robot
a8388f473b Merge pull request #4773 from natasha41575/openapitests
run openapi tests with other krusty tests
2022-08-26 08:36:24 -07:00
natasha41575
08918ea352 run openapi tests with other krusty tests 2022-08-26 09:01:44 -05:00
Yunchi Luo
5dcbd35e40 Enable SSH tests 2022-08-25 16:57:21 -04:00
Kubernetes Prow Robot
2e2674fa24 Merge pull request #4727 from KnVerey/improve_fieldspec_errors
Improve invalid node kind errors
2022-08-25 12:44:07 -07:00
Jihoon Seo
170eca7c52 Fix broken links 2022-08-24 17:25:29 +09:00
Anna Song
bf17fe1d8f Load and calculate Destination of files for kustomize localize (#4652)
* Implement file localization for localize

Implement file localization for new command kustomize localize

* Patch file localization

Fix lint errors, address feedback, begin transition to file loader from
localizer

* Add Repo() to Loader

* Implement locLoader factory + cleanup

* Add domain to RepoSpec

Fix ssh relative url host parsing for non-github domain on the side

* Implement Load(), New(), Root(), Dst() for LocLoader

* Address repospec code review comments

* Address 1st round of code review feedback

* Address feedback #2

Removed localized path calculations to cover edge case and improve readability.

* Remove ldr Cleanup logging

* Address code review round #3

* Address code review feedback #4
2022-08-19 14:33:53 -07:00
Natasha Sarkar
a8010ac469 Merge pull request #4764 from KnVerey/update_go_yaml
Update internal go-yaml fork to v3.0.1
2022-08-17 16:45:50 -05:00
Katrina Verey
f66936f6bf Internalize forked code 2022-08-17 16:09:05 -04:00
Natasha Sarkar
eb54c97947 fix leading newline issue 2022-08-17 16:09:05 -04:00
Natasha Sarkar
b84885d5c4 tests for compactSeqIndent 2022-08-17 16:09:04 -04:00
Natasha Sarkar
298d977ee7 add defaultSeqIndent method 2022-08-17 16:09:04 -04:00
Natasha Sarkar
d5a2009d3f compact sequence indentation option 2022-08-17 16:09:04 -04:00
Katrina Verey
d0ae8fba13 Internal copy of go-yaml at f6f7691b1fdeb513f56608cd2c32c51f8194bf51 2022-08-17 16:09:03 -04:00
Katrina Verey
f8d1e778c7 Commit go.sum updates 2022-08-16 18:26:04 -04:00
Katrina Verey
1948af8190 Wrap an error and remove a nolint 2022-08-16 18:24:20 -04:00
Katrina Verey
79a9154cf8 Improve error message when namespace transformer is given invalid fieldspecs
Also remove invalid+ignored fieldspecs from the defaults
2022-08-16 18:18:44 -04:00
Robert Facciol
26fcafdb57 Getting started guide part 2 (#4748)
* rename overlays

* add further examples in first kustomization

* fix typo

* fix formatting

* fix typo

* fix formatting

* fix typos

* restore overlay names to production and staging in original content

* restore overlay names to production and staging in original content

* restore overlay names to production and staging in new content

* updated doc to use "you/your" vs "we/our", and updated to use US spelling

* fix capitalization

* Update site/content/en/docs/Getting started/first_kustomization.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* Update site/content/en/docs/Getting started/first_kustomization.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* add "patch:" for patches in kustomization, and add url link

* Update site/content/en/docs/Getting started/first_kustomization.md

Co-authored-by: Katrina Verey <kn.verey@gmail.com>

* fix typo

Co-authored-by: Katrina Verey <kn.verey@gmail.com>
2022-08-16 11:11:08 -07:00
Kubernetes Prow Robot
2ec4b971e9 Merge pull request #4754 from KnVerey/ioutil
Stop using deprecated ioutil functions
2022-08-16 09:15:08 -07:00
Kubernetes Prow Robot
1d44793d79 Merge pull request #4648 from sklirg/fix/example-readme-install-url
docs(examples): Fix URL to installation instructions in examples
2022-08-12 15:42:30 -07:00
Katrina Verey
55a37de686 Fix other linters on modified lines 2022-08-10 19:34:25 -04:00
Katrina Verey
f6b72077c8 Stop using deprecated ioutil functions 2022-08-10 18:22:46 -04:00
Katrina Verey
416eed97c4 Merge pull request #4753 from kubernetes-sigs/revert-4751-fix-4717
Revert "[address #4717] create template/metadata when using includeTemplates if not present"
2022-08-10 14:35:28 -04:00
Katrina Verey
5762794793 Revert "[address #4717] create template/metadata when using includeTemplates if not present" 2022-08-10 14:06:33 -04:00
Kubernetes Prow Robot
91e002a560 Merge pull request #4751 from aibarbetta/fix-4717
[address #4717] create template/metadata when using includeTemplates if not present
2022-08-10 11:00:26 -07:00
Agustina Barbetta
15545cc228 create template/metadata in includeTemplates if not present 2022-08-07 20:48:51 -03:00
yugo kobayashi
3f0c21304c refactor edit fix test cases 2022-08-06 20:34:16 +00:00
yugo kobayashi
bb7ebe029c support file path patch to patchesStrategicMerge 2022-08-06 20:28:48 +00:00
yugo kobayashi
64f42ea45f add edit-fix for patchesStrategicMerge to patches 2022-08-06 20:28:48 +00:00
Natasha Sarkar
1b0fe2a078 update openapi scripts to fetch protobuffer schemas (#4582)
* update openapi scripts to fetch protobuffer schema

* code review

* code review

* restore makeOpenApiInfoDotGo.sh

* code review
2022-08-05 15:00:32 -07:00
Natasha Sarkar
56d82a8378 Merge pull request #4745 from natasha41575/pinToApi
pin to api v0.12.1
2022-08-02 11:28:01 -05:00
natasha41575
39dbdddb86 pin api to v0.12.1 2022-08-02 11:18:51 -05:00
Natasha Sarkar
27a1de1a19 Merge pull request #4744 from natasha41575/pinToCmdConfig
pin to cmd/config 0.10.9
2022-08-02 10:52:46 -05:00
natasha41575
7229f5fbed pin to cmd/config 0.10.9 2022-08-02 10:46:18 -05:00
Natasha Sarkar
ba9d5ee16f Merge pull request #4743 from natasha41575/PinToKyaml
Pin to kyaml v0.13.9
2022-08-02 10:37:42 -05:00
natasha41575
001b0c5fe5 pin to kyaml v0.13.9 2022-08-02 10:20:35 -05:00
Natasha Sarkar
bbeff6ddd6 prevent testing lib from being compiled in (#4742)
* remove testing dep from fsondisk

* code review
2022-08-01 14:26:29 -07:00
Kubernetes Prow Robot
e57b5d283f Merge pull request #4739 from natasha41575/updateReleaseNum
update latest release number to 4.5.6
2022-07-29 14:21:12 -07:00
natasha41575
dbd719bd3f update latest release number to 4.5.6 2022-07-29 16:05:15 -05:00
Natasha Sarkar
29ca6935bd Merge pull request #4738 from natasha41575/pinToApi
pin to api v0.12.0
2022-07-29 15:32:26 -05:00
natasha41575
f5c70b3929 pin to api v0.12.0 2022-07-29 15:23:05 -05:00
Natasha Sarkar
b816903c93 Merge pull request #4737 from natasha41575/pinCmdConfig
pin cmd/config 0.10.8
2022-07-29 15:13:29 -05:00
natasha41575
d32fe662af pin cmd/config 0.10.8 2022-07-29 15:06:34 -05:00
Natasha Sarkar
4b5fbf2b80 Merge pull request #4736 from natasha41575/pinToKyaml
pin to kyaml v0.13.8
2022-07-29 14:51:55 -05:00
Kubernetes Prow Robot
283f8ae0a5 Merge pull request #4735 from natasha41575/statik
update statik
2022-07-29 12:47:12 -07:00
natasha41575
f6a1e4af3b pin to kyaml v0.13.8 2022-07-29 14:44:06 -05:00
Katrina Verey
e7fe132df8 Update netlify config (#4732)
* Update netlify config

* Update site/netlify.toml
2022-07-29 12:33:13 -07:00
natasha41575
631f623d9c update statik 2022-07-29 14:30:18 -05:00
Kubernetes Prow Robot
19c467a924 Merge pull request #4734 from natasha41575/goSum
update go.sum files
2022-07-29 11:51:13 -07:00
natasha41575
afa2b52807 merge go.sum files 2022-07-29 13:42:32 -05:00
Kubernetes Prow Robot
30843e2dac Merge pull request #4730 from KnVerey/env_bug_warning
Emit a warning when env loading bug is being relied on
2022-07-28 15:33:12 -07:00
Katrina Verey
2a3b645758 Emit a warning when env loading bug is being relied on 2022-07-28 18:04:48 -04:00
Kubernetes Prow Robot
b89cb92c2d Merge pull request #4729 from natasha41575/colonInFSName
allow colon in filenames
2022-07-28 13:13:11 -07:00
natasha41575
9a6aad3ae4 allow colon in filenames 2022-07-28 14:52:28 -05:00
Kubernetes Prow Robot
c4b4a41913 Merge pull request #4704 from KnVerey/ns_transformer_options
Option to customize NamespaceTransformer role binding subject handling
2022-07-28 08:27:11 -07:00
Katrina Verey
0c37ee89af Option to customize NamespaceTransfomer role binding subject handling 2022-07-27 23:12:55 -04:00
Kubernetes Prow Robot
6917214251 Merge pull request #4726 from AlexVulaj/update-install-kustomize-error-message
Update error message for m1 mac users trying to fetch older versions
2022-07-27 12:03:53 -07:00
Alex Vulaj
a3a3140e4c Update hack/install_kustomize.sh
update error message to be more descriptive

Co-authored-by: Natasha Sarkar <natashasarkar@google.com>
2022-07-27 14:30:07 -04:00
Alex Vulaj
d244c8a8bb Update error message for m1 mac users trying to fetch older versions 2022-07-27 13:54:04 -04:00
Oscar Utbult
d96e47cc38 Remove dots from short descriptions 2022-07-22 17:33:24 +02:00
Natasha Sarkar
2f2ba40876 replacements: fix issue with create: true option when there is an existing field (#4667)
* replacements: demonstrate broken behavior when using 'create: true' with an already existing field

* replacements: fix issue with 'create: true' option when there is an existing field

* Suggestion for PR 4667

* code review

* lint error

Co-authored-by: Katrina Verey <katrina.verey@shopify.com>
2022-07-15 14:31:49 -07:00
Kubernetes Prow Robot
ab09d27ec7 Merge pull request #4711 from koba1t/fix/docker_build_post-kustomize-push-images_with_dockerignore
[fix] failed docker build on post-kustomize-push-images CI
2022-07-14 14:00:40 -07:00
yugo kobayashi
5e95c6ab06 delete ./functionsfor .dockerignore 2022-07-14 20:35:25 +00:00
Katrina Verey
0c6e827ab8 Option to customize NamespaceTransformer overwrite behaviour (#4708)
* Option to customize NamespaceTransformer overwrite behaviour

* Code review feedback
2022-07-14 12:00:58 -07:00
Kubernetes Prow Robot
17cbd96667 Merge pull request #4705 from natasha41575/gowork
update release tools for go workspace mode
2022-07-11 17:56:51 -07:00
Kubernetes Prow Robot
0fce7d53a9 Merge pull request #4703 from KnVerey/name-ref-annotations
Fix NameReference transformer handling of self-references in annotations
2022-07-11 17:22:50 -07:00
Katrina Verey
68780b4c0c Fix flakey test 2022-07-11 20:03:13 -04:00
Katrina Verey
04e1663b70 appendCsVAnnotation must mutate the annotations RNode in place
Otherwise, it is incompatible with filters like fieldSpec.Filter that recurse through a tree of RNodes. In the case of the bug this commit fixes, the leaf RNode is a metadata.annotation value field, and appendCsvAnnotation is called immediately before updating that leaf's value. If appendCsvAnnotation replaces the entire metadata.annotation RNode on the resource, the leaf RNode that gets updated is no longer attached to the resource.

Alternatively, `func (f Filter) setScalar` could be updated to change
the value of the leaf RNode BEFORE calling appendCsvAnnotation. However,
the modification of the entire metadata segment of the RNode in a
function that nominally just edits an annotation feels like a
side-effect prone to creating other difficult-to-debug situations,
beyond this ordering dependency.
2022-07-11 19:58:49 -04:00
natasha41575
ba77fd5b7f update release tools for go workspace mode 2022-07-11 10:34:08 -07:00
Katrina Verey
77814ac12b NameReferenceTransformer misses self references in annotations 2022-07-08 22:07:15 -04:00
Kubernetes Prow Robot
e1b6aa393a Merge pull request #4692 from koba1t/chore/add_support_for_go_workspace_mode
[proposal] add support for go workspace mode
2022-07-08 10:29:47 -07:00
yugo kobayashi
3229c810cc restore require sigs.k8s.io/kustomize/* in go.mod 2022-07-08 16:58:01 +00:00
Kubernetes Prow Robot
344d0eec83 Merge pull request #4700 from KnVerey/ns_transformer_err_on_ambiguous_ns
Correctly detect ambiguity between potential referrers when targeting a name+namespace reference
2022-07-07 15:48:37 -07:00
Katrina Verey
387c95be1f Correctly detect ambiguity between potential referrers when targeting a name+namespace reference 2022-07-07 18:33:48 -04:00
yugo kobayashi
c02d0e502a go work sync 2022-07-07 21:00:43 +00:00
yugo kobayashi
5806c6f4f7 Merge remote-tracking branch 'origin' into chore/add_support_for_go_workspace_mode 2022-07-07 20:54:10 +00:00
yugo kobayashi
396b693e1c fix from lint error 2022-07-07 20:35:27 +00:00
Kubernetes Prow Robot
f95ea9e6a0 Merge pull request #4699 from koba1t/chore/update_go_1.18
Update to go 1.18
2022-07-07 13:32:38 -07:00
yugo kobayashi
8c4d35470a restore cloudbuild.yaml 2022-07-07 20:25:52 +00:00
yugo kobayashi
6fb96b7d53 update go 1.18 2022-07-07 20:11:29 +00:00
Kubernetes Prow Robot
ca01b49614 Merge pull request #4698 from koba1t/chore/update_functions_examples_and_e2econtainerconfig
Update kyaml in functions/examples and e2econtainerconfig
2022-07-07 12:28:38 -07:00
yugo kobayashi
4653f5d9d3 update e2econtainerconfig 2022-07-07 18:56:50 +00:00
yugo kobayashi
bd67fc2781 update kyaml in functions/examples 2022-07-07 18:51:12 +00:00
yugo kobayashi
17af5d518f rerun ci 2022-07-07 18:39:38 +00:00
yugo kobayashi
670cef4fd1 remove 'replace sigs.k8s.io/kustomize/*' and cleanup 2022-07-07 18:30:49 +00:00
yugo kobayashi
5c9adf248c fix error handling and delete comment to e2econtainerconfig/main.go 2022-07-07 16:10:14 +00:00
yugo kobayashi
fd847108cd refactor cmd/config/internal/commands/e2e 2022-07-06 16:03:47 +00:00
Kubernetes Prow Robot
d2ceab5f30 Merge pull request #4689 from Chever-John/doc/typo_error_first_kustomization
doc(first_kustomization): change the wrong command (I think)
2022-07-05 10:59:20 -07:00
Anna Song
86a84ca486 Address nits on localize proposal and correct mistakes (#4668)
* Address nits on #4590 and correct mistakes

* Flesh out remote target use case

Remove scope, add ref, add user story
2022-07-05 10:51:20 -07:00
yugo kobayashi
876ec8fa6b update to go 1.18 in github-action 2022-07-05 17:40:44 +00:00
yugo kobayashi
2145d1984f add missing test case 2022-07-05 02:53:32 +00:00
koba1t
92288a8a02 fix ci error 2022-07-05 06:40:30 +09:00
koba1t
a6449aa03f try to fix e2econtainer test 2022-07-05 03:44:56 +09:00
koba1t
9c827f5362 restore ./cmd/config/internal/commands/e2e/e2econtainerconfig 2022-07-02 15:54:48 +09:00
koba1t
e201dbb31a go work sync 2022-07-02 15:31:24 +09:00
koba1t
bc981fcbc3 merge upstream master 2022-07-02 15:18:26 +09:00
Kubernetes Prow Robot
8a729459aa Merge pull request #4694 from annasong20/add-loc-tdata-remote
Add `localize` test data with remote reference
2022-06-30 14:22:44 -07:00
Anna Song
d1102fb726 Move demandDirectoryRoot into kyaml/filesys (#4677)
* Move demandDirectoryRoot into kyaml/filesys

* Make root directory platform-agnostic

Support windows root directory. Dogfood own error package.

* Use cleaner windows support implementation

* Address feedback

* Address feedback x2

* Re-apply go.sum changes to avoid CI errors
2022-06-30 11:12:07 -07:00
Anna Song
edb6294741 Add kustomization with remote reference 2022-06-30 17:21:23 +00:00
koba1t
175c99f9f6 try to update cmd/config/internal/commands/e2e/e2econtainerconfig code 2022-06-30 05:06:34 +09:00
koba1t
20a93fdd12 update functions/examples/template-go-nginx code and update go1.18 2022-06-30 03:05:00 +09:00
koba1t
0421c9fb50 update functions/examples/injection-tshirt-sizes code 2022-06-30 01:48:58 +09:00
koba1t
8c8a2125b7 update all go.mod to go1.18 2022-06-29 05:14:33 +09:00
koba1t
f39f914a98 add many pkgs for go.work 2022-06-29 03:32:54 +09:00
koba1t
c583f4164c add support for go workspace mode 2022-06-28 23:42:56 +09:00
CheverJohn
6a7cecddd7 doc(first_kustomization): change the wrong command (I think) 2022-06-27 12:05:56 +08:00
Nuno Anselmo
d8efc15169 Adds commentary on expected/unexpected test output 2022-06-21 23:52:39 +01:00
Nuno Anselmo
86d48b2a95 Implements TestNamedspacedServiceAccounts with and without overlap 2022-06-21 23:07:54 +01:00
Davanum Srinivas
7e0fd02783 Switch github.com/xlab/treeprint to release tag : v1.1.0 (#4675)
* Switch github.com/xlab/treeprint to release tag : v1.1.0

Signed-off-by: Davanum Srinivas <davanum@gmail.com>

* fix test to reflect changes in the dependency

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2022-06-10 14:33:46 -07:00
Kubernetes Prow Robot
1c53932166 Merge pull request #4670 from prasadkatti/patch-1
Update broken links to glossary terms
2022-06-08 11:36:00 -07:00
Prasad Katti
721a905e13 Update broken links to glossary terms 2022-06-08 11:13:34 -07:00
Anna Song
3fdf88d10e Allow tests to only run locally (#4664)
* Allow tests to only run locally

Allow tests that are flaky or currently unsupported on the server to run locally

* Address feedback
2022-06-08 10:04:23 -07:00
Kubernetes Prow Robot
4b19643b36 Merge pull request #4661 from annasong20/fileloader-require
fileloader_test: Replace lengthy t.Fatalf with require
2022-06-01 16:35:48 -07:00
Anna Song
b0b6c962dc Replace lengthy t.Fatalf with require 2022-06-01 17:46:30 -04:00
Kubernetes Prow Robot
78191b45fb Merge pull request #4611 from unrolled/unrolled-4338-overview-and-installation
Migrate site content: overview and installation
2022-06-01 08:47:07 -07:00
Natasha Sarkar
37a403fc65 Merge pull request #4650 from natasha41575/releaseUpdate
unpin modules and update latest release to 4.5.5
2022-05-23 20:11:27 +00:00
natasha41575
fd7e170b69 unpin modules and update latest release to 4.5.5 2022-05-23 12:47:59 -07:00
Håkon Solbjørg
afc1815f3f docs(examples): Fix URL to installation instructions in examples 2022-05-23 12:06:04 +02:00
Natasha Sarkar
daa3e5e2c2 Merge pull request #4647 from natasha41575/increase_cpu
increase vm size for cloud build
2022-05-20 20:21:22 +00:00
natasha41575
12adc1ff95 increase vm size for cloud build 2022-05-20 13:20:58 -07:00
Natasha Sarkar
41283c4727 Merge pull request #4646 from natasha41575/pinToApi
Update api to v0.11.5
2022-05-20 19:34:52 +00:00
natasha41575
30740f87f1 Update api to v0.11.5 2022-05-20 12:26:43 -07:00
Natasha Sarkar
6c8db65a90 Merge pull request #4645 from natasha41575/pinToCmdConfig
Update cmd/config to v0.10.7
2022-05-20 19:14:52 +00:00
natasha41575
35b5b7554f Update cmd/config to v0.10.7 2022-05-20 12:03:17 -07:00
Natasha Sarkar
6395344bcb Merge pull request #4644 from natasha41575/pinToKyaml
Update kyaml to v0.13.7
2022-05-20 18:51:47 +00:00
natasha41575
4a3bb926c5 Update kyaml to v0.13.7 2022-05-20 11:43:49 -07:00
Kubernetes Prow Robot
ba5335cf48 Merge pull request #4635 from konrad945/master
Testing code leaked to production
2022-05-19 10:49:21 -07:00
Anna Song
03ac2e1ada Proposal for new command "kustomize localize" (#4590)
* Propose kustomize localize

Write mini KEP proposal for new command kustomize localize.

* Incomplete commit

* Update proposal based on Katrina's feedback

Changes are summarized in comments in PR

* Address feedback in comments
2022-05-15 10:28:17 -07:00
Cory Jacobsen
2e036c24c2 Migrate site content: overview and installation 2022-05-13 19:53:38 +00:00
Kubernetes Prow Robot
1cf5b00af8 Merge pull request #4639 from annasong20/document-no-ports
Document urls cannot specify ports
2022-05-13 09:43:48 -07:00
Anna Song
9097f7b5a6 Document urls cannot specify ports 2022-05-13 09:15:30 -07:00
Kubernetes Prow Robot
0c8174544f Merge pull request #4638 from annasong20/skip-more-flaky
Skip more flaky tests
2022-05-12 16:39:48 -07:00
Anna Song
a37572d193 Skip more flaky tests 2022-05-12 16:23:42 -07:00
konrad945
ba7315ca76 Update testing_test.go 2022-05-12 19:38:15 +02:00
konrad945
ddf768195c Rename testing.go to testing_test.go 2022-05-12 16:43:27 +02:00
konrad945
b11cc3ae67 Fix comments 2022-05-12 16:42:28 +02:00
Kubernetes Prow Robot
22668eae16 Merge pull request #4634 from unrolled/unrolled-4338-copyright
Update copyright to match k8s docs site
2022-05-11 11:31:03 -07:00
Cory Jacobsen
02eb788b78 Update copyright to match k8s docs site 2022-05-11 16:59:24 +00:00
Anna Song
41fb6915b3 Document remote files in remoteBuild.md (#4624)
* Add file to remote build spec

* Address PR feedback
2022-05-10 11:21:43 -07:00
Kubernetes Prow Robot
596519d3f2 Merge pull request #4631 from annasong20/localize-test
Add test directory for command localize
2022-05-10 11:13:43 -07:00
Kubernetes Prow Robot
d3d92157fa Merge pull request #4567 from mvgmb/master
Add support for remote OpenAPI schema
2022-05-10 11:01:43 -07:00
Anna Song
c83ebd9530 Add test directory for command localize
Create simple kustomization directory that `kustomize localize` can download as remote reference in test.
2022-05-10 10:58:33 -07:00
Kubernetes Prow Robot
c3b5d8fa19 Merge pull request #4629 from KnVerey/configure_templateparser
fn framework: bugfix for schema providers + configurable template extensions
2022-05-09 17:25:43 -07:00
Katrina Verey
7a773a3a48 Configure wrapcheck linter to recognize wrapping done by kyaml's errors package 2022-05-09 17:02:02 -04:00
Kubernetes Prow Robot
46d4934b68 Merge pull request #4606 from unrolled/unrolled-4338-config-site-setup
Configuring hugo settings to match cli-experimental settings
2022-05-06 12:13:04 -07:00
Kubernetes Prow Robot
d0ef2f70a1 Merge pull request #4627 from annasong20/remove-flaky-tests
Skip flaky tests
2022-05-06 11:31:04 -07:00
Anna Song
b8d2ff2afa Fix TODO comment syntax 2022-05-06 09:24:23 -07:00
Anna Song
7e0158e1e9 Skip flaky tests
Skip tests that behave reliably locally, but are flaky on macOS server.
2022-05-06 08:12:39 -07:00
Agustina Barbetta
5948f6aa63 [Address #3937] Add labels to template/metadata if includeTemplates is true (#4209)
* add labels in template/metadata by default

* update comment

* fix kustomization labels test

* Add spec/template/metadata/labels when includeTemplate is true

* remove unnecessary test changes

* add error wrap

* Revert "add error wrap"

This reverts commit 0a203df83edb90a400b35d5521487b984619e919.

* add error wrap at template fieldSpec merge
2022-05-05 11:24:22 -07:00
Kubernetes Prow Robot
496a962a53 Merge pull request #4615 from annasong20/add-remote-resource-tests
Fix Issue #4588
2022-05-05 10:30:21 -07:00
Anna Song
17b42a99f5 Skip ssh tests
Skip ssh tests and correct error msg that's different on server.
2022-05-05 09:26:44 -07:00
Anna Song
271f393218 Address feedback
Change asserts to, on fail, fail tests. Address feedback on previous commit. Enable ssh to check if server has ssh keys.
2022-05-04 18:54:12 -07:00
Anna Song
c0dc68d6e7 Add url tests
Write comprehensive suite of integration tests for remote resources, as specified by Issue #4588
2022-05-03 13:53:03 -07:00
annelausf
188e35fbfd Added code for fields with dots(.) in their names work as needed (#4591)
* Added code for fields with dots(.) in their names work as needed

Co-authored-by: sarjamil <sjamil@salesforce.com>

* Fixed imports

Co-authored-by: sarjamil <sjamil@salesforce.com>

* Removed comments

Co-authored-by: sarjamil <sjamil@salesforce.com>

* Fix filter method

Co-authored-by: sarjamil <sjamil@salesforce.com>

* Fixed failing tests

Co-authored-by: sarjamil <sjamil@salesforce.com>

* Remove comments

Add co-author to PR.

Co-authored-by: sarjamil <sjamil@salesforce.com>

* Add co-author to PR.

Co-authored-by: sarjamil sjamil@salesforce.com

Co-authored-by: sarjamil <sjamil@salesforce.com>
2022-05-02 14:30:33 -07:00
Kubernetes Prow Robot
233b6adf7e Merge pull request #4605 from m-Bilal/fix-4559
Fix kustomize 4.5.3+ breaking remote resources (4559)
2022-05-02 13:34:31 -07:00
Cory Jacobsen
41296b9814 Configuring hugo settings to match cli-experimental 2022-04-27 17:12:30 +00:00
Mohd Bilal
66e4e1582b fix kustomize 4.5.3+ breaking remote resources (4559) 2022-04-23 06:25:24 +00:00
Katrina Verey
2e230b4d4b Regression test and fix for APIs that satisfy ValidationSchemaProvider but not Validator 2022-04-22 17:19:49 -04:00
Katrina Verey
bcae65770a Configurable extensions for template parser 2022-04-21 18:28:13 -04:00
Mário Bezerra
d49e5aa5aa Add tests for remote OpenAPI schema 2022-04-20 00:03:22 -03:00
Mário Bezerra
94af647556 Add support for remote OpenAPI schema 2022-04-19 23:58:04 -03:00
Natasha Sarkar
9d5491c2e2 fix containerized function mounts issue (#4489)
* fix containerized function mounts issue

* skip path test on windows

* move test out of temp dir

* update tests to deal with new working dir restrictions

* code review
2022-04-18 14:25:50 -07:00
Natasha Sarkar
cf89eae804 openapi parsing performance improvement with protobuffer (#4568)
* update necessary dependencies

* update openapi test structure

* remove old swagger files and generate new ones

* use protobuffer to parse openapi for performance improvement
2022-04-18 11:10:43 -07:00
Eng Zer Jun
9452a031ba test: use T.TempDir to create temporary test directory (#4587)
* test: use `T.TempDir` to create temporary test directory

This commit replaces `ioutil.TempDir` with `t.TempDir` in tests. The
directory created by `t.TempDir` is automatically removed when the test
and all its subtests complete.

Prior to this commit, temporary directory created using `ioutil.TempDir`
needs to be removed manually by calling `os.RemoveAll`, which is omitted
in some tests. The error handling boilerplate e.g.
	defer func() {
		if err := os.RemoveAll(dir); err != nil {
			t.Fatal(err)
		}
	}
is also tedious, but `t.TempDir` handles this for us nicely.

Reference: https://pkg.go.dev/testing#T.TempDir
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestInit_noargs` on Windows

--- FAIL: TestInit_noargs (0.01s)
    testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestInit_noargs3136084632\001: The process cannot access the file because it is being used by another process.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestTreeCommandDefaultCurDir_files` on Windows

--- FAIL: TestTreeCommandDefaultCurDir_files (0.01s)
    testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestTreeCommandDefaultCurDir_files716679291\001: The process cannot access the file because it is being used by another process.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestCreateSetterCommand` on Windows

--- FAIL: TestCreateSetterCommand (13.27s)
    --- FAIL: TestCreateSetterCommand/add_replicas (1.45s)
        testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestCreateSetterCommandadd_replicas176222064\001\k8s-cli-487197005.yaml: The process cannot access the file because it is being used by another process.
    ...
    and all subtests
    ...

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestCreateSubstitutionCommand` on Windows

--- FAIL: TestCreateSubstitutionCommand (4.16s)
    --- FAIL: TestCreateSubstitutionCommand/substitution_replicas (1.30s)
        testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestCreateSubstitutionCommandsubstitution_replicas1352417113\001\k8s-cli-3183612276.yaml: The process cannot access the file because it is being used by another process.
    ...
    and all subtests
    ...

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestDeleteSetterCommand` on Windows

--- FAIL: TestDeleteSetterCommand (4.36s)
    --- FAIL: TestDeleteSetterCommand/delete_replicas (1.31s)
        testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestDeleteSetterCommanddelete_replicas3949811929\001\k8s-cli-957077271.yaml: The process cannot access the file because it is being used by another process.
    ...
    and all subtests
    ...

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestDeleteSubstitutionCommand` on Windows

--- FAIL: TestDeleteSubstitutionCommand (2.35s)
    --- FAIL: TestDeleteSubstitutionCommand/delete_only_subst_if_setter_has_same_name_-_long_ref (1.15s)
        testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestDeleteSubstitutionCommanddelete_only_subst_if_setter_has_same_name_-_long_ref2039728641\001\k8s-cli-1602861478.yaml: The process cannot access the file because it is being used by another process.
    ...
    and all subtests
    ...

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>

* test: fix `TestSetCommand` on Windows

--- FAIL: TestSetCommand (13.76s)
    --- FAIL: TestSetCommand/set_replicas (1.13s)
        testing.go:1090: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestSetCommandset_replicas3781384539\001\k8s-cli-1030344459.yaml: The process cannot access the file because it is being used by another process.
    ...
    and all subtests
    ...

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2022-04-18 09:32:41 -07:00
Dipto Chakrabarty
a464ed0c59 add tagsuffix to take image tag suffix (#4364)
* add tagsuffix to take image tag suffix

* add comments to warn about specifications

* add test and error handle

* fix indent

* update comment

* fix merge errors and return updates

* update image update and fix example

* fix yamls formats

remove tabs in yamls

fix space in image name

tag error in name

* fix spacing issue

format of yaml

set example as above

* spacing of spec in testing templates

* change to switch case
2022-04-14 10:00:47 -07:00
Kubernetes Prow Robot
ec212711d4 Merge pull request #4577 from koba1t/fix/replacement_wildcard_and_create_option_error_message
fix error message using replacement wildcard and create option
2022-04-13 13:44:46 -07:00
koba1t
2f2e14e953 fix lint error to nolint:goerr113 2022-04-13 12:43:35 +09:00
koba1t
ed72bb02d4 fix lint error 2022-04-13 05:20:53 +09:00
koba1t
02e0b38bb0 fix lint error 2022-04-13 05:09:52 +09:00
koba1t
01ab069bd2 fix error message 2022-04-13 04:55:21 +09:00
koba1t
cdc4a5083b fix lint error 2022-04-12 12:53:58 +09:00
koba1t
5e84de2a89 fix errror message using replacement wildcard and create option 2022-04-12 05:14:24 +09:00
Kubernetes Prow Robot
e5041bae6f Merge pull request #4576 from kubernetes-sigs/dependabot/github_actions/actions/setup-go-3
Bump actions/setup-go from 2 to 3
2022-04-11 10:14:06 -07:00
dependabot[bot]
0d600af35a Bump actions/setup-go from 2 to 3
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v2...v3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 01:05:22 +00:00
Kubernetes Prow Robot
0989b26098 Merge pull request #4571 from KnVerey/releaser_1.18
Install goreleaser into go 1.18 image for build
2022-04-07 14:11:23 -07:00
Jennifer Cwagenberg
7888aef305 Raise error for external generators or transformers (#4565)
* Raise error if duplicate orgids for external transformers or external generators are configured

* Remove output of resources in error message

* Remove trailing newline
2022-04-06 15:46:25 -07:00
Katrina Verey
fe604fd3d1 Install goreleaser into go 1.18 image for build 2022-04-06 15:51:37 -04:00
Kubernetes Prow Robot
4fc02497ae Merge pull request #4564 from KnVerey/rework_ci
Make CI much more effective
2022-04-06 12:36:26 -07:00
Katrina Verey
e96c38e3ab Use verbose mode in all test runs 2022-04-05 15:56:32 -04:00
Katrina Verey
29104d6fa9 Ignore XML in license header script 2022-04-05 15:03:13 -04:00
Katrina Verey
df57e196d8 more makefile cleanup 2022-04-05 14:55:50 -04:00
Katrina Verey
f3c825f550 Make sure build targets all install into Go bin 2022-04-05 14:40:33 -04:00
Katrina Verey
03c94eabb7 Base makefile and root makefile target for functions/examples 2022-04-05 14:37:18 -04:00
Katrina Verey
c071cdaedd More makefile cleanup 2022-04-05 14:31:17 -04:00
Katrina Verey
f68a0c50d9 less redundancy in presubmit 2022-04-04 20:50:56 -04:00
Katrina Verey
db34e923c5 rever meaning of verify kustomize target 2022-04-04 20:40:07 -04:00
Katrina Verey
df80b29694 Test other modules on all platforms 2022-04-04 20:14:49 -04:00
Katrina Verey
ea193328e3 Run all non plugin module builds 2022-04-04 19:23:08 -04:00
Katrina Verey
2d4bce5112 Do not run ineffective targets, do run all module tests 2022-04-04 18:13:00 -04:00
Katrina Verey
af06ae6b69 add kustomize module to tests that run on master 2022-04-04 17:47:33 -04:00
Katrina Verey
46875b6ac4 More makefile cleanup 2022-04-04 16:46:41 -04:00
Katrina Verey
0fa010c7e7 Add missing boilerplate 2022-04-04 14:24:04 -04:00
Katrina Verey
3e652d6fea Add helpful error message to license check 2022-04-04 14:22:24 -04:00
Katrina Verey
f54014ce3b Add latest to go install commands 2022-04-04 14:10:29 -04:00
Katrina Verey
08924dc2f5 Fix root var and add sanity check 2022-04-04 14:03:29 -04:00
Kubernetes Prow Robot
49c0ed1326 Merge pull request #4563 from turrisxyz/naveensrinivasan/set-permissions
Add permissions to GitHub actions
2022-04-01 15:18:09 -07:00
Katrina Verey
7440f974b8 Lint needs goimports 2022-04-01 18:02:15 -04:00
Katrina Verey
ab9b89213b Delete duplicate copies of the license template 2022-04-01 17:56:06 -04:00
Katrina Verey
9fc012cc4e Do not change what the presubmit does yet 2022-04-01 17:55:52 -04:00
Katrina Verey
877d72b10b Run license check in CI 2022-04-01 17:42:59 -04:00
Naveen
c743f13d0d Add permissions to GitHub actions
- Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions

Setting token permissions to read-only follows the principle of least privilege. This is important because attackers may use a compromised token with write access to push malicious code into the project.

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
2022-04-01 16:34:21 -05:00
Katrina Verey
0d32543ebd Makefiles for all modules 2022-04-01 17:31:34 -04:00
Kubernetes Prow Robot
28ee975948 Merge pull request #4543 from turrisxyz/dependabot
Included githubactions in the dependabot config
2022-04-01 09:44:46 -07:00
Katrina Verey
2a9adbeb1e Makefile cleanup 2022-03-31 19:02:19 -04:00
Kubernetes Prow Robot
672c751715 Merge pull request #4560 from KnVerey/go1.18-tools
Update and re-enable linters
2022-03-31 10:59:02 -07:00
Katrina Verey
d3a7b9008b Enable linting from specific rev in CI 2022-03-31 11:37:37 -04:00
Katrina Verey
b0d2e4bdcd Enable more linters for new code 2022-03-31 11:37:26 -04:00
Katrina Verey
71bf0d5d14 Update full linter list and enable some easily resolved new ones 2022-03-31 11:37:26 -04:00
Katrina Verey
0a9c5cb0cf Refactor to fix gocyclo complaint 2022-03-31 11:37:26 -04:00
Katrina Verey
ff4136b1a2 cmd/config linter updates 2022-03-31 11:37:26 -04:00
Katrina Verey
1567b96ed3 Replace protobuf dep flagged by linter as deprecated 2022-03-31 11:37:26 -04:00
Katrina Verey
14947e449b Address new linter complaints 2022-03-31 11:37:26 -04:00
Katrina Verey
b368b347d1 Replace deprecated linters 2022-03-30 17:57:49 -04:00
Katrina Verey
5c359bda28 Go 1.18 compatibility updates 2022-03-30 17:57:48 -04:00
Natasha Sarkar
c94b5d8f25 Merge pull request #4553 from natasha41575/unpin
unpin modules and test against latest release
2022-03-28 17:45:50 -07:00
natasha41575
b699204a9e unpin modules and test against latest release 2022-03-28 16:21:42 -07:00
Natasha Sarkar
cf3a452ddd Merge pull request #4552 from KnVerey/version-mismatch
Copy of go 1.18 created version mismatch, reverting for now
2022-03-28 16:06:20 -07:00
Katrina Verey
faad014f96 Copy of go 1.18 created version mismatch, reverting for now 2022-03-28 19:03:47 -04:00
Natasha Sarkar
8e46ef57be Merge pull request #4551 from KnVerey/pipe_fail
Debug exit 141 failure
2022-03-28 15:46:23 -07:00
Katrina Verey
458d48430a Debug exit 141 failure 2022-03-28 18:45:07 -04:00
Kubernetes Prow Robot
3cecdc6214 Merge pull request #4550 from KnVerey/pinToApi
Update api to api/v0.11.4
2022-03-28 15:37:41 -07:00
Katrina Verey
7cac778866 Update api to api/v0.11.4 2022-03-28 18:27:12 -04:00
Katrina Verey
0aa379c228 Merge pull request #4549 from KnVerey/pinToCmdConfig
Update cmd/config to v0.10.6
2022-03-28 18:08:01 -04:00
Kubernetes Prow Robot
cd0f9b0c5b Merge pull request #4548 from KnVerey/improve-logs
Improve logging for changelong builder
2022-03-28 15:07:41 -07:00
Katrina Verey
651f0c1097 Update cmd/config to v0.10.6 2022-03-28 17:57:06 -04:00
Katrina Verey
6348ea9515 Improve logging for changelong builder 2022-03-28 17:54:09 -04:00
Katrina Verey
4b64f1e0e8 Merge pull request #4547 from KnVerey/pinToKyaml
Update kyaml to v0.13.6
2022-03-28 17:25:47 -04:00
Katrina Verey
7306402cca Update kyaml to v0.13.6 2022-03-28 17:07:02 -04:00
Natasha Sarkar
485f7d44d9 Merge pull request #4537 from KnVerey/release-updates
Converge local and cloud gorelease scripts, improve release notes
2022-03-28 13:41:02 -07:00
Katrina Verey
9e57ab72fc Copy newer Go into goreleaser image 2022-03-28 16:29:24 -04:00
Natasha Sarkar
d17ef91d94 Merge pull request #4545 from film42/gt/add_missing_refs
Add more name refs to PodTemplate for ConfigMap and Secret
2022-03-28 13:21:55 -07:00
Garrett Thornburg
e97cecf9dc Add more name refs to PodTemplate for ConfigMap and Secret 2022-03-28 14:00:17 -06:00
Katrina Verey
5833f4ca80 Make Goreleaser use the tag passed to the script 2022-03-28 14:37:29 -04:00
Katrina Verey
e86c479690 Converge local and cloud gorelease scripts, improve release notes 2022-03-28 13:43:18 -04:00
Naveen
d082c75b65 Included githubactions in the dependabot config
This should help with keeping the GitHub actions updated on new releases. This will also help with keeping it secure.

Dependabot helps in keeping the supply chain secure https://docs.github.com/en/code-security/dependabot

GitHub actions up to date https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot

https://github.com/ossf/scorecard/blob/main/docs/checks.md#dependency-update-tool

Signed-off-by: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com>
2022-03-27 17:06:31 -05:00
Kubernetes Prow Robot
d2e59002ae Merge pull request #4538 from natasha41575/kubeopenapiupgrade
move to google/gnostic v0.5.7-v3refs
2022-03-25 15:37:58 -07:00
natasha41575
c857ff8371 move to google/gnostic v0.5.7-v3refs 2022-03-25 15:05:18 -07:00
Kubernetes Prow Robot
866e84059f Merge pull request #4541 from annasong20/bug4487
Added test for bug 4487: cannot parse keys with dots
2022-03-25 14:59:58 -07:00
Anna Song
497d2ee031 Added test for bug 4487: cannot parse keys with dots 2022-03-25 17:45:55 -04:00
Katrina Verey
c4febc59d5 Merge pull request #4536 from kubernetes-sigs/updateProwExamplesTarget
Test examples against latest release
2022-03-24 17:51:18 -04:00
Katrina Verey
19955e73ff Test examples against latest release 2022-03-24 17:32:17 -04:00
Katrina Verey
271bf31ce9 Merge pull request #4535 from KnVerey/unpinEverything
Back to development mode; unpin the modules
2022-03-24 17:31:12 -04:00
Katrina Verey
809182c6b6 Back to development mode; unpin the modules 2022-03-24 17:07:20 -04:00
Katrina Verey
0dd3d84104 Merge pull request #4531 from KnVerey/update-release-instr
Update release instructions for kubectl integration
2022-03-24 17:04:27 -04:00
Natasha Sarkar
de6b978491 Merge pull request #4534 from KnVerey/add-git-to-builder
Add git to image build docker step
2022-03-24 13:47:55 -07:00
Katrina Verey
8fa8e14eeb Add git to image build docker step 2022-03-24 16:42:39 -04:00
Natasha Sarkar
26b5e628cf Merge pull request #4533 from natasha41575/pinToApi
Pin to api v0.11.3
2022-03-24 13:36:04 -07:00
natasha41575
80853c61b8 Pin to api v0.11.3 2022-03-24 13:34:47 -07:00
Katrina Verey
7ff87ef5b9 Update release instructions for kubectl integration 2022-03-24 16:07:02 -04:00
589 changed files with 55670 additions and 152966 deletions

View File

@@ -1,7 +1,6 @@
.github
docs
examples
functions
hack
site
travis

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -6,6 +6,9 @@ on:
pull_request:
branches: [ master ]
permissions:
contents: read
jobs:
lint:
@@ -14,18 +17,21 @@ jobs:
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ^1.16
go-version: ^1.18
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Lint
run: ./hack/kyaml-pre-commit.sh
env:
KUSTOMIZE_DOCKER_E2E: false # don't need to do e2e tests for linting
run: make lint
- name: Verify boilerplate
run: make check-license
test-linux:
name: Test Linux
@@ -33,25 +39,16 @@ jobs:
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ^1.16
go-version: ^1.18
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Test kyaml
run: go test -cover ./...
working-directory: ./kyaml
- name: Test api
run: go test -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
working-directory: ./api
- name: Test cmd/config
run: go test -cover ./...
working-directory: ./cmd/config
- name: Test all modules
run: make test-unit-non-plugin
env:
KUSTOMIZE_DOCKER_E2E: true
@@ -61,25 +58,16 @@ jobs:
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ^1.16
go-version: ^1.18
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Test kyaml
run: go test -cover ./...
working-directory: ./kyaml
- name: Test api
run: go test -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
working-directory: ./api
- name: Test cmd/config
run: go test -cover ./...
working-directory: ./cmd/config
- name: Test all modules
run: make test-unit-non-plugin
env:
KUSTOMIZE_DOCKER_E2E: false # docker not installed on mac
@@ -89,25 +77,26 @@ jobs:
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ^1.16
go-version: ^1.18
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Test kyaml
run: go test -cover ./...
working-directory: ./kyaml
# TODO: uncomment once Windows tests are passing.
# - name: Test api
# run: go test -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
# working-directory: ./api
- name: Test cmd/config
run: go test -cover ./...
working-directory: ./cmd/config
env:
KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
# TODO (#4001): replace specific modules above with this once Windows tests are passing.
#- name: Test all modules
# run: make test-unit-non-plugin
# env:
# KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet

4
.gitignore vendored
View File

@@ -23,7 +23,11 @@
.bin
# Hugo site
publishedSite/
site/public/
site/resources/
site/.hugo_build.lock
**/node_modules/
# goreleaser artifacts
**/dist/

View File

@@ -1,50 +0,0 @@
run:
deadline: 5m
linters:
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
# - dogsled
- dupl
# - errcheck
# - funlen
# - gochecknoinits
- goconst
# - gocritic
- gocyclo
- gofmt
- goimports
- golint
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- lll
- misspell
- nakedret
# - scopelint
- staticcheck
- structcheck
# stylecheck demands that acronyms not be treated as words
# in camelCase, so JsonOp become JSONOp, etc. Yuck.
# - stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
# - whitespace
linters-settings:
dupl:
threshold: 400
lll:
line-length: 170
gocyclo:
min-complexity: 15
golint:
min-confidence: 0.85

138
.golangci.yml Normal file
View File

@@ -0,0 +1,138 @@
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
run:
deadline: 5m
linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
disable-all: true
enable:
- asciicheck
- bidichk
- bodyclose
- contextcheck
# - cyclop
- depguard
- dogsled
- dupl
- durationcheck
- errcheck
- errname
- errorlint
- exhaustive
# - exhaustivestruct
- exportloopref
# - forbidigo
- forcetypeassert
# - funlen
# - gci
- gochecknoglobals
- gochecknoinits
# - gocognit
- goconst
- gocritic
- gocyclo
# - godot
# - godox
# - goerr113
- gofmt
# - gofumpt
- goheader
- goimports
- gomnd
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- gosimple
- govet
# - ifshort # too many false positives
- importas
- ineffassign
# - ireturn
- lll
- makezero
- misspell
- nakedret
- nestif
- nilerr
# - nilnil
# - nlreturn
# - noctx
- nolintlint
# - paralleltest
- prealloc
- predeclared
- promlinter
- revive
- rowserrcheck
- sqlclosecheck
- staticcheck
# - stylecheck
- tagliatelle
- tenv
- testpackage
- thelper
- tparallel
- typecheck
- unconvert
- unparam
- unused
# - varnamelen
- wastedassign
- whitespace
- wrapcheck
# - wsl
- asasalint
- usestdlibvars
- interfacebloat
- logrlint
- reassign
linters-settings:
dupl:
threshold: 400
lll:
line-length: 170
gocyclo:
min-complexity: 30
revive:
rules:
- name: var-naming
arguments:
- [ "ID", "API", "JSON" ] # AllowList
- [ ] # DenyList
gomnd:
ignored-functions:
- os.WriteFile
gomoddirectives:
replace-local: true
gosec:
config:
G306: "0644"
wrapcheck:
ignoreSigs:
# defaults
- .Errorf(
- errors.New(
- errors.Unwrap(
- .Wrap(
- .Wrapf(
- .WithMessage(
- .WithMessagef(
- .WithStack(
# from kyaml's errors package
- .WrapPrefixf(
issues:
new-from-rev: c94b5d8f2 # enables us to enforce a larger set of linters for new code than pass on existing code
max-same-issues: 0
exclude-rules:
- linters:
- revive
text: "don't use leading"
- linters:
- staticcheck
text: "SA1019: kioutil.Legacy"

349
Makefile
View File

@@ -3,6 +3,8 @@
#
# Makefile for kustomize CLI and API.
LATEST_V4_RELEASE=v4.5.6
SHELL := /usr/bin/env bash
GOOS = $(shell go env GOOS)
GOARCH = $(shell go env GOARCH)
@@ -11,8 +13,6 @@ ifeq ($(MYGOBIN),)
MYGOBIN = $(shell go env GOPATH)/bin
endif
export PATH := $(MYGOBIN):$(PATH)
MODULES := '"cmd/config" "api/" "kustomize/" "kyaml/"'
LATEST_V4_RELEASE=v4.5.2
# Provide defaults for REPO_OWNER and REPO_NAME if not present.
# Typically these values would be provided by Prow.
@@ -24,48 +24,35 @@ ifndef REPO_NAME
REPO_NAME := "kustomize"
endif
.PHONY: all
all: install-tools verify-kustomize
.PHONY: verify-kustomize
verify-kustomize: \
lint-kustomize \
test-unit-kustomize-all \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-v4-release
# --- Plugins ---
include Makefile-plugins.mk
# The following target referenced by a file in
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
.PHONY: prow-presubmit-check
prow-presubmit-check: \
install-tools \
lint-kustomize \
test-unit-kustomize-all \
test-unit-cmd-all \
test-go-mod \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-v4-release
.PHONY: verify-kustomize-e2e
verify-kustomize-e2e: test-examples-e2e-kustomize
# --- Tool management ---
include Makefile-tools.mk
# Other builds in this repo might want a different linter version.
# Without one Makefile to rule them all, the different makes
# cannot assume that golanci-lint is at the version they want.
# This installs what kustomize wants to use.
$(MYGOBIN)/golangci-lint-kustomize:
rm -f $(CURDIR)/hack/golangci-lint
GOBIN=$(CURDIR)/hack go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.23.8
mv $(CURDIR)/hack/golangci-lint $(MYGOBIN)/golangci-lint-kustomize
.PHONY: install-tools
install-tools: \
install-local-tools \
install-out-of-tree-tools
$(MYGOBIN)/mdrip:
go install github.com/monopole/mdrip@v1.0.2
.PHONY: uninstall-tools
uninstall-tools: \
uninstall-local-tools \
uninstall-out-of-tree-tools
$(MYGOBIN)/stringer:
go get golang.org/x/tools/cmd/stringer
.PHONY: install-local-tools
install-local-tools: \
$(MYGOBIN)/gorepomod \
$(MYGOBIN)/k8scopy \
$(MYGOBIN)/pluginator
$(MYGOBIN)/goimports:
go get golang.org/x/tools/cmd/goimports
.PHONY: uninstall-local-tools
uninstall-local-tools:
rm -f $(MYGOBIN)/gorepomod
rm -f $(MYGOBIN)/k8scopy
rm -f $(MYGOBIN)/pluginator
# Build from local source.
$(MYGOBIN)/gorepomod:
@@ -82,173 +69,93 @@ $(MYGOBIN)/pluginator:
cd cmd/pluginator; \
go install .
# --- Build targets ---
# Build from local source.
$(MYGOBIN)/kustomize: build-kustomize-api
cd kustomize; \
go install .
.PHONY: install-tools
install-tools: \
$(MYGOBIN)/goimports \
$(MYGOBIN)/golangci-lint-kustomize \
$(MYGOBIN)/gorepomod \
$(MYGOBIN)/helmV3 \
$(MYGOBIN)/k8scopy \
$(MYGOBIN)/mdrip \
$(MYGOBIN)/pluginator \
$(MYGOBIN)/stringer
### Begin kustomize plugin rules.
#
# The rules to deal with builtin plugins are a bit
# complicated because
#
# - Every builtin plugin is a Go plugin -
# meaning it gets its own module directory
# (outside of the api module) with Go
# code in a 'main' package per Go plugin rules.
# - kustomize locates plugins using the
# 'apiVersion' and 'kind' fields from the
# plugin config file.
# - k8s wants CamelCase in 'kind' fields.
# - The module name (the last name in the path)
# must be the lowercased 'kind' of the
# plugin because Go and related tools
# demand lowercase in import paths, but
# allow CamelCase in file names.
# - the generated code must live in the api
# module (it's linked into the api).
# Where all generated builtin plugin code should go.
pGen=api/internal/builtins
# Where the builtin Go plugin modules live.
pSrc=plugin/builtin
_builtinplugins = \
AnnotationsTransformer.go \
ConfigMapGenerator.go \
IAMPolicyGenerator.go \
HashTransformer.go \
ImageTagTransformer.go \
LabelTransformer.go \
LegacyOrderTransformer.go \
NamespaceTransformer.go \
PatchJson6902Transformer.go \
PatchStrategicMergeTransformer.go \
PatchTransformer.go \
PrefixTransformer.go \
SuffixTransformer.go \
ReplacementTransformer.go \
ReplicaCountTransformer.go \
SecretGenerator.go \
ValueAddTransformer.go \
HelmChartInflationGenerator.go
# Maintaining this explicit list of generated files, and
# adding it as a dependency to a few targets, to assure
# they get recreated if deleted. The rules below on how
# to make them don't, by themselves, assure they will be
# recreated if deleted.
builtinplugins = $(patsubst %,$(pGen)/%,$(_builtinplugins))
# These rules are verbose, but assure that if a source file
# is modified, the corresponding generated file, and only
# that file, will be recreated.
$(pGen)/AnnotationsTransformer.go: $(pSrc)/annotationstransformer/AnnotationsTransformer.go
$(pGen)/ConfigMapGenerator.go: $(pSrc)/configmapgenerator/ConfigMapGenerator.go
$(pGen)/GkeSaGenerator.go: $(pSrc)/gkesagenerator/GkeSaGenerator.go
$(pGen)/HashTransformer.go: $(pSrc)/hashtransformer/HashTransformer.go
$(pGen)/ImageTagTransformer.go: $(pSrc)/imagetagtransformer/ImageTagTransformer.go
$(pGen)/LabelTransformer.go: $(pSrc)/labeltransformer/LabelTransformer.go
$(pGen)/LegacyOrderTransformer.go: $(pSrc)/legacyordertransformer/LegacyOrderTransformer.go
$(pGen)/NamespaceTransformer.go: $(pSrc)/namespacetransformer/NamespaceTransformer.go
$(pGen)/PatchJson6902Transformer.go: $(pSrc)/patchjson6902transformer/PatchJson6902Transformer.go
$(pGen)/PatchStrategicMergeTransformer.go: $(pSrc)/patchstrategicmergetransformer/PatchStrategicMergeTransformer.go
$(pGen)/PatchTransformer.go: $(pSrc)/patchtransformer/PatchTransformer.go
$(pGen)/PrefixTransformer.go: $(pSrc)/prefixtransformer/PrefixTransformer.go
$(pGen)/SuffixTransformer.go: $(pSrc)/suffixtransformer/SuffixTransformer.go
$(pGen)/ReplacementTransformer.go: $(pSrc)/replacementtransformer/ReplacementTransformer.go
$(pGen)/ReplicaCountTransformer.go: $(pSrc)/replicacounttransformer/ReplicaCountTransformer.go
$(pGen)/SecretGenerator.go: $(pSrc)/secretgenerator/SecretGenerator.go
$(pGen)/ValueAddTransformer.go: $(pSrc)/valueaddtransformer/ValueAddTransformer.go
$(pGen)/HelmChartInflationGenerator.go: $(pSrc)/helmchartinflationgenerator/HelmChartInflationGenerator.go
# The (verbose but portable) Makefile way to convert to lowercase.
toLowerCase = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
$(pGen)/%.go: $(MYGOBIN)/pluginator
@echo "generating $*"
( \
set -e; \
cd $(pSrc)/$(call toLowerCase,$*); \
go generate .; \
cd ../../../$(pGen); \
$(MYGOBIN)/goimports -w $*.go \
)
# Target is for debugging.
.PHONY: generate-kustomize-builtin-plugins
generate-kustomize-builtin-plugins: $(builtinplugins)
.PHONY: build-kustomize-external-go-plugin
build-kustomize-external-go-plugin:
./hack/buildExternalGoPlugins.sh ./plugin
.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: $(MYGOBIN)/golangci-lint-kustomize $(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 ./...
kustomize: $(MYGOBIN)/kustomize
# Used to add non-default compilation flags when experimenting with
# plugin-to-api compatibility checks.
.PHONY: build-kustomize-api
build-kustomize-api: $(builtinplugins)
cd api; go build ./...
build-kustomize-api: $(MYGOBIN)/goimports $(builtinplugins)
cd api; $(MAKE) build
.PHONY: generate-kustomize-api
generate-kustomize-api: $(MYGOBIN)/k8scopy
cd api; go generate ./...
generate-kustomize-api:
cd api; $(MAKE) 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"
cd api/krusty; OPENAPI_TEST=true go test -run TestCustomOpenAPIFieldFromComponentWithOverlays
# --- Verification targets ---
.PHONY: verify-kustomize-repo
verify-kustomize-repo: \
install-tools \
lint \
check-license \
test-unit-all \
build-non-plugin-all \
test-go-mod \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-v4-release
# The following target referenced by a file in
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
.PHONY: prow-presubmit-check
prow-presubmit-check: \
install-tools \
test-unit-kustomize-plugins \
test-go-mod \
build-non-plugin-all \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-v4-release
.PHONY: license
license: $(MYGOBIN)/addlicense
./hack/add-license.sh run
.PHONY: check-license
check-license: $(MYGOBIN)/addlicense
./hack/add-license.sh check
.PHONY: lint
lint: $(MYGOBIN)/golangci-lint $(MYGOBIN)/goimports $(builtinplugins)
./hack/for-each-module.sh "make lint"
.PHONY: test-unit-all
test-unit-all: \
test-unit-non-plugin \
test-unit-kustomize-plugins
# This target is used by our Github Actions CI to run unit tests for all non-plugin modules in multiple GOOS environments.
.PHONY: test-unit-non-plugin
test-unit-non-plugin:
./hack/for-each-module.sh "make test" "./plugin/*" 15
.PHONY: build-non-plugin-all
build-non-plugin-all:
./hack/for-each-module.sh "make build" "./plugin/*" 15
.PHONY: test-unit-kustomize-plugins
test-unit-kustomize-plugins:
./hack/testUnitKustomizePlugins.sh
.PHONY: test-unit-kustomize-cli
test-unit-kustomize-cli:
cd kustomize; go test ./...
.PHONY: test-unit-kustomize-all
test-unit-kustomize-all: \
test-unit-kustomize-api \
test-unit-kustomize-cli \
test-unit-kustomize-plugins
test-unit-cmd-all:
./hack/kyaml-pre-commit.sh
.PHONY: functions-examples-all
functions-examples-all:
for dir in $(abspath $(wildcard functions/examples/*/.)); do \
echo -e "\n---Running make tasks for function $$dir---"; \
set -e; \
cd $$dir; $(MAKE) all; \
done
test-go-mod:
./hack/check-go-mod.sh
./hack/for-each-module.sh "go list -m -json all > /dev/null && go mod tidy -v"
.PHONY:
test-examples-e2e-kustomize: $(MYGOBIN)/mdrip $(MYGOBIN)/kind
verify-kustomize-e2e: $(MYGOBIN)/mdrip $(MYGOBIN)/kind
( \
set -e; \
/bin/rm -f $(MYGOBIN)/kustomize; \
@@ -265,85 +172,13 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
test-examples-kustomize-against-v4-release: $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh v4@$(LATEST_V4_RELEASE)
# linux only.
# This is for testing an example plugin that
# uses kubeval for validation.
# Don't want to add a hard dependence in go.mod file
# to github.com/instrumenta/kubeval.
# Instead, download the binary.
$(MYGOBIN)/kubeval:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-$(GOOS)-$(GOARCH).tar.gz; \
tar xf kubeval-$(GOOS)-$(GOARCH).tar.gz; \
mv kubeval $(MYGOBIN); \
rm -rf $$d; \
)
# linux only.
# This is for testing an example plugin that uses helm to inflate a chart
# for subsequent kustomization.
# Don't want to add a hard dependence in go.mod file to helm.
# Instead, download the binaries.
$(MYGOBIN)/helmV2:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=helm-v2.13.1-$(GOOS)-$(GOARCH).tar.gz; \
wget https://storage.googleapis.com/kubernetes-helm/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv $(GOOS)-$(GOARCH)/helm $(MYGOBIN)/helmV2; \
rm -rf $$d \
)
# Helm V3 differs from helm V2; downloading it to provide coverage for the
# chart inflator plugin under helm v3.
$(MYGOBIN)/helmV3:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=helm-v3.6.3-$(GOOS)-$(GOARCH).tar.gz; \
wget https://get.helm.sh/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv $(GOOS)-$(GOARCH)/helm $(MYGOBIN)/helmV3; \
rm -rf $$d \
)
$(MYGOBIN)/kind:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(GOOS)-$(GOARCH); \
chmod +x ./kind; \
mv ./kind $(MYGOBIN); \
rm -rf $$d; \
)
# linux only.
$(MYGOBIN)/gh:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=gh_1.0.0_$(GOOS)_$(GOARCH).tar.gz; \
wget https://github.com/cli/cli/releases/download/v1.0.0/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv gh_1.0.0_$(GOOS)_$(GOARCH)/bin/gh $(MYGOBIN)/gh; \
rm -rf $$d \
)
# --- Cleanup targets ---
.PHONY: clean
clean: clean-kustomize-external-go-plugin
clean: clean-kustomize-external-go-plugin uninstall-tools
go clean --cache
rm -f $(builtinplugins)
rm -f $(MYGOBIN)/goimports
rm -f $(MYGOBIN)/golangci-lint-kustomize
rm -f $(MYGOBIN)/kustomize
rm -f $(MYGOBIN)/mdrip
rm -f $(MYGOBIN)/stringer
# Handle pluginator manually.
# rm -f $(MYGOBIN)/pluginator
# Nuke the site from orbit. It's the only way to be sure.
.PHONY: nuke

38
Makefile-modules.mk Normal file
View File

@@ -0,0 +1,38 @@
# Copyright 2022 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
MYGOBIN = $(shell go env GOBIN)
ifeq ($(MYGOBIN),)
MYGOBIN = $(shell go env GOPATH)/bin
endif
export PATH := $(MYGOBIN):$(PATH)
# only set this if not already set, so importing makefiles can override it
export KUSTOMIZE_ROOT ?= $(shell pwd | sed -E 's|(.*\/kustomize)/(.*)|\1|')
include $(KUSTOMIZE_ROOT)/Makefile-tools.mk
.PHONY: lint test fix fmt tidy vet build
lint: $(MYGOBIN)/golangci-lint
$(MYGOBIN)/golangci-lint \
-c $$KUSTOMIZE_ROOT/.golangci.yml \
--path-prefix $(shell pwd | sed -E 's|(.*\/kustomize)/(.*)|\2|') \
run ./...
test:
go test -v -timeout 45m -cover ./...
fix:
go fix ./...
fmt:
go fmt ./...
tidy:
go mod tidy
vet:
go vet ./...
build:
go build -v -o $(MYGOBIN) ./...

102
Makefile-plugins.mk Normal file
View File

@@ -0,0 +1,102 @@
# Copyright 2022 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
### Kustomize plugin rules.
#
# The rules to deal with builtin plugins are a bit
# complicated because
#
# - Every builtin plugin is a Go plugin -
# meaning it gets its own module directory
# (outside of the api module) with Go
# code in a 'main' package per Go plugin rules.
# - kustomize locates plugins using the
# 'apiVersion' and 'kind' fields from the
# plugin config file.
# - k8s wants CamelCase in 'kind' fields.
# - The module name (the last name in the path)
# must be the lowercased 'kind' of the
# plugin because Go and related tools
# demand lowercase in import paths, but
# allow CamelCase in file names.
# - the generated code must live in the api
# module (it's linked into the api).
# Where all generated builtin plugin code should go.
pGen=api/internal/builtins
# Where the builtin Go plugin modules live.
pSrc=plugin/builtin
_builtinplugins = \
AnnotationsTransformer.go \
ConfigMapGenerator.go \
IAMPolicyGenerator.go \
HashTransformer.go \
ImageTagTransformer.go \
LabelTransformer.go \
LegacyOrderTransformer.go \
NamespaceTransformer.go \
PatchJson6902Transformer.go \
PatchStrategicMergeTransformer.go \
PatchTransformer.go \
PrefixTransformer.go \
SuffixTransformer.go \
ReplacementTransformer.go \
ReplicaCountTransformer.go \
SecretGenerator.go \
ValueAddTransformer.go \
HelmChartInflationGenerator.go
# Maintaining this explicit list of generated files, and
# adding it as a dependency to a few targets, to assure
# they get recreated if deleted. The rules below on how
# to make them don't, by themselves, assure they will be
# recreated if deleted.
builtinplugins = $(patsubst %,$(pGen)/%,$(_builtinplugins))
# These rules are verbose, but assure that if a source file
# is modified, the corresponding generated file, and only
# that file, will be recreated.
$(pGen)/AnnotationsTransformer.go: $(pSrc)/annotationstransformer/AnnotationsTransformer.go
$(pGen)/ConfigMapGenerator.go: $(pSrc)/configmapgenerator/ConfigMapGenerator.go
$(pGen)/GkeSaGenerator.go: $(pSrc)/gkesagenerator/GkeSaGenerator.go
$(pGen)/HashTransformer.go: $(pSrc)/hashtransformer/HashTransformer.go
$(pGen)/ImageTagTransformer.go: $(pSrc)/imagetagtransformer/ImageTagTransformer.go
$(pGen)/LabelTransformer.go: $(pSrc)/labeltransformer/LabelTransformer.go
$(pGen)/LegacyOrderTransformer.go: $(pSrc)/legacyordertransformer/LegacyOrderTransformer.go
$(pGen)/NamespaceTransformer.go: $(pSrc)/namespacetransformer/NamespaceTransformer.go
$(pGen)/PatchJson6902Transformer.go: $(pSrc)/patchjson6902transformer/PatchJson6902Transformer.go
$(pGen)/PatchStrategicMergeTransformer.go: $(pSrc)/patchstrategicmergetransformer/PatchStrategicMergeTransformer.go
$(pGen)/PatchTransformer.go: $(pSrc)/patchtransformer/PatchTransformer.go
$(pGen)/PrefixTransformer.go: $(pSrc)/prefixtransformer/PrefixTransformer.go
$(pGen)/SuffixTransformer.go: $(pSrc)/suffixtransformer/SuffixTransformer.go
$(pGen)/ReplacementTransformer.go: $(pSrc)/replacementtransformer/ReplacementTransformer.go
$(pGen)/ReplicaCountTransformer.go: $(pSrc)/replicacounttransformer/ReplicaCountTransformer.go
$(pGen)/SecretGenerator.go: $(pSrc)/secretgenerator/SecretGenerator.go
$(pGen)/ValueAddTransformer.go: $(pSrc)/valueaddtransformer/ValueAddTransformer.go
$(pGen)/HelmChartInflationGenerator.go: $(pSrc)/helmchartinflationgenerator/HelmChartInflationGenerator.go
# The (verbose but portable) Makefile way to convert to lowercase.
toLowerCase = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
$(pGen)/%.go: $(MYGOBIN)/pluginator
@echo "generating $*"
( \
set -e; \
cd $(pSrc)/$(call toLowerCase,$*); \
go generate .; \
cd ../../../$(pGen); \
$(MYGOBIN)/goimports -w $*.go \
)
# Target is for debugging.
.PHONY: generate-kustomize-builtin-plugins
generate-kustomize-builtin-plugins: $(builtinplugins)
.PHONY: build-kustomize-external-go-plugin
build-kustomize-external-go-plugin:
./hack/buildExternalGoPlugins.sh ./plugin
.PHONY: clean-kustomize-external-go-plugin
clean-kustomize-external-go-plugin:
./hack/buildExternalGoPlugins.sh ./plugin clean

105
Makefile-tools.mk Normal file
View File

@@ -0,0 +1,105 @@
# Copyright 2022 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
GOLANGCI_LINT_VERSION=v1.49.0
MYGOBIN = $(shell go env GOBIN)
ifeq ($(MYGOBIN),)
MYGOBIN = $(shell go env GOPATH)/bin
endif
export PATH := $(MYGOBIN):$(PATH)
# determines whether to run tests that only behave locally; can be overridden by override variable
export IS_LOCAL = false
.PHONY: install-out-of-tree-tools
install-out-of-tree-tools: \
$(MYGOBIN)/goimports \
$(MYGOBIN)/golangci-lint \
$(MYGOBIN)/helmV3 \
$(MYGOBIN)/mdrip \
$(MYGOBIN)/stringer \
$(MYGOBIN)/goimports
.PHONY: uninstall-out-of-tree-tools
uninstall-out-of-tree-tools:
rm -f $(MYGOBIN)/goimports
rm -f $(MYGOBIN)/golangci-lint
rm -f $(MYGOBIN)/helmV3
rm -f $(MYGOBIN)/mdrip
rm -f $(MYGOBIN)/stringer
$(MYGOBIN)/golangci-lint:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
$(MYGOBIN)/mdrip:
go install github.com/monopole/mdrip@v1.0.2
$(MYGOBIN)/stringer:
go install golang.org/x/tools/cmd/stringer@latest
$(MYGOBIN)/goimports:
go install golang.org/x/tools/cmd/goimports@latest
$(MYGOBIN)/mdtogo:
go install sigs.k8s.io/kustomize/cmd/mdtogo@latest
$(MYGOBIN)/addlicense:
go install github.com/google/addlicense@latest
$(MYGOBIN)/statik:
go install github.com/rakyll/statik@latest
$(MYGOBIN)/goreleaser:
go install github.com/goreleaser/goreleaser@v0.179.0 # https://github.com/kubernetes-sigs/kustomize/issues/4542
$(MYGOBIN)/kind:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(GOOS)-$(GOARCH); \
chmod +x ./kind; \
mv ./kind $(MYGOBIN); \
rm -rf $$d; \
)
# linux only.
$(MYGOBIN)/gh:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=gh_1.0.0_$(GOOS)_$(GOARCH).tar.gz; \
wget https://github.com/cli/cli/releases/download/v1.0.0/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv gh_1.0.0_$(GOOS)_$(GOARCH)/bin/gh $(MYGOBIN)/gh; \
rm -rf $$d \
)
# linux only.
# This is for testing an example plugin that
# uses kubeval for validation.
# Don't want to add a hard dependence in go.mod file
# to github.com/instrumenta/kubeval.
# Instead, download the binary.
$(MYGOBIN)/kubeval:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-$(GOOS)-$(GOARCH).tar.gz; \
tar xf kubeval-$(GOOS)-$(GOARCH).tar.gz; \
mv kubeval $(MYGOBIN); \
rm -rf $$d; \
)
# Helm V3 differs from helm V2; downloading it to provide coverage for the
# chart inflator plugin under helm v3.
$(MYGOBIN)/helmV3:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=helm-v3.6.3-$(GOOS)-$(GOARCH).tar.gz; \
wget https://get.helm.sh/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv $(GOOS)-$(GOARCH)/helm $(MYGOBIN)/helmV3; \
rm -rf $$d \
)

View File

@@ -11,6 +11,8 @@ aliases:
- knverey
- natasha41575
- yuwenma
- annasong20
- koba1t
kyaml-approvers:
- mengqiy

13
api/Makefile Normal file
View File

@@ -0,0 +1,13 @@
# Copyright 2022 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
include ../Makefile-modules.mk
test:
go test -v -timeout 45m -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
build:
go build -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222" ./...
generate: $(MYGOBIN)/k8scopy $(MYGOBIN)/stringer
go generate ./...

View File

@@ -285,7 +285,7 @@ spec:
t.Run(tn, func(t *testing.T) {
filter := tc.filter
filter.WithMutationTracker(tc.setEntryCallback)
filter.FsSlice = append(annosFs, tc.fsslice...)
filter.FsSlice = append(annosFs, tc.fsslice...) //nolint:gocritic
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filters
// Package filters collects various implementations

View File

@@ -8,10 +8,10 @@ import (
"strings"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/utils"
"sigs.k8s.io/kustomize/kyaml/yaml"
)

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filtersutil
import (
@@ -9,13 +12,13 @@ type SetFn func(*yaml.RNode) error
// SetScalar returns a SetFn to set a scalar value
func SetScalar(value string) SetFn {
return func(node *yaml.RNode) error {
return node.PipeE(yaml.FieldSetter{StringValue: value})
}
return SetEntry("", value, yaml.NodeTagEmpty)
}
// SetEntry returns a SetFn to set an entry in a map
func SetEntry(key, value, tag string) SetFn {
// SetEntry returns a SetFn to set a field or a map entry to a value.
// It can be used with an empty name to set both a value and a tag on a scalar node.
// When setting only a value on a scalar node, use SetScalar instead.
func SetEntry(name, value, tag string) SetFn {
n := &yaml.Node{
Kind: yaml.ScalarNode,
Value: value,
@@ -23,7 +26,7 @@ func SetEntry(key, value, tag string) SetFn {
}
return func(node *yaml.RNode) error {
return node.PipeE(yaml.FieldSetter{
Name: key,
Name: name,
Value: yaml.NewRNode(n),
})
}
@@ -31,36 +34,72 @@ func SetEntry(key, value, tag string) SetFn {
type TrackableSetter struct {
// SetValueCallback will be invoked each time a field is set
setValueCallback func(key, value, tag string, node *yaml.RNode)
setValueCallback func(name, value, tag string, node *yaml.RNode)
}
// WithMutationTracker registers a callback which will be invoked each time a field is mutated
func (s *TrackableSetter) WithMutationTracker(callback func(key, value, tag string, node *yaml.RNode)) {
func (s *TrackableSetter) WithMutationTracker(callback func(key, value, tag string, node *yaml.RNode)) *TrackableSetter {
s.setValueCallback = callback
return s
}
// SetScalar returns a SetFn to set a scalar value
// SetScalar returns a SetFn to set a scalar value.
// if a mutation tracker has been registered, the tracker will be invoked each
// time a scalar is set
func (s TrackableSetter) SetScalar(value string) SetFn {
origSetScalar := SetScalar(value)
return s.SetEntry("", value, yaml.NodeTagEmpty)
}
// SetScalarIfEmpty returns a SetFn to set a scalar value only if it isn't already set.
// If a mutation tracker has been registered, the tracker will be invoked each
// time a scalar is actually set.
func (s TrackableSetter) SetScalarIfEmpty(value string) SetFn {
return s.SetEntryIfEmpty("", value, yaml.NodeTagEmpty)
}
// SetEntry returns a SetFn to set a field or a map entry to a value.
// It can be used with an empty name to set both a value and a tag on a scalar node.
// When setting only a value on a scalar node, use SetScalar instead.
// If a mutation tracker has been registered, the tracker will be invoked each
// time an entry is set.
func (s TrackableSetter) SetEntry(name, value, tag string) SetFn {
origSetEntry := SetEntry(name, value, tag)
return func(node *yaml.RNode) error {
if s.setValueCallback != nil {
s.setValueCallback("", value, "", node)
s.setValueCallback(name, value, tag, node)
}
return origSetScalar(node)
return origSetEntry(node)
}
}
// SetEntry returns a SetFn to set an entry in a map
// if a mutation tracker has been registered, the tracker will be invoked each
// time an entry is set
func (s TrackableSetter) SetEntry(key, value, tag string) SetFn {
// SetEntryIfEmpty returns a SetFn to set a field or a map entry to a value only if it isn't already set.
// It can be used with an empty name to set both a value and a tag on a scalar node.
// When setting only a value on a scalar node, use SetScalar instead.
// If a mutation tracker has been registered, the tracker will be invoked each
// time an entry is actually set.
func (s TrackableSetter) SetEntryIfEmpty(key, value, tag string) SetFn {
origSetEntry := SetEntry(key, value, tag)
return func(node *yaml.RNode) error {
if hasExistingValue(node, key) {
return nil
}
if s.setValueCallback != nil {
s.setValueCallback(key, value, tag, node)
}
return origSetEntry(node)
}
}
func hasExistingValue(node *yaml.RNode, key string) bool {
if node.IsNilOrEmpty() {
return false
}
if err := yaml.ErrorIfInvalid(node, yaml.ScalarNode); err == nil {
return yaml.GetValue(node) != ""
}
entry := node.Field(key)
if entry.IsNilOrEmpty() {
return false
}
return yaml.GetValue(entry.Value) != ""
}

View File

@@ -0,0 +1,108 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filtersutil_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func TestTrackableSetter_SetScalarIfEmpty(t *testing.T) {
tests := []struct {
name string
input *yaml.RNode
value string
want string
}{
{
name: "sets null values",
input: yaml.MakeNullNode(),
value: "foo",
want: "foo",
},
{
name: "sets empty values",
input: yaml.NewScalarRNode(""),
value: "foo",
want: "foo",
},
{
name: "does not overwrite values",
input: yaml.NewStringRNode("a"),
value: "foo",
want: "a",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
wasSet := false
s := (&filtersutil.TrackableSetter{}).WithMutationTracker(func(_, _, _ string, _ *yaml.RNode) {
wasSet = true
})
wantSet := tt.value == tt.want
fn := s.SetScalarIfEmpty(tt.value)
require.NoError(t, fn(tt.input))
assert.Equal(t, tt.want, yaml.GetValue(tt.input))
assert.Equal(t, wantSet, wasSet, "tracker invoked even though value was not changed")
})
}
}
func TestTrackableSetter_SetEntryIfEmpty(t *testing.T) {
tests := []struct {
name string
input *yaml.RNode
key string
value string
want string
}{
{
name: "sets empty values",
input: yaml.NewMapRNode(&map[string]string{"setMe": ""}),
key: "setMe",
value: "foo",
want: "foo",
},
{
name: "sets missing keys",
input: yaml.NewMapRNode(&map[string]string{}),
key: "setMe",
value: "foo",
want: "foo",
},
{
name: "does not overwrite values",
input: yaml.NewMapRNode(&map[string]string{"existing": "original"}),
key: "existing",
value: "foo",
want: "original",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
wasSet := false
s := (&filtersutil.TrackableSetter{}).WithMutationTracker(func(_, _, _ string, _ *yaml.RNode) {
wasSet = true
})
wantSet := tt.value == tt.want
fn := s.SetEntryIfEmpty(tt.key, tt.value, "")
require.NoError(t, fn(tt.input))
assert.Equal(t, tt.want, yaml.GetValue(tt.input.Field(tt.key).Value))
assert.Equal(t, wantSet, wasSet, "tracker invoked even though value was not changed")
})
}
}
func TestTrackableSetter_SetEntryIfEmpty_BadInputNodeKind(t *testing.T) {
fn := filtersutil.TrackableSetter{}.SetEntryIfEmpty("foo", "false", yaml.NodeTagBool)
rn := yaml.NewListRNode("nope")
rn.AppendToFieldPath("dummy", "path")
assert.EqualError(t, fn(rn), `wrong node kind: expected MappingNode but got SequenceNode: node contents:
- nope
`)
}

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package gkesagenerator contains a kio.Filter that that generates a
// iampolicy-related resources for a given cloud provider
package iampolicygenerator

View File

@@ -43,7 +43,7 @@ metadata:
f.IAMPolicyGenerator.KubernetesService.Name)
if f.IAMPolicyGenerator.Namespace != "" {
input = input + fmt.Sprintf("\n namespace: %s", f.IAMPolicyGenerator.Namespace)
input += fmt.Sprintf("\n namespace: %s", f.IAMPolicyGenerator.Namespace)
}
sa, err := yaml.Parse(input)

View File

@@ -840,6 +840,45 @@ spec:
},
},
},
"updateimagesuffix": {
input: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploysuffix
spec:
template:
spec:
containers:
- image: redis:6.2.6
name: redis
`,
expectedOutput: `
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploysuffix
spec:
template:
spec:
containers:
- image: redis:6.2.6-alpine
name: redis
`,
filter: Filter{
ImageTag: types.Image{
Name: "redis",
TagSuffix: "-alpine",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/template/spec/containers[]/image",
},
},
},
}
for tn, tc := range testCases {

View File

@@ -6,6 +6,7 @@ package imagetag
import (
"sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
@@ -81,9 +82,7 @@ func (f findFieldsFilter) walk(node *yaml.RNode) error {
return nil
})
case yaml.SequenceNode:
return node.VisitElements(func(n *yaml.RNode) error {
return f.walk(n)
})
return errors.Wrap(node.VisitElements(f.walk))
}
return nil
}

View File

@@ -5,6 +5,7 @@ package imagetag
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/image"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -36,15 +37,19 @@ func (u imageTagUpdater) SetImageValue(rn *yaml.RNode) error {
}
// overriding tag or digest will replace both original tag and digest values
if u.ImageTag.NewTag != "" && u.ImageTag.Digest != "" {
switch {
case u.ImageTag.NewTag != "" && u.ImageTag.Digest != "":
tag = u.ImageTag.NewTag
digest = u.ImageTag.Digest
} else if u.ImageTag.NewTag != "" {
case u.ImageTag.NewTag != "":
tag = u.ImageTag.NewTag
digest = ""
} else if u.ImageTag.Digest != "" {
case u.ImageTag.Digest != "":
tag = ""
digest = u.ImageTag.Digest
case u.ImageTag.TagSuffix != "":
tag += u.ImageTag.TagSuffix
digest = ""
}
// build final image name

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package nameref contains a kio.Filter implementation of the kustomize
// name reference transformer.
package nameref

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package nameref
import (
@@ -115,7 +118,9 @@ func (f Filter) setMapping(node *yaml.RNode) error {
return err
}
oldName := nameNode.YNode().Value
referral, err := f.selectReferral(oldName, candidates)
// use allNamesAndNamespacesAreTheSame to compare referral candidates for functional identity,
// because we source both name and namespace values from the referral in this case.
referral, err := f.selectReferral(oldName, candidates, allNamesAndNamespacesAreTheSame)
if err != nil || referral == nil {
// Nil referral means nothing to do.
return err
@@ -164,8 +169,10 @@ func (f Filter) filterMapCandidatesByNamespace(
}
func (f Filter) setScalar(node *yaml.RNode) error {
// use allNamesAreTheSame to compare referral candidates for functional identity,
// because we only source the name from the referral in this case.
referral, err := f.selectReferral(
node.YNode().Value, f.ReferralCandidates.Resources())
node.YNode().Value, f.ReferralCandidates.Resources(), allNamesAreTheSame)
if err != nil || referral == nil {
// Nil referral means nothing to do.
return err
@@ -308,7 +315,9 @@ func (f Filter) sameCurrentNamespaceAsReferrer() sieveFunc {
func (f Filter) selectReferral(
// The name referral that may need to be updated.
oldName string,
candidates []*resource.Resource) (*resource.Resource, error) {
candidates []*resource.Resource,
// function that returns whether two referrals are identical for the purposes of the transformation
candidatesIdentical func(resources []*resource.Resource) bool) (*resource.Resource, error) {
candidates = doSieve(candidates, previousNameMatches(oldName))
candidates = doSieve(candidates, previousIdSelectedByGvk(&f.ReferralTarget))
candidates = doSieve(candidates, f.roleRefFilter())
@@ -323,24 +332,21 @@ func (f Filter) selectReferral(
if len(candidates) == 0 {
return nil, nil
}
if allNamesAreTheSame(candidates) {
if candidatesIdentical(candidates) {
// Just take the first one.
return candidates[0], nil
}
ids := getIds(candidates)
f.failureDetails(candidates)
return nil, fmt.Errorf(" found multiple possible referrals: %s", ids)
return nil, fmt.Errorf("found multiple possible referrals: %s\n%s", ids, f.failureDetails(candidates))
}
func (f Filter) failureDetails(resources []*resource.Resource) {
fmt.Printf(
"\n**** Too many possible referral targets to referrer:\n%s\n",
f.Referrer.MustYaml())
func (f Filter) failureDetails(resources []*resource.Resource) string {
msg := strings.Builder{}
msg.WriteString(fmt.Sprintf("\n**** Too many possible referral targets to referrer:\n%s\n", f.Referrer.MustYaml()))
for i, r := range resources {
fmt.Printf(
"--- possible referral %d:\n%s", i, r.MustYaml())
fmt.Println("------")
msg.WriteString(fmt.Sprintf("--- possible referral %d:\n%s\n", i, r.MustYaml()))
}
return msg.String()
}
func allNamesAreTheSame(resources []*resource.Resource) bool {
@@ -353,6 +359,17 @@ func allNamesAreTheSame(resources []*resource.Resource) bool {
return true
}
func allNamesAndNamespacesAreTheSame(resources []*resource.Resource) bool {
name := resources[0].GetName()
namespace := resources[0].GetNamespace()
for i := 1; i < len(resources); i++ {
if name != resources[i].GetName() || namespace != resources[i].GetNamespace() {
return false
}
}
return true
}
func getIds(rs []*resource.Resource) string {
var result []string
for _, r := range rs {

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package nameref
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package nameref
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package nameref
import (

View File

@@ -7,6 +7,7 @@ import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -19,9 +20,28 @@ type Filter struct {
// FsSlice contains the FieldSpecs to locate the namespace field
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
// UnsetOnly means only blank namespace fields will be set
UnsetOnly bool `json:"unsetOnly" yaml:"unsetOnly"`
// SetRoleBindingSubjects determines which subject fields in RoleBinding and ClusterRoleBinding
// objects will have their namespace fields set. Overrides field specs provided for these types, if any.
// - defaultOnly (default): namespace will be set only on subjects named "default".
// - allServiceAccounts: namespace will be set on all subjects with "kind: ServiceAccount"
// - none: all subjects will be skipped.
SetRoleBindingSubjects RoleBindingSubjectMode `json:"setRoleBindingSubjects" yaml:"setRoleBindingSubjects"`
trackableSetter filtersutil.TrackableSetter
}
type RoleBindingSubjectMode string
const (
DefaultSubjectsOnly RoleBindingSubjectMode = "defaultOnly"
SubjectModeUnspecified RoleBindingSubjectMode = ""
AllServiceAccountSubjects RoleBindingSubjectMode = "allServiceAccounts"
NoSubjects RoleBindingSubjectMode = "none"
)
var _ kio.Filter = Filter{}
var _ kio.TrackableFilter = &Filter{}
@@ -36,47 +56,38 @@ func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
// Run runs the filter on a single node rather than a slice
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
// hacks for hardcoded types -- :(
if err := ns.hacks(node); err != nil {
// Special handling for metadata.namespace -- :(
// never let SetEntry handle metadata.namespace--it will incorrectly include cluster-scoped resources
ns.FsSlice = ns.removeMetaNamespaceFieldSpecs(ns.FsSlice)
gvk := resid.GvkFromNode(node)
if err := ns.metaNamespaceHack(node, gvk); err != nil {
return nil, err
}
// Remove the fieldspecs that are for hardcoded fields. The fieldspecs
// exist for backwards compatibility with other implementations
// of this transformation.
// This implementation of the namespace transformation
// Does not use the fieldspecs for implementing cases which
// require hardcoded logic.
ns.FsSlice = ns.removeFieldSpecsForHacks(ns.FsSlice)
// Special handling for (cluster) role binding subjects -- :(
if isRoleBinding(gvk.Kind) {
ns.FsSlice = ns.removeRoleBindingSubjectFieldSpecs(ns.FsSlice)
if err := ns.roleBindingHack(node); err != nil {
return nil, err
}
}
// transformations based on data -- :)
err := node.PipeE(fsslice.Filter{
FsSlice: ns.FsSlice,
SetValue: ns.trackableSetter.SetEntry("", ns.Namespace, yaml.NodeTagString),
SetValue: ns.fieldSetter(),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
CreateTag: yaml.NodeTagString,
})
return node, err
}
// hacks applies the namespace transforms that are hardcoded rather
// than specified through FieldSpecs.
func (ns Filter) hacks(obj *yaml.RNode) error {
gvk := resid.GvkFromNode(obj)
if err := ns.metaNamespaceHack(obj, gvk); err != nil {
return err
invalidKindErr := &yaml.InvalidNodeKindError{}
if err != nil && errors.As(err, &invalidKindErr) && invalidKindErr.ActualNodeKind() != yaml.ScalarNode {
return nil, errors.WrapPrefixf(err, "namespace field specs must target scalar nodes")
}
return ns.roleBindingHack(obj, gvk)
return node, errors.WrapPrefixf(err, "namespace transformation failed")
}
// metaNamespaceHack is a hack for implementing the namespace transform
// for the metadata.namespace field on namespace scoped resources.
// namespace scoped resources are determined by NOT being present
// in a hard-coded list of cluster-scoped resource types (by apiVersion and kind).
//
// This hack should be updated to allow individual resources to specify
// if they are cluster scoped through either an annotation on the resources,
// or through inlined OpenAPI on the resource as a YAML comment.
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, gvk resid.Gvk) error {
if gvk.IsClusterScoped() {
return nil
@@ -85,19 +96,23 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, gvk resid.Gvk) error {
FsSlice: []types.FieldSpec{
{Path: types.MetadataNamespacePath, CreateIfNotPresent: true},
},
SetValue: ns.trackableSetter.SetEntry("", ns.Namespace, yaml.NodeTagString),
SetValue: ns.fieldSetter(),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
}
_, err := f.Filter(obj)
return err
}
// roleBindingHack is a hack for implementing the namespace transform
// roleBindingHack is a hack for implementing the transformer's SetRoleBindingSubjects option
// for RoleBinding and ClusterRoleBinding resource types.
// RoleBinding and ClusterRoleBinding have namespace set on
//
// In NoSubjects mode, it does nothing.
//
// In AllServiceAccountSubjects mode, it sets the namespace on subjects with "kind: ServiceAccount".
//
// In DefaultSubjectsOnly mode (default mode), RoleBinding and ClusterRoleBinding have namespace set on
// elements of the "subjects" field if and only if the subject elements
// "name" is "default". Otherwise the namespace is not set.
//
// Example:
//
// kind: RoleBinding
@@ -106,60 +121,64 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, gvk resid.Gvk) error {
// ...
// - name: "something-else" # this will not have the namespace set
// ...
func (ns Filter) roleBindingHack(obj *yaml.RNode, gvk resid.Gvk) error {
if gvk.Kind != roleBindingKind && gvk.Kind != clusterRoleBindingKind {
func (ns Filter) roleBindingHack(obj *yaml.RNode) error {
var visitor filtersutil.SetFn
switch ns.SetRoleBindingSubjects {
case NoSubjects:
return nil
case DefaultSubjectsOnly, SubjectModeUnspecified:
visitor = ns.setSubjectsNamedDefault
case AllServiceAccountSubjects:
visitor = ns.setServiceAccountNamespaces
default:
return errors.Errorf("invalid value %q for setRoleBindingSubjects: "+
"must be one of %q, %q or %q", ns.SetRoleBindingSubjects,
DefaultSubjectsOnly, NoSubjects, AllServiceAccountSubjects)
}
// Lookup the namespace field on all elements.
// We should change the fieldspec so this isn't necessary.
// Lookup the subjects field on all elements.
obj, err := obj.Pipe(yaml.Lookup(subjectsField))
if err != nil || yaml.IsMissingOrNull(obj) {
return err
}
// add the namespace to each "subject" with name: default
err = obj.VisitElements(func(o *yaml.RNode) error {
// The only case we need to force the namespace
// if for the "service account". "default" is
// kind of hardcoded here for right now.
name, err := o.Pipe(
yaml.Lookup("name"), yaml.Match("default"),
)
if err != nil || yaml.IsMissingOrNull(name) {
return err
}
// set the namespace for the default account
node, err := o.Pipe(
yaml.LookupCreate(yaml.ScalarNode, "namespace"),
)
if err != nil {
return err
}
return ns.trackableSetter.SetEntry("", ns.Namespace, yaml.NodeTagString)(node)
})
return err
// Use the appropriate visitor to set the namespace field on the correct subset of subjects
return errors.WrapPrefixf(obj.VisitElements(visitor), "setting namespace on (cluster)role binding subjects")
}
// removeFieldSpecsForHacks removes from the list fieldspecs that
func isRoleBinding(kind string) bool {
return kind == roleBindingKind || kind == clusterRoleBindingKind
}
func (ns Filter) setServiceAccountNamespaces(o *yaml.RNode) error {
name, err := o.Pipe(yaml.Lookup("kind"), yaml.Match("ServiceAccount"))
if err != nil || yaml.IsMissingOrNull(name) {
return errors.WrapPrefixf(err, "looking up kind on (cluster)role binding subject")
}
return setNamespaceField(o, ns.fieldSetter())
}
func (ns Filter) setSubjectsNamedDefault(o *yaml.RNode) error {
name, err := o.Pipe(yaml.Lookup("name"), yaml.Match("default"))
if err != nil || yaml.IsMissingOrNull(name) {
return errors.WrapPrefixf(err, "looking up name on (cluster)role binding subject")
}
return setNamespaceField(o, ns.fieldSetter())
}
func setNamespaceField(node *yaml.RNode, setter filtersutil.SetFn) error {
node, err := node.Pipe(yaml.LookupCreate(yaml.ScalarNode, "namespace"))
if err != nil {
return errors.WrapPrefixf(err, "setting namespace field on (cluster)role binding subject")
}
return setter(node)
}
// removeRoleBindingSubjectFieldSpecs removes from the list fieldspecs that
// have hardcoded implementations
func (ns Filter) removeFieldSpecsForHacks(fs types.FsSlice) types.FsSlice {
func (ns Filter) removeRoleBindingSubjectFieldSpecs(fs types.FsSlice) types.FsSlice {
var val types.FsSlice
for i := range fs {
// implemented by metaNamespaceHack
if fs[i].Path == types.MetadataNamespacePath {
continue
}
// implemented by roleBindingHack
if fs[i].Kind == roleBindingKind && fs[i].Path == subjectsField {
continue
}
// implemented by roleBindingHack
if fs[i].Kind == clusterRoleBindingKind && fs[i].Path == subjectsField {
if isRoleBinding(fs[i].Kind) && fs[i].Path == subjectsNamespacePath {
continue
}
val = append(val, fs[i])
@@ -167,8 +186,27 @@ func (ns Filter) removeFieldSpecsForHacks(fs types.FsSlice) types.FsSlice {
return val
}
func (ns Filter) removeMetaNamespaceFieldSpecs(fs types.FsSlice) types.FsSlice {
var val types.FsSlice
for i := range fs {
if fs[i].Path == types.MetadataNamespacePath {
continue
}
val = append(val, fs[i])
}
return val
}
func (ns *Filter) fieldSetter() filtersutil.SetFn {
if ns.UnsetOnly {
return ns.trackableSetter.SetEntryIfEmpty("", ns.Namespace, yaml.NodeTagString)
}
return ns.trackableSetter.SetEntry("", ns.Namespace, yaml.NodeTagString)
}
const (
subjectsField = "subjects"
subjectsNamespacePath = "subjects/namespace"
roleBindingKind = "RoleBinding"
clusterRoleBindingKind = "ClusterRoleBinding"
)

View File

@@ -406,7 +406,7 @@ func TestNamespace_Filter(t *testing.T) {
test := tests[i]
test.filter.WithMutationTracker(test.mutationTracker)
t.Run(test.name, func(t *testing.T) {
test.filter.FsSlice = append(config.NameSpace, test.fsslice...)
test.filter.FsSlice = append(config.NameSpace, test.fsslice...) //nolint:gocritic
if !assert.Equal(t,
strings.TrimSpace(test.expected),
strings.TrimSpace(

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package patchstrategicmerge
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package refvar contains a kio.Filter implementation of the kustomize
// refvar transformer (find and replace $(FOO) style variables in strings).
package refvar

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package refvar
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package refvar_test
import (
@@ -17,7 +20,6 @@ var makeMf = func(theMap map[string]interface{}) MappingFunc {
}
func TestFilter(t *testing.T) {
testCases := map[string]struct {
input string
expected string

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package replacement contains a kio.Filter implementation of the kustomize
// replacement transformer (accepts sources and looks for targets to replace
// their values with values from the sources).

View File

@@ -4,6 +4,7 @@
package replacement
import (
"errors"
"fmt"
"strings"
@@ -11,6 +12,7 @@ import (
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/resid"
kyaml_utils "sigs.k8s.io/kustomize/kyaml/utils"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
@@ -20,11 +22,11 @@ type Filter struct {
// Filter replaces values of targets with values from sources
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
for _, r := range f.Replacements {
for i, r := range f.Replacements {
if r.Source == nil || r.Targets == nil {
return nil, fmt.Errorf("replacements must specify a source and at least one target")
}
value, err := getReplacement(nodes, &r)
value, err := getReplacement(nodes, &f.Replacements[i])
if err != nil {
return nil, err
}
@@ -36,22 +38,86 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return nodes, nil
}
func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.TargetSelector) ([]*yaml.RNode, error) {
for _, t := range targets {
if t.Select == nil {
return nil, fmt.Errorf("target must specify resources to select")
func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, error) {
source, err := selectSourceNode(nodes, r.Source)
if err != nil {
return nil, err
}
if r.Source.FieldPath == "" {
r.Source.FieldPath = types.DefaultReplacementFieldPath
}
fieldPath := kyaml_utils.SmarterPathSplitter(r.Source.FieldPath, ".")
rn, err := source.Pipe(yaml.Lookup(fieldPath...))
if err != nil {
return nil, fmt.Errorf("error looking up replacement source: %w", err)
}
if rn.IsNilOrEmpty() {
return nil, fmt.Errorf("fieldPath `%s` is missing for replacement source %s", r.Source.FieldPath, r.Source.ResId)
}
return getRefinedValue(r.Source.Options, rn)
}
// selectSourceNode finds the node that matches the selector, returning
// an error if multiple or none are found
func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) {
var matches []*yaml.RNode
for _, n := range nodes {
ids, err := utils.MakeResIds(n)
if err != nil {
return nil, fmt.Errorf("error getting node IDs: %w", err)
}
if len(t.FieldPaths) == 0 {
t.FieldPaths = []string{types.DefaultReplacementFieldPath}
for _, id := range ids {
if id.IsSelectedBy(selector.ResId) {
if len(matches) > 0 {
return nil, fmt.Errorf(
"multiple matches for selector %s", selector)
}
matches = append(matches, n)
break
}
}
for _, n := range nodes {
ids, err := utils.MakeResIds(n)
}
if len(matches) == 0 {
return nil, fmt.Errorf("nothing selected by %s", selector)
}
return matches[0], nil
}
func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, error) {
if options == nil || options.Delimiter == "" {
return rn, nil
}
if rn.YNode().Kind != yaml.ScalarNode {
return nil, fmt.Errorf("delimiter option can only be used with scalar nodes")
}
value := strings.Split(yaml.GetValue(rn), options.Delimiter)
if options.Index >= len(value) || options.Index < 0 {
return nil, fmt.Errorf("options.index %d is out of bounds for value %s", options.Index, yaml.GetValue(rn))
}
n := rn.Copy()
n.YNode().Value = value[options.Index]
return n, nil
}
func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targetSelectors []*types.TargetSelector) ([]*yaml.RNode, error) {
for _, selector := range targetSelectors {
if selector.Select == nil {
return nil, errors.New("target must specify resources to select")
}
if len(selector.FieldPaths) == 0 {
selector.FieldPaths = []string{types.DefaultReplacementFieldPath}
}
for _, possibleTarget := range nodes {
ids, err := utils.MakeResIds(possibleTarget)
if err != nil {
return nil, err
}
// filter targets by label and annotation selectors
selectByAnnoAndLabel, err := selectByAnnoAndLabel(n, t)
selectByAnnoAndLabel, err := selectByAnnoAndLabel(possibleTarget, selector)
if err != nil {
return nil, err
}
@@ -60,9 +126,9 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.T
}
// filter targets by matching resource IDs
for _, id := range ids {
if id.IsSelectedBy(t.Select.ResId) && !rejectId(t.Reject, &id) {
err := applyToNode(n, value, t)
for i, id := range ids {
if id.IsSelectedBy(selector.Select.ResId) && !rejectId(selector.Reject, &ids[i]) {
err := copyValueToTarget(possibleTarget, value, selector)
if err != nil {
return nil, err
}
@@ -111,56 +177,50 @@ func rejectId(rejects []*types.Selector, id *resid.ResId) bool {
return false
}
func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelector) error {
for _, fp := range target.FieldPaths {
fieldPath := utils.SmarterPathSplitter(fp, ".")
var t *yaml.RNode
var err error
if target.Options != nil && target.Options.Create {
t, err = node.Pipe(yaml.LookupCreate(value.YNode().Kind, fieldPath...))
} else {
t, err = node.Pipe(&yaml.PathMatcher{Path: fieldPath})
}
func copyValueToTarget(target *yaml.RNode, value *yaml.RNode, selector *types.TargetSelector) error {
for _, fp := range selector.FieldPaths {
fieldPath := kyaml_utils.SmarterPathSplitter(fp, ".")
create, err := shouldCreateField(selector.Options, fieldPath)
if err != nil {
return err
}
if t != nil {
if err = applyToOneNode(target.Options, t, value); err != nil {
var targetFields []*yaml.RNode
if create {
createdField, createErr := target.Pipe(yaml.LookupCreate(value.YNode().Kind, fieldPath...))
if createErr != nil {
return fmt.Errorf("error creating replacement node: %w", createErr)
}
targetFields = append(targetFields, createdField)
} else {
// may return multiple fields, always wrapped in a sequence node
foundFieldSequence, lookupErr := target.Pipe(&yaml.PathMatcher{Path: fieldPath})
if lookupErr != nil {
return fmt.Errorf("error finding field in replacement target: %w", lookupErr)
}
targetFields, err = foundFieldSequence.Elements()
if err != nil {
return fmt.Errorf("error fetching elements in replacement target: %w", err)
}
}
for _, t := range targetFields {
if err := setFieldValue(selector.Options, t, value); err != nil {
return err
}
}
}
return nil
}
func applyToOneNode(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNode) error {
if len(t.YNode().Content) == 0 {
if err := setTargetValue(options, t, value); err != nil {
return err
}
return nil
}
for _, scalarNode := range t.YNode().Content {
if options != nil && options.Create {
return fmt.Errorf("cannot use create option in a multi-value target")
}
rn := yaml.NewRNode(scalarNode)
if err := setTargetValue(options, rn, value); err != nil {
return err
}
}
return nil
}
func setTargetValue(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNode) error {
func setFieldValue(options *types.FieldOptions, targetField *yaml.RNode, value *yaml.RNode) error {
value = value.Copy()
if options != nil && options.Delimiter != "" {
if t.YNode().Kind != yaml.ScalarNode {
if targetField.YNode().Kind != yaml.ScalarNode {
return fmt.Errorf("delimiter option can only be used with scalar nodes")
}
tv := strings.Split(t.YNode().Value, options.Delimiter)
tv := strings.Split(targetField.YNode().Value, options.Delimiter)
v := yaml.GetValue(value)
// TODO: Add a way to remove an element
switch {
@@ -174,76 +234,25 @@ func setTargetValue(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNod
value.YNode().Value = strings.Join(tv, options.Delimiter)
}
if t.YNode().Kind == yaml.ScalarNode {
if targetField.YNode().Kind == yaml.ScalarNode {
// For scalar, only copy the value (leave any type intact to auto-convert int->string or string->int)
t.YNode().Value = value.YNode().Value
targetField.YNode().Value = value.YNode().Value
} else {
t.SetYNode(value.YNode())
targetField.SetYNode(value.YNode())
}
return nil
}
func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, error) {
source, err := selectSourceNode(nodes, r.Source)
if err != nil {
return nil, err
func shouldCreateField(options *types.FieldOptions, fieldPath []string) (bool, error) {
if options == nil || !options.Create {
return false, nil
}
if r.Source.FieldPath == "" {
r.Source.FieldPath = types.DefaultReplacementFieldPath
}
fieldPath := utils.SmarterPathSplitter(r.Source.FieldPath, ".")
rn, err := source.Pipe(yaml.Lookup(fieldPath...))
if err != nil {
return nil, err
}
if rn.IsNilOrEmpty() {
return nil, fmt.Errorf("fieldPath `%s` is missing for replacement source %s", r.Source.FieldPath, r.Source.ResId)
}
return getRefinedValue(r.Source.Options, rn)
}
func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, error) {
if options == nil || options.Delimiter == "" {
return rn, nil
}
if rn.YNode().Kind != yaml.ScalarNode {
return nil, fmt.Errorf("delimiter option can only be used with scalar nodes")
}
value := strings.Split(yaml.GetValue(rn), options.Delimiter)
if options.Index >= len(value) || options.Index < 0 {
return nil, fmt.Errorf("options.index %d is out of bounds for value %s", options.Index, yaml.GetValue(rn))
}
n := rn.Copy()
n.YNode().Value = value[options.Index]
return n, nil
}
// selectSourceNode finds the node that matches the selector, returning
// an error if multiple or none are found
func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) {
var matches []*yaml.RNode
for _, n := range nodes {
ids, err := utils.MakeResIds(n)
if err != nil {
return nil, err
}
for _, id := range ids {
if id.IsSelectedBy(selector.ResId) {
if len(matches) > 0 {
return nil, fmt.Errorf(
"multiple matches for selector %s", selector)
}
matches = append(matches, n)
break
}
// create option is not supported in a wildcard matching
for _, f := range fieldPath {
if f == "*" {
return false, fmt.Errorf("cannot support create option in a multi-value target")
}
}
if len(matches) == 0 {
return nil, fmt.Errorf("nothing selected by %s", selector)
}
return matches[0], nil
return true, nil
}

View File

@@ -1634,6 +1634,45 @@ spec:
- name: deployment-name
value: sample-deploy`,
},
"index contains '*' character and create options": {
input: `apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: sample-deploy
name: sample-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sample-deploy
template:
metadata:
labels:
app: sample-deploy
spec:
containers:
- image: nginx
name: main
env:
- name: other-env
value: YYYYY
`,
replacements: `replacements:
- source:
kind: Deployment
name: sample-deploy
fieldPath: metadata.name
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.*.env.[name=deployment-name].value
options:
create: true
`,
expectedErr: "cannot support create option in a multi-value target",
},
"multiple field paths in target": {
input: `apiVersion: v1
kind: ConfigMap
@@ -2315,6 +2354,66 @@ spec:
name: myapp-container
ports:
- containerPort: 80
`,
},
"replace an existing mapping value": {
input: `apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
spec:
containers:
- image: busybox
name: myapp-container
restartPolicy: old
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- image: busybox
name: myapp-container
restartPolicy: new
`,
replacements: `replacements:
- source:
kind: Pod
name: my-pod
fieldPath: spec
targets:
- select:
name: hello
kind: Job
fieldPaths:
- spec.template.spec
options:
create: true
`,
expected: `apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
spec:
containers:
- image: busybox
name: myapp-container
restartPolicy: new
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- image: busybox
name: myapp-container
restartPolicy: new
`,
},
}

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package replicacount
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package replicacount
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package replicacount
import (

View File

@@ -1,16 +1,39 @@
module sigs.k8s.io/kustomize/api
go 1.16
go 1.18
require (
github.com/evanphx/json-patch v4.11.0+incompatible
github.com/go-errors/errors v1.0.1
github.com/go-errors/errors v1.4.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/imdario/mergo v0.3.5
github.com/imdario/mergo v0.3.6
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.8.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
sigs.k8s.io/kustomize/kyaml v0.13.4
k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661
sigs.k8s.io/kustomize/kyaml v0.13.9
sigs.k8s.io/yaml v1.2.0
)
require (
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/xlab/treeprint v1.1.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -1,641 +1,216 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
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/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/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/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
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/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/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 v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
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/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
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.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
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.3/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.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/kustomize/kyaml v0.13.4 h1:UP4niyzHP8yBDZTJu3OyZMCbJUfT6PIj0fJZFcn8gQw=
sigs.k8s.io/kustomize/kyaml v0.13.4/go.mod h1:/ya3Gk4diiQzlE4mBh7wykyLRFZNvqlbh+JnwQ9Vhrc=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661 h1:nqYOUleKLC/0P1zbU29F5q6aoezM6MOAVz+iyfQbZ5M=
k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk=
sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -341,6 +341,7 @@ data:
// The return value indicates whether we should skip the rest of the test case
// due to the error result.
func SkipRest(t *testing.T, desc string, err error, contains string) bool {
t.Helper()
if err != nil {
if len(contains) == 0 {
t.Errorf("case %q, expect nil error but got %q", desc, err.Error())

View File

@@ -28,12 +28,20 @@ type KvLoader interface {
// Loader interface exposes methods to read bytes.
type Loader interface {
// Repo returns the repo location if this Loader was created from a url
// or the empty string otherwise.
Repo() string
// Root returns the root location for this Loader.
Root() string
// New returns Loader located at newRoot.
New(newRoot string) (Loader, error)
// Load returns the bytes read from the location or an error.
Load(location string) ([]byte, error)
// Cleanup cleans the loader
Cleanup() error
}

View File

@@ -113,7 +113,6 @@ func debug(fMap filterMap) {
// 'spec/scaleTargetRef/name' field. Return a filter that can do that.
func (t *nameReferenceTransformer) determineFilters(
resources []*resource.Resource) (fMap filterMap) {
// We cache the resource OrgId values because they don't change and otherwise are very visible in a memory pprof
resourceOrgIds := make([]resid.ResId, len(resources))
for i, resource := range resources {

View File

@@ -7,6 +7,7 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
@@ -524,6 +525,52 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
`considering field 'rules/resourceNames' of object ClusterRole.v1.rbac.authorization.k8s.io/cr.[noNs]: visit traversal on ` +
`path: [resourceNames]: path config error; no 'name' field in node`,
},
{
// When targeting a map reference, we need to update both name and namespace, so multiple
// possible referral targets with different namespaces should not be considered identical.
// This test covers a bug where the difference in namespace was ignored and one candidate was chosen at random.
resMap: resmaptest_test.NewRmBuilderDefault(t).AddWithNsAndName(
"", orgname,
map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": orgname,
"namespace": ns1,
},
},
).AddWithNsAndName(
"", orgname,
map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": orgname,
"namespace": ns2,
},
},
).Add(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleBinding",
"metadata": map[string]interface{}{
"name": orgname,
},
"roleRef": map[string]interface{}{
"apiGroup": "rbac.authorization.k8s.io",
"kind": "ClusterRole",
"name": orgname,
},
"subjects": []interface{}{
map[string]interface{}{
"kind": "ServiceAccount",
"name": orgname,
},
},
},
).ResMap(),
expectedErr: "found multiple possible referrals: ServiceAccount.v1.[noGrp]/uniquename.ns1, ServiceAccount.v1.[noGrp]/uniquename.ns2",
},
}
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
@@ -1061,3 +1108,76 @@ func TestNameReferenceCandidateSelection(t *testing.T) {
t.Fatalf(notEqualErrFmt, err)
}
}
func TestNameReferenceCandidateDisambiguationByNamespace(t *testing.T) {
// The ClusterRole refers to both configmaps, since it is not namespace-specific.
// Since both names are updated consistently, the transformer should be able to
// silently update the ClusterRole as well.
// This test guards against a regression where allNamesAndNamespacesAreTheSame would be
// used to detect referral candidate identity instead of allNamesAreTheSame.
m := resmaptest_test.NewRmBuilderDefault(t).AddWithName(orgname,
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": suffixedname,
"namespace": ns1,
},
},
).AddWithName(orgname,
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": suffixedname,
"namespace": ns2,
},
},
).Add(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": orgname,
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"configmaps",
},
"resourceNames": []interface{}{
orgname,
},
},
},
},
).ResMap()
expected := resmaptest_test.NewSeededRmBuilderDefault(t, m.ShallowCopy()).
ReplaceResource(map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": orgname,
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"configmaps",
},
"resourceNames": []interface{}{
suffixedname,
},
},
},
},
).ResMap()
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
require.NoError(t, nrt.Transform(m))
m.RemoveBuildAnnotations()
if err := expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf(notEqualErrFmt, err)
}
}

View File

@@ -107,7 +107,6 @@ func (ra *ResAccumulator) findVarValueFromResources(v types.Var) (interface{}, e
for _, res := range ra.resMap.Resources() {
for _, varName := range res.GetRefVarNames() {
if varName == v.Name {
//nolint: staticcheck
s, err := res.GetFieldValue(v.FieldRef.FieldPath)
if err != nil {
return "", fmt.Errorf(

View File

@@ -22,6 +22,7 @@ import (
)
func makeResAccumulator(t *testing.T) *ResAccumulator {
t.Helper()
ra := MakeEmptyAccumulator()
err := ra.MergeConfig(builtinconfig.MakeDefaultConfig())
if err != nil {
@@ -133,6 +134,7 @@ func TestResolveVarsOneUnused(t *testing.T) {
}
func expectLog(t *testing.T, log bytes.Buffer, expect string) {
t.Helper()
if !strings.Contains(log.String(), expect) {
t.Fatalf("expected log containing '%s', got '%s'", expect, log.String())
}

View File

@@ -6,7 +6,6 @@ package builtins
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -73,7 +72,7 @@ func (p *HelmChartInflationGeneratorPlugin) establishTmpDir() (err error) {
// already done.
return nil
}
p.tmpDir, err = ioutil.TempDir("", "kustomize-helm-")
p.tmpDir, err = os.MkdirTemp("", "kustomize-helm-")
return err
}
@@ -211,7 +210,7 @@ func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(
return "", fmt.Errorf("cannot create tmp dir to write helm values")
}
path := filepath.Join(p.tmpDir, p.Name+"-kustomize-values.yaml")
return path, ioutil.WriteFile(path, b, 0644)
return path, errors.Wrap(os.WriteFile(path, b, 0644), "failed to write values file")
}
func (p *HelmChartInflationGeneratorPlugin) cleanup() {
@@ -283,6 +282,9 @@ func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
if p.IncludeCRDs {
args = append(args, "--include-crds")
}
if p.SkipHooks {
args = append(args, "--no-hooks")
}
return args
}

View File

@@ -9,20 +9,37 @@ import (
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/yaml"
)
// Change or set the namespace of non-cluster level resources.
type NamespaceTransformerPlugin struct {
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
UnsetOnly bool `json:"unsetOnly" yaml:"unsetOnly"`
SetRoleBindingSubjects namespace.RoleBindingSubjectMode `json:"setRoleBindingSubjects" yaml:"setRoleBindingSubjects"`
}
func (p *NamespaceTransformerPlugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Namespace = ""
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
if err := yaml.Unmarshal(c, p); err != nil {
return errors.WrapPrefixf(err, "unmarshalling NamespaceTransformer config")
}
switch p.SetRoleBindingSubjects {
case namespace.AllServiceAccountSubjects, namespace.DefaultSubjectsOnly, namespace.NoSubjects:
// valid
case namespace.SubjectModeUnspecified:
p.SetRoleBindingSubjects = namespace.DefaultSubjectsOnly
default:
return errors.Errorf("invalid value %q for setRoleBindingSubjects: "+
"must be one of %q, %q or %q", p.SetRoleBindingSubjects,
namespace.DefaultSubjectsOnly, namespace.NoSubjects, namespace.AllServiceAccountSubjects)
}
return nil
}
func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
@@ -36,8 +53,10 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
}
r.StorePreviousId()
if err := r.ApplyFilter(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
SetRoleBindingSubjects: p.SetRoleBindingSubjects,
UnsetOnly: p.UnsetOnly,
}); err != nil {
return err
}

View File

@@ -22,15 +22,11 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
if err = r.run("init"); err != nil {
return err
}
if err = r.run(
"remote", "add", "origin", repoSpec.CloneSpec()); err != nil {
return err
}
ref := "HEAD"
if repoSpec.Ref != "" {
ref = repoSpec.Ref
}
if err = r.run("fetch", "--depth=1", "origin", ref); err != nil {
if err = r.run("fetch", "--depth=1", repoSpec.CloneSpec(), ref); err != nil {
return err
}
if err = r.run("checkout", "FETCH_HEAD"); err != nil {

View File

@@ -46,9 +46,9 @@ func (r gitRunner) run(args ...string) error {
cmd.String(),
r.duration,
func() error {
_, err := cmd.CombinedOutput()
out, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrapf(err, "git cmd = '%s'", cmd.String())
return errors.Wrapf(err, "failed to run '%s': %s", cmd.String(), string(out))
}
return err
})

View File

@@ -27,7 +27,7 @@ type RepoSpec struct {
// TODO(monopole): Drop raw, use processed fields instead.
raw string
// Host, e.g. github.com
// Host, e.g. https://github.com/
Host string
// orgRepo name (organization/repoName),
@@ -78,15 +78,15 @@ func (x *RepoSpec) Cleaner(fSys filesys.FileSystem) func() error {
return func() error { return fSys.RemoveAll(x.Dir.String()) }
}
// NewRepoSpecFromUrl parses git-like urls.
// NewRepoSpecFromURL parses git-like urls.
// From strings like git@github.com:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
func NewRepoSpecFromURL(n string) (*RepoSpec, error) {
if filepath.IsAbs(n) {
return nil, fmt.Errorf("uri looks like abs path: %s", n)
}
host, orgRepo, path, gitRef, gitSubmodules, suffix, gitTimeout := parseGitUrl(n)
host, orgRepo, path, gitRef, gitSubmodules, suffix, gitTimeout := parseGitURL(n)
if orgRepo == "" {
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
}
@@ -108,44 +108,66 @@ const (
// From strings like git@github.com:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func parseGitUrl(n string) (
func parseGitURL(n string) (
host string, orgRepo string, path string, gitRef string, gitSubmodules bool, gitSuff string, gitTimeout time.Duration) {
// parse query first
// safe because according to rfc3986: ? only allowed in query
// and not recognized %-encoded
beforeQuery, query, _ := strings.Cut(n, "?")
n = beforeQuery
// if no query, defaults returned
gitRef, gitTimeout, gitSubmodules = parseQuery(query)
if strings.Contains(n, gitDelimiter) {
index := strings.Index(n, gitDelimiter)
// Adding _git/ to host
host = normalizeGitHostSpec(n[:index+len(gitDelimiter)])
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
orgRepo = strings.Split(n[index+len(gitDelimiter):], "/")[0]
path = parsePath(n[index+len(gitDelimiter)+len(orgRepo):])
return
}
host, n = parseHostSpec(n)
gitSuff = gitSuffix
isLocal := strings.HasPrefix(host, "file://")
if !isLocal {
gitSuff = gitSuffix
}
if strings.Contains(n, gitSuffix) {
gitSuff = gitSuffix
index := strings.Index(n, gitSuffix)
orgRepo = n[0:index]
n = n[index+len(gitSuffix):]
if len(n) > 0 && n[0] == '/' {
n = n[1:]
}
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
path = parsePath(n)
return
}
if isLocal {
if idx := strings.Index(n, "//"); idx > 0 {
orgRepo = n[:idx]
n = n[idx+2:]
path = parsePath(n)
return
}
orgRepo = parsePath(n)
return
}
i := strings.Index(n, "/")
if i < 1 {
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
path = parsePath(n)
return
}
j := strings.Index(n[i+1:], "/")
if j >= 0 {
j += i + 1
orgRepo = n[:j]
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[j+1:])
path = parsePath(n[j+1:])
return
}
path = ""
orgRepo, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
orgRepo = parsePath(n)
return host, orgRepo, path, gitRef, gitSubmodules, gitSuff, gitTimeout
}
@@ -155,14 +177,12 @@ const defaultSubmodules = true
// Arbitrary, but non-infinite, timeout for running commands.
const defaultTimeout = 27 * time.Second
func peelQuery(arg string) (string, string, time.Duration, bool) {
// Parse the given arg into a URL. In the event of a parse failure, return
// our defaults.
parsed, err := url.Parse(arg)
func parseQuery(query string) (string, time.Duration, bool) {
values, err := url.ParseQuery(query)
// in event of parse failure, return defaults
if err != nil {
return arg, "", defaultTimeout, defaultSubmodules
return "", defaultTimeout, defaultSubmodules
}
values := parsed.Query()
// ref is the desired git ref to target. Can be specified by in a git URL
// with ?ref=<string> or ?version=<string>, although ref takes precedence.
@@ -193,7 +213,16 @@ func peelQuery(arg string) (string, string, time.Duration, bool) {
}
}
return parsed.Path, ref, duration, submodules
return ref, duration, submodules
}
func parsePath(n string) string {
parsed, err := url.Parse(n)
// TODO(annasong): decide how to handle error, i.e. return error, empty string, etc.
if err != nil {
return n
}
return parsed.Path
}
func parseHostSpec(n string) (string, string) {
@@ -201,7 +230,7 @@ func parseHostSpec(n string) (string, string) {
// Start accumulating the host part.
for _, p := range []string{
// Order matters here.
"git::", "gh:", "ssh://", "https://", "http://",
"git::", "gh:", "ssh://", "https://", "http://", "file://",
"git@", "github.com:", "github.com/"} {
if len(p) < len(n) && strings.ToLower(n[:len(p)]) == p {
n = n[len(p):]
@@ -229,7 +258,7 @@ func parseHostSpec(n string) (string, string) {
if strings.HasSuffix(host, p) {
i := strings.Index(n, "/")
if i > -1 {
host = host + n[0:i+1]
host += n[0 : i+1]
n = n[i+1:]
}
break

View File

@@ -6,200 +6,485 @@ package git
import (
"fmt"
"path/filepath"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var orgRepos = []string{"someOrg/someRepo", "kubernetes/website"}
var pathNames = []string{"README.md", "foo/krusty.txt", ""}
var hrefArgs = []string{"someBranch", "master", "v0.1.0", ""}
var hostNamesRawAndNormalized = [][]string{
{"gh:", "gh:"},
{"GH:", "gh:"},
{"gitHub.com/", "https://github.com/"},
{"github.com:", "https://github.com/"},
{"http://github.com/", "https://github.com/"},
{"https://github.com/", "https://github.com/"},
{"hTTps://github.com/", "https://github.com/"},
{"https://git-codecommit.us-east-2.amazonaws.com/", "https://git-codecommit.us-east-2.amazonaws.com/"},
{"https://fabrikops2.visualstudio.com/", "https://fabrikops2.visualstudio.com/"},
{"ssh://git.example.com:7999/", "ssh://git.example.com:7999/"},
{"git::https://gitlab.com/", "https://gitlab.com/"},
{"git::http://git.example.com/", "http://git.example.com/"},
{"git::https://git.example.com/", "https://git.example.com/"},
{"git@github.com:", "git@github.com:"},
{"git@github.com/", "git@github.com:"},
}
func makeUrl(hostFmt, orgRepo, path, href string) string {
if len(path) > 0 {
orgRepo = filepath.Join(orgRepo, path)
func TestNewRepoSpecFromUrl_Permute(t *testing.T) {
// Generate all many permutations of host, orgRepo, pathName, and ref.
// Not all combinations make sense, but the parsing is very permissive and
// we probably stil don't want to break backwards compatibility for things
// that are unintentionally supported.
var schemeAuthority = []struct{ raw, normalized string }{
{"gh:", "gh:"},
{"GH:", "gh:"},
{"gitHub.com/", "https://github.com/"},
{"github.com:", "https://github.com/"},
{"http://github.com/", "https://github.com/"},
{"https://github.com/", "https://github.com/"},
{"hTTps://github.com/", "https://github.com/"},
{"https://git-codecommit.us-east-2.amazonaws.com/", "https://git-codecommit.us-east-2.amazonaws.com/"},
{"https://fabrikops2.visualstudio.com/", "https://fabrikops2.visualstudio.com/"},
{"ssh://git.example.com:7999/", "ssh://git.example.com:7999/"},
{"git::https://gitlab.com/", "https://gitlab.com/"},
{"git::http://git.example.com/", "http://git.example.com/"},
{"git::https://git.example.com/", "https://git.example.com/"},
{"git@github.com:", "git@github.com:"},
{"git@github.com/", "git@github.com:"},
}
url := hostFmt + orgRepo
if href != "" {
url += refQuery + href
}
return url
}
var orgRepos = []string{"someOrg/someRepo", "kubernetes/website"}
var pathNames = []string{"README.md", "foo/krusty.txt", ""}
var refArgs = []string{"group/version", "someBranch", "master", "v0.1.0", ""}
func TestNewRepoSpecFromUrl(t *testing.T) {
var bad [][]string
for _, tuple := range hostNamesRawAndNormalized {
hostRaw := tuple[0]
hostSpec := tuple[1]
makeURL := func(hostFmt, orgRepo, path, ref string) string {
if len(path) > 0 {
orgRepo = filepath.Join(orgRepo, path)
}
url := hostFmt + orgRepo
if ref != "" {
url += refQuery + ref
}
return url
}
var i int
for _, v := range schemeAuthority {
hostRaw := v.raw
hostSpec := v.normalized
for _, orgRepo := range orgRepos {
for _, pathName := range pathNames {
for _, hrefArg := range hrefArgs {
uri := makeUrl(hostRaw, orgRepo, pathName, hrefArg)
rs, err := NewRepoSpecFromUrl(uri)
if err != nil {
t.Errorf("problem %v", err)
}
if rs.Host != hostSpec {
bad = append(bad, []string{"host", uri, rs.Host, hostSpec})
}
if rs.OrgRepo != orgRepo {
bad = append(bad, []string{"orgRepo", uri, rs.OrgRepo, orgRepo})
}
if rs.Path != pathName {
bad = append(bad, []string{"path", uri, rs.Path, pathName})
}
if rs.Ref != hrefArg {
bad = append(bad, []string{"ref", uri, rs.Ref, hrefArg})
}
for _, hrefArg := range refArgs {
t.Run(fmt.Sprintf("t%d", i), func(t *testing.T) {
uri := makeURL(hostRaw, orgRepo, pathName, hrefArg)
rs, err := NewRepoSpecFromURL(uri)
require.NoErrorf(t, err, "unexpected error creating RepoSpec for uri %s", uri)
assert.Equal(t, hostSpec, rs.Host, "unexpected host for uri %s", uri)
assert.Equal(t, orgRepo, rs.OrgRepo, "unexpected orgRepo for uri %s", uri)
assert.Equal(t, pathName, rs.Path, "unexpected path for uri %s", uri)
assert.Equal(t, hrefArg, rs.Ref, "unexpected ref for uri %s", uri)
})
i++
}
}
}
}
if len(bad) > 0 {
for _, tuple := range bad {
fmt.Printf("\n"+
" from uri: %s\n"+
" actual %4s: %s\n"+
"expected %4s: %s\n",
tuple[1], tuple[0], tuple[2], tuple[0], tuple[3])
}
t.Fail()
}
}
var badData = [][]string{
{"/tmp", "uri looks like abs path"},
{"iauhsdiuashduas", "url lacks orgRepo"},
{"htxxxtp://github.com/", "url lacks host"},
{"ssh://git.example.com", "url lacks orgRepo"},
{"git::___", "url lacks orgRepo"},
}
func TestNewRepoSpecFromUrlErrors(t *testing.T) {
for _, tuple := range badData {
_, err := NewRepoSpecFromUrl(tuple[0])
if err == nil {
t.Error("expected error")
}
if !strings.Contains(err.Error(), tuple[1]) {
t.Errorf("unexpected error: %s", err)
}
badData := map[string]struct {
url, error string
}{
"absolute_path": {
"/tmp",
"uri looks like abs path",
},
"no_slashes": {
"iauhsdiuashduas",
"url lacks orgRepo",
},
"bad_scheme": {
"htxxxtp://github.com/",
"url lacks host",
},
"no_org_repo": {
"ssh://git.example.com",
"url lacks orgRepo",
},
"hashicorp_git_only": {
"git::___",
"url lacks orgRepo",
},
"query_after_host": {
"https://host?ref=group/version/minor_version",
"url lacks orgRepo",
},
}
for name, testCase := range badData {
t.Run(name, func(t *testing.T) {
_, err := NewRepoSpecFromURL(testCase.url)
require.Error(t, err)
require.Contains(t, err.Error(), testCase.error)
})
}
}
func TestNewRepoSpecFromUrl_CloneSpecs(t *testing.T) {
testcases := map[string]struct {
func TestNewRepoSpecFromUrl_Smoke(t *testing.T) {
// A set of end to end parsing tests that smoke out obvious issues
// No tests for submodules and timeout as the expectations are hard-coded
// to the defaults for compactness.
testcases := []struct {
name string
input string
repoSpec RepoSpec
cloneSpec string
absPath string
ref string
skip string
}{
"t1": {
{
name: "t1",
input: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somedir",
cloneSpec: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
absPath: notCloned.Join("somedir"),
ref: "",
repoSpec: RepoSpec{
Host: "https://git-codecommit.us-east-2.amazonaws.com/",
OrgRepo: "someorg/somerepo",
Path: "somedir",
GitSuffix: ".git",
},
},
"t2": {
{
name: "t2",
input: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somedir?ref=testbranch",
cloneSpec: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
absPath: notCloned.Join("somedir"),
ref: "testbranch",
repoSpec: RepoSpec{
Host: "https://git-codecommit.us-east-2.amazonaws.com/",
OrgRepo: "someorg/somerepo",
Path: "somedir",
Ref: "testbranch",
GitSuffix: ".git",
},
},
"t3": {
{
name: "t3",
input: "https://fabrikops2.visualstudio.com/someorg/somerepo?ref=master",
cloneSpec: "https://fabrikops2.visualstudio.com/someorg/somerepo",
absPath: notCloned.String(),
ref: "master",
repoSpec: RepoSpec{
Host: "https://fabrikops2.visualstudio.com/",
OrgRepo: "someorg/somerepo",
Ref: "master",
GitSuffix: ".git",
},
},
"t4": {
{
name: "t4",
input: "http://github.com/someorg/somerepo/somedir",
cloneSpec: "https://github.com/someorg/somerepo.git",
absPath: notCloned.Join("somedir"),
ref: "",
repoSpec: RepoSpec{
Host: "https://github.com/",
OrgRepo: "someorg/somerepo",
Path: "somedir",
GitSuffix: ".git",
},
},
"t5": {
{
name: "t5",
input: "git@github.com:someorg/somerepo/somedir",
cloneSpec: "git@github.com:someorg/somerepo.git",
absPath: notCloned.Join("somedir"),
ref: "",
repoSpec: RepoSpec{
Host: "git@github.com:",
OrgRepo: "someorg/somerepo",
Path: "somedir",
GitSuffix: ".git",
},
},
"t6": {
{
name: "t6",
input: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git?ref=v0.1.0",
cloneSpec: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git",
absPath: notCloned.String(),
ref: "v0.1.0",
repoSpec: RepoSpec{
Host: "git@gitlab2.sqtools.ru:10022/",
OrgRepo: "infra/kubernetes/thanos-base",
Ref: "v0.1.0",
GitSuffix: ".git",
},
},
"t7": {
{
name: "t7",
input: "git@bitbucket.org:company/project.git//path?ref=branch",
cloneSpec: "git@bitbucket.org:company/project.git",
absPath: notCloned.Join("path"),
ref: "branch",
repoSpec: RepoSpec{
Host: "git@bitbucket.org:company/",
OrgRepo: "project",
Path: "/path",
Ref: "branch",
GitSuffix: ".git",
},
},
"t8": {
{
name: "t8",
input: "https://itfs.mycompany.com/collection/project/_git/somerepos",
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
absPath: notCloned.String(),
ref: "",
repoSpec: RepoSpec{
Host: "https://itfs.mycompany.com/collection/project/_git/",
OrgRepo: "somerepos",
},
},
"t9": {
{
name: "t9",
input: "https://itfs.mycompany.com/collection/project/_git/somerepos?version=v1.0.0",
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
absPath: notCloned.String(),
ref: "v1.0.0",
repoSpec: RepoSpec{
Host: "https://itfs.mycompany.com/collection/project/_git/",
OrgRepo: "somerepos",
Ref: "v1.0.0",
},
},
"t10": {
{
name: "t10",
input: "https://itfs.mycompany.com/collection/project/_git/somerepos/somedir?version=v1.0.0",
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
absPath: notCloned.Join("somedir"),
ref: "v1.0.0",
repoSpec: RepoSpec{
Host: "https://itfs.mycompany.com/collection/project/_git/",
OrgRepo: "somerepos",
Path: "/somedir",
Ref: "v1.0.0",
},
},
"t11": {
{
name: "t11",
input: "git::https://itfs.mycompany.com/collection/project/_git/somerepos",
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
absPath: notCloned.String(),
ref: "",
repoSpec: RepoSpec{
Host: "https://itfs.mycompany.com/collection/project/_git/",
OrgRepo: "somerepos",
},
},
"t12": {
{
name: "t12",
input: "https://bitbucket.example.com/scm/project/repository.git",
cloneSpec: "https://bitbucket.example.com/scm/project/repository.git",
absPath: notCloned.String(),
ref: "",
repoSpec: RepoSpec{
Host: "https://bitbucket.example.com/",
OrgRepo: "scm/project/repository",
GitSuffix: ".git",
},
},
{
name: "t13",
input: "ssh://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somepath",
cloneSpec: "ssh://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
absPath: notCloned.Join("somepath"),
repoSpec: RepoSpec{
Host: "ssh://git-codecommit.us-east-2.amazonaws.com/",
OrgRepo: "someorg/somerepo",
Path: "somepath",
GitSuffix: ".git",
},
},
{
name: "t14",
input: "git@github.com/someorg/somerepo/somepath",
cloneSpec: "git@github.com:someorg/somerepo.git",
absPath: notCloned.Join("somepath"),
repoSpec: RepoSpec{
Host: "git@github.com:",
OrgRepo: "someorg/somerepo",
Path: "somepath",
GitSuffix: ".git",
},
},
{
name: "t15",
input: "https://github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?ref=v1.0.6",
cloneSpec: "https://github.com/kubernetes-sigs/kustomize.git",
absPath: notCloned.Join("/examples/multibases/dev"),
repoSpec: RepoSpec{
Host: "https://github.com/",
OrgRepo: "kubernetes-sigs/kustomize",
Path: "/examples/multibases/dev/",
Ref: "v1.0.6",
GitSuffix: ".git",
},
},
{
name: "t16",
input: "file://a/b/c/someRepo.git/somepath?ref=someBranch",
cloneSpec: "file://a/b/c/someRepo.git",
absPath: notCloned.Join("somepath"),
repoSpec: RepoSpec{
Host: "file://",
OrgRepo: "a/b/c/someRepo",
Path: "somepath",
Ref: "someBranch",
GitSuffix: ".git",
},
},
{
name: "t17",
input: "file://a/b/c/someRepo//somepath?ref=someBranch",
cloneSpec: "file://a/b/c/someRepo",
absPath: notCloned.Join("somepath"),
repoSpec: RepoSpec{
Host: "file://",
OrgRepo: "a/b/c/someRepo",
Path: "somepath",
Ref: "someBranch",
},
},
{
name: "t18",
input: "file://a/b/c/someRepo?ref=someBranch",
cloneSpec: "file://a/b/c/someRepo",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "file://",
OrgRepo: "a/b/c/someRepo",
Ref: "someBranch",
},
},
{
name: "t19",
input: "file:///a/b/c/someRepo?ref=someBranch",
cloneSpec: "file:///a/b/c/someRepo",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "file://",
OrgRepo: "/a/b/c/someRepo",
Ref: "someBranch",
},
},
{
name: "t20",
input: "ssh://git@github.com/kubernetes-sigs/kustomize//examples/multibases/dev?ref=v1.0.6",
cloneSpec: "git@github.com:kubernetes-sigs/kustomize.git",
absPath: notCloned.Join("examples/multibases/dev"),
repoSpec: RepoSpec{
Host: "git@github.com:",
OrgRepo: "kubernetes-sigs/kustomize",
Path: "/examples/multibases/dev",
Ref: "v1.0.6",
GitSuffix: ".git",
},
},
{
name: "t21",
input: "file:///a/b/c/someRepo",
cloneSpec: "file:///a/b/c/someRepo",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "file://",
OrgRepo: "/a/b/c/someRepo",
},
},
{
name: "t22",
input: "file:///",
cloneSpec: "file:///",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "file://",
OrgRepo: "/",
},
},
{
name: "t23",
skip: "the `//` repo separator does not work",
input: "https://fake-git-hosting.org/path/to/repo//examples/multibases/dev",
cloneSpec: "https://fake-git-hosting.org/path/to.git",
absPath: notCloned.Join("/examples/multibases/dev"),
repoSpec: RepoSpec{
Host: "https://fake-git-hosting.org/",
OrgRepo: "path/to/repo",
Path: "/examples/multibases/dev",
GitSuffix: ".git",
},
},
{
name: "t24",
skip: "the `//` repo separator does not work",
input: "ssh://alice@acme.co/path/to/repo//examples/multibases/dev",
cloneSpec: "ssh://alice@acme.co/path/to/repo.git",
absPath: notCloned.Join("/examples/multibases/dev"),
repoSpec: RepoSpec{
Host: "ssh://alice@acme.co",
OrgRepo: "path/to/repo",
Path: "/examples/multibases/dev",
GitSuffix: ".git",
},
},
{
name: "query_slash",
input: "https://authority/org/repo?ref=group/version",
cloneSpec: "https://authority/org/repo.git",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "https://authority/",
OrgRepo: "org/repo",
Ref: "group/version",
GitSuffix: ".git",
},
},
{
name: "query_git_delimiter",
input: "https://authority/org/repo/?ref=includes_git/for_some_reason",
cloneSpec: "https://authority/org/repo.git",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "https://authority/",
OrgRepo: "org/repo",
Ref: "includes_git/for_some_reason",
GitSuffix: ".git",
},
},
{
name: "query_git_suffix",
input: "https://authority/org/repo/?ref=includes.git/for_some_reason",
cloneSpec: "https://authority/org/repo.git",
absPath: notCloned.String(),
repoSpec: RepoSpec{
Host: "https://authority/",
OrgRepo: "org/repo",
Ref: "includes.git/for_some_reason",
GitSuffix: ".git",
},
},
{
name: "non_parsable_path",
input: "https://authority/org/repo/%-invalid-uri-so-not-parsable-by-net/url.Parse",
cloneSpec: "https://authority/org/repo.git",
absPath: notCloned.Join("%-invalid-uri-so-not-parsable-by-net/url.Parse"),
repoSpec: RepoSpec{
Host: "https://authority/",
OrgRepo: "org/repo",
Path: "%-invalid-uri-so-not-parsable-by-net/url.Parse",
GitSuffix: ".git",
},
},
}
for tn, tc := range testcases {
t.Run(tn, func(t *testing.T) {
rs, err := NewRepoSpecFromUrl(tc.input)
assert.NoError(t, err)
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
if tc.skip != "" {
t.Skip(tc.skip)
}
rs, err := NewRepoSpecFromURL(tc.input)
require.NoError(t, err)
assert.Equal(t, tc.cloneSpec, rs.CloneSpec(), "cloneSpec mismatch")
assert.Equal(t, tc.absPath, rs.AbsPath(), "absPath mismatch")
assert.Equal(t, tc.ref, rs.Ref, "ref mismatch")
// some values have defaults. Clear them here so test cases remain compact.
// This means submodules and timeout cannot be tested here. That's fine since
// they are tested in TestParseQuery.
rs.raw = ""
rs.Dir = ""
rs.Submodules = false
rs.Timeout = 0
assert.Equal(t, &tc.repoSpec, rs)
})
}
}
func TestNewRepoSpecFromURL_DefaultQueryParams(t *testing.T) {
repoSpec, err := NewRepoSpecFromURL("https://github.com/org/repo")
require.NoError(t, err)
require.Equal(t, defaultSubmodules, repoSpec.Submodules)
require.Equal(t, defaultTimeout, repoSpec.Timeout)
}
func TestIsAzureHost(t *testing.T) {
testcases := []struct {
input string
@@ -230,131 +515,136 @@ func TestIsAzureHost(t *testing.T) {
}
}
func TestPeelQuery(t *testing.T) {
testcases := map[string]struct {
func TestParseQuery(t *testing.T) {
testcases := []struct {
name string
input string
path string
ref string
submodules bool
timeout time.Duration
}{
"t1": {
// All empty.
input: "somerepos",
path: "somerepos",
{
name: "empty",
input: "",
ref: "",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t2": {
input: "somerepos?ref=v1.0.0",
path: "somerepos",
{
name: "ref",
input: "ref=v1.0.0",
ref: "v1.0.0",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t3": {
input: "somerepos?version=master",
path: "somerepos",
{
name: "ref_slash",
input: "ref=kustomize/v4.5.7",
ref: "kustomize/v4.5.7",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
{
name: "version",
input: "version=master",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t4": {
{
name: "ref_and_version",
// A ref value takes precedence over a version value.
input: "somerepos?version=master&ref=v1.0.0",
path: "somerepos",
input: "version=master&ref=v1.0.0",
ref: "v1.0.0",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t5": {
{
name: "empty_submodules",
// Empty submodules value uses default.
input: "somerepos?version=master&submodules=",
path: "somerepos",
input: "version=master&submodules=",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t6": {
{
name: "bad_submodules",
// Malformed submodules value uses default.
input: "somerepos?version=master&submodules=maybe",
path: "somerepos",
input: "version=master&submodules=maybe",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t7": {
input: "somerepos?version=master&submodules=true",
path: "somerepos",
{
name: "submodules_true",
input: "version=master&submodules=true",
ref: "master",
submodules: true,
timeout: defaultTimeout,
},
"t8": {
input: "somerepos?version=master&submodules=false",
path: "somerepos",
{
name: "submodules_false",
input: "version=master&submodules=false",
ref: "master",
submodules: false,
timeout: defaultTimeout,
},
"t9": {
{
name: "empty_timeout",
// Empty timeout value uses default.
input: "somerepos?version=master&timeout=",
path: "somerepos",
input: "version=master&timeout=",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t10": {
{
name: "bad_timeout",
// Malformed timeout value uses default.
input: "somerepos?version=master&timeout=jiffy",
path: "somerepos",
input: "version=master&timeout=jiffy",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t11": {
{
name: "zero_timeout",
// Zero timeout value uses default.
input: "somerepos?version=master&timeout=0",
path: "somerepos",
input: "version=master&timeout=0",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t12": {
input: "somerepos?version=master&timeout=0s",
path: "somerepos",
{
name: "zero_unit_timeout",
input: "version=master&timeout=0s",
ref: "master",
submodules: defaultSubmodules,
timeout: defaultTimeout,
},
"t13": {
input: "somerepos?version=master&timeout=61",
path: "somerepos",
{
name: "timeout",
input: "version=master&timeout=61",
ref: "master",
submodules: defaultSubmodules,
timeout: 61 * time.Second,
},
"t14": {
input: "somerepos?version=master&timeout=1m1s",
path: "somerepos",
{
name: "timeout_unit",
input: "version=master&timeout=1m1s",
ref: "master",
submodules: defaultSubmodules,
timeout: 61 * time.Second,
},
"t15": {
input: "somerepos?version=master&submodules=false&timeout=1m1s",
path: "somerepos",
{
name: "all",
input: "version=master&submodules=false&timeout=1m1s",
ref: "master",
submodules: false,
timeout: 61 * time.Second,
},
}
for tn, tc := range testcases {
t.Run(tn, func(t *testing.T) {
path, ref, timeout, submodules := peelQuery(tc.input)
assert.Equal(t, tc.path, path, "path mismatch")
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
ref, timeout, submodules := parseQuery(tc.input)
assert.Equal(t, tc.ref, ref, "ref mismatch")
assert.Equal(t, tc.timeout, timeout, "timeout mismatch")
assert.Equal(t, tc.submodules, submodules, "submodules mismatch")

View File

@@ -0,0 +1,7 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package localizer contains utilities for the command kustomize localize, which is
// documented under proposals/localize-command or at
// https://github.com/kubernetes-sigs/kustomize/blob/master/proposals/22-04-localize-command.md
package localizer

View File

@@ -0,0 +1,129 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package localizer
import (
"log"
"path/filepath"
"sigs.k8s.io/kustomize/api/ifc"
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/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/yaml"
)
// Localizer encapsulates all state needed to localize the root at ldr.
type Localizer struct {
fSys filesys.FileSystem
// kusttarget fields
validator ifc.Validator
rFactory *resmap.Factory
pLdr *pLdr.Loader
// underlying type is Loader
ldr ifc.Loader
// destination directory in newDir that mirrors ldr's current root.
dst filesys.ConfirmedDir
}
// NewLocalizer is the factory method for Localizer
func NewLocalizer(ldr *Loader, validator ifc.Validator, rFactory *resmap.Factory, pLdr *pLdr.Loader) (*Localizer, error) {
toDst, err := filepath.Rel(ldr.args.Scope.String(), ldr.Root())
if err != nil {
log.Fatalf("cannot find path from %q to child directory %q: %s", ldr.args.Scope, ldr.Root(), err)
}
dst := ldr.args.NewDir.Join(toDst)
if err = ldr.fSys.MkdirAll(dst); err != nil {
return nil, errors.WrapPrefixf(err, "unable to create directory in localize destination")
}
return &Localizer{
fSys: ldr.fSys,
validator: validator,
rFactory: rFactory,
pLdr: pLdr,
ldr: ldr,
dst: filesys.ConfirmedDir(dst),
}, nil
}
// Localize localizes the root that lc is at
func (lc *Localizer) Localize() error {
kt := target.NewKustTarget(lc.ldr, lc.validator, lc.rFactory, lc.pLdr)
err := kt.Load()
if err != nil {
return errors.Wrap(err)
}
kust, err := lc.processKust(kt)
if err != nil {
return err
}
content, err := yaml.Marshal(kust)
if err != nil {
return errors.WrapPrefixf(err, "unable to serialize localized kustomization file")
}
if err = lc.fSys.WriteFile(lc.dst.Join(konfig.DefaultKustomizationFileName()), content); err != nil {
return errors.WrapPrefixf(err, "unable to write localized kustomization file")
}
return nil
}
// processKust returns a copy of the kustomization at kt with paths localized.
func (lc *Localizer) processKust(kt *target.KustTarget) (*types.Kustomization, error) {
kust := kt.Kustomization()
for i := range kust.Patches {
if kust.Patches[i].Path != "" {
newPath, err := lc.localizeFile(kust.Patches[i].Path)
if err != nil {
return nil, errors.WrapPrefixf(err, "unable to localize patches path %q", kust.Patches[i].Path)
}
kust.Patches[i].Path = newPath
}
}
// TODO(annasong): localize all other kustomization fields: resources, components, crds, configurations,
// openapi, patchesStrategicMerge, replacements, configMapGenerators, secretGenerators
// TODO(annasong): localize built-in plugins under generators, transformers, and validators fields
return &kust, nil
}
// localizeFile localizes file path and returns the localized path
func (lc *Localizer) localizeFile(path string) (string, error) {
content, err := lc.ldr.Load(path)
if err != nil {
return "", errors.Wrap(err)
}
var locPath string
if loader.IsRemoteFile(path) {
// TODO(annasong): check if able to add localize directory
locPath = locFilePath(path)
} else {
// ldr has checked that path must be relative; this is subject to change in beta.
// We must clean path to:
// 1. avoid symlinks. A `kustomize build` run will fail if we write files to
// symlink paths outside the current root, given that we don't want to recreate
// the symlinks. Even worse, we could be writing files outside the localize destination.
// 2. avoid paths that temporarily traverse outside the current root,
// i.e. ../../../scope/target/current-root. The localized file will be surrounded by
// different directories than its source, and so an uncleaned path may no longer be valid.
locPath = cleanFilePath(lc.fSys, filesys.ConfirmedDir(lc.ldr.Root()), path)
// TODO(annasong): check if hits localize directory
}
absPath := lc.dst.Join(locPath)
if err = lc.fSys.MkdirAll(filepath.Dir(absPath)); err != nil {
return "", errors.WrapPrefixf(err, "unable to create directories to localize file %q", path)
}
if err = lc.fSys.WriteFile(absPath, content); err != nil {
return "", errors.WrapPrefixf(err, "unable to localize file %q", path)
}
return locPath, nil
}

View File

@@ -0,0 +1,301 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package localizer_test
import (
"fmt"
"io/fs"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/api/hasher"
. "sigs.k8s.io/kustomize/api/internal/localizer"
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/validate"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
const podConfiguration = `apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
`
func makeMemoryFs(t *testing.T) filesys.FileSystem {
t.Helper()
req := require.New(t)
fSys := filesys.MakeFsInMemory()
req.NoError(fSys.MkdirAll("/a/b"))
req.NoError(fSys.WriteFile("/a/pod.yaml", []byte(podConfiguration)))
dirChain := "/alpha/beta/gamma/delta"
req.NoError(fSys.MkdirAll(dirChain))
req.NoError(fSys.WriteFile(filepath.Join(dirChain, "deployment.yaml"), []byte("deployment configuration")))
req.NoError(fSys.Mkdir("/alpha/beta/say"))
return fSys
}
func addFiles(t *testing.T, fSys filesys.FileSystem, parentDir string, files map[string]string) {
t.Helper()
// in-memory file system makes all necessary dirs when writing files
for file, content := range files {
require.NoError(t, fSys.WriteFile(filepath.Join(parentDir, file), []byte(content)))
}
}
func createLocalizer(t *testing.T, fSys filesys.FileSystem, target string, scope string, newDir string) *Localizer {
t.Helper()
// no need to re-test Loader
ldr, _, err := NewLoader(target, scope, newDir, fSys)
require.NoError(t, err)
rmFactory := resmap.NewFactory(resource.NewFactory(&hasher.Hasher{}))
lc, err := NewLocalizer(
ldr,
validate.NewFieldValidator(),
rmFactory,
// file system can be in memory, as plugin configuration will prevent the use of file system anyway
loader.NewLoader(types.DisabledPluginConfig(), rmFactory, fSys))
require.NoError(t, err)
return lc
}
func checkFSys(t *testing.T, fSysExpected filesys.FileSystem, fSysActual filesys.FileSystem) {
t.Helper()
assert.Equal(t, fSysExpected, fSysActual)
if t.Failed() {
reportFSysDiff(t, fSysExpected, fSysActual)
}
}
func reportFSysDiff(t *testing.T, fSysExpected filesys.FileSystem, fSysActual filesys.FileSystem) {
t.Helper()
visited := make(map[string]struct{})
err := fSysActual.Walk("/", func(path string, info fs.FileInfo, err error) error {
require.NoError(t, err)
visited[path] = struct{}{}
if info.IsDir() {
assert.Truef(t, fSysExpected.IsDir(path), "unexpected directory %q", path)
} else {
actualContent, readErr := fSysActual.ReadFile(path)
require.NoError(t, readErr)
expectedContent, findErr := fSysExpected.ReadFile(path)
assert.NoError(t, findErr)
if findErr == nil {
assert.Equal(t, string(expectedContent), string(actualContent))
}
}
return nil
})
require.NoError(t, err)
err = fSysExpected.Walk("/", func(path string, info fs.FileInfo, err error) error {
require.NoError(t, err)
visited[path] = struct{}{}
if _, exists := visited[path]; !exists {
t.Errorf("expected path %q not found", path)
}
return nil
})
require.NoError(t, err)
}
func TestNewLocalizerTargetIsScope(t *testing.T) {
fSys := makeMemoryFs(t)
kustomization := map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: my-
`,
}
addFiles(t, fSys, "/a", kustomization)
lclzr := createLocalizer(t, fSys, "/a", "", "/a/b/dst")
require.NoError(t, lclzr.Localize())
fSysExpected := makeMemoryFs(t)
addFiles(t, fSysExpected, "/a", kustomization)
addFiles(t, fSysExpected, "/a/b/dst", kustomization)
checkFSys(t, fSysExpected, fSys)
}
func TestNewLocalizerTargetNestedInScope(t *testing.T) {
fSys := makeMemoryFs(t)
kustomization := map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- patch: |-
- op: replace
path: /some/existing/path
value: new value
target:
kind: Deployment
labelSelector: env=dev
`,
}
addFiles(t, fSys, "/a/b", kustomization)
lclzr := createLocalizer(t, fSys, "/a/b", "/", "/a/b/dst")
require.NoError(t, lclzr.Localize())
fSysExpected := makeMemoryFs(t)
addFiles(t, fSysExpected, "/a/b", kustomization)
addFiles(t, fSysExpected, "/a/b/dst/a/b", kustomization)
checkFSys(t, fSysExpected, fSys)
}
func TestLocalizeKustomizationName(t *testing.T) {
fSys := makeMemoryFs(t)
kustomization := map[string]string{
"Kustomization": `apiVersion: kustomize.config.k8s.io/v1beta1
commonLabels:
label-one: value-one
label-two: value-two
kind: Kustomization
`,
}
addFiles(t, fSys, "/a", kustomization)
lclzr := createLocalizer(t, fSys, "/a", "/", "/dst")
require.NoError(t, lclzr.Localize())
fSysExpected := makeMemoryFs(t)
addFiles(t, fSysExpected, "/a", kustomization)
addFiles(t, fSysExpected, "/dst/a", map[string]string{
"kustomization.yaml": kustomization["Kustomization"],
})
checkFSys(t, fSysExpected, fSys)
}
func TestLocalizeFileName(t *testing.T) {
for name, path := range map[string]string{
"nested_directories": "a/b/c/d/patch.yaml",
"localize_dir_name_when_absent": LocalizeDir,
"in_localize_dir_name_when_absent": fmt.Sprintf("%s/patch.yaml", LocalizeDir),
"no_file_extension": "patch",
"kustomization_name": "a/kustomization.yaml",
} {
t.Run(name, func(t *testing.T) {
fSys := makeMemoryFs(t)
kustAndPatch := map[string]string{
"kustomization.yaml": fmt.Sprintf(`apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- path: %s
`, path),
path: podConfiguration,
}
addFiles(t, fSys, "/a", kustAndPatch)
lclzr := createLocalizer(t, fSys, "/a", "/", "/a/dst")
require.NoError(t, lclzr.Localize())
fSysExpected := makeMemoryFs(t)
addFiles(t, fSysExpected, "/a", kustAndPatch)
addFiles(t, fSysExpected, "/a/dst/a", kustAndPatch)
checkFSys(t, fSysExpected, fSys)
})
}
}
func TestLocalizeFileCleaned(t *testing.T) {
fSys := makeMemoryFs(t)
kustAndPatch := map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- path: ../gamma/../../../alpha/beta/./gamma/patch.yaml
`,
"patch.yaml": podConfiguration,
}
addFiles(t, fSys, "/alpha/beta/gamma", kustAndPatch)
lclzr := createLocalizer(t, fSys, "/alpha/beta/gamma", "/", "")
require.NoError(t, lclzr.Localize())
fSysExpected := makeMemoryFs(t)
addFiles(t, fSysExpected, "/alpha/beta/gamma", kustAndPatch)
addFiles(t, fSysExpected, "/localized-gamma/alpha/beta/gamma", map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- path: patch.yaml
`,
"patch.yaml": podConfiguration,
})
checkFSys(t, fSysExpected, fSys)
}
func TestLocalizePatches(t *testing.T) {
fSys := makeMemoryFs(t)
kustAndPatch := map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- patch: |-
apiVersion: v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/version: 1.21.0
name: dummy-app
target:
labelSelector: app.kubernetes.io/name=nginx
- options:
allowNameChange: true
path: patch.yaml
`,
"patch.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Deployment
metadata:
name: not-used
spec:
template:
spec:
containers:
- name: nginx
image: nginx:1.21.0
`,
}
addFiles(t, fSys, "/", kustAndPatch)
lclzr := createLocalizer(t, fSys, "/", "", "")
require.NoError(t, lclzr.Localize())
fSysExpected := makeMemoryFs(t)
addFiles(t, fSysExpected, "/", kustAndPatch)
addFiles(t, fSysExpected, "/localized", kustAndPatch)
checkFSys(t, fSysExpected, fSys)
}
func TestLocalizeFileNoFile(t *testing.T) {
fSys := makeMemoryFs(t)
kustAndPatch := map[string]string{
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- path: name-DNE.yaml
`,
}
addFiles(t, fSys, "/a/b", kustAndPatch)
lclzr := createLocalizer(t, fSys, "/a/b", "", "/dst")
require.Error(t, lclzr.Localize())
}

View File

@@ -0,0 +1,135 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package localizer
import (
"path/filepath"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/git"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
// Args holds localize arguments
type Args struct {
// target; local copy if remote
Target filesys.ConfirmedDir
// directory that bounds target's local references
// repo directory of local copy if target is remote
Scope filesys.ConfirmedDir
// localize destination
NewDir filesys.ConfirmedDir
}
// Loader is an ifc.Loader that enforces additional constraints specific to kustomize localize.
type Loader struct {
fSys filesys.FileSystem
args *Args
// loader at Loader's current directory
ifc.Loader
// whether Loader and all its ancestors are the result of local references
local bool
}
var _ ifc.Loader = &Loader{}
// NewLoader is the factory method for Loader, under localize constraints, at rawTarget. For invalid localize arguments,
// NewLoader returns an error.
func NewLoader(rawTarget string, rawScope string, rawNewDir string, fSys filesys.FileSystem) (*Loader, Args, error) {
// check earlier to avoid cleanup
repoSpec, err := git.NewRepoSpecFromURL(rawTarget)
if err == nil && repoSpec.Ref == "" {
return nil, Args{}, errors.Errorf("localize remote root %q missing ref query string parameter", rawTarget)
}
// for security, should enforce load restrictions
ldr, err := loader.NewLoader(loader.RestrictionRootOnly, rawTarget, fSys)
if err != nil {
return nil, Args{}, errors.WrapPrefixf(err, "unable to establish localize target %q", rawTarget)
}
scope, err := establishScope(rawScope, rawTarget, ldr, fSys)
if err != nil {
_ = ldr.Cleanup()
return nil, Args{}, errors.WrapPrefixf(err, "invalid localize scope %q", rawScope)
}
newDir, err := createNewDir(rawNewDir, ldr, repoSpec, fSys)
if err != nil {
_ = ldr.Cleanup()
return nil, Args{}, errors.WrapPrefixf(err, "invalid localize destination %q", rawNewDir)
}
args := Args{
Target: filesys.ConfirmedDir(ldr.Root()),
Scope: scope,
NewDir: newDir,
}
return &Loader{
fSys: fSys,
args: &args,
Loader: ldr,
local: scope != "",
}, args, nil
}
// Load returns the contents of path if path is a valid localize file.
// Otherwise, Load returns an error.
func (ll *Loader) Load(path string) ([]byte, error) {
// checks in root, and thus in scope
content, err := ll.Loader.Load(path)
if err != nil {
return nil, errors.WrapPrefixf(err, "invalid file reference")
}
if filepath.IsAbs(path) {
return nil, errors.Errorf("absolute paths not yet supported in alpha: file path %q is absolute", path)
}
if ll.local {
cleanPath := cleanFilePath(ll.fSys, filesys.ConfirmedDir(ll.Root()), path)
cleanAbs := filepath.Join(ll.Root(), cleanPath)
dir := filesys.ConfirmedDir(filepath.Dir(cleanAbs))
// target cannot reference newDir, as this load would've failed prior to localize;
// not a problem if remote because then reference could only be in newDir if repo copy,
// which will be cleaned, is inside newDir
if dir.HasPrefix(ll.args.NewDir) {
return nil, errors.Errorf("file %q at %q enters localize destination %q", path, cleanAbs, ll.args.NewDir)
}
}
return content, nil
}
// New returns a Loader at path if path is a valid localize root.
// Otherwise, New returns an error.
func (ll *Loader) New(path string) (ifc.Loader, error) {
ldr, err := ll.Loader.New(path)
if err != nil {
return nil, errors.WrapPrefixf(err, "invalid root reference")
}
if repo := ldr.Repo(); repo == "" {
if ll.local && !filesys.ConfirmedDir(ldr.Root()).HasPrefix(ll.args.Scope) {
return nil, errors.Errorf("root %q outside localize scope %q", ldr.Root(), ll.args.Scope)
}
if ll.local && filesys.ConfirmedDir(ldr.Root()).HasPrefix(ll.args.NewDir) {
return nil, errors.Errorf(
"root %q references into localize destination %q", ldr.Root(), ll.args.NewDir)
}
} else if !hasRef(path) {
return nil, errors.Errorf("localize remote root %q missing ref query string parameter", path)
}
return &Loader{
fSys: ll.fSys,
args: ll.args,
Loader: ldr,
local: ll.local && ldr.Repo() == "",
}, nil
}

View File

@@ -0,0 +1,293 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package localizer_test
import (
"bytes"
"log"
"testing"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/api/ifc"
. "sigs.k8s.io/kustomize/api/internal/localizer"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
func checkNewLoader(req *require.Assertions, ldr *Loader, args *Args, target string, scope string, newDir string, fSys filesys.FileSystem) {
checkLoader(req, ldr, target)
checkArgs(req, args, target, scope, newDir, fSys)
}
func checkLoader(req *require.Assertions, ldr ifc.Loader, root string) {
req.Equal(root, ldr.Root())
req.Empty(ldr.Repo())
}
func checkArgs(req *require.Assertions, args *Args, target string, scope string, newDir string, fSys filesys.FileSystem) {
req.Equal(target, args.Target.String())
req.Equal(scope, args.Scope.String())
req.Equal(newDir, args.NewDir.String())
req.True(fSys.Exists(newDir))
}
func TestLocalLoadNewAndCleanup(t *testing.T) {
req := require.New(t)
fSys := makeMemoryFs(t)
var buf bytes.Buffer
log.SetOutput(&buf)
// typical setup
ldr, args, err := NewLoader("a", "/", "/newDir", fSys)
req.NoError(err)
checkNewLoader(req, ldr, &args, "/a", "/", "/newDir", fSys)
fSysCopy := makeMemoryFs(t)
req.NoError(fSysCopy.Mkdir("/newDir"))
req.Equal(fSysCopy, fSys)
// easy load directly in root
content, err := ldr.Load("pod.yaml")
req.NoError(err)
req.Equal([]byte(podConfiguration), content)
// typical sibling root reference
sibLdr, err := ldr.New("../alpha")
req.NoError(err)
checkLoader(req, sibLdr, "/alpha")
// only need to test once, since don't need to call Cleanup() on local target
req.NoError(sibLdr.Cleanup())
req.NoError(ldr.Cleanup())
// file system and buffer checks are also one-time
req.Equal(fSysCopy, fSys)
req.Empty(buf.String())
}
func TestNewLocLoaderDefaultForRootTarget(t *testing.T) {
cases := map[string]struct {
target string
scope string
}{
"explicit": {
"/",
".",
},
"implicit": {
".",
"",
},
}
for name, params := range cases {
params := params
t.Run(name, func(t *testing.T) {
req := require.New(t)
fSys := makeMemoryFs(t)
ldr, args, err := NewLoader(params.target, params.scope, "", fSys)
req.NoError(err)
checkNewLoader(req, ldr, &args, "/", "/", "/"+DstPrefix, fSys)
// file in root, but nested
content, err := ldr.Load("a/pod.yaml")
req.NoError(err)
req.Equal([]byte(podConfiguration), content)
childLdr, err := ldr.New("a")
req.NoError(err)
checkLoader(req, childLdr, "/a")
// messy, uncleaned path
content, err = childLdr.Load("./../a/pod.yaml")
req.NoError(err)
req.Equal([]byte(podConfiguration), content)
})
}
}
func TestNewMultiple(t *testing.T) {
req := require.New(t)
fSys := makeMemoryFs(t)
// default destination for non-file system root target
// destination outside of scope
ldr, args, err := NewLoader("/alpha/beta", "/alpha", "", fSys)
req.NoError(err)
checkNewLoader(req, ldr, &args, "/alpha/beta", "/alpha", "/"+DstPrefix+"-beta", fSys)
// nested child root that isn't cleaned
descLdr, err := ldr.New("../beta/gamma/delta")
req.NoError(err)
checkLoader(req, descLdr, "/alpha/beta/gamma/delta")
// upwards traversal
higherLdr, err := descLdr.New("../../say")
req.NoError(err)
checkLoader(req, higherLdr, "/alpha/beta/say")
}
func makeWdFs(t *testing.T) map[string]filesys.FileSystem {
t.Helper()
req := require.New(t)
root := filesys.MakeEmptyDirInMemory()
req.NoError(root.MkdirAll("a/b/c/d/e"))
outer, err := root.Find("a")
req.NoError(err)
middle, err := root.Find("a/b/c")
req.NoError(err)
return map[string]filesys.FileSystem{
"a": outer,
"a/b/c": middle,
}
}
func TestNewLocLoaderCwdNotRoot(t *testing.T) {
cases := map[string]struct {
wd string
target string
scope string
newDir string
}{
// target not immediate child of scope
"outer dir": {
"a",
"b/c/d/e",
"b/c",
"b/newDir",
},
"scope": {
"a/b/c",
"d/e",
".",
"d/e/newDir",
},
}
for name, test := range cases {
test := test
t.Run(name, func(t *testing.T) {
req := require.New(t)
fSys := makeWdFs(t)[test.wd]
ldr, args, err := NewLoader(test.target, test.scope, test.newDir, fSys)
req.NoError(err)
checkLoader(req, ldr, "a/b/c/d/e")
req.Equal("a/b/c/d/e", args.Target.String())
req.Equal("a/b/c", args.Scope.String())
req.Equal(test.wd+"/"+test.newDir, args.NewDir.String())
// memory file system can only find paths rooted at current node
req.True(fSys.Exists(test.newDir))
})
}
}
func TestNewLocLoaderFails(t *testing.T) {
cases := map[string]struct {
target string
scope string
dest string
}{
"non-existent target": {
"/b",
"/",
"/newDir",
},
"file target": {
"/a/pod.yaml",
"/",
"/newDir",
},
"inner scope": {
"/alpha",
"/alpha/beta",
"/newDir",
},
"side scope": {
"/alpha",
"/a",
"/newDir",
},
"existing dst": {
"/alpha",
"/",
"/a",
},
}
for name, params := range cases {
params := params
t.Run(name, func(t *testing.T) {
var buf bytes.Buffer
log.SetOutput(&buf)
_, _, err := NewLoader(params.target, params.scope, params.dest, makeMemoryFs(t))
require.Error(t, err)
require.Empty(t, buf.String())
})
}
}
func TestNewFails(t *testing.T) {
req := require.New(t)
fSys := makeMemoryFs(t)
ldr, args, err := NewLoader("/alpha/beta/gamma", "alpha", "alpha/beta/gamma/newDir", fSys)
req.NoError(err)
checkNewLoader(req, ldr, &args, "/alpha/beta/gamma", "/alpha", "/alpha/beta/gamma/newDir", fSys)
cases := map[string]string{
"outside scope": "../../../a",
"at dst": "newDir",
"ancestor": "../../beta",
"non-existent root": "delt",
"file": "delta/deployment.yaml",
}
for name, root := range cases {
root := root
t.Run(name, func(t *testing.T) {
fSys := makeMemoryFs(t)
ldr, _, err := NewLoader("/alpha/beta/gamma", "alpha", "alpha/beta/gamma/newDir", fSys)
require.NoError(t, err)
_, err = ldr.New(root)
require.Error(t, err)
})
}
}
func TestLoadFails(t *testing.T) {
req := require.New(t)
fSys := makeMemoryFs(t)
ldr, args, err := NewLoader("./a/../a", "/a/../a", "/a/newDir", fSys)
req.NoError(err)
checkNewLoader(req, ldr, &args, "/a", "/a", "/a/newDir", fSys)
cases := map[string]string{
"absolute path": "/a/pod.yaml",
"directory": "b",
"non-existent file": "kubectl.yaml",
"file outside root": "../alpha/beta/gamma/delta/deployment.yaml",
"inside dst": "newDir/pod.yaml",
}
for name, file := range cases {
file := file
t.Run(name, func(t *testing.T) {
req := require.New(t)
fSys := makeMemoryFs(t)
ldr, _, err := NewLoader("./a/../a", "/a/../a", "/a/newDir", fSys)
req.NoError(err)
req.NoError(fSys.WriteFile("/a/newDir/pod.yaml", []byte(podConfiguration)))
_, err = ldr.Load(file)
req.Error(err)
})
}
}

View File

@@ -0,0 +1,127 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package localizer
import (
"log"
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/git"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
// DstPrefix prefixes the target and ref, if target is remote, in the default localize destination directory name
const DstPrefix = "localized"
// LocalizeDir is the name of the localize directories used to store remote content in the localize destination
const LocalizeDir = "localized-files"
// establishScope returns the effective scope given localize arguments and targetLdr at rawTarget. For remote rawTarget,
// the effective scope is the downloaded repo.
func establishScope(rawScope string, rawTarget string, targetLdr ifc.Loader, fSys filesys.FileSystem) (filesys.ConfirmedDir, error) {
if repo := targetLdr.Repo(); repo != "" {
if rawScope != "" {
return "", errors.Errorf("scope %q specified for remote localize target %q", rawScope, rawTarget)
}
return filesys.ConfirmedDir(repo), nil
}
// default scope
if rawScope == "" {
return filesys.ConfirmedDir(targetLdr.Root()), nil
}
scope, err := filesys.ConfirmDir(fSys, rawScope)
if err != nil {
return "", errors.WrapPrefixf(err, "unable to establish localize scope")
}
if !filesys.ConfirmedDir(targetLdr.Root()).HasPrefix(scope) {
return scope, errors.Errorf("localize scope %q does not contain target %q at %q", rawScope, rawTarget,
targetLdr.Root())
}
return scope, nil
}
// createNewDir returns the localize destination directory or error. Note that spec is nil if targetLdr is at local
// target.
func createNewDir(rawNewDir string, targetLdr ifc.Loader, spec *git.RepoSpec, fSys filesys.FileSystem) (filesys.ConfirmedDir, error) {
if rawNewDir == "" {
rawNewDir = defaultNewDir(targetLdr, spec)
}
if fSys.Exists(rawNewDir) {
return "", errors.Errorf("localize destination %q already exists", rawNewDir)
}
// destination directory must sit in an existing directory
if err := fSys.Mkdir(rawNewDir); err != nil {
return "", errors.WrapPrefixf(err, "unable to create localize destination directory")
}
newDir, err := filesys.ConfirmDir(fSys, rawNewDir)
if err != nil {
if errCleanup := fSys.RemoveAll(newDir.String()); errCleanup != nil {
log.Printf("%s", errors.WrapPrefixf(errCleanup, "unable to clean localize destination"))
}
return "", errors.WrapPrefixf(err, "unable to establish localize destination")
}
return newDir, nil
}
// defaultNewDir calculates the default localize destination directory name from targetLdr at the localize target
// and spec of target, which is nil if target is local
func defaultNewDir(targetLdr ifc.Loader, spec *git.RepoSpec) string {
targetDir := filepath.Base(targetLdr.Root())
if repo := targetLdr.Repo(); repo != "" {
// kustomize doesn't download repo into repo-named folder
// must find repo folder name from url
if repo == targetLdr.Root() {
targetDir = urlBase(spec.OrgRepo)
}
return strings.Join([]string{DstPrefix, targetDir, strings.ReplaceAll(spec.Ref, "/", "-")}, "-")
}
// special case for local target directory since destination directory cannot have "/" in name
if targetDir == string(filepath.Separator) {
return DstPrefix
}
return strings.Join([]string{DstPrefix, targetDir}, "-")
}
// urlBase is the url equivalent of filepath.Base
func urlBase(url string) string {
cleaned := strings.TrimRight(url, "/")
i := strings.LastIndex(cleaned, "/")
if i < 0 {
return cleaned
}
return cleaned[i+1:]
}
// hasRef checks if repoURL has ref query string parameter
func hasRef(repoURL string) bool {
repoSpec, err := git.NewRepoSpecFromURL(repoURL)
if err != nil {
log.Fatalf("unable to parse validated root url: %s", err)
}
return repoSpec.Ref != ""
}
// cleanFilePath returns file cleaned, where file is a relative path to root on fSys
func cleanFilePath(fSys filesys.FileSystem, root filesys.ConfirmedDir, file string) string {
abs := root.Join(file)
dir, f, err := fSys.CleanedAbs(abs)
if err != nil {
log.Fatalf("cannot clean validated file path %q: %s", abs, err)
}
locPath, err := filepath.Rel(root.String(), dir.Join(f))
if err != nil {
log.Fatalf("cannot find path from parent %q to file %q: %s", root, dir.Join(f), err)
}
return locPath
}
// locFilePath returns the relative localized path of validated file url fileURL
// TODO(annasong): implement
func locFilePath(_ string) string {
return filepath.Join(LocalizeDir, "")
}

View File

@@ -0,0 +1,18 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package localizer //nolint:testpackage
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestUrlBase(t *testing.T) {
require.Equal(t, "repo", urlBase("https://github.com/org/repo"))
}
func TestUrlBaseTrailingSlash(t *testing.T) {
require.Equal(t, "repo", urlBase("github.com/org/repo//"))
}

View File

@@ -22,7 +22,7 @@ import (
// contains a Pod; Deployment, Job, StatefulSet, etc.
// The ConfigMap is the ReferralTarget, the others are Referrers.
//
// If the the name of a ConfigMap instance changed from 'alice' to 'bob',
// If the name of a ConfigMap instance changed from 'alice' to 'bob',
// one must
// - visit all objects that could refer to the ConfigMap (the Referrers)
// - see if they mention 'alice',

View File

@@ -10,6 +10,7 @@ import (
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
)
// TransformerConfig holds the data needed to perform transformations.
@@ -18,6 +19,7 @@ type TransformerConfig struct {
NameSuffix types.FsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
NameSpace types.FsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
CommonLabels types.FsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`
TemplateLabels types.FsSlice `json:"templateLabels,omitempty" yaml:"templateLabels,omitempty"`
CommonAnnotations types.FsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
VarReference types.FsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
@@ -60,6 +62,7 @@ func (t *TransformerConfig) sortFields() {
sort.Sort(t.NamePrefix)
sort.Sort(t.NameSpace)
sort.Sort(t.CommonLabels)
sort.Sort(t.TemplateLabels)
sort.Sort(t.CommonAnnotations)
sort.Sort(t.NameReference)
sort.Sort(t.VarReference)
@@ -108,40 +111,44 @@ func (t *TransformerConfig) Merge(input *TransformerConfig) (
merged = &TransformerConfig{}
merged.NamePrefix, err = t.NamePrefix.MergeAll(input.NamePrefix)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge NamePrefix fieldSpec")
}
merged.NameSuffix, err = t.NameSuffix.MergeAll(input.NameSuffix)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge NameSuffix fieldSpec")
}
merged.NameSpace, err = t.NameSpace.MergeAll(input.NameSpace)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge NameSpace fieldSpec")
}
merged.CommonAnnotations, err = t.CommonAnnotations.MergeAll(
input.CommonAnnotations)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge CommonAnnotations fieldSpec")
}
merged.CommonLabels, err = t.CommonLabels.MergeAll(input.CommonLabels)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge CommonLabels fieldSpec")
}
merged.TemplateLabels, err = t.TemplateLabels.MergeAll(input.TemplateLabels)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to merge TemplateLabels fieldSpec")
}
merged.VarReference, err = t.VarReference.MergeAll(input.VarReference)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge VarReference fieldSpec")
}
merged.NameReference, err = t.NameReference.mergeAll(input.NameReference)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge NameReference fieldSpec")
}
merged.Images, err = t.Images.MergeAll(input.Images)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge Images fieldSpec")
}
merged.Replicas, err = t.Replicas.MergeAll(input.Replicas)
if err != nil {
return nil, err
return nil, errors.WrapPrefixf(err, "failed to merge Replicas fieldSpec")
}
merged.sortFields()
return merged, nil

View File

@@ -36,7 +36,7 @@ const (
var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
func init() {
func init() { //nolint:gochecknoinits
stringToBuiltinPluginTypeMap = makeStringToBuiltinPluginTypeMap()
}

View File

@@ -6,7 +6,6 @@ package execplugin
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"runtime"
@@ -150,7 +149,7 @@ func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
// passes the full temp file path as the first arg to a process
// running the plugin binary. Process output is returned.
func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
f, err := ioutil.TempFile("", tmpConfigFilePrefix)
f, err := os.CreateTemp("", tmpConfigFilePrefix)
if err != nil {
return nil, errors.Wrap(
err, "creating tmp plugin config file")

View File

@@ -83,7 +83,6 @@ metadata:
`
if expected != string(p.Cfg()) {
t.Fatalf("expected cfg '%s', got '%s'", expected, string(p.Cfg()))
}
if len(p.Args()) != 6 {
t.Fatalf("unexpected arg len %d, %#v", len(p.Args()), p.Args())

View File

@@ -51,13 +51,16 @@ func resourceToRNode(res *resource.Resource) (*yaml.RNode, error) {
}
// GetFunctionSpec return function spec is there is. Otherwise return nil
func GetFunctionSpec(res *resource.Resource) *runtimeutil.FunctionSpec {
func GetFunctionSpec(res *resource.Resource) (*runtimeutil.FunctionSpec, error) {
rnode, err := resourceToRNode(res)
if err != nil {
return nil
return nil, fmt.Errorf("could not convert resource to RNode: %w", err)
}
return runtimeutil.GetFunctionSpec(rnode)
functionSpec, err := runtimeutil.GetFunctionSpec(rnode)
if err != nil {
return nil, fmt.Errorf("failed to get FunctionSpec: %w", err)
}
return functionSpec, nil
}
func toStorageMounts(mounts []string) []runtimeutil.StorageMount {

View File

@@ -42,27 +42,35 @@ func NewLoader(
return &Loader{pc: pc, rf: rf, fs: fs}
}
// LoaderWithWorkingDir returns loader after setting its working directory.
// NOTE: This is not really a new loader since some of the Loader struct fields are pointers.
func (l *Loader) LoaderWithWorkingDir(wd string) *Loader {
lpc := &types.PluginConfig{
PluginRestrictions: l.pc.PluginRestrictions,
BpLoadingOptions: l.pc.BpLoadingOptions,
FnpLoadingOptions: l.pc.FnpLoadingOptions,
HelmConfig: l.pc.HelmConfig,
}
lpc.FnpLoadingOptions.WorkingDir = wd
return &Loader{pc: lpc, rf: l.rf, fs: l.fs}
}
// Config provides the global (not plugin specific) PluginConfig data.
func (l *Loader) Config() *types.PluginConfig {
return l.pc
}
// SetWorkDir sets the working directory for this loader's plugins
func (l *Loader) SetWorkDir(wd string) {
l.pc.FnpLoadingOptions.WorkingDir = wd
}
func (l *Loader) LoadGenerators(
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) (
result []*resmap.GeneratorWithProperties, err error) {
for _, res := range rm.Resources() {
g, err := l.LoadGenerator(ldr, v, res)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to load generator: %w", err)
}
generatorOrigin, err := resource.OriginFromCustomPlugin(res)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to get origin from CustomPlugin: %w", err)
}
result = append(result, &resmap.GeneratorWithProperties{Generator: g, Origin: generatorOrigin})
}
@@ -130,15 +138,19 @@ func (l *Loader) AbsolutePluginPath(id resid.ResId) (string, error) {
// absPluginHome is the home of kustomize Exec and Go plugins.
// Kustomize plugin configuration files are k8s-style objects
// containing the fields 'apiVersion' and 'kind', e.g.
// apiVersion: apps/v1
// kind: Deployment
//
// apiVersion: apps/v1
// kind: Deployment
//
// kustomize reads plugin configuration data from a file path
// specified in the 'generators:' or 'transformers:' field of a
// kustomization file. For Exec and Go plugins, kustomize
// uses this data to both locate the plugin and configure it.
// Each Exec or Go plugin (its code, its tests, its supporting data
// files, etc.) must be housed in its own directory at
// ${absPluginHome}/${pluginApiVersion}/LOWERCASE(${pluginKind})
//
// ${absPluginHome}/${pluginApiVersion}/LOWERCASE(${pluginKind})
//
// where
// - ${absPluginHome} is an absolute path, defined below.
// - ${pluginApiVersion} is taken from the plugin config file.
@@ -226,8 +238,22 @@ func (l *Loader) makeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
}
func (l *Loader) loadPlugin(res *resource.Resource) (resmap.Configurable, error) {
spec := fnplugin.GetFunctionSpec(res)
spec, err := fnplugin.GetFunctionSpec(res)
if err != nil {
return nil, fmt.Errorf("loader: %w", err)
}
if spec != nil {
// validation check that function mounts are under the current kustomization directory
for _, mount := range spec.Container.StorageMounts {
if filepath.IsAbs(mount.Src) {
return nil, errors.New(fmt.Sprintf("plugin %s with mount path '%s' is not permitted; "+
"mount paths must be relative to the current kustomization directory", res.OrgId(), mount.Src))
}
if strings.HasPrefix(filepath.Clean(mount.Src), "../") {
return nil, errors.New(fmt.Sprintf("plugin %s with mount path '%s' is not permitted; "+
"mount paths must be under the current kustomization directory", res.OrgId(), mount.Src))
}
}
return fnplugin.NewFnPlugin(&l.pc.FnpLoadingOptions), nil
}
return l.loadExecOrGoPlugin(res.OrgId())

View File

@@ -6,6 +6,7 @@ package loader_test
import (
"testing"
"github.com/stretchr/testify/require"
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
@@ -78,3 +79,20 @@ func TestLoader(t *testing.T) {
}
}
}
func TestLoaderWithWorkingDir(t *testing.T) {
p := provider.NewDefaultDepProvider()
rmF := resmap.NewFactory(p.GetResourceFactory())
fsys := filesys.MakeFsInMemory()
c := types.EnabledPluginConfig(types.BploLoadFromFileSys)
pLdr := NewLoader(c, rmF, fsys)
npLdr := pLdr.LoaderWithWorkingDir("/tmp/dummy")
require.Equal(t,
"",
pLdr.Config().FnpLoadingOptions.WorkingDir,
"the plugin working dir should not change")
require.Equal(t,
"/tmp/dummy",
npLdr.Config().FnpLoadingOptions.WorkingDir,
"the plugin working dir is not updated")
}

View File

@@ -105,10 +105,10 @@ func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
"TrUe",
"potato",
}
for i, c := range cases {
for i := range cases {
name := fmt.Sprintf("test%d", i)
in := resmap.New()
err := in.Append(makeConfigMap(rf, name, "", &c))
err := in.Append(makeConfigMap(rf, name, "", &cases[i]))
require.NoError(t, err)
_, err = UpdateResourceOptions(in)
require.Error(t, err)

View File

@@ -6,7 +6,7 @@ package target
import (
"encoding/json"
"fmt"
"path/filepath"
"os"
"strings"
"github.com/pkg/errors"
@@ -45,13 +45,11 @@ func NewKustTarget(
validator ifc.Validator,
rFactory *resmap.Factory,
pLdr *loader.Loader) *KustTarget {
pLdrCopy := *pLdr
pLdrCopy.SetWorkDir(ldr.Root())
return &KustTarget{
ldr: ldr,
validator: validator,
rFactory: rFactory,
pLdr: &pLdrCopy,
pLdr: pLdr.LoaderWithWorkingDir(ldr.Root()),
}
}
@@ -70,6 +68,15 @@ func (kt *KustTarget) Load() error {
if err != nil {
return err
}
// show warning message when using deprecated fields.
warningMessages := k.CheckDeprecatedFields()
if warningMessages != nil {
for _, msg := range *warningMessages {
fmt.Fprintf(os.Stderr, "%v\n", msg)
}
}
k.FixKustomizationPostUnmarshalling()
errs := k.EnforceFields()
if len(errs) > 0 {
@@ -304,7 +311,9 @@ func (kt *KustTarget) configureExternalGenerators() (
rm.Replace(r)
}
}
ra.AppendAll(rm)
if err = ra.AppendAll(rm); err != nil {
return nil, errors.Wrapf(err, "configuring external generator")
}
}
ra, err := kt.accumulateResources(ra, generatorPaths)
if err != nil {
@@ -348,7 +357,10 @@ func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]*r
rm.Replace(r)
}
}
ra.AppendAll(rm)
if err = ra.AppendAll(rm); err != nil {
return nil, errors.Wrapf(err, "configuring external transformer")
}
}
ra, err := kt.accumulateResources(ra, transformerPaths)
if err != nil {
@@ -403,14 +415,14 @@ func (kt *KustTarget) accumulateResources(
// try loading resource as file then as base (directory or git repository)
if errF := kt.accumulateFile(ra, path); errF != nil {
// not much we can do if the error is an HTTP error so we bail out
if errors.Is(errF, load.ErrorHTTP) {
return nil, errF
}
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
if errors.Is(errF, load.ErrHTTP) {
return nil, errF
}
ldr, err := kt.ldr.New(path)
if err != nil {
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
return nil, errF
}
return nil, errors.Wrapf(
err, "accumulation err='%s'", errF.Error())
}
@@ -425,6 +437,9 @@ func (kt *KustTarget) accumulateResources(
ra, err = kt.accumulateDirectory(ra, ldr, false)
}
if err != nil {
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
return nil, errF
}
return nil, errors.Wrapf(
err, "accumulation err='%s'", errF.Error())
}
@@ -473,9 +488,8 @@ func (kt *KustTarget) accumulateDirectory(
subKt.kustomization.BuildMetadata = kt.kustomization.BuildMetadata
subKt.origin = kt.origin
var bytes []byte
path := ldr.Root()
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
bytes, err = ldr.Load(filepath.Join(path, openApiPath))
bytes, err = ldr.Load(openApiPath)
if err != nil {
return nil, err
}

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"path/filepath"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
"sigs.k8s.io/kustomize/api/resmap"
@@ -285,6 +286,13 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
if label.IncludeSelectors {
fss, err = fss.MergeAll(tc.CommonLabels)
} else {
// merge spec/template/metadata fieldSpecs if includeTemplate flag is true
if label.IncludeTemplates {
fss, err = fss.MergeAll(tc.TemplateLabels)
if err != nil {
return nil, errors.Wrap(err, "failed to merge template fieldSpec")
}
}
// only add to metadata by default
fss, err = fss.MergeOne(types.FieldSpec{Path: "metadata/labels", CreateIfNotPresent: true})
}

View File

@@ -257,3 +257,71 @@ metadata:
assert.NoError(t, err)
assert.Equal(t, string(expYaml), string(actYaml))
}
func TestDuplicateExternalGeneratorsForbidden(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/generator", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
generators:
- |-
apiVersion: generators.example/v1
kind: ManifestGenerator
metadata:
name: ManifestGenerator
annotations:
config.kubernetes.io/function: |
container:
image: ManifestGenerator:latest
spec:
image: 'someimage:12345'
configPath: config.json
- |-
apiVersion: generators.example/v1
kind: ManifestGenerator
metadata:
name: ManifestGenerator
annotations:
config.kubernetes.io/function: |
container:
image: ManifestGenerator:latest
spec:
image: 'someimage:12345'
configPath: another_config.json
`)
_, err := makeAndLoadKustTarget(t, th.GetFSys(), "/generator").AccumulateTarget()
assert.Error(t, err)
assert.Contains(t, err.Error(), "may not add resource with an already registered id: ManifestGenerator.v1.generators.example/ManifestGenerator")
}
func TestDuplicateExternalTransformersForbidden(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/transformer", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
transformers:
- |-
apiVersion: transformers.example.co/v1
kind: ValueAnnotator
metadata:
name: notImportantHere
annotations:
config.kubernetes.io/function: |
container:
image: example.docker.com/my-functions/valueannotator:1.0.0
value: 'pass'
- |-
apiVersion: transformers.example.co/v1
kind: ValueAnnotator
metadata:
name: notImportantHere
annotations:
config.kubernetes.io/function: |
container:
image: example.docker.com/my-functions/valueannotator:1.0.0
value: 'fail'
`)
_, err := makeAndLoadKustTarget(t, th.GetFSys(), "/transformer").AccumulateTarget()
assert.Error(t, err)
assert.Contains(t, err.Error(), "may not add resource with an already registered id: ValueAnnotator.v1.transformers.example.co/notImportantHere")
}

View File

@@ -20,6 +20,7 @@ func makeAndLoadKustTarget(
t *testing.T,
fSys filesys.FileSystem,
root string) *target.KustTarget {
t.Helper()
kt := makeKustTargetWithRf(t, fSys, root, provider.NewDefaultDepProvider())
if err := kt.Load(); err != nil {
t.Fatalf("Unexpected load error %v", err)
@@ -32,6 +33,7 @@ func makeKustTargetWithRf(
fSys filesys.FileSystem,
root string,
pvd *provider.DepProvider) *target.KustTarget {
t.Helper()
ldr, err := fLdr.NewLoader(fLdr.RestrictionRootOnly, root, fSys)
if err != nil {
t.Fatal(err)

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import "sigs.k8s.io/kustomize/api/konfig"

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import (
@@ -46,12 +49,9 @@ func PrevIds(n *yaml.RNode) ([]resid.ResId, error) {
"number of previous namespaces, " +
"number of previous kinds not equal")
}
apiVersion := n.GetApiVersion()
group, version := resid.ParseGroupVersion(apiVersion)
for i := range names {
meta, err := n.GetMeta()
if err != nil {
return nil, err
}
group, version := resid.ParseGroupVersion(meta.APIVersion)
gvk := resid.Gvk{
Group: group,
Version: version,

View File

@@ -5,9 +5,6 @@ package builtinpluginconsts
const commonLabelFieldSpecs = `
commonLabels:
- path: metadata/labels
create: true
- path: spec/selector
create: true
version: v1
@@ -17,20 +14,10 @@ commonLabels:
create: true
version: v1
kind: ReplicationController
- path: spec/template/metadata/labels
create: true
version: v1
kind: ReplicationController
- path: spec/selector/matchLabels
create: true
kind: Deployment
- path: spec/template/metadata/labels
create: true
kind: Deployment
- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
@@ -60,28 +47,15 @@ commonLabels:
create: true
kind: ReplicaSet
- path: spec/template/metadata/labels
create: true
kind: ReplicaSet
- path: spec/selector/matchLabels
create: true
kind: DaemonSet
- path: spec/template/metadata/labels
create: true
kind: DaemonSet
- path: spec/selector/matchLabels
create: true
group: apps
kind: StatefulSet
- path: spec/template/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
@@ -107,36 +81,16 @@ commonLabels:
group: apps
kind: StatefulSet
- path: spec/volumeClaimTemplates[]/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/selector/matchLabels
create: false
group: batch
kind: Job
- path: spec/template/metadata/labels
create: true
group: batch
kind: Job
- path: spec/jobTemplate/spec/selector/matchLabels
create: false
group: batch
kind: CronJob
- path: spec/jobTemplate/metadata/labels
create: true
group: batch
kind: CronJob
- path: spec/jobTemplate/spec/template/metadata/labels
create: true
group: batch
kind: CronJob
- path: spec/selector/matchLabels
create: false
group: policy
@@ -156,4 +110,4 @@ commonLabels:
create: false
group: networking.k8s.io
kind: NetworkPolicy
`
` + metadataLabelsFieldSpecs

View File

@@ -13,6 +13,7 @@ func GetDefaultFieldSpecs() []byte {
[]byte(namePrefixFieldSpecs),
[]byte(nameSuffixFieldSpecs),
[]byte(commonLabelFieldSpecs),
[]byte(templateLabelFieldSpecs),
[]byte(commonAnnotationFieldSpecs),
[]byte(namespaceFieldSpecs),
[]byte(varReferenceFieldSpecs),
@@ -30,6 +31,7 @@ func GetDefaultFieldSpecsAsMap() map[string]string {
result["nameprefix"] = namePrefixFieldSpecs
result["namesuffix"] = nameSuffixFieldSpecs
result["commonlabels"] = commonLabelFieldSpecs
result["templatelabels"] = templateLabelFieldSpecs
result["commonannotations"] = commonAnnotationFieldSpecs
result["namespace"] = namespaceFieldSpecs
result["varreference"] = varReferenceFieldSpecs

View File

@@ -0,0 +1,51 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package builtinpluginconsts
const metadataLabelsFieldSpecs = `
- path: metadata/labels
create: true
- path: spec/template/metadata/labels
create: true
version: v1
kind: ReplicationController
- path: spec/template/metadata/labels
create: true
kind: Deployment
- path: spec/template/metadata/labels
create: true
kind: ReplicaSet
- path: spec/template/metadata/labels
create: true
kind: DaemonSet
- path: spec/template/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/volumeClaimTemplates[]/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/template/metadata/labels
create: true
group: batch
kind: Job
- path: spec/jobTemplate/metadata/labels
create: true
group: batch
kind: CronJob
- path: spec/jobTemplate/spec/template/metadata/labels
create: true
group: batch
kind: CronJob
`

View File

@@ -50,6 +50,16 @@ nameReference:
kind: Pod
- path: template/spec/volumes/configMap/name
kind: PodTemplate
- path: template/spec/containers/env/valueFrom/configMapKeyRef/name
kind: PodTemplate
- path: template/spec/initContainers/env/valueFrom/configMapKeyRef/name
kind: PodTemplate
- path: template/spec/containers/envFrom/configMapRef/name
kind: PodTemplate
- path: template/spec/initContainers/envFrom/configMapRef/name
kind: PodTemplate
- path: template/spec/volumes/projected/sources/configMap/name
kind: PodTemplate
- path: spec/template/spec/volumes/configMap/name
kind: Deployment
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
@@ -155,6 +165,20 @@ nameReference:
- path: spec/volumes/projected/sources/secret/name
version: v1
kind: Pod
- path: template/spec/volumes/secret/secretName
kind: PodTemplate
- path: template/spec/containers/env/valueFrom/secretKeyRef/name
kind: PodTemplate
- path: template/spec/initContainers/env/valueFrom/secretKeyRef/name
kind: PodTemplate
- path: template/spec/containers/envFrom/secretRef/name
kind: PodTemplate
- path: template/spec/initContainers/envFrom/secretRef/name
kind: PodTemplate
- path: template/spec/imagePullSecrets/name
kind: PodTemplate
- path: template/spec/volumes/projected/sources/secret/name
kind: PodTemplate
- path: spec/template/spec/volumes/secret/secretName
kind: Deployment
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name

View File

@@ -6,15 +6,9 @@ package builtinpluginconsts
const (
namespaceFieldSpecs = `
namespace:
- path: metadata/namespace
create: true
- path: metadata/name
kind: Namespace
create: true
- path: subjects
kind: RoleBinding
- path: subjects
kind: ClusterRoleBinding
- path: spec/service/namespace
group: apiregistration.k8s.io
kind: APIService

View File

@@ -0,0 +1,8 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package builtinpluginconsts
const templateLabelFieldSpecs = `
templateLabels:
` + metadataLabelsFieldSpecs

View File

@@ -179,9 +179,11 @@ func TestDefaultAbsPluginHomeNoXdgJustHomeDir(t *testing.T) {
}
func setenv(t *testing.T, key, value string) {
t.Helper()
require.NoError(t, os.Setenv(key, value))
}
func unsetenv(t *testing.T, key string) {
t.Helper()
require.NoError(t, os.Unsetenv(key))
}

View File

@@ -82,7 +82,7 @@ spec:
`)
}
//test for https://github.com/kubernetes-sigs/kustomize/issues/3812#issuecomment-862339267
// test for https://github.com/kubernetes-sigs/kustomize/issues/3812#issuecomment-862339267
func TestBasicIO3812(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -9,6 +9,7 @@ import (
"testing"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/loader"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
@@ -551,7 +552,7 @@ components:
`),
},
runPath: "filesincomponents",
expectedError: "'/filesincomponents/stub.yaml' must be a directory so that it can used as a build root",
expectedError: fmt.Sprintf("%s: '%s'", loader.ErrRtNotDir.Error(), "/filesincomponents/stub.yaml"),
},
"invalid-component-api-version": {
input: []FileGen{writeTestBase, writeOverlayProd,

View File

@@ -460,7 +460,6 @@ metadata:
}
func TestConfigMapGeneratorMergeNamePrefix(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
configMapGenerator:

View File

@@ -34,7 +34,7 @@ const container = `{ "image": "my-image", "livenessProbe": { "httpGet" : {"path"
const patchJsonAddProbe = `[{"op": "replace", "path": "/spec/template/spec/containers/0", "value": ` +
container + `}]`
const patchDnsPolicy = `
const patchDNSPolicy = `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -44,7 +44,7 @@ spec:
spec:
dnsPolicy: ClusterFirst
`
const patchJsonDnsPolicy = `[{"op": "add", "path": "/spec/template/spec/dnsPolicy", "value": "ClusterFirst"}]`
const patchJsonDNSPolicy = `[{"op": "add", "path": "/spec/template/spec/dnsPolicy", "value": "ClusterFirst"}]`
const patchRestartPolicy = `
apiVersion: apps/v1
@@ -96,7 +96,7 @@ resources:
patchesStrategicMerge:
- dep-patch.yaml
`)
th.WriteF("dns/dep-patch.yaml", patchDnsPolicy)
th.WriteF("dns/dep-patch.yaml", patchDNSPolicy)
}
func writeRestartOverlay(th kusttest_test.Harness) {
@@ -209,7 +209,7 @@ patchesStrategicMerge:
- patchRestartPolicy.yaml
`)
th.WriteF("composite/patchRestartPolicy.yaml", patchRestartPolicy)
th.WriteF("composite/patchDnsPolicy.yaml", patchDnsPolicy)
th.WriteF("composite/patchDnsPolicy.yaml", patchDNSPolicy)
th.WriteF("composite/patchAddProbe.yaml", patchAddProbe)
m := th.Run("composite", th.MakeDefaultOptions())
@@ -220,7 +220,7 @@ func definePatchDirStructure(th kusttest_test.Harness) {
writeDeploymentBase(th)
th.WriteF("patches/patchRestartPolicy.yaml", patchRestartPolicy)
th.WriteF("patches/patchDnsPolicy.yaml", patchDnsPolicy)
th.WriteF("patches/patchDnsPolicy.yaml", patchDNSPolicy)
th.WriteF("patches/patchAddProbe.yaml", patchAddProbe)
}
@@ -368,7 +368,7 @@ func TestIssue1251_Plugins_Local(t *testing.T) {
writeDeploymentBase(th.Harness)
writeJsonTransformerPluginConfig(
th, "composite", "addDnsPolicy", patchJsonDnsPolicy)
th, "composite", "addDnsPolicy", patchJsonDNSPolicy)
writeJsonTransformerPluginConfig(
th, "composite", "addRestartPolicy", patchJsonRestartPolicy)
writeJsonTransformerPluginConfig(
@@ -417,7 +417,7 @@ resources:
- addProbeConfig.yaml
`)
writeJsonTransformerPluginConfig(
th, "patches", "addDnsPolicy", patchJsonDnsPolicy)
th, "patches", "addDnsPolicy", patchJsonDNSPolicy)
writeJsonTransformerPluginConfig(
th, "patches", "addRestartPolicy", patchJsonRestartPolicy)
writeJsonTransformerPluginConfig(
@@ -441,7 +441,7 @@ resources:
- addDnsPolicyConfig.yaml
`)
writeJsonTransformerPluginConfig(
th, "patches/addDnsPolicy", "addDnsPolicy", patchJsonDnsPolicy)
th, "patches/addDnsPolicy", "addDnsPolicy", patchJsonDNSPolicy)
th.WriteK("patches/addRestartPolicy", `
resources:

View File

@@ -82,21 +82,19 @@ metadata:
secret := findSecret(m, "")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "foo-secret-bar-82c2g5f8f6" {
} else if secret.GetName() != "foo-secret-bar-82c2g5f8f6" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
th.WriteK("/whatever",
strings.Replace(kustomizationContent,
strings.ReplaceAll(kustomizationContent,
"disableNameSuffixHash: false",
"disableNameSuffixHash: true", -1))
"disableNameSuffixHash: true"))
m = th.Run("/whatever", th.MakeDefaultOptions())
secret = findSecret(m, "")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "foo-secret-bar" { // No hash at end.
} else if secret.GetName() != "foo-secret-bar" { // No hash at end.
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}
@@ -131,16 +129,14 @@ secretGenerator:
secret := findSecret(m, "nohash")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "nohash" {
} else if secret.GetName() != "nohash" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
secret = findSecret(m, "yeshash")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "yeshash-82c2g5f8f6" {
} else if secret.GetName() != "yeshash-82c2g5f8f6" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
@@ -7,6 +10,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/krusty"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
@@ -37,7 +41,19 @@ spec:
EOF
`
func TestFnExecGenerator(t *testing.T) {
const krmTransformerDotSh = `#!/bin/bash
cat << EOF
apiVersion: v1
kind: Secret
metadata:
name: dummyTransformed
stringData:
foo: bar
type: Opaque
EOF
`
func TestFnExecGeneratorInBase(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
@@ -83,7 +99,6 @@ spec:
`)
m := th.Run(tmpDir.String(), o)
assert.NoError(t, err)
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
@@ -122,7 +137,7 @@ spec:
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
}
func TestFnExecGeneratorWithOverlay(t *testing.T) {
func TestFnExecGeneratorInBaseWithOverlay(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
@@ -213,7 +228,276 @@ spec:
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
}
func TestFnExecGeneratorInOverlay(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
o := th.MakeOptionsPluginsEnabled()
o.PluginConfig.FnpLoadingOptions.EnableExec = true
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
base := filepath.Join(tmpDir.String(), "base")
prod := filepath.Join(tmpDir.String(), "prod")
assert.NoError(t, fSys.Mkdir(base))
assert.NoError(t, fSys.Mkdir(prod))
th.WriteK(base, `
resources:
- short_secret.yaml
`)
th.WriteK(prod, `
resources:
- ../base
generators:
- gener.yaml
`)
th.WriteF(filepath.Join(base, "short_secret.yaml"),
`
apiVersion: v1
kind: Secret
metadata:
labels:
airshipit.org/ephemeral-user-data: "true"
name: node1-bmc-secret
type: Opaque
stringData:
userData: |
bootcmd:
- mkdir /mnt/vda
`)
th.WriteF(filepath.Join(prod, "generateDeployment.sh"), generateDeploymentDotSh)
assert.NoError(t, os.Chmod(filepath.Join(prod, "generateDeployment.sh"), 0777))
th.WriteF(filepath.Join(prod, "gener.yaml"), `
kind: executable
metadata:
name: demo
annotations:
config.kubernetes.io/function: |
exec:
path: ./generateDeployment.sh
spec:
`)
m := th.Run(prod, o)
assert.NoError(t, err)
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Secret
metadata:
labels:
airshipit.org/ephemeral-user-data: "true"
name: node1-bmc-secret
stringData:
userData: |
bootcmd:
- mkdir /mnt/vda
type: Opaque
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
tshirt-size: small
labels:
app: nginx
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
`, string(yml))
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
}
func TestFnExecTransformerInBase(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
o := th.MakeOptionsPluginsEnabled()
o.PluginConfig.FnpLoadingOptions.EnableExec = true
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
base := filepath.Join(tmpDir.String(), "base")
assert.NoError(t, fSys.Mkdir(base))
th.WriteK(base, `
resources:
- secret.yaml
transformers:
- krm-transformer.yaml
`)
th.WriteF(filepath.Join(base, "secret.yaml"),
`
apiVersion: v1
kind: Secret
metadata:
name: dummy
type: Opaque
stringData:
foo: bar
`)
th.WriteF(filepath.Join(base, "krmTransformer.sh"), krmTransformerDotSh)
assert.NoError(t, os.Chmod(filepath.Join(base, "krmTransformer.sh"), 0777))
th.WriteF(filepath.Join(base, "krm-transformer.yaml"), `
apiVersion: examples.config.kubernetes.io/v1beta1
kind: MyPlugin
metadata:
name: notImportantHere
annotations:
config.kubernetes.io/function: |
exec:
path: ./krmTransformer.sh
`)
m := th.Run(base, o)
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Secret
metadata:
name: dummyTransformed
stringData:
foo: bar
type: Opaque
`, string(yml))
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
}
func TestFnExecTransformerInBaseWithOverlay(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
o := th.MakeOptionsPluginsEnabled()
o.PluginConfig.FnpLoadingOptions.EnableExec = true
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
base := filepath.Join(tmpDir.String(), "base")
prod := filepath.Join(tmpDir.String(), "prod")
assert.NoError(t, fSys.Mkdir(base))
assert.NoError(t, fSys.Mkdir(prod))
th.WriteK(base, `
resources:
- secret.yaml
transformers:
- krm-transformer.yaml
`)
th.WriteK(prod, `
resources:
- ../base
`)
th.WriteF(filepath.Join(base, "secret.yaml"),
`
apiVersion: v1
kind: Secret
metadata:
name: dummy
type: Opaque
stringData:
foo: bar
`)
th.WriteF(filepath.Join(base, "krmTransformer.sh"), krmTransformerDotSh)
assert.NoError(t, os.Chmod(filepath.Join(base, "krmTransformer.sh"), 0777))
th.WriteF(filepath.Join(base, "krm-transformer.yaml"), `
apiVersion: examples.config.kubernetes.io/v1beta1
kind: MyPlugin
metadata:
name: notImportantHere
annotations:
config.kubernetes.io/function: |
exec:
path: ./krmTransformer.sh
`)
m := th.Run(prod, o)
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Secret
metadata:
name: dummyTransformed
stringData:
foo: bar
type: Opaque
`, string(yml))
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
}
func TestFnExecTransformerInOverlay(t *testing.T) {
fSys := filesys.MakeFsOnDisk()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
o := th.MakeOptionsPluginsEnabled()
o.PluginConfig.FnpLoadingOptions.EnableExec = true
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
base := filepath.Join(tmpDir.String(), "base")
prod := filepath.Join(tmpDir.String(), "prod")
assert.NoError(t, fSys.Mkdir(base))
assert.NoError(t, fSys.Mkdir(prod))
th.WriteK(base, `
resources:
- secret.yaml
`)
th.WriteK(prod, `
resources:
- ../base
transformers:
- krm-transformer.yaml
`)
th.WriteF(filepath.Join(base, "secret.yaml"),
`
apiVersion: v1
kind: Secret
metadata:
name: dummy
type: Opaque
stringData:
foo: bar
`)
th.WriteF(filepath.Join(prod, "krmTransformer.sh"), krmTransformerDotSh)
assert.NoError(t, os.Chmod(filepath.Join(prod, "krmTransformer.sh"), 0777))
th.WriteF(filepath.Join(prod, "krm-transformer.yaml"), `
apiVersion: examples.config.kubernetes.io/v1beta1
kind: MyPlugin
metadata:
name: notImportantHere
annotations:
config.kubernetes.io/function: |
exec:
path: ./krmTransformer.sh
`)
m := th.Run(prod, o)
yml, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Secret
metadata:
name: dummyTransformed
stringData:
foo: bar
type: Opaque
`, string(yml))
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
}
func skipIfNoDocker(t *testing.T) {
t.Helper()
if _, err := exec.LookPath("docker"); err != nil {
t.Skip("skipping because docker binary wasn't found in PATH")
}
@@ -531,30 +815,33 @@ spec:
func TestFnContainerTransformerWithConfig(t *testing.T) {
skipIfNoDocker(t)
// Function plugins should not need the env setup done by MakeEnhancedHarness
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
o := th.MakeOptionsPluginsEnabled()
fSys := filesys.MakeFsOnDisk()
b := MakeKustomizer(&o)
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
resources:
- data1.yaml
- data2.yaml
transformers:
- label_namespace.yaml
`)
th.WriteF("data1.yaml", `apiVersion: v1
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "data1.yaml"), []byte(`
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
`)
th.WriteF("data2.yaml", `apiVersion: v1
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "data2.yaml"), []byte(`
apiVersion: v1
kind: Namespace
metadata:
name: another-namespace
`)
th.WriteF("label_namespace.yaml", `apiVersion: v1
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "label_namespace.yaml"), []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: label_namespace
@@ -565,11 +852,14 @@ metadata:
data:
label_name: my-ns-name
label_value: function-test
`)
m := th.Run(".", th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
`)))
m, err := b.Run(
fSys,
tmpDir.String())
assert.NoError(t, err)
actual, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
kind: Namespace
metadata:
labels:
@@ -582,24 +872,22 @@ metadata:
labels:
my-ns-name: function-test
name: another-namespace
`)
`, string(actual))
}
func TestFnContainerEnvVars(t *testing.T) {
skipIfNoDocker(t)
// Function plugins should not need the env setup done by MakeEnhancedHarness
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
o := th.MakeOptionsPluginsEnabled()
fSys := filesys.MakeFsOnDisk()
b := MakeKustomizer(&o)
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
generators:
- gener.yaml
`)
// TODO: cheange image to gcr.io/kpt-functions/templater:stable
// when https://github.com/GoogleContainerTools/kpt-functions-catalog/pull/103
// is merged
th.WriteF("gener.yaml", `
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "gener.yaml"), []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
@@ -618,14 +906,176 @@ data:
name: env
data:
value: '{{ env "TESTTEMPLATE" }}'
`)
m := th.Run(".", th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
`)))
m, err := b.Run(
fSys,
tmpDir.String())
assert.NoError(t, err)
actual, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: v1
data:
value: value
kind: ConfigMap
metadata:
name: env
`)
`, string(actual))
}
func TestFnContainerFnMounts(t *testing.T) {
skipIfNoDocker(t)
th := kusttest_test.MakeHarness(t)
o := th.MakeOptionsPluginsEnabled()
fSys := filesys.MakeFsOnDisk()
b := MakeKustomizer(&o)
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
generators:
- gener.yaml
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "gener.yaml"), []byte(`
apiVersion: v1alpha1
kind: RenderHelmChart
metadata:
name: demo
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/kpt-fn/render-helm-chart:v0.1.0
mounts:
- type: "bind"
src: "./charts"
dst: "/tmp/charts"
helmCharts:
- name: helloworld-chart
releaseName: test
valuesFile: /tmp/charts/helloworld-values/values.yaml
`)))
assert.NoError(t, fSys.MkdirAll(filepath.Join(tmpDir.String(), "charts", "helloworld-chart", "templates")))
assert.NoError(t, fSys.MkdirAll(filepath.Join(tmpDir.String(), "charts", "helloworld-values")))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "charts", "helloworld-chart", "Chart.yaml"), []byte(`
apiVersion: v2
name: helloworld-chart
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: 1.16.0
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "charts", "helloworld-chart", "templates", "deployment.yaml"), []byte(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: name
spec:
replicas: {{ .Values.replicaCount }}
`)))
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "charts", "helloworld-values", "values.yaml"), []byte(`
replicaCount: 5
`)))
m, err := b.Run(
fSys,
tmpDir.String())
assert.NoError(t, err)
actual, err := m.AsYaml()
assert.NoError(t, err)
assert.Equal(t, `apiVersion: apps/v1
kind: Deployment
metadata:
name: name
spec:
replicas: 5
`, string(actual))
}
func TestFnContainerMountsLoadRestrictions_absolute(t *testing.T) {
skipIfNoDocker(t)
th := kusttest_test.MakeHarness(t)
o := th.MakeOptionsPluginsEnabled()
fSys := filesys.MakeFsOnDisk()
b := MakeKustomizer(&o)
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
generators:
- |-
apiVersion: v1alpha1
kind: RenderHelmChart
metadata:
name: demo
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/kpt-fn/render-helm-chart:v0.1.0
mounts:
- type: "bind"
src: "/tmp/dir"
dst: "/tmp/charts"
`)))
_, err = b.Run(
fSys,
tmpDir.String())
assert.Error(t, err)
assert.Contains(t, err.Error(), "loading generator plugins: failed to load generator: plugin RenderHelmChart."+
"v1alpha1.[noGrp]/demo.[noNs] with mount path '/tmp/dir' is not permitted; mount paths must"+
" be relative to the current kustomization directory")
}
func TestFnContainerMountsLoadRestrictions_outsideCurrentDir(t *testing.T) {
skipIfNoDocker(t)
th := kusttest_test.MakeHarness(t)
o := th.MakeOptionsPluginsEnabled()
fSys := filesys.MakeFsOnDisk()
b := MakeKustomizer(&o)
tmpDir, err := filesys.NewTmpConfirmedDir()
assert.NoError(t, err)
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
generators:
- |-
apiVersion: v1alpha1
kind: RenderHelmChart
metadata:
name: demo
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/kpt-fn/render-helm-chart:v0.1.0
mounts:
- type: "bind"
src: "./tmp/../../dir"
dst: "/tmp/charts"
`)))
_, err = b.Run(
fSys,
tmpDir.String())
assert.Error(t, err)
assert.Contains(t, err.Error(), "loading generator plugins: failed to load generator: plugin RenderHelmChart."+
"v1alpha1.[noGrp]/demo.[noNs] with mount path './tmp/../../dir' is not permitted; mount paths must "+
"be under the current kustomization directory")
}
func TestFnContainerMountsLoadRestrictions_root(t *testing.T) {
skipIfNoDocker(t)
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
generators:
- gener.yaml
`)
// Create generator config
th.WriteF("gener.yaml", `
apiVersion: examples.config.kubernetes.io/v1beta1
kind: CockroachDB
metadata:
name: demo
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
spec:
replicas: 3
`)
err := th.RunWithErr(".", th.MakeOptionsPluginsEnabled())
assert.Error(t, err)
assert.EqualError(t, err, "couldn't execute function: root working directory '/' not allowed")
}

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -91,3 +91,437 @@ spec:
c: d
`)
}
func TestKustomizationLabelsInDeploymentTemplate(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
name: deployment
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
template:
metadata:
labels:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
`)
th.WriteK("/app", `
resources:
- deployment.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
foo: bar
name: deployment
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
template:
metadata:
labels:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
foo: bar
`)
}
func TestKustomizationLabelsInTemplateWhenLabelsIsNil(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 1
template:
spec:
containers:
- name: test-server
image: test-server
`)
th.WriteK("/app", `
resources:
- deployment.yaml
commonLabels:
app: test-server
labels:
- pairs:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test-server
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
name: deployment
spec:
replicas: 1
selector:
matchLabels:
app: test-server
template:
metadata:
labels:
app: test-server
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
spec:
containers:
- image: test-server
name: test-server
`)
}
func TestKustomizationLabelsDoesNotCreateInvalidTemplatePaths(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 1
template:
spec:
containers:
- name: test-server
image: test-server
`)
th.WriteF("app/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 9376
`)
th.WriteK("/app", `
resources:
- deployment.yaml
- service.yaml
commonLabels:
app: test-server
labels:
- pairs:
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test-server
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
name: deployment
spec:
replicas: 1
selector:
matchLabels:
app: test-server
template:
metadata:
labels:
app: test-server
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
spec:
containers:
- image: test-server
name: test-server
---
apiVersion: v1
kind: Service
metadata:
labels:
app: test-server
app.kubernetes.io/component: a
app.kubernetes.io/instance: b
app.kubernetes.io/name: c
app.kubernetes.io/part-of: d
name: service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 9376
selector:
app: test-server
`)
}
func TestKustomizationLabelsInDaemonSetTemplate(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/ds.yaml", `
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app.kubernetes.io/name: daemon
name: daemon
spec:
selector:
matchLabels:
app.kubernetes.io/name: daemon
template:
metadata:
labels:
app.kubernetes.io/name: daemon
`)
th.WriteK("/app", `
resources:
- ds.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app.kubernetes.io/name: daemon
foo: bar
name: daemon
spec:
selector:
matchLabels:
app.kubernetes.io/name: daemon
template:
metadata:
labels:
app.kubernetes.io/name: daemon
foo: bar
`)
}
func TestKustomizationLabelsInStatefulSetTemplate(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/sts.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
`)
th.WriteK("/app", `
resources:
- sts.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
name: set
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: set
serviceName: set
template:
metadata:
labels:
app.kubernetes.io/name: set
foo: bar
`)
}
func TestKustomizationLabelsInCronJobTemplate(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/cjob.yaml", `
apiVersion: batch/v1
kind: CronJob
metadata:
labels:
app.kubernetes.io/name: job
name: job
spec:
jobTemplate:
spec:
backoffLimit: 4
template:
metadata:
labels:
app.kubernetes.io/name: job
spec:
restartPolicy: Never
schedule: '* * * * *'
`)
th.WriteK("/app", `
resources:
- cjob.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: batch/v1
kind: CronJob
metadata:
labels:
app.kubernetes.io/name: job
foo: bar
name: job
spec:
jobTemplate:
metadata:
labels:
foo: bar
spec:
backoffLimit: 4
template:
metadata:
labels:
app.kubernetes.io/name: job
foo: bar
spec:
restartPolicy: Never
schedule: '* * * * *'
`)
}
func TestKustomizationLabelsInJobTemplate(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("app/job.yaml", `
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/name: job
name: job
spec:
backoffLimit: 4
template:
metadata:
labels:
app.kubernetes.io/name: job
spec:
restartPolicy: Never
`)
th.WriteK("/app", `
resources:
- job.yaml
labels:
- pairs:
foo: bar
includeSelectors: false
includeTemplates: true
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/name: job
foo: bar
name: job
spec:
backoffLimit: 4
template:
metadata:
labels:
app.kubernetes.io/name: job
foo: bar
spec:
restartPolicy: Never
`)
}

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -5,7 +5,6 @@ package krusty
import (
"fmt"
"path/filepath"
"sigs.k8s.io/kustomize/api/internal/builtins"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
@@ -17,6 +16,7 @@ import (
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/kustomize/kyaml/openapi"
)
@@ -76,7 +76,7 @@ func (b *Kustomizer) Run(
}
var bytes []byte
if openApiPath, exists := kt.Kustomization().OpenAPI["path"]; exists {
bytes, err = ldr.Load(filepath.Join(ldr.Root(), openApiPath))
bytes, err = ldr.Load(openApiPath)
if err != nil {
return nil, err
}
@@ -113,10 +113,16 @@ func (b *Kustomizer) Run(
}
m.RemoveBuildAnnotations()
if !utils.StringSliceContains(kt.Kustomization().BuildMetadata, types.OriginAnnotations) {
m.RemoveOriginAnnotations()
err = m.RemoveOriginAnnotations()
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to clean up origin tracking annotations")
}
}
if !utils.StringSliceContains(kt.Kustomization().BuildMetadata, types.TransformerAnnotations) {
m.RemoveTransformerAnnotations()
err = m.RemoveTransformerAnnotations()
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to clean up transformer annotations")
}
}
return m, nil
}

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2022 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (

View File

@@ -0,0 +1,74 @@
// Copyright 2022 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"
)
func TestNamedspacedServiceAccountsWithOverlap(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("a/a.yaml", `
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: crb-a
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cr-a
subjects:
- kind: ServiceAccount
name: sa
`)
th.WriteK("a/", `
namespace: a
resources:
- a.yaml
`)
th.WriteF("b/b.yaml", `
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: crb-b
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cr-b
subjects:
- kind: ServiceAccount
name: sa
`)
th.WriteK("b/", `
namespace: b
resources:
- b.yaml
`)
th.WriteK(".", `
resources:
- a
- b
`)
err := th.RunWithErr(".", th.MakeDefaultOptions())
assert.Contains(t, err.Error(), "found multiple possible referrals: ServiceAccount.v1.[noGrp]/sa.a, ServiceAccount.v1.[noGrp]/sa.b")
}

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