Compare commits

...

448 Commits

Author SHA1 Message Date
Jeff Regan
4263d18c1a Update kustomize/api/internal/crawl/go.sum 2021-02-26 16:40:04 -08:00
Jeff Regan
827fb1e1da Merge pull request #3643 from monopole/pinToCmdConfig
Pin to cmd/config v0.9.4
2021-02-26 16:21:30 -08:00
monopole
03c77cee9b Pin to cmd/config v0.9.4 2021-02-26 15:51:25 -08:00
Jeff Regan
2db34e7127 Merge pull request #3642 from monopole/pinToKyamlAndCliUtils
Pin to kyaml v0.10.12
2021-02-26 15:49:11 -08:00
monopole
821b14bfd1 Pin to kyaml v0.10.12 2021-02-26 15:35:13 -08:00
Jeff Regan
33b4735f98 Merge pull request #3641 from monopole/dropReGenerationDirectives
Drop regeneration directives from copied code.
2021-02-26 15:18:24 -08:00
monopole
bbebd1e56a Drop regeneration directives from copied code. 2021-02-26 14:34:22 -08:00
Jeff Regan
c9d9348944 Drop commands replacement from go.mod 2021-02-25 11:15:22 -08:00
Jeff Regan
555c4cb279 Merge pull request #3638 from monopole/pinToApi
Pin to api v0.8.2
2021-02-25 08:19:56 -08:00
monopole
3da90dbde7 Pin to api v0.8.2 2021-02-25 08:04:59 -08:00
Jeff Regan
4ac0f59b8a Merge pull request #3637 from monopole/pinToCmdConfig
Pin to cmd/config v0.9.3
2021-02-25 07:56:06 -08:00
monopole
2b9c69f964 Pin to cmd/config v0.9.3 2021-02-25 07:03:38 -08:00
Jeff Regan
437c960d86 Merge pull request #3636 from monopole/moregosum
More go sum changes.
2021-02-25 07:02:01 -08:00
monopole
131aba8f14 More go sum changes. 2021-02-25 07:01:32 -08:00
Jeff Regan
ada02703cf Merge pull request #3634 from monopole/pinToKyamlAndCliUtils
Pin to kyaml v0.10.11
2021-02-25 07:00:31 -08:00
monopole
f96dfb5772 Pin to kyaml v0.10.11 2021-02-24 21:30:40 -08:00
Jeff Regan
57b3e70cef Merge pull request #3633 from monopole/goSumFix
More go tidy adjustments.
2021-02-24 20:09:02 -08:00
monopole
f4fbcc6fb4 More go tidy adjustments.
ALLOW_MODULE_SPAN
2021-02-24 19:50:37 -08:00
Jeff Regan
867da9631a Merge pull request #3632 from monopole/dropMoreDeps
Remove tool deps from shippable modules.
2021-02-24 18:09:20 -08:00
monopole
cd2b0fce7e Remove tool deps from shippable modules. 2021-02-24 17:37:16 -08:00
Kubernetes Prow Robot
66504c263c Merge pull request #3631 from natasha41575/KrustyTestPaths
Change paths for krusty tests to relative, and have top level be '.'
2021-02-24 16:55:25 -08:00
Jeff Regan
bce4f75fc5 Merge pull request #3630 from natasha41575/UseCustomOpenApiSchema
kustomization openapi data should be parsed for custom schema
2021-02-24 16:32:05 -08:00
Natasha Sarkar
8b082aff5a Change paths for krusty tests to relative, and have top level be '.' instead of 'app' 2021-02-24 16:23:45 -08:00
Natasha Sarkar
48e4cad72e kustomization openapi data should be parsed for custom schema 2021-02-24 15:27:50 -08:00
Kubernetes Prow Robot
30e53a992b Merge pull request #3617 from natasha41575/UseCustomOpenApiSchema
add openapi/path field to use custom openapi schema document
2021-02-24 15:03:24 -08:00
Kubernetes Prow Robot
2df9f85a20 Merge pull request #3621 from natasha41575/OpenApiFetchCommand
added `kustomize openapi fetch` command to get schema from local cluster
2021-02-24 14:37:24 -08:00
Jeff Regan
01733d970a Merge pull request #3608 from argyle-systems/repeat-base-test
Add repeatbase_test.
2021-02-24 14:22:16 -08:00
Kubernetes Prow Robot
ac178c539c Merge pull request #3629 from pwittrock/main
Fork starlib/util for serialization libs.
2021-02-24 14:11:26 -08:00
Phillip Wittrock
61dcb3f548 Fork starlib/util for serialization libs.
Prevents pulling in excessive transitive deps.

See: https://github.com/kubernetes/kubernetes/pull/98946
2021-02-24 11:17:08 -08:00
Chico Venancio
6f15b1e56d Simplify paths and rename objects 2021-02-24 15:13:32 -03:00
Kubernetes Prow Robot
9a94c5ecd3 Merge pull request #3613 from phanimarupaka/DefaultRFalseForListSetters
List setters default false for recurse-subpackages
2021-02-24 07:56:50 -08:00
Kubernetes Prow Robot
2ba148d9b5 Merge pull request #3615 from pwittrock/main
fn framework support for legacy kustomize plugin io
2021-02-24 07:40:51 -08:00
Natasha Sarkar
5a0e193002 moved common resource definitions to separate function 2021-02-23 17:21:16 -08:00
Jeff Regan
3265f64cd5 Merge pull request #3546 from zhijianli88/master
Fix ineffectual assignment to err
2021-02-22 10:24:11 -08:00
Jeff Regan
c2b1ab8303 Add makeKubectlPr.sh 2021-02-22 06:51:37 -08:00
Natasha Sarkar
7dd0ade0f9 add openapi/path field to use custom openapi schema document 2021-02-19 14:19:22 -08:00
Natasha Sarkar
316e4314ed added openapi fetch command to get schema from local cluster 2021-02-19 11:08:31 -08:00
Donny Xia
324353eaf6 Merge pull request #3619 from natasha41575/PatchDeleteOnObjectPanic
fixed panic on patch delete for objects
2021-02-19 10:32:36 -08:00
Natasha Sarkar
6361c3b1b7 fixed panic on patch delete for objects 2021-02-18 10:47:13 -08:00
Phillip Wittrock
f7d13ade35 fn framework support for legacy kustomize plugin io 2021-02-17 09:19:02 -08:00
Kubernetes Prow Robot
99e82890e1 Merge pull request #3606 from qrilka/patch-1
Add name reference for fastcgi-params-configmap
2021-02-17 08:39:09 -08:00
Kubernetes Prow Robot
4a35bfa84c Merge pull request #3612 from Shell32-Natsu/edit-metadata
fix edit commands remove metadata
2021-02-16 15:09:06 -08:00
Phani Teja Marupaka
27f28d5fe0 List setters default false for recurse-subpackages 2021-02-16 14:48:19 -08:00
Donny Xia
c04cf01b45 fix test 2021-02-16 14:31:32 -08:00
Donny Xia
5614852b33 fix edit commands remove metadata 2021-02-16 14:17:09 -08:00
Kubernetes Prow Robot
4f23ae5e1a Merge pull request #3611 from Shell32-Natsu/release-doc
add doc for releasing image
2021-02-16 13:25:06 -08:00
Donny Xia
3bd088a77c update links 2021-02-16 12:57:41 -08:00
Chico Venancio
fe30a9321a Adds repeatbase_test 2021-02-16 16:23:53 -03:00
Donny Xia
c715b82ad7 add doc for releasing image 2021-02-16 11:03:08 -08:00
Kirill Zaborsky
44d308cbba Add name reference for fastcgi-params-configmap
See https://kubernetes.github.io/ingress-nginx/user-guide/fcgi-services/#the-nginxingresskubernetesiofastcgi-params-configmap-annotation
2021-02-15 12:38:41 +03:00
Jeff Regan
c9e7f627fe Update makeKubectlPr.sh 2021-02-13 15:29:39 -08:00
Jeff Regan
00fa7e636c Merge pull request #3604 from monopole/tweakMake
git stTweak make
2021-02-13 14:04:49 -08:00
monopole
c7a504c9cf Add 4.0.1 to example tests and unpin. 2021-02-13 13:51:59 -08:00
Jeff Regan
516ff1fa56 Merge pull request #3603 from monopole/pinForRelease
Pin for kustomize/v4.0.1 release.
2021-02-13 13:07:33 -08:00
monopole
81562a7a37 Pin for kustomize/v4.0.1 release. 2021-02-13 12:55:18 -08:00
Jeff Regan
ba0baa828c Merge pull request #3600 from natasha41575/TestExamplesAgainst4.0
Test examples against 4.0
2021-02-13 12:47:30 -08:00
Jeff Regan
420f03d429 Merge pull request #3601 from monopole/addBuildTest
Hyphenate flags and add more build command tests.
2021-02-13 12:26:48 -08:00
monopole
6cf48442df Hyphenate flags and add more build command tests. 2021-02-13 11:59:08 -08:00
Jeff Regan
8cf7bc67bb Create makeKubectlPr.sh 2021-02-13 07:26:13 -08:00
Natasha Sarkar
48d6af6e38 test examples against kustomize 4.0 2021-02-12 17:08:45 -08:00
Kubernetes Prow Robot
0309a0fb07 Merge pull request #3599 from natasha41575/unpinEverything
Back to development mode; unpin the modules
2021-02-12 15:33:04 -08:00
Natasha Sarkar
d7b29455ab Back to development mode; unpin the modules 2021-02-12 15:09:16 -08:00
Natasha Sarkar
a414f75f1b Merge pull request #3598 from monopole/majorVersionChangeToV4
Increment major version from v3 to v4
2021-02-12 14:40:50 -08:00
monopole
1c3832f897 Increment major version from v3 to v4 2021-02-12 13:26:41 -08:00
Jeff Regan
3ec62c6e26 Merge pull request #3597 from monopole/fixGoSum
Fix crawl/go.sum
2021-02-12 13:20:47 -08:00
Jeff Regan
c7ee4c281e Fix crawl/go.sum 2021-02-12 13:19:37 -08:00
Jeff Regan
471ff0c4bb Merge pull request #3595 from natasha41575/pinToApi
Pin to api v0.8.1
2021-02-12 13:01:53 -08:00
Natasha Sarkar
cd0d416a11 Pin to api v0.8.1 2021-02-12 12:40:49 -08:00
Jeff Regan
4a1a2bfdd8 Merge pull request #3594 from natasha41575/pinToCmdConfig
Pin to cmd/config v0.9.2
2021-02-12 12:33:25 -08:00
Natasha Sarkar
8d75824bb6 Pin to cmd/config v0.9.2 2021-02-12 12:30:01 -08:00
Jeff Regan
232e615afe Merge pull request #3592 from natasha41575/pinToKyaml
Pin to kyaml v0.10.10
2021-02-12 12:20:04 -08:00
Natasha Sarkar
50bfa0564c Pin to kyaml v0.10.10 2021-02-12 12:04:11 -08:00
Jeff Regan
d0b101dc90 Update README.md 2021-02-12 11:24:36 -08:00
Jeff Regan
526ae9ff57 Merge pull request #3590 from monopole/morePublicSutff
Make more high level build methods public.
2021-02-12 11:21:37 -08:00
monopole
b553997447 Make more high level build methods public. 2021-02-12 10:58:20 -08:00
Jeff Regan
66b7c5968b Merge pull request #3589 from monopole/dropEnableKyamlFlag
Delete --enable_kyaml flag.
2021-02-12 10:57:28 -08:00
monopole
003b4946a2 Delete --enable_kyaml flag. 2021-02-12 09:26:36 -08:00
Kubernetes Prow Robot
2d7b6a57ca Merge pull request #3586 from monopole/dropGetter
Drop go-getter use.
2021-02-11 19:14:47 -08:00
Kubernetes Prow Robot
ecda4f423e Merge pull request #3584 from Shell32-Natsu/binarydata
fix merging ConfigMap with binaryData
2021-02-11 17:12:47 -08:00
monopole
9dc4004fbe Tidy go.sum after dropping go-getter. 2021-02-11 16:48:40 -08:00
monopole
a815774e5e Drop the go-getter dependence. 2021-02-11 16:48:39 -08:00
Kubernetes Prow Robot
f170af70fd Merge pull request #3582 from alexal/fix/3575
Kustomize file should be ignored when adding resources and components
2021-02-11 16:28:47 -08:00
Donny Xia
6518393f5d support binaryData merge 2021-02-11 15:34:16 -08:00
Donny Xia
dd72ea1e6a add functions for binaryData 2021-02-11 15:34:16 -08:00
Jeff Regan
dbbe340b4f Simplify gorepomod manager 2021-02-11 15:25:19 -08:00
Jeff Regan
38b30b0edc Merge pull request #3583 from monopole/addKyamlReplacements
Add kyaml replacements to modules with dependency on api.
2021-02-11 15:18:46 -08:00
Jeff Regan
10f9a5afda Merge pull request #3580 from pwittrock/main
Support fnframework to write expected testdata based on observed results
2021-02-11 15:06:38 -08:00
monopole
8a61bff299 Run: gorepomod unpin kyaml api --doIt 2021-02-11 15:05:01 -08:00
monopole
52fbe73d49 Modify gorepomod to unpin conditionally. 2021-02-11 15:04:16 -08:00
Alex Rodin
17ecec2f0a Kustomize file should be ignored when adding resources and components 2021-02-11 15:53:47 -05:00
Jeff Regan
aeb6024e72 Merge pull request #3581 from monopole/dropHashicorpMultierror
Drop hashicorp multierror due to MPL
2021-02-11 12:42:44 -08:00
monopole
e33addc16b Drop hashicorp multierror due to MPL 2021-02-11 12:24:22 -08:00
Phillip Wittrock
2db4121c6a Support fnframework to write expected testdata based on observed results 2021-02-11 09:48:50 -08:00
Jeff Regan
c764bc1618 Merge pull request #3573 from monopole/unpinEverything
Unpin everything, back to development mode.
2021-02-09 17:34:23 -08:00
monopole
2d2fbe9f14 Unpin everything, back to development mode. 2021-02-09 16:42:11 -08:00
Jeff Regan
7073371c1a Merge pull request #3572 from monopole/fix3571
Sort release versions using a version sensitive sort
2021-02-09 16:30:17 -08:00
monopole
dc25a6a1ce Fix #3571 with a -V 2021-02-09 16:28:31 -08:00
Jeff Regan
602ad8aa98 Merge pull request #3569 from monopole/pinToApi
Pin to api v0.8.0
2021-02-09 15:50:17 -08:00
monopole
1fa3b224b1 Pin to api v0.8.0 2021-02-09 14:44:12 -08:00
Jeff Regan
5a328ababf Merge pull request #3568 from monopole/deleteK8sIoDeps
Delete dependence on k8s.io/...
2021-02-09 14:30:54 -08:00
monopole
3ae1aa7cd7 Delete dependence on k8s.io/... 2021-02-09 14:15:54 -08:00
monopole
703fee93af Delete kyaml replacements. 2021-02-09 13:00:50 -08:00
Jeff Regan
3e4a59c1cd Merge pull request #3567 from monopole/unpinEverything
Unpin from api.
2021-02-09 11:46:29 -08:00
monopole
f98edf1b55 Unpin from api. 2021-02-09 11:22:46 -08:00
Jeff Regan
e41d94ddef Merge pull request #3566 from monopole/pinToApi
Pin to api
2021-02-09 11:18:44 -08:00
monopole
0508c89b4b Pin to api 2021-02-09 10:59:18 -08:00
Jeff Regan
e653cffab6 Merge pull request #3565 from monopole/pinToCmdConfig
Pin to cmd/config v0.9.1
2021-02-09 10:38:46 -08:00
monopole
e036f85b71 Pin to cmd/config v0.9.1 2021-02-09 10:17:53 -08:00
Jeff Regan
cee1324d18 Merge pull request #3564 from kubernetes-sigs/pinToKyamlAndCliUtils
Pin to kyaml v0.10.9
2021-02-09 10:14:01 -08:00
monopole
b062ce0f66 Pin to kyaml v0.10.9 2021-02-09 09:57:21 -08:00
Jeff Regan
fbcb15b15f Merge pull request #3563 from monopole/commitGeneratedCode
Commit generated doc changes.
2021-02-09 09:19:32 -08:00
monopole
8eb062637f Commit generated doc changes. 2021-02-09 09:18:31 -08:00
Jeff Regan
2fe85be932 Merge pull request #3557 from natasha41575/PatchMergeIssue
fixed ports merging issue and refactored some kyaml/walk code
2021-02-09 08:48:19 -08:00
Jeff Regan
44edfa87fe Merge pull request #3562 from monopole/changeGenMessage
Fix message in generated code.
2021-02-09 08:08:04 -08:00
monopole
bbccee0219 Fix message in generated code. 2021-02-09 07:34:32 -08:00
Jeff Regan
7cdc6cbe2f Merge pull request #3561 from monopole/unpin
Unpin; back to development mode.
2021-02-09 07:13:20 -08:00
monopole
264bfa8998 Unpin; back to development mode. 2021-02-09 06:54:18 -08:00
Jeff Regan
041181afe4 Merge pull request #3560 from monopole/dropQuantityProto
Drop unused quantity protobuf - avoid bad init.
2021-02-09 06:36:56 -08:00
monopole
5db79285a7 Drop unused quantity protobuf - avoid bad init. 2021-02-09 06:19:13 -08:00
Jeff Regan
556692c9f5 Merge pull request #3556 from monopole/dropKubeOpenAi
Drop dependence on k8s.io/kube-openapi
2021-02-08 18:01:02 -08:00
Natasha Sarkar
71f4cecb4c fixed ports merging issue and refactored some kyaml.walk code 2021-02-08 17:49:10 -08:00
monopole
d4d5fca2a5 Drop dependence on k8s.io/kube-openapi 2021-02-08 17:31:54 -08:00
Jeff Regan
811e1dca05 Merge pull request #3554 from monopole/pinToCmdConfig
Pin to cmd/config v0.9.0
2021-02-08 16:46:36 -08:00
monopole
09bc6e76b1 Pin to cmd/config v0.9.0 2021-02-08 16:30:57 -08:00
Jeff Regan
065b14c5c5 Merge pull request #3553 from monopole/pinToKyamlAndCliUtils
Pin to kyaml v0.10.8
2021-02-08 16:24:49 -08:00
monopole
adb2f2237a Pin to kyaml v0.10.8 2021-02-08 16:09:17 -08:00
Jeff Regan
024bbd0777 Merge pull request #3549 from monopole/removeApiMachDep
Remove grep's dependence on apimachinery.
2021-02-08 15:34:53 -08:00
monopole
ca1929abfb Remove grep's dependence on apimachinery. 2021-02-08 15:16:46 -08:00
Jeff Regan
a13ef4da65 Update Makefile 2021-02-08 15:14:47 -08:00
Jeff Regan
81ec59fa62 Update Makefile 2021-02-08 14:58:31 -08:00
Jeff Regan
075a2d6c0f Merge pull request #3552 from monopole/tweakCopier
Fix prefix bug in copier.
2021-02-08 14:45:12 -08:00
monopole
1df430255a Fix prefix bug in copier. 2021-02-08 14:39:25 -08:00
Jeff Regan
94d06e1e18 Merge pull request #3550 from Shell32-Natsu/value-add
fix forward slash in value add path
2021-02-08 13:39:58 -08:00
Jeff Regan
c3b240639d Merge pull request #3551 from monopole/fixKyamlMake
Normalize deps in kyaml makefile.
2021-02-08 13:34:40 -08:00
monopole
4de6db3d59 Normalize deps in makefile. 2021-02-08 13:21:42 -08:00
Donny Xia
58216d1d33 fix forward slash in value add path 2021-02-08 13:11:24 -08:00
Jeff Regan
4c456d60a4 Merge pull request #3548 from monopole/moveCopier
Move the k8s-related code generator.
2021-02-08 12:49:41 -08:00
monopole
582bc4de01 Move the k8s code generator. 2021-02-08 12:32:13 -08:00
Li Zhijian
a167084ccf api/internal/crawl/index/elasticsearch: Fix ineffectual assignment to err
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
2021-02-08 13:55:17 +08:00
Jeff Regan
a3a11bf3f4 Merge pull request #3545 from monopole/testExamplesAgainstLatestReleases
Test examples against latest releases.
2021-02-07 10:52:26 -08:00
monopole
4e96502ec6 Test examples against latest releases. 2021-02-07 10:31:34 -08:00
Jeff Regan
1ae8303bdc Merge pull request #3544 from monopole/pinToApi
Pin to api v0.7.3
2021-02-07 08:56:03 -08:00
monopole
41df2bed1f Pin to api v0.7.3 2021-02-07 08:40:52 -08:00
Jeff Regan
1f1304194d Update cloudbuild.sh 2021-02-07 07:57:10 -08:00
Jeff Regan
4157933c8d Update cloudbuild.sh 2021-02-07 07:47:06 -08:00
Jeff Regan
a79253e02f Merge pull request #3543 from monopole/releaserUpdates
Use goreleaser/v0.155.0, --parallelism 4
2021-02-07 07:21:14 -08:00
monopole
3b35b121b3 Use goreleaser/v0.155.0, --parallelism 4 2021-02-07 07:19:39 -08:00
Jeff Regan
3c94d20599 Deleting goarch=arm build, leaving arm64
Hitting hard step limit of 10m
Increasing timeout field in cloudbuild.yaml past 10m seems to have no effect.
Maybe break goreleaser step into multiple substeps?
2021-02-06 09:45:01 -08:00
Jeff Regan
1faeb91cc4 Set build timeout=800s, goreleaser timeout =720s 2021-02-06 09:16:02 -08:00
Jeff Regan
9f1ef993a1 Set FlagEnableKyamlDefaultValue = true 2021-02-06 08:31:12 -08:00
Jeff Regan
55d8cb3d3a Merge pull request #3541 from monopole/pinToApi
Pin to api v0.6.9
2021-02-06 08:16:35 -08:00
monopole
a684592639 Pin to api v0.6.9 2021-02-06 07:59:54 -08:00
Jeff Regan
386d10834b Set FlagEnableKyamlDefaultValue = false 2021-02-06 07:16:55 -08:00
Jeff Regan
af32126e80 Merge pull request #3540 from monopole/pinToCmdConfig
Pin to cmd/config v0.8.9
2021-02-05 22:01:41 -08:00
monopole
b0cfa15b9c Pin to cmd/config v0.8.9 2021-02-05 21:40:42 -08:00
Jeff Regan
62e7df6812 Merge pull request #3539 from monopole/pinToKyamlAndCliUtils
Pin to kyaml v0.10.7 and cli-utils v0.23.1
2021-02-05 21:29:06 -08:00
monopole
c077ed4b58 Pin to kyaml v0.10.7 and cli-utils v0.23.1 2021-02-05 20:34:05 -08:00
Jeff Regan
156beb300c Update README.md 2021-02-05 20:23:59 -08:00
Jeff Regan
25b02d2d6c Merge pull request #3538 from monopole/fixnits
Make starlarkmixer plugin module name match path.
2021-02-05 18:07:34 -08:00
monopole
781098843e Make starlarkmixer plugin module name match path. 2021-02-05 17:57:12 -08:00
Jeff Regan
af3ffa7059 Merge pull request #3493 from natasha41575/UseIntermediateName
Allow references to intermediate IDs after multiple name transformations
2021-02-05 16:31:31 -08:00
Donny Xia
9d7b8952a0 Merge pull request #3535 from MaXinjian/tmpfile
Cleanup tempfiles introduced in confirmeddir_test.go
2021-02-05 12:57:05 -08:00
Natasha Sarkar
cb400c895e added test to check for resources with the same name in different layers 2021-02-05 12:35:59 -08:00
Ma Xinjian
9a8dcf6a8e Cleanup tempfiles introduced in confirmeddir_test.go
Signed-off-by: Ma Xinjian <maxj.fnst@cn.fujitsu.com>
2021-02-05 13:26:58 +08:00
Natasha Sarkar
384b71b5f5 Allow references to intermediate names 2021-02-04 20:38:08 -08:00
Kubernetes Prow Robot
4345cd2ade Merge pull request #3534 from KnVerey/starlark_genformer
Fix function/exec transformer plugin ability to add/remove resources
2021-02-04 19:54:51 -08:00
Katrina Verey
1460d13d50 Allow exec and function transformers to delete resources 2021-02-04 13:01:09 -08:00
Katrina Verey
97a2b15be6 Allow exec and function transformers to generate resources 2021-02-04 13:01:09 -08:00
Katrina Verey
f927cf0b8e Regression test for inability to add resources in function-based transfomer 2021-02-04 13:01:09 -08:00
Jeff Regan
cbb121e651 Merge pull request #3533 from monopole/updateNRtest
Update namerefence tests for apimachinery code path.
2021-02-04 12:15:17 -08:00
monopole
447b315a61 Update namerefence tests for apimachinery code path. 2021-02-04 12:14:16 -08:00
Kubernetes Prow Robot
b3cb61b80f Merge pull request #3532 from monopole/commandsOption3
Expose some top level kustomize commands.
2021-02-04 10:02:26 -08:00
monopole
b9f05dd357 Expose some top level kustomize commands.
The PR exposes some of the top level kustomize commands
(especially `build`) for reuse in other command line tools
(expecially `kubectl`, see #1500).

This PR represents option 3 from the following list of ways
this exposure could be arranged.

1. Expose the commands in the `api` module.

```
REPO/api/go.mod
REPO/api/builtins
REPO/api/commands <- new
REPO/api/...
```

Disadvantage: This would make `api` module depend on cobra.
That's bad for clients that want to depend on the api, but
want to write their own commands at their own version of
cobra.  The `api` module shouldn't depend on UX libraries
like cobra.

2. Expose the commands in their own `commands` module.

They'd appear alongside `api`, e.g. `

```
REPO/api/go.mod
REPO/api/builtins
REPO/api/...
REPO/commands/go.mod
REPO/commands/build
REPO/commands/edit
REPO/commands/...
```

Advantage: The commands would be consumed by the kustomize
binary and the kubectl binary in the same way.

Disadvantage: The kustomize binary module and the commands
module could evolve separately with their own version
numbers, creating confusion.

3. Expose the commands in the existing `kustomize` module

```
REPO/api/go.mod
REPO/api/builtins
REPO/api/...
REPO/kustomize/go.mod
REPO/kustomize/main.go
REPO/kustomize/commands/build
REPO/kustomize/commands/edit
REPO/kustomize/commands/...
```

Outside users, e.g. kubectl, could then

```
import sigs.k8s.io/kustomize/kustomize/v3/commands/build
```

and hopefully still get the `main` package
as they do now via:

```
go get sigs.k8s.io/kustomize/kustomize/v3
```

Advantage: 1) The kustomize binary ships at the same version
as the commands - which makes sense as the binary's
_version_ refers to how the CLI operates (command names,
flags, etc.).  This makes it easy to related the version of
a kustomize binary with the version of commands running in
some other CLI binary.  2) The path to the kustomize binary
doesn't change.

Disadvantage: It's an atypical Go module arrangement.
Usually `main` packages live as leaves under a directory
called `cmd` inside a module, rather than at the _top_ of
the module.  This might cause some problems.  If so, we can
go with option 4.

4. Same as 3, but move `main.go` (the `main` package) down one step.

```
REPO/api/go.mod
REPO/api/builtins
REPO/api/...
REPO/kustomize/go.mod
REPO/kustomize/cmd/main.go
REPO/kustomize/commands/build
REPO/kustomize/commands/edit
REPO/kustomize/commands/...
```
2021-02-04 08:35:01 -08:00
Jeff Regan
1ee16d9f52 Merge pull request #3525 from natasha41575/RefactorNameTransformers
Refactored resource to store all previous names and namespaces
2021-02-03 16:53:16 -08:00
Natasha Sarkar
43157f5d35 cleaned up resource refactoring 2021-02-03 14:30:25 -08:00
Natasha Sarkar
cd918483f9 removed some prefix methods from resource 2021-02-03 12:02:12 -08:00
Natasha Sarkar
f71854a0c8 Refactored resource to store all previous names and namespaces 2021-02-03 12:01:09 -08:00
Kubernetes Prow Robot
6246262965 Merge pull request #3529 from monopole/fix3489
Fix 3489
2021-02-03 11:04:28 -08:00
monopole
d3ea87220b Fix Issue 3489. 2021-02-03 10:49:17 -08:00
Jeff Regan
61daea0202 Merge pull request #3245 from natasha41575/UseOpenApiVersions
Use `openApi` field in kustomization file to specify OpenAPI schema version
2021-02-03 10:35:08 -08:00
Jeff Regan
a54cd12b39 Delete fixgomod.sh 2021-02-03 10:20:28 -08:00
Kubernetes Prow Robot
11ce6363b4 Merge pull request #3528 from monopole/refactorNameref
Refactor nameref for readability.
2021-02-03 10:16:29 -08:00
monopole
4de26ccf9d Refactor nameref for readability. 2021-02-02 19:02:41 -08:00
Jeff Regan
7801830152 Merge pull request #3527 from monopole/addTests
Add tests in support of Issue 3489.
2021-02-02 18:53:31 -08:00
monopole
aae2be1a79 Add tests in support of Issue 3489. 2021-02-02 18:35:46 -08:00
Kubernetes Prow Robot
79e15c05d5 Merge pull request #3522 from Shell32-Natsu/chart-generator
fix relative path to values file
2021-02-02 15:44:28 -08:00
Donny Xia
507244e6f8 fix relative path to values file 2021-02-01 13:55:48 -08:00
Jeff Regan
3892e3c910 Merge pull request #3519 from monopole/fieldspectest
More fieldspec filter tests and comments.
2021-01-31 20:01:47 -08:00
monopole
dcb26d0901 More fieldspec tests. 2021-01-31 19:08:48 -08:00
Jeff Regan
f5f1a15226 Merge pull request #3518 from monopole/nits
Improve name reference transformer testing.
2021-01-31 09:04:45 -08:00
monopole
64644643d4 Improve name reference transformer testing. 2021-01-31 08:40:47 -08:00
Jeff Regan
4d1eebbb82 Merge pull request #3517 from monopole/pathSplitter
Expose smart path splitter as a utility.
2021-01-31 07:56:42 -08:00
monopole
b3a9314e27 Expose smart path splitter as a utility. 2021-01-31 06:45:04 -08:00
Kubernetes Prow Robot
86168cebbc Merge pull request #3514 from natasha41575/TestForPortsIssue
Add test for ports issue #3513
2021-01-29 12:51:49 -08:00
Natasha Sarkar
57a53797d3 Add test for ports issue #3513 2021-01-29 11:10:00 -08:00
Kubernetes Prow Robot
f5beffe394 Merge pull request #3512 from monopole/improveNameRefTests
Add test for issue 3489 and improve error messages.
2021-01-29 10:49:41 -08:00
monopole
4287e28ff4 Add test for issue 3489 and improve error messages. 2021-01-29 06:55:23 -08:00
Jeff Regan
a5cdd98414 Merge pull request #3498 from piyushpgupta/patch-1
Update README.md
2021-01-27 17:20:22 -08:00
Piyush Gupta
16a49c50c4 Update README.md 2021-01-28 09:17:39 +09:00
Piyush Gupta
a6f29f2bf7 Update README.md 2021-01-28 09:17:10 +09:00
Piyush Gupta
22fcf3b3fa Update README.md 2021-01-28 09:16:28 +09:00
Piyush Gupta
a31b846fa5 Update README.md 2021-01-28 09:10:59 +09:00
Jeff Regan
22fb23071b Merge pull request #3483 from msk-/master
Bug: configMapRefs in patches are not resolved correctly in diamond structure
2021-01-27 15:43:49 -08:00
Jeff Regan
382cf5c2e0 Merge pull request #3506 from natasha41575/FixSmpDirectiveWhenElementNotFound
$patch:delete should not add elements when element is not found
2021-01-27 11:24:38 -08:00
Jeff Regan
8d4508a041 Merge pull request #3484 from kubernetes-sigs/issue3377
Demonstrate issue #3377 is fixed.
2021-01-26 16:53:58 -08:00
Natasha Sarkar
4d5657f037 smpdirectives shouldn't add elements when element isn't found 2021-01-26 16:43:30 -08:00
Natasha Sarkar
5958edda14 don't merge patches until they are applied 2021-01-26 16:43:15 -08:00
Natasha Sarkar
48676fe34b updated patch delete test 2021-01-26 16:42:59 -08:00
Jeff Regan
a8278b6da9 Merge pull request #3495 from MaXinjian/install
Add support to install kustomize to specified directory
2021-01-26 12:30:46 -08:00
Kubernetes Prow Robot
31d6e24fa4 Merge pull request #3491 from Shell32-Natsu/error-message
add error message for AsYAML
2021-01-26 12:26:30 -08:00
Jeff Regan
25e11e9020 Update install_kustomize.sh 2021-01-26 12:15:20 -08:00
Jeff Regan
d8e2a76ef3 Merge pull request #3499 from MaXinjian/validator
Fix wrong Validator dir
2021-01-26 12:01:41 -08:00
Jeff Regan
cff7bd4eb2 Merge pull request #3496 from msk-/use-usr-bin-env-bash-for-scripts
Use `/usr/bin/env bash` instead of `/bin/bash` in scripts
2021-01-26 12:01:01 -08:00
Kubernetes Prow Robot
58db58202c Merge pull request #3500 from Shell32-Natsu/ingress-name-ref
support anchor in filedspec
2021-01-26 11:48:31 -08:00
Donny Xia
fc29d7e108 Merge pull request #3503 from dimw/3487-set-image-tag-name
Add support for setting new tag while preserving the current name
2021-01-26 10:32:33 -08:00
dimw
ae060cc225 Add documentation/help on preserving the digest
Issue: #3487
2021-01-25 22:06:44 +01:00
dimw
9b4fdcf35a Add support for setting the name while keeping the digest
- And the other way around

Issue: #3487
2021-01-25 21:38:28 +01:00
dimw
bb2d63ab58 Use raw string to avoid double escape
Issue: #3487
2021-01-25 21:15:05 +01:00
dimw
b5012385c8 Add support for setting new tag while preserving the current name
- As well as setting new name while keeping the tag

Issue: #3487
2021-01-25 15:31:19 +01:00
Natasha Sarkar
659a7de8f9 edited kyaml libraries to use the openapi field from the kustomization file 2021-01-22 16:07:18 -08:00
Natasha Sarkar
866dbf2017 added an openapi field to the kustomization file 2021-01-22 16:06:57 -08:00
Donny Xia
ef89df6123 support anchor in filedspec 2021-01-22 11:01:07 -08:00
Ma Xinjian
97f23966af Fix wrong Validator dir
Signed-off-by: Ma Xinjian <maxj.fnst@cn.fujitsu.com>
2021-01-22 13:54:34 +08:00
Piyush Gupta
5059033b13 Update README.md
Fixed the typo #
2021-01-21 22:41:54 +09:00
msk-
d91e8af702 Use /usr/bin/env bash instead of /bin/bash for scripts to support more systems 2021-01-21 10:43:18 +00:00
msk-
1bef8c4cdd Added ASCII art per PR feedback 2021-01-21 10:13:42 +00:00
msk-
9b87f78511 Modified test name per PR feedback 2021-01-21 10:04:19 +00:00
msk-
eda827c317 Added line break to all WriteK, WriteF calls per PR feedback 2021-01-21 10:03:18 +00:00
Ma Xinjian
be57e1f6c2 Add support to install kustomize to specified directory
Signed-off-by: Ma Xinjian <maxj.fnst@cn.fujitsu.com>
2021-01-21 15:59:04 +08:00
Kubernetes Prow Robot
021c3ce3fc Merge pull request #3494 from KnVerey/template-cmd-without-cobra
[kyaml] Framework/TemplateCommand usability improvements
2021-01-20 16:49:01 -08:00
Katrina Verey
4f184e8ce3 Add validation hook to template command execution 2021-01-20 15:53:46 -08:00
Katrina Verey
2e0d6d42bf Improve framework usability without cobra 2021-01-20 15:53:10 -08:00
Donny Xia
6cf6eb9f76 use reource.AsYAML in resWrangler.AsYAML 2021-01-20 12:51:25 -08:00
Donny Xia
ffed8f1430 add error message for AsYAML 2021-01-20 10:40:59 -08:00
monopole
3d17503329 Demonstrate that #3377 is fixed. 2021-01-19 19:06:36 -08:00
msk-
7ac37867dc tidy-up, added desired behaviour 2021-01-19 18:00:02 +00:00
msk-
d8f2d2256d Fixed test 2021-01-19 17:57:42 +00:00
msk-
463b776486 Initial test commit 2021-01-19 17:41:44 +00:00
Jeff Regan
d28ce28130 Merge pull request #3478 from kubernetes-sigs/testAgainst3.9.2
Test examples against v3.9.2 and v3.8.9
2021-01-17 11:14:46 -08:00
monopole
4f72faeecb Test examples against v3.9.2 and v3.8.9 2021-01-17 10:54:13 -08:00
Jeff Regan
29814b556b Update README.md 2021-01-17 10:25:19 -08:00
Jeff Regan
d94ed369fa Merge pull request #3477 from kubernetes-sigs/unpinEverything
Back to development mode; unpin the modules
2021-01-17 10:25:10 -08:00
monopole
0cf18987d7 Back to development mode; unpin the modules 2021-01-17 10:10:12 -08:00
Jeff Regan
a6374db2cb Update README.md 2021-01-17 10:09:08 -08:00
Jeff Regan
e98eada736 Merge pull request #3476 from kubernetes-sigs/pinToApi
Pin to api v0.7.2
2021-01-17 09:36:37 -08:00
monopole
8a65ece956 Pin to api v0.7.2 2021-01-17 09:19:41 -08:00
Jeff Regan
4cdc3b0bad Merge pull request #3475 from kubernetes-sigs/pinToCmdConfig
Pin to cmd/config v0.8.8
2021-01-17 09:09:20 -08:00
monopole
40bf89abcd Pin to cmd/config v0.8.8 2021-01-17 08:40:13 -08:00
Jeff Regan
7f548eddd0 Merge pull request #3474 from kubernetes-sigs/pinToKyamlAndCliUtils
Pin to kyaml v0.10.6 and cli-utils v0.22.4
2021-01-17 07:17:43 -08:00
monopole
86e9983bb7 Pin to kyaml v0.10.6 and cli-utils v0.22.4 2021-01-17 06:55:10 -08:00
Jeff Regan
cbbcfde99d Update multiplepatch_test.go 2021-01-16 20:43:57 -08:00
Jeff Regan
304a9e57ee Update factory_test.go 2021-01-16 20:36:46 -08:00
Jeff Regan
f23f26aa05 Update factory_test.go 2021-01-16 20:24:39 -08:00
Jeff Regan
720857623f Merge pull request #3473 from monopole/doImportantStuff
Fix unfiled bug in port replacement where ports were being quoted.
2021-01-16 18:02:06 -08:00
monopole
065c2b861a Fix unfiled bug; don't quote port numbers. 2021-01-16 16:56:48 -08:00
monopole
2a16af80bf Simplify, document and add more tests to var replacement. 2021-01-16 16:48:26 -08:00
Jeff Regan
81d324c68c Merge pull request #3472 from monopole/issue3449
Reproduce issue #3449
2021-01-16 16:47:45 -08:00
monopole
b8702561ef Add test for issue 3449 2021-01-16 16:45:13 -08:00
Jeff Regan
ea039b36bc Merge pull request #3471 from monopole/mergeExpansionRefvar
Merge expansion package into refvar package.
2021-01-16 13:54:32 -08:00
monopole
561cef1d5c Merge expansion package into refvar package. 2021-01-16 13:50:56 -08:00
Jeff Regan
62c5e424a6 Merge pull request #3470 from monopole/annotateIssue3304
Annotate code with decisions on issue 3304 in kyaml conversion
2021-01-16 09:09:49 -08:00
monopole
45b1bf17d3 Annotate decisions on issue 3304 in api. 2021-01-16 08:08:52 -08:00
monopole
11dce34407 Annotate decisions on issue 3304 in plugins. 2021-01-16 08:08:39 -08:00
Kubernetes Prow Robot
550a89295a Merge pull request #3469 from monopole/labelAndAnnotationQuoting
Always quote non-string values in labels and annotations
2021-01-15 18:43:43 -08:00
monopole
8083b3607f Harden anno transformer test. 2021-01-15 17:37:46 -08:00
monopole
cb42142161 Fix api tests that accomodated bad label and anno quoting. 2021-01-15 17:37:46 -08:00
monopole
cb59e0ef5f Always tag label and annotations values as strings. 2021-01-15 17:37:46 -08:00
Jeff Regan
1a4a9fcdaf Update go.mod 2021-01-15 17:33:00 -08:00
Kubernetes Prow Robot
eb8dc5e20a Merge pull request #3462 from mikhail-nikitin/master
$patch: delete of not existing elements
2021-01-15 14:23:43 -08:00
Jeff Regan
0fb30a1010 In plugin tests, yell FAILURE on failure. 2021-01-15 13:58:09 -08:00
Jeff Regan
fdfdfa9e4d Update go.mod 2021-01-15 13:56:18 -08:00
Jeff Regan
6042aca7a4 Update CalvinDuplicator.go 2021-01-15 13:33:46 -08:00
Jeff Regan
94962c8bac Update CalvinDuplicator_test.go 2021-01-15 13:10:40 -08:00
Mikhail Nikitin
f6ddea435c Make test file paths consistent and relative
Signed-off-by: Mikhail Nikitin <mikhail.nikitin@ispringsolutions.com>
2021-01-15 22:50:23 +03:00
Jeff Regan
a9d4b7615f Merge pull request #3466 from monopole/renameAnnotations
Rename id annotations to build annotations.
2021-01-15 11:27:49 -08:00
Jeff Regan
822cac26f9 Merge pull request #3467 from monopole/calvinDuplicator
Add calvin duplicator example plugin.
2021-01-15 07:58:11 -08:00
monopole
97eedc8a43 Add calvin duplicator example plugin. 2021-01-15 07:22:46 -08:00
monopole
2cb972de3b Rename id annotations to build annotations. 2021-01-15 06:43:13 -08:00
Jeff Regan
79d0d6b5e1 Merge pull request #3465 from monopole/pdbTest
Add test covering pod disruption budget treatment.
2021-01-15 06:38:38 -08:00
monopole
fabaf35c72 Add test covering pod disruption budget treatment. 2021-01-15 06:09:52 -08:00
Mikhail Nikitin
e13f8803eb Add test case of deleting not existing elements 2021-01-15 00:08:49 +03:00
Jeff Regan
64ffbcb15d Merge pull request #3461 from monopole/anotherTest
Add another test covering fix of 3412
2021-01-14 11:52:56 -08:00
monopole
b41df2293b Add another test covering fix of 3412 2021-01-14 11:32:34 -08:00
Kubernetes Prow Robot
e3fcec122a Merge pull request #3460 from monopole/fix3412
Fix 3412, retaining quotes in configmap data fields
2021-01-14 11:25:32 -08:00
monopole
1edf9b630c Update configmap test with quotes fixed. 2021-01-14 11:01:37 -08:00
monopole
7c6bf2e21d When merging configmaps, retain proper quoting. 2021-01-14 11:01:06 -08:00
monopole
b3fc306f6a Move some code to make it reusable without import cycles. 2021-01-14 10:29:51 -08:00
Jeff Regan
e92d048af2 Merge pull request #3441 from natasha41575/namePrefixNamespaceBehavior
Update name references by checking both the original and current namespaces
2021-01-13 16:21:05 -08:00
Kubernetes Prow Robot
f76059b824 Merge pull request #3454 from monopole/evenMoreTests
Add more tests and explain some quoting behavior.
2021-01-13 16:05:03 -08:00
monopole
bb41d018b5 Add more tests and explain some strange quotes. 2021-01-13 15:49:12 -08:00
Kubernetes Prow Robot
cf8815b0a0 Merge pull request #3453 from Shell32-Natsu/wnode-field-value
fix GetFieldValue cannot handle slice index
2021-01-13 15:07:03 -08:00
Donny Xia
64beee22e9 fix GetFieldValue cannot handle slice index 2021-01-13 14:14:01 -08:00
Jeff Regan
79afd219a5 Merge pull request #3450 from monopole/anotherTest
Add a test that only loads an annotated resource.
2021-01-13 11:27:14 -08:00
monopole
c68cf40d75 Add a test that only loads an annotated resource. 2021-01-13 10:56:50 -08:00
Kubernetes Prow Robot
c7337a7d87 Merge pull request #3445 from KnVerey/resource_list_empty_items
[kio] Unwrap ResourceList with a functionConfig but no items
2021-01-12 17:04:35 -08:00
Jeff Regan
875e265e5d Merge pull request #3372 from natasha41575/AddNameAnnotations
Refactor resource to use annotations in the yaml instead of fields in resource struct
2021-01-12 16:38:48 -08:00
Katrina Verey
bdbfb28139 Unwrap ResourceList with a functionConfig but no items 2021-01-12 16:13:40 -08:00
Natasha Sarkar
d54bc674f2 Update name references by checking both the original and current namespaces 2021-01-11 18:08:52 -08:00
Natasha Sarkar
bd4580d73a Manage name changes (prefix/suffix) via YAML annotations rather than via in-memory-only fields. 2021-01-11 13:08:45 -08:00
Kubernetes Prow Robot
ea5d08bac5 Merge pull request #3438 from monopole/fix3424
Fix 3424 by avoiding a JSON round trip
2021-01-11 10:18:24 -08:00
monopole
14a1a0e4a8 Fix 3424 by avoiding a JSON round trip 2021-01-10 20:39:01 -08:00
Jeff Regan
497e8038a3 Merge pull request #3439 from monopole/clarifyErrorMessage
Clarify var-related error message.
2021-01-10 20:38:39 -08:00
monopole
44b5acad51 Clarify var-related error message. 2021-01-10 20:35:55 -08:00
Jeff Regan
e5e19f7c09 Merge pull request #3431 from Shell32-Natsu/newline
keep \n in the end of resource yaml
2021-01-10 12:51:36 -08:00
Jeff Regan
a03843dfc7 Merge pull request #3437 from monopole/regressionTestsForKyaml
In kyaml, loosen interpretation of string node and add tests.
2021-01-10 12:28:30 -08:00
monopole
b7cce27d40 In kyaml, loosen interpretation of string node and add tests. 2021-01-10 12:08:50 -08:00
Jeff Regan
126f5481f3 Merge pull request #3436 from monopole/addTestsAroundVarRefTransformer
Add var ref replacement tests and more doc.
2021-01-10 09:38:30 -08:00
monopole
30dcf38609 Add var ref replacement tests and more doc. 2021-01-10 09:16:52 -08:00
Jeff Regan
1a2779b2c3 Merge pull request #3434 from monopole/reduceComplexityInNameReferenceTransformer
Reduce complexity in NameReferenceTransformer.
2021-01-10 07:12:23 -08:00
monopole
658b62c6f1 Reduce complexity in NameReferenceTransformer. 2021-01-10 06:56:06 -08:00
Jeff Regan
cf0bb49610 Merge pull request #3433 from monopole/anotherTowards3412
Improve handling of empty resource maps.
2021-01-09 07:20:19 -08:00
monopole
c2fbb709da Don't swallow error in SM patch and use new RNode Map method. 2021-01-09 07:00:21 -08:00
monopole
1a002005c1 Add RNode.Map method and test to help decoding. 2021-01-09 06:57:01 -08:00
Jeff Regan
4f468fcc90 Merge pull request #3432 from monopole/towards3412
Short circuit anno/label transformer for performance.
2021-01-08 18:53:47 -08:00
monopole
769f65d6c4 Short circuit anno/label transformer for performance. 2021-01-08 18:02:58 -08:00
Donny Xia
378eaedc82 keep \n in the end of resource yaml 2021-01-08 15:36:36 -08:00
Jeff Regan
6f2f401f6b Merge pull request #3428 from monopole/confineApplyToJson
Confine calls to ApplyToJSON.
2021-01-07 20:53:55 -08:00
monopole
614e853db3 Confine calls to ApplyToJSON. 2021-01-07 20:31:10 -08:00
Jeff Regan
33be04db45 Merge pull request #3427 from monopole/avoidCycle
Move plugin lister to avoid import cycle.
2021-01-07 19:27:45 -08:00
monopole
8c6a9f6495 Move plugin lister to avoid import cycle. 2021-01-07 18:46:04 -08:00
Jeff Regan
03b2fff0ee Merge pull request #3425 from monopole/issue3424
Add test for issue 3424
2021-01-07 15:55:47 -08:00
monopole
69cade143f Add test for issue 3424 2021-01-06 16:23:12 -08:00
Jeff Regan
90f45651d1 Merge pull request #3416 from HansK-p/Fix-link-to-lugins-doc
Updated link to Kustomize plugins documentation
2021-01-06 15:49:19 -08:00
Hans Kristian Nordengen
1b740034f7 Updated link to Kustomize plugins documentation 2021-01-03 19:44:32 +01:00
Jeff Regan
a2d8e686de Merge pull request #3411 from monopole/unpinApiKyamlCmdConfig
Unpin kyaml, cmd/config, api
2020-12-29 18:17:48 -08:00
jregan
ce2ab487a5 Unpin kyaml, cmd/config, api 2020-12-29 16:18:12 -08:00
Jeff Regan
7439f1809e Merge pull request #3410 from monopole/pinToApiv0.7.1
Pin to api/v0.7.1 (--enableKyaml=true)
2020-12-29 09:43:42 -08:00
jregan
6977c83a83 Pin to api/v0.7.1 (--enableKyaml=true) 2020-12-29 09:24:25 -08:00
Jeff Regan
7b9eb05058 Merge pull request #3408 from monopole/enableKyamlForApiv0.7.1
Set FlagEnableKyamlDefaultValue = true
2020-12-29 08:36:33 -08:00
jregan
e2806a09fd Set FlagEnableKyamlDefaultValue = true 2020-12-29 08:17:45 -08:00
Jeff Regan
f30fea4c07 Merge pull request #3407 from monopole/pinToApiv0.6.8
Pin to api/v0.6.8
2020-12-29 07:44:13 -08:00
jregan
8732671919 Pin to api/v0.6.8 2020-12-29 07:27:11 -08:00
Jeff Regan
07cada36fa Merge pull request #3406 from monopole/pinToCmdConfig_v0.8.7
Pin to cmd/confg v0.8.7
2020-12-29 07:11:12 -08:00
jregan
0d6b232b49 Pin to cmd/confg v0.8.7 2020-12-29 06:55:07 -08:00
Jeff Regan
61455fe489 Merge pull request #3404 from monopole/pinKyamlv0.10.5
Pin to kyaml v0.10.5
2020-12-28 20:50:59 -08:00
jregan
c63ed033ad Pin to kyaml v0.10.5
ALLOW_MODULE_SPAN
2020-12-28 20:30:22 -08:00
Jeff Regan
455bd0c563 Merge pull request #3403 from monopole/betterPin
Unpin versioned and unversioned pins.
2020-12-28 18:11:39 -08:00
jregan
9ad4b1ddca Unpin versioned and unversioned pins. 2020-12-28 18:10:53 -08:00
Jeff Regan
d529eb8777 Merge pull request #3402 from monopole/upgradeGopkg.in_yaml.v3
Pin to gopkg.in/yaml.v3 v3.0.0-20200313102051
2020-12-28 18:02:41 -08:00
jregan
f7b2f0c067 Pin to gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
This is the last commit in yaml.v3 before

  ae27a74434

which changed the indentation of sequence.

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

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

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

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

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

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

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

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

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

View File

@@ -4,7 +4,7 @@
# Makefile for kustomize CLI and API.
MYGOBIN := $(shell go env GOPATH)/bin
SHELL := /bin/bash
SHELL := /usr/bin/env bash
export PATH := $(MYGOBIN):$(PATH)
MODULES := '"cmd/config" "api/" "kustomize/" "kyaml/"'
@@ -26,7 +26,8 @@ verify-kustomize: \
lint-kustomize \
test-unit-kustomize-all \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.6
test-examples-kustomize-against-4.0 \
test-examples-kustomize-against-3.10
# The following target referenced by a file in
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
@@ -38,7 +39,8 @@ prow-presubmit-check: \
test-unit-cmd-all \
test-go-mod \
test-examples-kustomize-against-HEAD \
test-examples-kustomize-against-3.8.6
test-examples-kustomize-against-4.0 \
test-examples-kustomize-against-3.10
.PHONY: verify-kustomize-e2e
verify-kustomize-e2e: test-examples-e2e-kustomize
@@ -77,6 +79,11 @@ $(MYGOBIN)/gorepomod:
cd cmd/gorepomod; \
go install .
# Build from local source.
$(MYGOBIN)/k8scopy:
cd cmd/k8scopy; \
go install .
# Build from local source.
$(MYGOBIN)/pluginator:
cd cmd/pluginator; \
@@ -96,13 +103,13 @@ $(MYGOBIN)/kustomize:
install-tools: \
$(MYGOBIN)/goimports \
$(MYGOBIN)/golangci-lint-kustomize \
$(MYGOBIN)/gh \
$(MYGOBIN)/gorepomod \
$(MYGOBIN)/helm \
$(MYGOBIN)/k8scopy \
$(MYGOBIN)/mdrip \
$(MYGOBIN)/pluginator \
$(MYGOBIN)/prchecker \
$(MYGOBIN)/stringer \
$(MYGOBIN)/helm
$(MYGOBIN)/stringer
### Begin kustomize plugin rules.
#
@@ -219,7 +226,7 @@ build-kustomize-api: $(builtinplugins)
cd api; go build ./...
.PHONY: generate-kustomize-api
generate-kustomize-api:
generate-kustomize-api: $(MYGOBIN)/k8scopy
cd api; go generate ./...
.PHONY: test-unit-kustomize-api
@@ -274,17 +281,12 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh HEAD
.PHONY:
test-examples-kustomize-against-3.8.6: $(MYGOBIN)/mdrip
( \
set -e; \
tag=v3.8.6; \
/bin/rm -f $(MYGOBIN)/kustomize; \
echo "Installing kustomize $$tag."; \
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@$${tag}; \
./hack/testExamplesAgainstKustomize.sh $$tag; \
echo "Reinstalling kustomize from HEAD."; \
cd kustomize; go install .; \
)
test-examples-kustomize-against-4.0: $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh v4@v4.0.1
.PHONY:
test-examples-kustomize-against-3.10: $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh v3@v3.10.0
# linux only.
# This is for testing an example plugin that

View File

@@ -7,7 +7,6 @@ import (
"sigs.k8s.io/kustomize/api/filters/annotations"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -25,11 +24,14 @@ func (p *AnnotationsTransformerPlugin) Config(
}
func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
if len(p.Annotations) == 0 {
return nil
}
for _, r := range m.Resources() {
err := filtersutil.ApplyToJSON(annotations.Filter{
err := r.ApplyFilter(annotations.Filter{
Annotations: p.Annotations,
FsSlice: p.FieldSpecs,
}, r)
})
if err != nil {
return err
}

View File

@@ -28,6 +28,7 @@ func (p *HashTransformerPlugin) Transform(m resmap.ResMap) error {
if err != nil {
return err
}
res.StorePreviousId()
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
}
}

View File

@@ -6,12 +6,15 @@ package builtins
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"github.com/imdario/mergo"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/resmap"
@@ -48,7 +51,7 @@ func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, conf
return fmt.Errorf("chartName cannot be empty")
}
if p.ChartHome == "" {
p.ChartHome = path.Join(p.tmpDir, "chart")
p.ChartHome = filepath.Join(p.tmpDir, "chart")
}
if p.ChartRepoName == "" {
p.ChartRepoName = "stable"
@@ -57,10 +60,13 @@ func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, conf
p.HelmBin = "helm"
}
if p.HelmHome == "" {
p.HelmHome = path.Join(p.tmpDir, ".helm")
p.HelmHome = filepath.Join(p.tmpDir, ".helm")
}
if p.Values == "" {
p.Values = path.Join(p.ChartHome, p.ChartName, "values.yaml")
p.Values = filepath.Join(p.ChartHome, p.ChartName, "values.yaml")
}
if p.ValuesMerge == "" {
p.ValuesMerge = "override"
}
// runHelmCommand will run `helm` command with args provided. Return stdout
// and error if there is any.
@@ -88,6 +94,94 @@ func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, conf
return nil
}
// EncodeValues for writing
func (p *HelmChartInflationGeneratorPlugin) EncodeValues(w io.Writer) error {
d, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
_, err = w.Write(d)
if err != nil {
return err
}
return nil
}
// useValuesLocal process (merge) inflator config provided values with chart default values.yaml
func (p *HelmChartInflationGeneratorPlugin) useValuesLocal() error {
// not override, merge, none
if !(p.ValuesMerge == "none" || p.ValuesMerge == "no" || p.ValuesMerge == "false") {
var pValues []byte
var err error
if filepath.IsAbs(p.Values) {
pValues, err = ioutil.ReadFile(p.Values)
} else {
pValues, err = p.h.Loader().Load(p.Values)
}
if err != nil {
return err
}
chValues := make(map[string]interface{})
err = yaml.Unmarshal(pValues, &chValues)
if err != nil {
return err
}
if p.ValuesMerge == "override" {
err = mergo.Merge(&chValues, p.ValuesLocal, mergo.WithOverride)
if err != nil {
return err
}
}
if p.ValuesMerge == "merge" {
err = mergo.Merge(&chValues, p.ValuesLocal)
if err != nil {
return err
}
}
p.ValuesLocal = chValues
}
b, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
path, err := p.writeValuesBytes(b)
if err != nil {
return err
}
p.Values = path
return nil
}
// copyValues will copy the relative values file into the temp directory
// to avoid messing up with CWD.
func (p *HelmChartInflationGeneratorPlugin) copyValues() error {
// only copy when the values path is not absolute
if filepath.IsAbs(p.Values) {
return nil
}
// we must use use loader to read values file
b, err := p.h.Loader().Load(p.Values)
if err != nil {
return err
}
path, err := p.writeValuesBytes(b)
if err != nil {
return err
}
p.Values = path
return nil
}
func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(b []byte) (string, error) {
path := filepath.Join(p.ChartHome, p.ChartName, "kustomize-values.yaml")
err := ioutil.WriteFile(path, b, 0644)
if err != nil {
return "", err
}
return path, nil
}
// Generate implements generator
func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
// cleanup
@@ -104,6 +198,20 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
return nil, err
}
}
// inflator config valuesLocal
if len(p.ValuesLocal) > 0 {
err := p.useValuesLocal()
if err != nil {
return nil, err
}
} else {
err := p.copyValues()
if err != nil {
return nil, err
}
}
// render the charts
stdout, err := p.runHelmCommand(p.getTemplateCommandArgs())
if err != nil {
@@ -118,7 +226,7 @@ func (p *HelmChartInflationGeneratorPlugin) getTemplateCommandArgs() []string {
if p.ReleaseName != "" {
args = append(args, p.ReleaseName)
}
args = append(args, path.Join(p.ChartHome, p.ChartName))
args = append(args, filepath.Join(p.ChartHome, p.ChartName))
if p.ReleaseNamespace != "" {
args = append(args, "--namespace", p.ReleaseNamespace)
}
@@ -148,7 +256,7 @@ func (p *HelmChartInflationGeneratorPlugin) getPullCommandArgs() []string {
// checkLocalChart will return true if the chart does exist in
// local chart home.
func (p *HelmChartInflationGeneratorPlugin) checkLocalChart() bool {
path := path.Join(p.ChartHome, p.ChartName)
path := filepath.Join(p.ChartHome, p.ChartName)
s, err := os.Stat(path)
if err != nil {
return false

View File

@@ -11,7 +11,6 @@ import (
"sigs.k8s.io/kustomize/api/filters/imagetag"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -32,17 +31,17 @@ func (p *ImageTagTransformerPlugin) Config(
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
for _, r := range m.Resources() {
// traverse all fields at first
err := filtersutil.ApplyToJSON(imagetag.LegacyFilter{
err := r.ApplyFilter(imagetag.LegacyFilter{
ImageTag: p.ImageTag,
}, r)
})
if err != nil {
return err
}
// then use user specified field specs
err = filtersutil.ApplyToJSON(imagetag.Filter{
err = r.ApplyFilter(imagetag.Filter{
ImageTag: p.ImageTag,
FsSlice: p.FieldSpecs,
}, r)
})
if err != nil {
return err
}

View File

@@ -7,7 +7,6 @@ import (
"sigs.k8s.io/kustomize/api/filters/labels"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -25,11 +24,14 @@ func (p *LabelTransformerPlugin) Config(
}
func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error {
if len(p.Labels) == 0 {
return nil
}
for _, r := range m.Resources() {
err := filtersutil.ApplyToJSON(labels.Filter{
err := r.ApplyFilter(labels.Filter{
Labels: p.Labels,
FsSlice: p.FieldSpecs,
}, r)
})
if err != nil {
return err
}

View File

@@ -9,7 +9,6 @@ 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/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -35,10 +34,11 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
// Don't mutate empty objects?
continue
}
err := filtersutil.ApplyToJSON(namespace.Filter{
r.StorePreviousId()
err := r.ApplyFilter(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
}, r)
})
if err != nil {
return err
}

View File

@@ -12,7 +12,6 @@ import (
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -79,9 +78,9 @@ func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
return err
}
for _, res := range resources {
err = filtersutil.ApplyToJSON(patchjson6902.Filter{
err = res.ApplyFilter(patchjson6902.Filter{
Patch: p.JsonOp,
}, res)
})
if err != nil {
return err
}

View File

@@ -13,7 +13,6 @@ import (
)
type PatchStrategicMergeTransformerPlugin struct {
h *resmap.PluginHelpers
loadedPatches []*resource.Resource
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
@@ -21,7 +20,6 @@ type PatchStrategicMergeTransformerPlugin struct {
func (p *PatchStrategicMergeTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.h = h
err = yaml.Unmarshal(c, p)
if err != nil {
return err
@@ -36,13 +34,13 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
// All tests pass if this code is commented out. This code should
// be deleted; the user should use the Patches field which
// exists for this purpose (inline patch declaration).
res, err := p.h.ResmapFactory().RF().SliceFromBytes([]byte(onePath))
res, err := h.ResmapFactory().RF().SliceFromBytes([]byte(onePath))
if err == nil {
p.loadedPatches = append(p.loadedPatches, res...)
continue
}
res, err = p.h.ResmapFactory().RF().SliceFromPatches(
p.h.Loader(), []types.PatchStrategicMerge{onePath})
res, err = h.ResmapFactory().RF().SliceFromPatches(
h.Loader(), []types.PatchStrategicMerge{onePath})
if err != nil {
return err
}
@@ -50,7 +48,7 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
}
}
if p.Patches != "" {
res, err := p.h.ResmapFactory().RF().SliceFromBytes([]byte(p.Patches))
res, err := h.ResmapFactory().RF().SliceFromBytes([]byte(p.Patches))
if err != nil {
return err
}
@@ -61,15 +59,16 @@ func (p *PatchStrategicMergeTransformerPlugin) Config(
return fmt.Errorf(
"patch appears to be empty; files=%v, Patch=%s", p.Paths, p.Patches)
}
return err
}
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
patches, err := p.h.ResmapFactory().Merge(p.loadedPatches)
// Merge the patches, looking for conflicts.
_, err = h.ResmapFactory().ConflatePatches(p.loadedPatches)
if err != nil {
return err
}
for _, patch := range patches.Resources() {
return nil
}
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
for _, patch := range p.loadedPatches {
target, err := m.GetById(patch.OrgId())
if err != nil {
return err

View File

@@ -12,7 +12,6 @@ import (
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -105,9 +104,10 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
return err
}
for _, res := range resources {
err = filtersutil.ApplyToJSON(patchjson6902.Filter{
res.StorePreviousId()
err = res.ApplyFilter(patchjson6902.Filter{
Patch: p.Patch,
}, res)
})
if err != nil {
return err
}

View File

@@ -10,7 +10,6 @@ import (
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -67,14 +66,18 @@ func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
// this will add a prefix and a suffix
// to the resource even if those are
// empty
r.AddNamePrefix(p.Prefix)
r.AddNameSuffix(p.Suffix)
if p.Prefix != "" || p.Suffix != "" {
r.StorePreviousId()
}
}
err := filtersutil.ApplyToJSON(prefixsuffix.Filter{
err := r.ApplyFilter(prefixsuffix.Filter{
Prefix: p.Prefix,
Suffix: p.Suffix,
FieldSpec: fs,
}, r)
})
if err != nil {
return err
}

View File

@@ -7,8 +7,6 @@ import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/replicacount"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
@@ -33,19 +31,17 @@ func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
found := false
for _, fs := range p.FieldSpecs {
matcher := p.createMatcher(fs)
matchOriginal := m.GetMatchingResourcesByOriginalId(matcher)
resList := append(
matchOriginal, m.GetMatchingResourcesByCurrentId(matcher)...)
resList := m.GetMatchingResourcesByAnyId(matcher)
if len(resList) > 0 {
found = true
for _, r := range resList {
// There are redundant checks in the filter
// that we'll live with until resolution of
// https://github.com/kubernetes-sigs/kustomize/issues/2506
err := filtersutil.ApplyToJSON(replicacount.Filter{
err := r.ApplyFilter(replicacount.Filter{
Replica: p.Replica,
FieldSpec: fs,
}, r)
})
if err != nil {
return err
}

View File

@@ -13,7 +13,6 @@ import (
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -119,15 +118,15 @@ func (p *ValueAddTransformerPlugin) Transform(m resmap.ResMap) (err error) {
// TODO: consider t.NotSelector if implemented
for _, res := range resources {
if t.FieldPath == types.MetadataNamespacePath {
err = filtersutil.ApplyToJSON(namespace.Filter{
err = res.ApplyFilter(namespace.Filter{
Namespace: p.Value,
}, res)
})
} else {
err = filtersutil.ApplyToJSON(valueadd.Filter{
err = res.ApplyFilter(valueadd.Filter{
Value: p.Value,
FieldPath: t.FieldPath,
FilePathPosition: t.FilePathPosition,
}, res)
})
}
if err != nil {
return err

View File

@@ -4,6 +4,7 @@
package filesys_test
import (
"os"
"path/filepath"
"testing"
@@ -98,6 +99,7 @@ func TestNewTempConfirmDir(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
defer os.RemoveAll(string(tmp))
delinked, err := filepath.EvalSymlinks(string(tmp))
if err != nil {

View File

@@ -24,7 +24,7 @@ type Filter struct {
var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
keys := filtersutil.SortedMapKeys(f.Annotations)
keys := yaml.SortedMapKeys(f.Annotations)
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
for _, k := range keys {

View File

@@ -28,7 +28,9 @@ metadata:
`)}},
Filters: []kio.Filter{Filter{
Annotations: map[string]string{
"foo": "bar",
"foo": "bar",
"booleanValue": "true",
"numberValue": "42",
},
FsSlice: fss,
}},
@@ -44,12 +46,16 @@ metadata:
// metadata:
// name: instance
// annotations:
// booleanValue: "true"
// foo: bar
// numberValue: "42"
// ---
// apiVersion: example.com/v1
// kind: Bar
// metadata:
// name: instance
// annotations:
// booleanValue: "true"
// foo: bar
// numberValue: "42"
}

View File

@@ -4,9 +4,11 @@
package fieldspec
import (
"fmt"
"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/yaml"
@@ -14,7 +16,16 @@ import (
var _ yaml.Filter = Filter{}
// Filter applies a single fieldSpec to a single object
// Filter possibly mutates its object argument using a FieldSpec.
// If the object matches the FieldSpec, and the node found
// by following the fieldSpec's path is non-null, this filter calls
// the setValue function on the node at the end of the path.
// If any part of the path doesn't exist, the filter returns
// without doing anything and without error, unless it was set
// to create the path. If set to create, it creates a tree of maps
// along the path, and the leaf node gets the setValue called on it.
// Error on GVK mismatch, empty or poorly formed path.
// Filter expect kustomize style paths, not JSON paths.
// Filter stores internal state and should not be reused
type Filter struct {
// FieldSpec contains the path to the value to set.
@@ -37,44 +48,51 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
return obj, errors.Wrap(err)
}
fltr.path = splitPath(fltr.FieldSpec.Path)
if err := fltr.filter(obj); err != nil {
fltr.path = utils.PathSplitter(fltr.FieldSpec.Path)
err := fltr.filter(obj)
if err != nil {
s, _ := obj.String()
return nil, errors.WrapPrefixf(err,
"obj '%s' at path '%v'", s, fltr.FieldSpec.Path)
"considering field '%s' of object\n%v", fltr.FieldSpec.Path, s)
}
return obj, nil
}
// Recursively called.
func (fltr Filter) filter(obj *yaml.RNode) error {
if len(fltr.path) == 0 {
// found the field -- set its value
return fltr.SetValue(obj)
}
if obj.IsTaggedNull() {
if obj.IsTaggedNull() || obj.IsNil() {
return nil
}
switch obj.YNode().Kind {
case yaml.SequenceNode:
return fltr.seq(obj)
return fltr.handleSequence(obj)
case yaml.MappingNode:
return fltr.field(obj)
return fltr.handleMap(obj)
case yaml.AliasNode:
return fltr.filter(yaml.NewRNode(obj.YNode().Alias))
default:
return errors.Errorf("expected sequence or mapping node")
}
}
// field calls filter on the field matching the next path element
func (fltr Filter) field(obj *yaml.RNode) error {
// handleMap calls filter on the map field matching the next path element
func (fltr Filter) handleMap(obj *yaml.RNode) error {
fieldName, isSeq := isSequenceField(fltr.path[0])
if fieldName == "" {
return fmt.Errorf("cannot set or create an empty field name")
}
// lookup the field matching the next path element
var lookupField yaml.Filter
var operation yaml.Filter
var kind yaml.Kind
tag := yaml.NodeTagEmpty
switch {
case !fltr.FieldSpec.CreateIfNotPresent || fltr.CreateKind == 0 || isSeq:
// dont' create the field if we don't find it
lookupField = yaml.Lookup(fieldName)
// don't create the field if we don't find it
operation = yaml.Lookup(fieldName)
if isSeq {
// The query path thinks this field should be a sequence;
// accept this hint for use later if the tag is NodeTagNull.
@@ -82,21 +100,25 @@ func (fltr Filter) field(obj *yaml.RNode) error {
}
case len(fltr.path) <= 1:
// create the field if it is missing: use the provided node kind
lookupField = yaml.LookupCreate(fltr.CreateKind, fieldName)
operation = yaml.LookupCreate(fltr.CreateKind, fieldName)
kind = fltr.CreateKind
tag = fltr.CreateTag
default:
// create the field if it is missing: must be a mapping node
lookupField = yaml.LookupCreate(yaml.MappingNode, fieldName)
operation = yaml.LookupCreate(yaml.MappingNode, fieldName)
kind = yaml.MappingNode
tag = yaml.NodeTagMap
}
// locate (or maybe create) the field
field, err := obj.Pipe(lookupField)
if err != nil || field == nil {
field, err := obj.Pipe(operation)
if err != nil {
return errors.WrapPrefixf(err, "fieldName: %s", fieldName)
}
if field == nil {
// No error if field not found.
return nil
}
// if the value exists, but is null and kind is set,
// then change it to the creation type
@@ -114,7 +136,7 @@ func (fltr Filter) field(obj *yaml.RNode) error {
}
// seq calls filter on all sequence elements
func (fltr Filter) seq(obj *yaml.RNode) error {
func (fltr Filter) handleSequence(obj *yaml.RNode) error {
if err := obj.VisitElements(func(node *yaml.RNode) error {
// recurse on each element -- re-allocating a Filter is
// not strictly required, but is more consistent with field
@@ -125,16 +147,14 @@ func (fltr Filter) seq(obj *yaml.RNode) error {
return errors.WrapPrefixf(err,
"visit traversal on path: %v", fltr.path)
}
return nil
}
// isSequenceField returns true if the path element is for a sequence field.
// isSequence also returns the path element with the '[]' suffix trimmed
func isSequenceField(name string) (string, bool) {
isSeq := strings.HasSuffix(name, "[]")
name = strings.TrimSuffix(name, "[]")
return name, isSeq
shorter := strings.TrimSuffix(name, "[]")
return shorter, shorter != name
}
// isMatchGVK returns true if the fs.GVK matches the obj GVK.
@@ -163,18 +183,3 @@ func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) {
return true, nil
}
func splitPath(path string) []string {
ps := strings.Split(path, "/")
var res []string
res = append(res, ps[0])
for i := 1; i < len(ps); i++ {
lastIndex := len(res) - 1
if strings.HasSuffix(res[lastIndex], "\\") {
res[lastIndex] = strings.TrimSuffix(res[lastIndex], "\\") + "/" + ps[i]
} else {
res = append(res, ps[i])
}
}
return res
}

View File

@@ -15,206 +15,243 @@ import (
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type TestCase struct {
name string
input string
expected string
filter fieldspec.Filter
fieldSpec string
error string
}
var tests = []TestCase{
{
name: "update",
fieldSpec: `
func TestFilter_Filter(t *testing.T) {
testCases := map[string]struct {
input string
expected string
filter fieldspec.Filter
fieldSpec string
error string
}{
"path not found": {
fieldSpec: `
path: a/b
group: foo
kind: Bar
`,
input: `
input: `
apiVersion: foo
kind: Bar
xxx:
`,
expected: `
apiVersion: foo
kind: Bar
xxx:
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
"empty path": {
fieldSpec: `
group: foo
kind: Bar
`,
input: `
apiVersion: foo
kind: Bar
xxx:
`,
expected: `
apiVersion: foo
kind: Bar
xxx:
`,
error: `considering field '' of object
apiVersion: foo
kind: Bar
xxx:
: cannot set or create an empty field name`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
"update": {
fieldSpec: `
path: a/b
group: foo
kind: Bar
`,
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b: c
`,
expected: `
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b: e
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
{
name: "update-kind-not-match",
fieldSpec: `
"update-kind-not-match": {
fieldSpec: `
path: a/b
group: foo
kind: Bar1
`,
input: `
input: `
apiVersion: foo/v1beta1
kind: Bar2
a:
b: c
`,
expected: `
expected: `
apiVersion: foo/v1beta1
kind: Bar2
a:
b: c
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
{
name: "update-group-not-match",
fieldSpec: `
"update-group-not-match": {
fieldSpec: `
path: a/b
group: foo1
kind: Bar
`,
input: `
input: `
apiVersion: foo2/v1beta1
kind: Bar
a:
b: c
`,
expected: `
expected: `
apiVersion: foo2/v1beta1
kind: Bar
a:
b: c
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
{
name: "update-version-not-match",
fieldSpec: `
"update-version-not-match": {
fieldSpec: `
path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
input: `
apiVersion: foo/v1beta2
kind: Bar
a:
b: c
`,
expected: `
expected: `
apiVersion: foo/v1beta2
kind: Bar
a:
b: c
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
{
name: "bad-version",
fieldSpec: `
"bad-version": {
fieldSpec: `
path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
input: `
apiVersion: foo/v1beta2/something
kind: Bar
a:
b: c
`,
expected: `
expected: `
apiVersion: foo/v1beta2/something
kind: Bar
a:
b: c
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
{
name: "bad-meta",
fieldSpec: `
"bad-meta": {
fieldSpec: `
path: a/b
group: foo
version: v1beta1
kind: Bar
`,
input: `
input: `
a:
b: c
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
error: "missing Resource metadata",
},
error: "missing Resource metadata",
},
{
name: "miss-match-type",
fieldSpec: `
"miss-match-type": {
fieldSpec: `
path: a/b/c
kind: Bar
`,
input: `
input: `
kind: Bar
a:
b: a
`,
error: "obj 'kind: Bar\na:\n b: a\n' at path 'a/b/c': " +
"expected sequence or mapping node",
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
error: `considering field 'a/b/c' of object
kind: Bar
a:
b: a
: expected sequence or mapping node`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
{
name: "add",
fieldSpec: `
"add": {
fieldSpec: `
path: a/b/c/d
group: foo
create: true
kind: Bar
`,
input: `
input: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
expected: `
expected: `
apiVersion: foo/v1beta1
kind: Bar
a: {b: {c: {d: e}}}
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "update-in-sequence",
fieldSpec: `
"update-in-sequence": {
fieldSpec: `
path: a/b[]/c/d
group: foo
kind: Bar
`,
input: `
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
@@ -222,7 +259,7 @@ a:
- c:
d: a
`,
expected: `
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
@@ -230,244 +267,237 @@ a:
- c:
d: e
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
},
},
},
// Don't create a sequence
{
name: "empty-sequence-no-create",
fieldSpec: `
// Don't create a sequence
"empty-sequence-no-create": {
fieldSpec: `
path: a/b[]/c/d
group: foo
create: true
kind: Bar
`,
input: `
input: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
expected: `
expected: `
apiVersion: foo/v1beta1
kind: Bar
a: {}
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
},
// Create a new field for an element in a sequence
{
name: "empty-sequence-create",
fieldSpec: `
// Create a new field for an element in a sequence
"empty-sequence-create": {
fieldSpec: `
path: a/b[]/c/d
group: foo
create: true
kind: Bar
`,
input: `
input: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c: {}
`,
expected: `
expected: `
apiVersion: foo/v1beta1
kind: Bar
a:
b:
- c: {d: e}
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "group v1",
fieldSpec: `
"group v1": {
fieldSpec: `
path: a/b
group: v1
create: true
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "version v1",
fieldSpec: `
"version v1": {
fieldSpec: `
path: a/b
version: v1
create: true
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
a:
b: e
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "successfully set field on array entry no sequence hint",
fieldSpec: `
"successfully set field on array entry no sequence hint": {
fieldSpec: `
path: spec/containers/image
version: v1
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: foo
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "successfully set field on array entry with sequence hint",
fieldSpec: `
"successfully set field on array entry with sequence hint": {
fieldSpec: `
path: spec/containers[]/image
version: v1
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: foo
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
spec:
containers:
- image: bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "failure to set field on array entry with sequence hint in path",
fieldSpec: `
"failure to set field on array entry with sequence hint in path": {
fieldSpec: `
path: spec/containers[]/image
version: v1
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
spec:
containers:
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
spec:
containers: []
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "failure to set field on array entry, no sequence hint in path",
fieldSpec: `
"failure to set field on array entry, no sequence hint in path": {
fieldSpec: `
path: spec/containers/image
version: v1
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
spec:
containers:
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
spec:
containers:
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "filedname with slash '/'",
fieldSpec: `
"fieldname with slash '/'": {
fieldSpec: `
path: a/b\/c/d
version: v1
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
a:
b/c:
d: foo
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
a:
b/c:
d: bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
},
{
name: "filedname with multiple '/'",
fieldSpec: `
"fieldname with multiple '/'": {
fieldSpec: `
path: a/b\/c/d\/e/f
version: v1
kind: Bar
`,
input: `
input: `
apiVersion: v1
kind: Bar
a:
@@ -475,7 +505,7 @@ a:
d/e:
f: foo
`,
expected: `
expected: `
apiVersion: v1
kind: Bar
a:
@@ -483,25 +513,24 @@ a:
d/e:
f: bar
`,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
filter: fieldspec.Filter{
SetValue: filtersutil.SetScalar("bar"),
CreateKind: yaml.ScalarNode,
},
},
},
}
}
func TestFilter_Filter(t *testing.T) {
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
err := yaml.Unmarshal([]byte(test.fieldSpec), &test.filter.FieldSpec)
for n := range testCases {
tc := testCases[n]
t.Run(n, func(t *testing.T) {
err := yaml.Unmarshal([]byte(tc.fieldSpec), &tc.filter.FieldSpec)
if !assert.NoError(t, err) {
t.FailNow()
}
out := &bytes.Buffer{}
rw := &kio.ByteReadWriter{
Reader: bytes.NewBufferString(test.input),
Reader: bytes.NewBufferString(tc.input),
Writer: out,
OmitReaderAnnotations: true,
}
@@ -509,11 +538,11 @@ func TestFilter_Filter(t *testing.T) {
// run the filter
err = kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{kio.FilterAll(test.filter)},
Filters: []kio.Filter{kio.FilterAll(tc.filter)},
Outputs: []kio.Writer{rw},
}.Execute()
if test.error != "" {
if !assert.EqualError(t, err, test.error) {
if tc.error != "" {
if !assert.EqualError(t, err, tc.error) {
t.FailNow()
}
// stop rest of test
@@ -526,7 +555,7 @@ func TestFilter_Filter(t *testing.T) {
// check results
if !assert.Equal(t,
strings.TrimSpace(test.expected),
strings.TrimSpace(tc.expected),
strings.TrimSpace(out.String())) {
t.FailNow()
}

View File

@@ -1,21 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filtersutil
import (
"sort"
)
// SortedMapKeys returns a sorted slice of keys to the given map.
// Writing this function never gets old.
func SortedMapKeys(m map[string]string) []string {
keys := make([]string, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}

View File

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

View File

@@ -25,7 +25,7 @@ type Filter struct {
var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
keys := filtersutil.SortedMapKeys(f.Labels)
keys := yaml.SortedMapKeys(f.Labels)
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
for _, k := range keys {

View File

@@ -5,100 +5,189 @@ import (
"fmt"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/fieldspec"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
kyaml_filtersutil "sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Filter will update the name reference
// Filter updates a name references.
type Filter struct {
FieldSpec types.FieldSpec `json:"fieldSpec,omitempty" yaml:"fieldSpec,omitempty"`
Referrer *resource.Resource
Target resid.Gvk
// Referrer refers to another resource X by X's name.
// E.g. A Deployment can refer to a ConfigMap.
// The Deployment is the Referrer,
// the ConfigMap is the ReferralTarget.
// This filter seeks to repair the reference in Deployment, given
// that the ConfigMap's name may have changed.
Referrer *resource.Resource
// NameFieldToUpdate is the field in the Referrer
// that holds the name requiring an update.
// This is the field to write.
NameFieldToUpdate types.FieldSpec
// ReferralTarget is the source of the new value for
// the name, always in the 'metadata/name' field.
// This is the field to read.
ReferralTarget resid.Gvk
// Set of resources to scan to find the ReferralTarget.
ReferralCandidates resmap.ResMap
isRoleRef bool
}
// At time of writing, in practice this is called with a slice with only
// one entry, the node also referred to be the resource in the Referrer field.
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
return kio.FilterAll(yaml.FilterFunc(f.run)).Filter(nodes)
}
// The node passed in here is the same node as held in Referrer;
// that's how the referrer's name field is updated.
// Currently, however, this filter still needs the extra methods on Referrer
// to consult things like the resource Id, its namespace, etc.
// TODO(3455): No filter should use the Resource api; all information
// about names should come from annotations, with helper methods
// on the RNode object. Resource should get stupider, RNode smarter.
func (f Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
err := node.PipeE(fieldspec.Filter{
FieldSpec: f.FieldSpec,
if err := f.confirmNodeMatchesReferrer(node); err != nil {
// sanity check.
return nil, err
}
if err := node.PipeE(fieldspec.Filter{
FieldSpec: f.NameFieldToUpdate,
SetValue: f.set,
})
return node, err
}); err != nil {
return nil, errors.Wrapf(
err, "updating name reference in '%s' field of '%s'",
f.NameFieldToUpdate.Path, f.Referrer.CurId().String())
}
return node, nil
}
// This function is called on the node found at FieldSpec.Path.
// It's some node in the Referrer.
func (f Filter) set(node *yaml.RNode) error {
if yaml.IsMissingOrNull(node) {
return nil
}
if strings.HasSuffix(f.FieldSpec.Path, "roleRef/name") {
f.isRoleRef = true
}
switch node.YNode().Kind {
case yaml.ScalarNode:
return f.setScalar(node)
case yaml.MappingNode:
// Kind: ValidatingWebhookConfiguration
// FieldSpec is webhooks/clientConfig/service
return f.setMapping(node)
case yaml.SequenceNode:
return f.setSequence(node)
return applyFilterToSeq(seqFilter{
setScalarFn: f.setScalar,
setMappingFn: f.setMapping,
}, node)
default:
return fmt.Errorf(
"node is expected to be either a string or a slice of string or a map of string")
return fmt.Errorf("node must be a scalar, sequence or map")
}
}
func (f Filter) setSequence(node *yaml.RNode) error {
return applyFilterToSeq(seqFilter{
setScalarFn: f.setScalar,
setMappingFn: f.setMapping,
}, node)
// This method used when NameFieldToUpdate doesn't lead to
// one scalar field (typically called 'name'), but rather
// leads to a map field (called anything). In this case we
// must complete the field path, looking for both a 'name'
// and a 'namespace' field to help select the proper
// ReferralTarget to read the name and namespace from.
func (f Filter) setMapping(node *yaml.RNode) error {
if node.YNode().Kind != yaml.MappingNode {
return fmt.Errorf("expect a mapping node")
}
nameNode, err := node.Pipe(yaml.FieldMatcher{Name: "name"})
if err != nil {
return errors.Wrap(err, "trying to match 'name' field")
}
if nameNode == nil {
// This is a _configuration_ error; the field path
// specified in NameFieldToUpdate.Path doesn't resolve
// to a map with a 'name' field, so we have no idea what
// field to update with a new name.
return fmt.Errorf("path config error; no 'name' field in node")
}
candidates, err := f.filterMapCandidatesByNamespace(node)
if err != nil {
return err
}
oldName := nameNode.YNode().Value
referral, err := f.selectReferral(oldName, candidates)
if err != nil || referral == nil {
// Nil referral means nothing to do.
return err
}
f.recordTheReferral(referral)
if referral.GetName() == oldName && referral.GetNamespace() == "" {
// The name has not changed, nothing to do.
return nil
}
if err = node.PipeE(yaml.FieldSetter{
Name: "name",
StringValue: referral.GetName(),
}); err != nil {
return err
}
if referral.GetNamespace() == "" {
// Don't write an empty string into the namespace field, as
// it should not replace the value "default". The empty
// string is handled as a wild card here, not as an implicit
// specification of the "default" k8s namespace.
return nil
}
return node.PipeE(yaml.FieldSetter{
Name: "namespace",
StringValue: referral.GetNamespace(),
})
}
func (f Filter) setMapping(node *yaml.RNode) error {
return setNameAndNs(
node,
f.Referrer,
f.Target,
f.ReferralCandidates,
f.isRoleRef,
)
func (f Filter) filterMapCandidatesByNamespace(
node *yaml.RNode) ([]*resource.Resource, error) {
namespaceNode, err := node.Pipe(yaml.FieldMatcher{Name: "namespace"})
if err != nil {
return nil, errors.Wrap(err, "trying to match 'namespace' field")
}
if namespaceNode == nil {
return f.ReferralCandidates.Resources(), nil
}
namespace := namespaceNode.YNode().Value
nsMap := f.ReferralCandidates.GroupedByOriginalNamespace()
if candidates, ok := nsMap[namespace]; ok {
return candidates, nil
}
nsMap = f.ReferralCandidates.GroupedByCurrentNamespace()
// This could be nil, or an empty list.
return nsMap[namespace], nil
}
func (f Filter) setScalar(node *yaml.RNode) error {
newValue, err := getSimpleNameField(
node.YNode().Value,
f.Referrer,
f.Target,
f.ReferralCandidates,
f.ReferralCandidates.Resources(),
f.isRoleRef,
)
if err != nil {
referral, err := f.selectReferral(
node.YNode().Value, f.ReferralCandidates.Resources())
if err != nil || referral == nil {
// Nil referral means nothing to do.
return err
}
err = filtersutil.SetScalar(newValue)(node)
if err != nil {
return err
f.recordTheReferral(referral)
if referral.GetName() == node.YNode().Value {
// The name has not changed, nothing to do.
return nil
}
return nil
return node.PipeE(yaml.FieldSetter{StringValue: referral.GetName()})
}
// In the resource, make a note that it is referred to by the Referrer.
func (f Filter) recordTheReferral(referral *resource.Resource) {
referral.AppendRefBy(f.Referrer.CurId())
}
// getRoleRefGvk returns a Gvk in the roleRef field. Return error
// if the roleRef, roleRef/apiGroup or roleRef/kind is missing.
func getRoleRefGvk(res json.Marshaler) (*resid.Gvk, error) {
n, err := kyaml_filtersutil.GetRNode(res)
n, err := filtersutil.GetRNode(res)
if err != nil {
return nil, err
}
@@ -114,14 +203,16 @@ func getRoleRefGvk(res json.Marshaler) (*resid.Gvk, error) {
return nil, err
}
if apiGroup.IsNil() {
return nil, fmt.Errorf("apiGroup cannot be found in roleRef %s", roleRef.MustString())
return nil, fmt.Errorf(
"apiGroup cannot be found in roleRef %s", roleRef.MustString())
}
kind, err := roleRef.Pipe(yaml.Lookup("kind"))
if err != nil {
return nil, err
}
if kind.IsNil() {
return nil, fmt.Errorf("kind cannot be found in roleRef %s", roleRef.MustString())
return nil, fmt.Errorf(
"kind cannot be found in roleRef %s", roleRef.MustString())
}
return &resid.Gvk{
Group: apiGroup.YNode().Value,
@@ -129,169 +220,183 @@ func getRoleRefGvk(res json.Marshaler) (*resid.Gvk, error) {
}, nil
}
func filterReferralCandidates(
referrer *resource.Resource,
matches []*resource.Resource,
target resid.Gvk,
) []*resource.Resource {
var ret []*resource.Resource
for _, m := range matches {
// If target kind is not ServiceAccount, we shouldn't consider condidates which
// doesn't have same namespace.
if target.Kind != "ServiceAccount" && m.GetNamespace() != referrer.GetNamespace() {
continue
// sieveFunc returns true if the resource argument satisfies some criteria.
type sieveFunc func(*resource.Resource) bool
// doSieve uses a function to accept or ignore resources from a list.
// If list is nil, returns immediately.
// It's a filter obviously, but that term is overloaded here.
func doSieve(list []*resource.Resource, fn sieveFunc) (s []*resource.Resource) {
for _, r := range list {
if fn(r) {
s = append(s, r)
}
if !referrer.PrefixesSuffixesEquals(m) {
continue
}
ret = append(ret, m)
}
return ret
return
}
// selectReferral picks the referral among a subset of candidates.
// It returns the current name and namespace of the selected candidate.
// Note that the content of the referricalCandidateSubset slice is most of the time
// identical to the referralCandidates resmap. Still in some cases, such
// as ClusterRoleBinding, the subset only contains the resources of a specific
// namespace.
func selectReferral(
oldName string,
referrer *resource.Resource,
target resid.Gvk,
referralCandidates resmap.ResMap,
referralCandidateSubset []*resource.Resource,
isRoleRef bool) (string, string, error) {
var roleRefGvk *resid.Gvk
if isRoleRef {
var err error
roleRefGvk, err = getRoleRefGvk(referrer)
if err != nil {
return "", "", err
}
}
for _, res := range referralCandidateSubset {
id := res.OrgId()
// If the we are processing a roleRef, the apiGroup and Kind in the
// roleRef are needed to be considered.
if (!isRoleRef || id.IsSelected(roleRefGvk)) &&
id.IsSelected(&target) && res.GetOriginalName() == oldName {
matches := referralCandidates.GetMatchingResourcesByOriginalId(id.Equals)
// If there's more than one match,
// filter the matches by prefix and suffix
if len(matches) > 1 {
filteredMatches := filterReferralCandidates(referrer, matches, target)
if len(filteredMatches) > 1 {
return "", "", fmt.Errorf(
"multiple matches for %s:\n %v",
id, getIds(filteredMatches))
}
// Check is the match the resource we are working on
if len(filteredMatches) == 0 || res != filteredMatches[0] {
continue
}
func acceptAll(r *resource.Resource) bool {
return true
}
func previousNameMatches(name string) sieveFunc {
return func(r *resource.Resource) bool {
for _, id := range r.PrevIds() {
if id.Name == name {
return true
}
// In the resource, note that it is referenced
// by the referrer.
res.AppendRefBy(referrer.CurId())
// Return transformed name of the object,
// complete with prefixes, hashes, etc.
return res.GetName(), res.GetNamespace(), nil
}
return false
}
}
func previousIdSelectedByGvk(gvk *resid.Gvk) sieveFunc {
return func(r *resource.Resource) bool {
for _, id := range r.PrevIds() {
if id.IsSelected(gvk) {
return true
}
}
return false
}
}
// If the we are updating a 'roleRef/name' field, the 'apiGroup' and 'kind'
// fields in the same 'roleRef' map must be considered.
// If either object is cluster-scoped (!IsNamespaceableKind), there
// can be a referral.
// E.g. a RoleBinding (which exists in a namespace) can refer
// to a ClusterRole (cluster-scoped) object.
// https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole
// Likewise, a ClusterRole can refer to a Secret (in a namespace).
// Objects in different namespaces generally cannot refer to other
// with some exceptions (e.g. RoleBinding and ServiceAccount are both
// namespaceable, but the former can refer to accounts in other namespaces).
func (f Filter) roleRefFilter() sieveFunc {
if !strings.HasSuffix(f.NameFieldToUpdate.Path, "roleRef/name") {
return acceptAll
}
roleRefGvk, err := getRoleRefGvk(f.Referrer)
if err != nil {
return acceptAll
}
return previousIdSelectedByGvk(roleRefGvk)
}
func prefixSuffixEquals(other resource.ResCtx) sieveFunc {
return func(r *resource.Resource) bool {
return r.PrefixesSuffixesEquals(other)
}
}
func (f Filter) sameCurrentNamespaceAsReferrer() sieveFunc {
referrerCurId := f.Referrer.CurId()
if !referrerCurId.IsNamespaceableKind() {
// If the referrer is cluster-scoped, let anything through.
return acceptAll
}
return func(r *resource.Resource) bool {
if !r.CurId().IsNamespaceableKind() {
// Allow cluster-scoped through.
return true
}
if r.GetKind() == "ServiceAccount" {
// Allow service accounts through, even though they
// are in a namespace. A RoleBinding in another namespace
// can reference them.
return true
}
return referrerCurId.IsNsEquals(r.CurId())
}
}
// selectReferral picks the best referral from a list of candidates.
func (f Filter) selectReferral(
// The name referral that may need to be updated.
oldName string,
candidates []*resource.Resource) (*resource.Resource, error) {
candidates = doSieve(candidates, previousNameMatches(oldName))
candidates = doSieve(candidates, previousIdSelectedByGvk(&f.ReferralTarget))
candidates = doSieve(candidates, f.roleRefFilter())
candidates = doSieve(candidates, f.sameCurrentNamespaceAsReferrer())
if len(candidates) == 1 {
return candidates[0], nil
}
candidates = doSieve(candidates, prefixSuffixEquals(f.Referrer))
if len(candidates) == 1 {
return candidates[0], nil
}
if len(candidates) == 0 {
return nil, nil
}
if allNamesAreTheSame(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)
}
func (f Filter) failureDetails(resources []*resource.Resource) {
fmt.Printf(
"\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("------")
}
}
func allNamesAreTheSame(resources []*resource.Resource) bool {
name := resources[0].GetName()
for i := 1; i < len(resources); i++ {
if name != resources[i].GetName() {
return false
}
}
return oldName, "", nil
return true
}
// utility function to replace a simple string by the new name
func getSimpleNameField(
oldName string,
referrer *resource.Resource,
target resid.Gvk,
referralCandidates resmap.ResMap,
referralCandidateSubset []*resource.Resource,
isRoleRef bool) (string, error) {
newName, _, err := selectReferral(oldName, referrer, target,
referralCandidates, referralCandidateSubset, isRoleRef)
return newName, err
}
func getIds(rs []*resource.Resource) []string {
func getIds(rs []*resource.Resource) string {
var result []string
for _, r := range rs {
result = append(result, r.CurId().String()+"\n")
result = append(result, r.CurId().String())
}
return result
return strings.Join(result, ", ")
}
// utility function to replace name field within a map RNode
// and leverage the namespace field.
func setNameAndNs(
in *yaml.RNode,
referrer *resource.Resource,
target resid.Gvk,
referralCandidates resmap.ResMap,
isRoleRef bool) error {
if in.YNode().Kind != yaml.MappingNode {
return fmt.Errorf("expect a mapping node")
}
// Get name field
nameNode, err := in.Pipe(yaml.FieldMatcher{
Name: "name",
})
if err != nil || nameNode == nil {
return fmt.Errorf("cannot find field 'name' in node")
}
// Get namespace field
namespaceNode, err := in.Pipe(yaml.FieldMatcher{
Name: "namespace",
})
if err != nil {
return fmt.Errorf("error when find field 'namespace'")
}
// check is namespace matched
// name will bot be updated if the namespace doesn't match
subset := referralCandidates.Resources()
if namespaceNode != nil {
namespace := namespaceNode.YNode().Value
bynamespace := referralCandidates.GroupedByOriginalNamespace()
if _, ok := bynamespace[namespace]; !ok {
return nil
}
subset = bynamespace[namespace]
}
oldName := nameNode.YNode().Value
newname, newnamespace, err := selectReferral(oldName, referrer, target,
referralCandidates, subset, isRoleRef)
if err != nil {
return err
}
if (newname == oldName) && (newnamespace == "") {
// no candidate found.
return nil
}
// set name
in.Pipe(yaml.FieldSetter{
Name: "name",
StringValue: newname,
})
if newnamespace != "" {
// We don't want value "" to replace value "default" since
// the empty string is handled as a wild card here not default namespace
// by kubernetes.
in.Pipe(yaml.FieldSetter{
Name: "namespace",
StringValue: newnamespace,
})
func checkEqual(k, a, b string) error {
if a != b {
return fmt.Errorf(
"node-referrerOriginal '%s' mismatch '%s' != '%s'",
k, a, b)
}
return nil
}
func (f Filter) confirmNodeMatchesReferrer(node *yaml.RNode) error {
meta, err := node.GetMeta()
if err != nil {
return err
}
gvk := f.Referrer.GetGvk()
if err = checkEqual(
"APIVersion", meta.APIVersion, gvk.ApiVersion()); err != nil {
return err
}
if err = checkEqual(
"Kind", meta.Kind, gvk.Kind); err != nil {
return err
}
if err = checkEqual(
"Name", meta.Name, f.Referrer.GetName()); err != nil {
return err
}
if err = checkEqual(
"Namespace", meta.Namespace, f.Referrer.GetNamespace()); err != nil {
return err
}
return nil
}

View File

@@ -14,14 +14,14 @@ import (
func TestNamerefFilter(t *testing.T) {
testCases := map[string]struct {
input string
candidates string
expected string
filter Filter
originalNames []string
referrerOriginal string
candidates string
referrerFinal string
filter Filter
originalNames []string
}{
"simple scalar": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -40,8 +40,8 @@ kind: NotSecret
metadata:
name: newName2
`,
originalNames: []string{"oldName", ""},
expected: `
originalNames: []string{"oldName", "newName2"},
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -50,8 +50,8 @@ ref:
name: newName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -59,7 +59,7 @@ ref:
},
},
"sequence": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -79,8 +79,8 @@ kind: NotSecret
metadata:
name: newName2
`,
originalNames: []string{"oldName1", ""},
expected: `
originalNames: []string{"oldName1", "newName2"},
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -90,8 +90,8 @@ seq:
- oldName2
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "seq"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "seq"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -99,7 +99,7 @@ seq:
},
},
"mapping": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -118,8 +118,8 @@ kind: NotSecret
metadata:
name: newName2
`,
originalNames: []string{"oldName", ""},
expected: `
originalNames: []string{"oldName", "newName2"},
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -128,8 +128,8 @@ map:
name: newName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "map"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "map"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -137,40 +137,47 @@ map:
},
},
"mapping with namespace": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
namespace: someNs
map:
name: oldName
namespace: oldNs
namespace: someNs
`,
candidates: `
apiVersion: apps/v1
kind: Secret
metadata:
name: newName
namespace: oldNs
namespace: someNs
---
apiVersion: apps/v1
kind: NotSecret
metadata:
name: newName2
---
apiVersion: apps/v1
kind: Secret
metadata:
name: thirdName
`,
originalNames: []string{"oldName", ""},
expected: `
originalNames: []string{"oldName", "oldName", "oldName"},
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
namespace: someNs
map:
name: newName
namespace: oldNs
namespace: someNs
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "map"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "map"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -178,7 +185,7 @@ map:
},
},
"null value": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -197,8 +204,8 @@ kind: NotSecret
metadata:
name: newName2
`,
originalNames: []string{"oldName", ""},
expected: `
originalNames: []string{"oldName", "newName2"},
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -207,8 +214,8 @@ map:
name: null
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "map"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "map"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -220,7 +227,7 @@ map:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
factory := provider.NewDefaultDepProvider().GetResourceFactory()
referrer, err := factory.FromBytes([]byte(tc.input))
referrer, err := factory.FromBytes([]byte(tc.referrerOriginal))
if err != nil {
t.Fatal(err)
}
@@ -236,10 +243,10 @@ map:
candidates := resMapFactory.FromResourceSlice(candidatesRes)
tc.filter.ReferralCandidates = candidates
result := filtertest_test.RunFilter(t, tc.referrerOriginal, tc.filter)
if !assert.Equal(t,
strings.TrimSpace(tc.expected),
strings.TrimSpace(
filtertest_test.RunFilter(t, tc.input, tc.filter))) {
strings.TrimSpace(tc.referrerFinal),
strings.TrimSpace(result)) {
t.FailNow()
}
})
@@ -248,14 +255,14 @@ map:
func TestNamerefFilterUnhappy(t *testing.T) {
testCases := map[string]struct {
input string
candidates string
expected string
filter Filter
originalNames []string
referrerOriginal string
candidates string
referrerFinal string
filter Filter
originalNames []string
}{
"multiple match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -275,10 +282,10 @@ metadata:
name: newName2
`,
originalNames: []string{"oldName", "oldName"},
expected: "",
referrerFinal: "",
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -286,7 +293,7 @@ metadata:
},
},
"no name": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -306,10 +313,10 @@ metadata:
name: newName2
`,
originalNames: []string{"oldName", "oldName"},
expected: "",
referrerFinal: "",
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -321,7 +328,7 @@ metadata:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
factory := provider.NewDefaultDepProvider().GetResourceFactory()
referrer, err := factory.FromBytes([]byte(tc.input))
referrer, err := factory.FromBytes([]byte(tc.referrerOriginal))
if err != nil {
t.Fatal(err)
}
@@ -337,11 +344,11 @@ metadata:
candidates := resMapFactory.FromResourceSlice(candidatesRes)
tc.filter.ReferralCandidates = candidates
_, err = filtertest_test.RunFilterE(t, tc.input, tc.filter)
_, err = filtertest_test.RunFilterE(t, tc.referrerOriginal, tc.filter)
if err == nil {
t.Fatalf("expect an error")
}
if tc.expected != "" && !assert.EqualError(t, err, tc.expected) {
if tc.referrerFinal != "" && !assert.EqualError(t, err, tc.referrerFinal) {
t.FailNow()
}
})
@@ -350,19 +357,19 @@ metadata:
func TestCandidatesWithDifferentPrefixSuffix(t *testing.T) {
testCases := map[string]struct {
input string
candidates string
expected string
filter Filter
originalNames []string
prefix []string
suffix []string
inputPrefix string
inputSuffix string
err bool
referrerOriginal string
candidates string
referrerFinal string
filter Filter
originalNames []string
prefix []string
suffix []string
inputPrefix string
inputSuffix string
err bool
}{
"prefix match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -386,7 +393,7 @@ metadata:
suffix: []string{"", "suffix2"},
inputPrefix: "prefix1",
inputSuffix: "",
expected: `
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -395,8 +402,8 @@ ref:
name: newName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -405,7 +412,7 @@ ref:
err: false,
},
"suffix match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -429,7 +436,7 @@ metadata:
suffix: []string{"suffix1", "suffix2"},
inputPrefix: "",
inputSuffix: "suffix1",
expected: `
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -438,8 +445,8 @@ ref:
name: newName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -448,7 +455,7 @@ ref:
err: false,
},
"prefix suffix both match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -472,7 +479,7 @@ metadata:
suffix: []string{"suffix1", "suffix2"},
inputPrefix: "prefix1",
inputSuffix: "suffix1",
expected: `
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -481,8 +488,8 @@ ref:
name: newName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -491,7 +498,7 @@ ref:
err: false,
},
"multiple match: both": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -515,10 +522,10 @@ metadata:
suffix: []string{"suffix", "suffix"},
inputPrefix: "prefix",
inputSuffix: "suffix",
expected: "",
referrerFinal: "",
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -527,7 +534,7 @@ metadata:
err: true,
},
"multiple match: only prefix": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -551,10 +558,10 @@ metadata:
suffix: []string{"", ""},
inputPrefix: "prefix",
inputSuffix: "",
expected: "",
referrerFinal: "",
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -563,7 +570,7 @@ metadata:
err: true,
},
"multiple match: only suffix": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -587,10 +594,10 @@ metadata:
suffix: []string{"suffix", "suffix"},
inputPrefix: "",
inputSuffix: "suffix",
expected: "",
referrerFinal: "",
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -599,7 +606,7 @@ metadata:
err: true,
},
"no match: neither match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -623,7 +630,7 @@ metadata:
suffix: []string{"suffix1", "suffix2"},
inputPrefix: "prefix",
inputSuffix: "suffix",
expected: `
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -632,8 +639,8 @@ ref:
name: oldName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -642,7 +649,7 @@ ref:
err: false,
},
"no match: prefix doesn't match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -666,7 +673,7 @@ metadata:
suffix: []string{"suffix", "suffix"},
inputPrefix: "prefix",
inputSuffix: "suffix",
expected: `
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -675,8 +682,8 @@ ref:
name: oldName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -685,7 +692,7 @@ ref:
err: false,
},
"no match: suffix doesn't match": {
input: `
referrerOriginal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -709,7 +716,7 @@ metadata:
suffix: []string{"suffix1", "suffix2"},
inputPrefix: "prefix",
inputSuffix: "suffix",
expected: `
referrerFinal: `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -718,8 +725,8 @@ ref:
name: oldName
`,
filter: Filter{
FieldSpec: types.FieldSpec{Path: "ref/name"},
Target: resid.Gvk{
NameFieldToUpdate: types.FieldSpec{Path: "ref/name"},
ReferralTarget: resid.Gvk{
Group: "apps",
Version: "v1",
Kind: "Secret",
@@ -732,7 +739,7 @@ ref:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
factory := provider.NewDefaultDepProvider().GetResourceFactory()
referrer, err := factory.FromBytes([]byte(tc.input))
referrer, err := factory.FromBytes([]byte(tc.referrerOriginal))
if err != nil {
t.Fatal(err)
}
@@ -764,13 +771,15 @@ ref:
if !tc.err {
if !assert.Equal(t,
strings.TrimSpace(tc.expected),
strings.TrimSpace(tc.referrerFinal),
strings.TrimSpace(
filtertest_test.RunFilter(t, tc.input, tc.filter))) {
filtertest_test.RunFilter(
t, tc.referrerOriginal, tc.filter))) {
t.FailNow()
}
} else {
_, err := filtertest_test.RunFilterE(t, tc.input, tc.filter)
_, err := filtertest_test.RunFilterE(
t, tc.referrerOriginal, tc.filter)
if err == nil {
t.Fatalf("an error is expected")
}

View File

@@ -4,6 +4,7 @@
package patchstrategicmerge
import (
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/kustomize/kyaml/yaml/merge2"
@@ -15,6 +16,7 @@ type Filter struct {
var _ kio.Filter = Filter{}
// Filter does a strategic merge patch, which can delete nodes.
func (pf Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
var result []*yaml.RNode
for i := range nodes {
@@ -27,7 +29,9 @@ func (pf Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
if err != nil {
return nil, err
}
result = append(result, r)
if !konfig.FlagEnableKyamlDefaultValue || r != nil {
result = append(result, r)
}
}
return result, nil
}

View File

@@ -15,6 +15,29 @@ func TestFilter(t *testing.T) {
patch *yaml.RNode
expected string
}{
"simple": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 1
`,
patch: yaml.MustParse(`apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`),
expected: `apiVersion: v1
kind: Deployment
metadata:
name: clown
spec:
numReplicas: 999
`,
},
"nullMapEntry1": {
input: `
apiVersion: example.com/v1
@@ -649,6 +672,63 @@ spec:
ports:
- containerPort: 80
- containerPort: 8080
`,
},
// Test for issue #3513
// Currently broken; when one port has only containerPort, the output
// should not merge containerPort 8301 together
// This occurs because when protocol is missing on the first port,
// the merge code uses [containerPort] as the merge key rather than
// [containerPort, protocol]
"list map keys - protocol only present on some ports": {
input: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
spec:
template:
spec:
containers:
- name: consul
image: "dashicorp/consul:1.9.1"
ports:
- containerPort: 8500
name: http
- containerPort: 8301
protocol: "TCP"
- containerPort: 8301
protocol: "UDP"
`,
patch: yaml.MustParse(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
labels:
test: label
`),
expected: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
labels:
test: label
spec:
template:
spec:
containers:
- name: consul
image: "dashicorp/consul:1.9.1"
ports:
- containerPort: 8301
protocol: "TCP"
- containerPort: 8301
protocol: "UDP"
- containerPort: 8500
name: http
`,
},
}

View File

@@ -1,3 +1,3 @@
// Package refvar contains a kio.Filter implementation of the kustomize
// refvar transformer.
// refvar transformer (find and replace $(FOO) style variables in strings).
package refvar

View File

@@ -1,12 +1,12 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package expansion provides functions find and replace $(FOO) style variables in strings.
package expansion
package refvar
import (
"bytes"
"fmt"
"log"
"strings"
)
const (
@@ -17,38 +17,64 @@ const (
// syntaxWrap returns the input string wrapped by the expansion syntax.
func syntaxWrap(input string) string {
return string(operator) + string(referenceOpener) + input + string(referenceCloser)
var sb strings.Builder
sb.WriteByte(operator)
sb.WriteByte(referenceOpener)
sb.WriteString(input)
sb.WriteByte(referenceCloser)
return sb.String()
}
// MappingFuncFor returns a mapping function for use with Expand that
// implements the expansion semantics defined in the expansion spec; it
// returns the input string wrapped in the expansion syntax if no mapping
// for the input is found.
func MappingFuncFor(
counts map[string]int,
context ...map[string]interface{}) func(string) interface{} {
return func(input string) interface{} {
for _, vars := range context {
val, ok := vars[input]
if ok {
counts[input]++
switch typedV := val.(type) {
case string, int64, float64, bool:
return typedV
default:
return syntaxWrap(input)
}
// MappingFunc maps a string to anything.
type MappingFunc func(string) interface{}
// MakePrimitiveReplacer returns a MappingFunc that uses a map to do
// replacements, and a histogram to count map hits.
//
// Func behavior:
//
// If the input key is NOT found in the map, the key is wrapped up as
// as a variable declaration string and returned, e.g. key FOO becomes $(FOO).
// This string is presumably put back where it was found, and might get replaced
// later.
//
// If the key is found in the map, the value is returned if it is a primitive
// type (string, bool, number), and the hit is counted.
//
// If it's not a primitive type (e.g. a map, struct, func, etc.) then this
// function doesn't know what to do with it and it returns the key wrapped up
// again as if it had not been replaced. This should probably be an error.
func MakePrimitiveReplacer(
counts map[string]int, someMap map[string]interface{}) MappingFunc {
return func(key string) interface{} {
if value, ok := someMap[key]; ok {
switch typedV := value.(type) {
case string, int, int32, int64, float32, float64, bool:
counts[key]++
return typedV
default:
// If the value is some complicated type (e.g. a map or struct),
// this function doesn't know how to jam it into a string,
// so just pretend it was a cache miss.
// Likely this should be an error instead of a silent failure,
// since the programmer passed an impossible value.
log.Printf(
"MakePrimitiveReplacer: bad replacement type=%T val=%v",
typedV, typedV)
return syntaxWrap(key)
}
}
return syntaxWrap(input)
// If unable to return the mapped variable, return it
// as it was found, and a later mapping might be able to
// replace it.
return syntaxWrap(key)
}
}
// Expand replaces variable references in the input string according to
// the expansion spec using the given mapping function to resolve the
// values of variables.
func Expand(input string, mapping func(string) interface{}) interface{} {
var buf bytes.Buffer
// DoReplacements replaces variable references in the input string
// using the mapping function.
func DoReplacements(input string, mapping MappingFunc) interface{} {
var buf strings.Builder
checkpoint := 0
for cursor := 0; cursor < len(input); cursor++ {
if input[cursor] == operator && cursor+1 < len(input) {

View File

@@ -1,13 +1,14 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package expansion_test
package refvar_test
import (
"fmt"
"testing"
. "sigs.k8s.io/kustomize/api/internal/accumulator/expansion"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/filters/refvar"
)
type expected struct {
@@ -15,6 +16,48 @@ type expected struct {
edited string
}
func TestPrimitiveReplacer(t *testing.T) {
varCounts := make(map[string]int)
f := MakePrimitiveReplacer(
varCounts,
map[string]interface{}{
"FOO": "bar",
"ZOO": "$(FOO)-1",
"BLU": "$(ZOO)-2",
"EIGHT": 8,
"PI": 3.14159,
"ZINT": "$(INT)",
"BOOL": "true",
"HUGENUMBER": int64(9223372036854775807),
"CRAZYMAP": map[string]int{"crazy": 200},
"ZBOOL": "$(BOOL)",
})
assert.Equal(t, "$()", f(""))
assert.Equal(t, "$( )", f(" "))
assert.Equal(t, "$(florida)", f("florida"))
assert.Equal(t, "$(0)", f("0"))
assert.Equal(t, "bar", f("FOO"))
assert.Equal(t, "bar", f("FOO"))
assert.Equal(t, "bar", f("FOO"))
assert.Equal(t, 8, f("EIGHT"))
assert.Equal(t, 8, f("EIGHT"))
assert.Equal(t, 3.14159, f("PI"))
assert.Equal(t, "true", f("BOOL"))
assert.Equal(t, int64(9223372036854775807), f("HUGENUMBER"))
assert.Equal(t, "$(FOO)-1", f("ZOO"))
assert.Equal(t, "$(CRAZYMAP)", f("CRAZYMAP"))
assert.Equal(t,
map[string]int{
"FOO": 3,
"EIGHT": 2,
"BOOL": 1,
"PI": 1,
"ZOO": 1,
"HUGENUMBER": 1,
},
varCounts)
}
func TestMapReference(t *testing.T) {
type env struct {
Name string
@@ -51,7 +94,7 @@ func TestMapReference(t *testing.T) {
},
}
declaredEnv := map[string]interface{}{
varMap := map[string]interface{}{
"FOO": "bar",
"ZOO": "$(FOO)-1",
"BLU": "$(ZOO)-2",
@@ -61,11 +104,11 @@ func TestMapReference(t *testing.T) {
"ZBOOL": "$(BOOL)",
}
counts := make(map[string]int)
mapping := MappingFuncFor(counts, declaredEnv)
varCounts := make(map[string]int)
for _, env := range envs {
declaredEnv[env.Name] = Expand(fmt.Sprintf("%v", env.Value), mapping)
varMap[env.Name] = DoReplacements(
fmt.Sprintf("%v", env.Value),
MakePrimitiveReplacer(varCounts, varMap))
}
expectedEnv := map[string]expected{
@@ -79,45 +122,20 @@ func TestMapReference(t *testing.T) {
}
for k, v := range expectedEnv {
if e, a := v, declaredEnv[k]; e.edited != a || e.count != counts[k] {
if e, a := v, varMap[k]; e.edited != a || e.count != varCounts[k] {
t.Errorf("Expected %v count=%d, got %v count=%d",
e.edited, e.count, a, counts[k])
e.edited, e.count, a, varCounts[k])
} else {
delete(declaredEnv, k)
delete(varMap, k)
}
}
if len(declaredEnv) != 0 {
t.Errorf("Unexpected keys in declared env: %v", declaredEnv)
if len(varMap) != 0 {
t.Errorf("Unexpected keys in declared env: %v", varMap)
}
}
func TestMapping(t *testing.T) {
context := map[string]interface{}{
"VAR_A": "A",
"VAR_B": "B",
"VAR_C": "C",
"VAR_REF": "$(VAR_A)",
"VAR_EMPTY": "",
}
doExpansionTest(t, context)
}
func TestMappingDual(t *testing.T) {
context := map[string]interface{}{
"VAR_A": "A",
"VAR_EMPTY": "",
}
context2 := map[string]interface{}{
"VAR_B": "B",
"VAR_C": "C",
"VAR_REF": "$(VAR_A)",
}
doExpansionTest(t, context, context2)
}
func doExpansionTest(t *testing.T, context ...map[string]interface{}) {
cases := []struct {
name string
input string
@@ -333,11 +351,17 @@ func doExpansionTest(t *testing.T, context ...map[string]interface{}) {
expected: "\n",
},
}
for _, tc := range cases {
counts := make(map[string]int)
mapping := MappingFuncFor(counts, context...)
expanded := Expand(fmt.Sprintf("%v", tc.input), mapping)
expanded := DoReplacements(
fmt.Sprintf("%v", tc.input),
MakePrimitiveReplacer(counts, map[string]interface{}{
"VAR_A": "A",
"VAR_B": "B",
"VAR_C": "C",
"VAR_REF": "$(VAR_A)",
"VAR_EMPTY": "",
}))
if e, a := tc.expected, expanded; e != a {
t.Errorf("%v: expected %q, got %q", tc.name, e, a)
}
@@ -347,8 +371,7 @@ func doExpansionTest(t *testing.T, context ...map[string]interface{}) {
}
if len(tc.counts) > 0 {
for k, expectedCount := range tc.counts {
c, ok := counts[k]
if ok {
if c, ok := counts[k]; ok {
if c != expectedCount {
t.Errorf(
"%v: k=%s, expected count %d, got %d",

View File

@@ -8,15 +8,13 @@ import (
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
expansion2 "sigs.k8s.io/kustomize/api/internal/accumulator/expansion"
)
// Filter updates $(VAR) style variables with values.
// The fieldSpecs are the places to look for occurrences of $(VAR).
type Filter struct {
MappingFunc func(string) interface{} `json:"mappingFunc,omitempty" yaml:"mappingFunc,omitempty"`
FieldSpec types.FieldSpec `json:"fieldSpec,omitempty" yaml:"fieldSpec,omitempty"`
MappingFunc MappingFunc `json:"mappingFunc,omitempty" yaml:"mappingFunc,omitempty"`
FieldSpec types.FieldSpec `json:"fieldSpec,omitempty" yaml:"fieldSpec,omitempty"`
}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
@@ -49,12 +47,21 @@ func (f Filter) set(node *yaml.RNode) error {
func updateNodeValue(node *yaml.Node, newValue interface{}) {
switch newValue := newValue.(type) {
case int:
node.Value = strconv.FormatInt(int64(newValue), 10)
node.Tag = yaml.NodeTagInt
case int32:
node.Value = strconv.FormatInt(int64(newValue), 10)
node.Tag = yaml.NodeTagInt
case int64:
node.Value = strconv.FormatInt(newValue, 10)
node.Tag = yaml.NodeTagInt
case bool:
node.SetString(strconv.FormatBool(newValue))
node.Tag = yaml.NodeTagBool
case float32:
node.SetString(strconv.FormatFloat(float64(newValue), 'f', -1, 32))
node.Tag = yaml.NodeTagFloat
case float64:
node.SetString(strconv.FormatFloat(newValue, 'f', -1, 64))
node.Tag = yaml.NodeTagFloat
@@ -69,7 +76,7 @@ func (f Filter) setScalar(node *yaml.RNode) error {
if !yaml.IsYNodeString(node.YNode()) {
return nil
}
v := expansion2.Expand(node.YNode().Value, f.MappingFunc)
v := DoReplacements(node.YNode().Value, f.MappingFunc)
updateNodeValue(node.YNode(), v)
return nil
}
@@ -78,12 +85,14 @@ func (f Filter) setMap(node *yaml.RNode) error {
contents := node.YNode().Content
for i := 0; i < len(contents); i += 2 {
if !yaml.IsYNodeString(contents[i]) {
return fmt.Errorf("invalid map key: %s, type: %s", contents[i].Value, contents[i].Tag)
return fmt.Errorf(
"invalid map key: value='%s', tag='%s'",
contents[i].Value, contents[i].Tag)
}
if !yaml.IsYNodeString(contents[i+1]) {
continue
}
newValue := expansion2.Expand(contents[i+1].Value, f.MappingFunc)
newValue := DoReplacements(contents[i+1].Value, f.MappingFunc)
updateNodeValue(contents[i+1], newValue)
}
return nil
@@ -94,7 +103,7 @@ func (f Filter) setSeq(node *yaml.RNode) error {
if !yaml.IsYNodeString(item) {
return fmt.Errorf("invalid value type expect a string")
}
newValue := expansion2.Expand(item.Value, f.MappingFunc)
newValue := DoReplacements(item.Value, f.MappingFunc)
updateNodeValue(item, newValue)
}
return nil

View File

@@ -1,18 +1,22 @@
package refvar
package refvar_test
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
expansion2 "sigs.k8s.io/kustomize/api/internal/accumulator/expansion"
. "sigs.k8s.io/kustomize/api/filters/refvar"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var makeMf = func(theMap map[string]interface{}) MappingFunc {
ignored := make(map[string]int)
return MakePrimitiveReplacer(ignored, theMap)
}
func TestFilter(t *testing.T) {
replacementCounts := make(map[string]int)
testCases := map[string]struct {
input string
@@ -35,7 +39,7 @@ metadata:
spec:
replicas: 5`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"VAR": int64(5),
}),
FieldSpec: types.FieldSpec{Path: "spec/replicas"},
@@ -57,7 +61,7 @@ metadata:
spec:
replicas: 1`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"VAR": int64(5),
}),
FieldSpec: types.FieldSpec{Path: "spec/replicas"},
@@ -79,7 +83,7 @@ metadata:
spec:
replicas: 1`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"VAR": int64(5),
}),
FieldSpec: types.FieldSpec{Path: "a/b/c"},
@@ -111,7 +115,7 @@ data:
- false
- 1.23`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"FOO": "foo",
"BAR": "bar",
"BOOL": false,
@@ -142,7 +146,7 @@ data:
BAZ: $(BAZ)
PLUS: foo+bar`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"FOO": "foo",
"BAR": "bar",
}),
@@ -181,7 +185,7 @@ data:
SLICE:
- $(FOO)`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"FOO": "foo",
"BAR": "bar",
}),
@@ -204,8 +208,10 @@ metadata:
data:
FOO: null`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{}),
FieldSpec: types.FieldSpec{Path: "data/FOO"},
MappingFunc: makeMf(map[string]interface{}{
// no replacements!
}),
FieldSpec: types.FieldSpec{Path: "data/FOO"},
},
},
}
@@ -223,8 +229,6 @@ data:
}
func TestFilterUnhappy(t *testing.T) {
replacementCounts := make(map[string]int)
testCases := map[string]struct {
input string
expectedError string
@@ -239,7 +243,8 @@ metadata:
data:
slice:
- false`,
expectedError: `obj 'apiVersion: apps/v1
expectedError: `considering field 'data/slice' of object
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
@@ -248,9 +253,9 @@ metadata:
data:
slice:
- false
' at path 'data/slice': invalid value type expect a string`,
: invalid value type expect a string`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"VAR": int64(5),
}),
FieldSpec: types.FieldSpec{Path: "data/slice"},
@@ -264,7 +269,8 @@ metadata:
name: dep
data:
1: str`,
expectedError: `obj 'apiVersion: apps/v1
expectedError: `considering field 'data' of object
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
@@ -272,9 +278,9 @@ metadata:
config.kubernetes.io/index: '0'
data:
1: str
' at path 'data': invalid map key: 1, type: ` + yaml.NodeTagInt,
: invalid map key: value='1', tag='` + yaml.NodeTagInt + `'`,
filter: Filter{
MappingFunc: expansion2.MappingFuncFor(replacementCounts, map[string]interface{}{
MappingFunc: makeMf(map[string]interface{}{
"VAR": int64(5),
}),
FieldSpec: types.FieldSpec{Path: "data"},

View File

@@ -98,7 +98,17 @@ var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
fields := strings.Split(f.FieldPath, "/")
var fields []string
// if there is forward slash '/' in the field name, a back slash '\'
// will be used to escape it.
for _, f := range strings.Split(f.FieldPath, "/") {
if len(fields) > 0 && strings.HasSuffix(fields[len(fields)-1], "\\") {
concatField := strings.TrimSuffix(fields[len(fields)-1], "\\") + "/" + f
fields = append(fields[:len(fields)-1], concatField)
} else {
fields = append(fields, f)
}
}
// TODO: support SequenceNode.
// Presumably here one could look for array indices (digits) at
// the end of the field path (as described in IETF RFC 6902 JSON),

View File

@@ -94,6 +94,20 @@ spec:
FilePathPosition: 2,
},
},
"backSlash": {
input: `
kind: SomeKind
`,
expectedOutput: `
kind: SomeKind
spec:
resourceRef/external: valueAdded
`,
filter: Filter{
Value: "valueAdded",
FieldPath: "spec/resourceRef\\/external",
},
},
}
for tn, tc := range testCases {

View File

@@ -6,22 +6,13 @@ require (
github.com/evanphx/json-patch v4.5.0+incompatible
github.com/go-errors/errors v1.0.1
github.com/go-openapi/spec v0.19.5
github.com/golangci/golangci-lint v1.21.0
github.com/google/go-cmp v0.3.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/hashicorp/go-multierror v1.1.0
github.com/imdario/mergo v0.3.5
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.4.0
github.com/yujunz/go-getter v1.4.1-lite
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
sigs.k8s.io/kustomize/kyaml v0.9.4
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
sigs.k8s.io/kustomize/kyaml v0.10.12
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/kyaml v0.9.4 => ../kyaml

View File

@@ -1,43 +1,21 @@
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=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
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-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
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/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bombsimon/wsl v1.2.5 h1:9gTOkIwVtoDZywvX802SDHokeX4kW1cKnV8ZTVAPkRs=
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
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=
@@ -45,14 +23,10 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@@ -60,33 +34,18 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db h1:GYXWx7Vr3+zv833u+8IoXbNnQY0AdXsxAgI0kX7xcwA=
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0=
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
@@ -95,13 +54,11 @@ github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -115,7 +72,6 @@ github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCs
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
@@ -127,7 +83,6 @@ github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pL
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@@ -137,138 +92,38 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8=
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ=
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg=
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b h1:ekuhfTjngPhisSjOJ0QWKpPQE8/rbknHaes6WVJj5Hw=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w=
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw=
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.21.0 h1:HxAxpR8Z0M8omihvQdsD3PF0qPjlqYqp2vMJzstoKeI=
github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us=
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg=
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -276,14 +131,10 @@ github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -291,55 +142,21 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -351,202 +168,100 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d h1:BzRvVq1EHuIjxpijCEKpAxzKUUMurOQ4sknehIATRh8=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs=
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517 h1:ChMKTho2hWKpks/nD/FL2KqM1wuVt62oJeiE8+eFpGs=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190320223903-b7391e95e576/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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
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 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
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/sys v0.0.0-20170830134202-bb24a47a89ea/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c h1:Vco5b+cuG5NNfORVxZy6bYZQ7rsigisU1WQFkvQ0L5E=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/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-20190125232054-d66bd3c5d5a6/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-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/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-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff h1:XdBG6es/oFDr1HwaxkxgVve7NB281QhxgK/i4voubFs=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
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/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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -554,53 +269,19 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg=
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/kustomize/kyaml v0.10.12 h1:1lUvuSVETthZspl4X+Xdic/FgPAfxUbc7MKtc1vcO2c=
sigs.k8s.io/kustomize/kyaml v0.10.12/go.mod h1:uD7q6dIrZV02fBV6D7FOgdOBcLfUmhG3ExxDIGbUM3w=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

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

View File

@@ -9,7 +9,6 @@ import (
"github.com/go-openapi/spec"
"github.com/pkg/errors"
"k8s.io/kube-openapi/pkg/common"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
@@ -18,8 +17,16 @@ import (
"sigs.k8s.io/yaml"
)
// OpenAPIDefinition describes single type.
// Normally these definitions are auto-generated using gen-openapi.
// Same as in k8s.io / kube-openapi / pkg / common.
type OpenAPIDefinition struct {
Schema spec.Schema
Dependencies []string
}
type myProperties map[string]spec.Schema
type nameToApiMap map[string]common.OpenAPIDefinition
type nameToApiMap map[string]OpenAPIDefinition
// LoadConfigFromCRDs parse CRD schemas from paths into a TransformerConfig
func LoadConfigFromCRDs(
@@ -162,7 +169,7 @@ func loadCrdIntoConfig(
err = theConfig.AddNamereferenceFieldSpec(
builtinconfig.NameBackReferences{
Gvk: resid.Gvk{Kind: kind, Version: version},
FieldSpecs: []types.FieldSpec{
Referrers: []types.FieldSpec{
makeFs(theGvk, append(path, propName, nameKey))},
})
if err != nil {

View File

@@ -8,10 +8,9 @@ import (
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/loader"
. "sigs.k8s.io/kustomize/api/internal/accumulator"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
)
@@ -140,21 +139,19 @@ func TestLoadCRDs(t *testing.T) {
nbrs := []builtinconfig.NameBackReferences{
{
Gvk: resid.Gvk{Kind: "Secret", Version: "v1"},
FieldSpecs: []types.FieldSpec{
Referrers: []types.FieldSpec{
{
CreateIfNotPresent: false,
Gvk: resid.Gvk{Kind: "MyKind"},
Path: "spec/secretRef/name",
Gvk: resid.Gvk{Kind: "MyKind"},
Path: "spec/secretRef/name",
},
},
},
{
Gvk: resid.Gvk{Kind: "Bee", Version: "v1beta1"},
FieldSpecs: []types.FieldSpec{
Referrers: []types.FieldSpec{
{
CreateIfNotPresent: false,
Gvk: resid.Gvk{Kind: "MyKind"},
Path: "spec/beeRef/name",
Gvk: resid.Gvk{Kind: "MyKind"},
Path: "spec/beeRef/name",
},
},
},

View File

@@ -4,23 +4,29 @@
package accumulator
import (
"fmt"
"log"
"sigs.k8s.io/kustomize/api/filters/nameref"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/kustomize/api/resource"
)
type nameReferenceTransformer struct {
backRefs []builtinconfig.NameBackReferences
}
const doDebug = false
var _ resmap.Transformer = &nameReferenceTransformer{}
type filterMap map[*resource.Resource][]nameref.Filter
// newNameReferenceTransformer constructs a nameReferenceTransformer
// with a given slice of NameBackReferences.
func newNameReferenceTransformer(br []builtinconfig.NameBackReferences) resmap.Transformer {
func newNameReferenceTransformer(
br []builtinconfig.NameBackReferences) resmap.Transformer {
if br == nil {
log.Fatal("backrefs not expected to be nil")
}
@@ -33,13 +39,61 @@ func newNameReferenceTransformer(br []builtinconfig.NameBackReferences) resmap.T
//
// For example, a HorizontalPodAutoscaler (HPA)
// necessarily refers to a Deployment, the thing that
// the HPA scales. The Deployment name might change
// (e.g. prefix added), and the reference in the HPA
// has to be fixed.
// an HPA scales. In this case:
//
// In the outer loop over the ResMap below, say we
// encounter a specific HPA. Then, in scanning backrefs,
// we encounter an entry like
// - the HPA instance is the Referrer,
// - the Deployment instance is the ReferralTarget.
//
// If the Deployment's name changes, e.g. a prefix is added,
// then the HPA's reference to the Deployment must be fixed.
//
func (t *nameReferenceTransformer) Transform(m resmap.ResMap) error {
fMap := t.determineFilters(m.Resources())
debug(fMap)
for r, fList := range fMap {
c := m.SubsetThatCouldBeReferencedByResource(r)
for _, f := range fList {
f.Referrer = r
f.ReferralCandidates = c
if err := f.Referrer.ApplyFilter(f); err != nil {
return err
}
}
}
return nil
}
func debug(fMap filterMap) {
if !doDebug {
return
}
fmt.Printf("filterMap has %d entries:\n", len(fMap))
rCount := 0
for r, fList := range fMap {
yml, _ := r.AsYAML()
rCount++
fmt.Printf(`
---- %3d. possible referrer -------------
%s
---------`, rCount, string(yml),
)
for i, f := range fList {
fmt.Printf(`
%3d/%3d update: %s
from: %s
`, rCount, i+1, f.NameFieldToUpdate.Path, f.ReferralTarget,
)
}
}
}
// Produce a map from referrer resources that might need to be fixed
// to filters that might fix them. The keys to this map are potential
// referrers, so won't include resources like ConfigMap or Secret.
//
// In the inner loop over the resources below, say we
// encounter an HPA instance. Then, in scanning the set
// of all known backrefs, we encounter an entry like
//
// - kind: Deployment
// fieldSpecs:
@@ -48,54 +102,53 @@ func newNameReferenceTransformer(br []builtinconfig.NameBackReferences) resmap.T
//
// This entry says that an HPA, via its
// 'spec/scaleTargetRef/name' field, may refer to a
// Deployment. This match to HPA means we may need to
// modify the value in its 'spec/scaleTargetRef/name'
// field, by searching for the thing it refers to,
// and getting its new name.
// Deployment.
//
// As a filter, and search optimization, we compute a
// subset of all resources that the HPA could refer to,
// by excluding objects from other namespaces, and
// excluding objects that don't have the same prefix-
// suffix mods as the HPA.
//
// We look in this subset for all Deployment objects
// with a resId that has a Name matching the field value
// present in the HPA. If no match do nothing; if more
// than one match, it's an error.
//
// We overwrite the HPA name field with the value found
// in the Deployment's name field (the name in the raw
// object - the modified name - not the unmodified name
// in the Deployment's resId).
//
// This process assumes that the name stored in a ResId
// (the ResMap key) isn't modified by name transformers.
// Name transformers should only modify the name in the
// body of the resource object (the value in the ResMap).
//
func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error {
// TODO: Too much looping, here and in transitive calls.
for _, referrer := range m.Resources() {
var candidates resmap.ResMap
for _, target := range o.backRefs {
for _, fSpec := range target.FieldSpecs {
if referrer.OrgId().IsSelected(&fSpec.Gvk) {
if candidates == nil {
candidates = m.SubsetThatCouldBeReferencedByResource(referrer)
}
err := filtersutil.ApplyToJSON(nameref.Filter{
FieldSpec: fSpec,
Referrer: referrer,
Target: target.Gvk,
ReferralCandidates: candidates,
}, referrer)
if err != nil {
return err
// This means that a filter will need to hunt for the right Deployment,
// obtain it's new name, and write that name into the HPA's
// 'spec/scaleTargetRef/name' field. Return a filter that can do that.
func (t *nameReferenceTransformer) determineFilters(
resources []*resource.Resource) (fMap filterMap) {
fMap = make(filterMap)
for _, backReference := range t.backRefs {
for _, referrerSpec := range backReference.Referrers {
for _, res := range resources {
if res.OrgId().IsSelected(&referrerSpec.Gvk) {
// If this is true, the res might be a referrer, and if
// so, the name reference it holds might need an update.
if resHasField(res, referrerSpec.Path) {
// Optimization - the referrer has the field
// that might need updating.
fMap[res] = append(fMap[res], nameref.Filter{
// Name field to write in the Referrer.
// If the path specified here isn't found in
// the Referrer, nothing happens (no error,
// no field creation).
NameFieldToUpdate: referrerSpec,
// Specification of object class to read from.
// Always read from metadata/name field.
ReferralTarget: backReference.Gvk,
})
}
}
}
}
}
return nil
return fMap
}
// TODO: check res for field existence here to avoid extra work.
// res.GetFieldValue, which uses yaml.Lookup under the hood, doesn't know
// how to parse fieldspec-style paths that make no distinction
// between maps and sequences. This means it cannot lookup commonly
// used "indeterminate" paths like
// spec/containers/env/valueFrom/configMapKeyRef/name
// ('containers' is a list, not a map).
// However, the fieldspec filter does know how to handle this;
// extract that code and call it here?
func resHasField(res *resource.Resource, path string) bool {
return true
// fld := strings.Join(utils.PathSplitter(path), ".")
// _, e := res.GetFieldValue(fld)
// return e == nil
}

View File

@@ -8,12 +8,15 @@ import (
"testing"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
)
const notEqualErrFmt = "expected (self) doesn't match actual (other): %v"
func TestNameReferenceHappyRun(t *testing.T) {
m := resmaptest_test.NewRmBuilderDefault(t).AddWithName(
"cm1",
@@ -217,6 +220,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
"secret1",
"secret1",
"secret2",
"cm1",
},
},
},
@@ -420,6 +424,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
"someprefix-secret1-somehash",
"someprefix-secret1-somehash",
"secret2",
"someprefix-cm1-somehash",
},
},
},
@@ -468,7 +473,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
t.Fatalf(notEqualErrFmt, err)
}
}
@@ -516,7 +521,27 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
},
},
}).ResMap(),
expectedErr: "cannot find field 'name' in node"},
// TODO(#3304): DECISION - kyaml better; not a bug.
expectedErr: konfig.IfApiMachineryElseKyaml(
`updating name reference in 'rules/resourceNames' field of `+
`'rbac.authorization.k8s.io_v1_ClusterRole|~X|cr'`+
`: considering field 'rules/resourceNames' of object
{"apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", "metadata": {
"name": "cr"}, "rules": [{"resourceNames": {"foo": "bar"}, "resources": ["secrets"]}]}
: visit traversal on path: [resourceNames]: path config error; no 'name' field in node`,
`updating name reference in 'rules/resourceNames' field of `+
`'rbac.authorization.k8s.io_v1_ClusterRole|~X|cr'`+
`: considering field 'rules/resourceNames' of object
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cr
rules:
- resourceNames:
foo: bar
resources:
- secrets
: visit traversal on path: [resourceNames]: path config error; no 'name' field in node`)},
}
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
@@ -527,7 +552,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
}
if !strings.Contains(err.Error(), test.expectedErr) {
t.Fatalf("Incorrect error.\nExpected: %s, but got %v",
t.Fatalf("Incorrect error.\nExpected:\n %s\nGot:\n%v",
test.expectedErr, err)
}
}
@@ -585,7 +610,7 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
v2.AppendRefBy(c2.CurId())
if err := m1.ErrorIfNotEqualLists(m2); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
t.Fatalf(notEqualErrFmt, err)
}
}
@@ -719,8 +744,9 @@ func TestNameReferenceNamespace(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
m.RemoveBuildAnnotations()
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
t.Fatalf(notEqualErrFmt, err)
}
}
@@ -880,8 +906,9 @@ func TestNameReferenceClusterWide(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
m.RemoveBuildAnnotations()
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
t.Fatalf(notEqualErrFmt, err)
}
}
@@ -1006,8 +1033,9 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
m.RemoveBuildAnnotations()
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
t.Fatalf(notEqualErrFmt, err)
}
}
@@ -1042,7 +1070,8 @@ func TestNameReferenceCandidateSelection(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
m.RemoveBuildAnnotations()
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
t.Fatalf(notEqualErrFmt, err)
}
}

View File

@@ -4,19 +4,15 @@
package accumulator
import (
expansion2 "sigs.k8s.io/kustomize/api/internal/accumulator/expansion"
"sigs.k8s.io/kustomize/api/filters/refvar"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
)
type refVarTransformer struct {
varMap map[string]interface{}
replacementCounts map[string]int
fieldSpecs []types.FieldSpec
mappingFunc func(string) interface{}
}
// newRefVarTransformer returns a new refVarTransformer
@@ -35,8 +31,7 @@ func newRefVarTransformer(
func (rv *refVarTransformer) UnusedVars() []string {
var unused []string
for k := range rv.varMap {
_, ok := rv.replacementCounts[k]
if !ok {
if _, ok := rv.replacementCounts[k]; !ok {
unused = append(unused, k)
}
}
@@ -46,14 +41,13 @@ func (rv *refVarTransformer) UnusedVars() []string {
// Transform replaces $(VAR) style variables with values.
func (rv *refVarTransformer) Transform(m resmap.ResMap) error {
rv.replacementCounts = make(map[string]int)
rv.mappingFunc = expansion2.MappingFuncFor(
rv.replacementCounts, rv.varMap)
mf := refvar.MakePrimitiveReplacer(rv.replacementCounts, rv.varMap)
for _, res := range m.Resources() {
for _, fieldSpec := range rv.fieldSpecs {
err := filtersutil.ApplyToJSON(refvar.Filter{
MappingFunc: rv.mappingFunc,
err := res.ApplyFilter(refvar.Filter{
MappingFunc: mf,
FieldSpec: fieldSpec,
}, res)
})
if err != nil {
return err
}

View File

@@ -7,6 +7,7 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
@@ -23,14 +24,12 @@ func TestRefVarTransformer(t *testing.T) {
res resmap.ResMap
unused []string
}
testCases := []struct {
description string
given given
expected expected
errMessage string
testCases := map[string]struct {
given given
expected expected
errMessage string
}{
{
description: "var replacement in map[string]",
"var replacement in map[string]": {
given: given{
varMap: map[string]interface{}{
"FOO": "replacementForFoo",
@@ -105,8 +104,7 @@ func TestRefVarTransformer(t *testing.T) {
unused: []string{"BAR"},
},
},
{
description: "var replacement panic in map[string]",
"var replacement panic in map[string]": {
given: given{
varMap: map[string]interface{}{},
fs: []types.FieldSpec{
@@ -123,11 +121,23 @@ func TestRefVarTransformer(t *testing.T) {
"slice": []interface{}{5}, // noticeably *not* a []string
}}).ResMap(),
},
errMessage: `obj '{"apiVersion": "v1", "data": {"slice": [5]}, "kind": "ConfigMap", "metadata": {"name": "cm1"}}
' at path 'data/slice': invalid value type expect a string`,
// TODO(#3304): DECISION - kyaml better; not a bug.
errMessage: konfig.IfApiMachineryElseKyaml(
`considering field 'data/slice' of object
{"apiVersion": "v1", "data": {"slice": [5]}, "kind": "ConfigMap", "metadata": {"name": "cm1"}}
: invalid value type expect a string`,
`considering field 'data/slice' of object
apiVersion: v1
data:
slice:
- 5
kind: ConfigMap
metadata:
name: cm1
: invalid value type expect a string`,
),
},
{
description: "var replacement in nil",
"var replacement in nil": {
given: given{
varMap: map[string]interface{}{},
fs: []types.FieldSpec{
@@ -159,20 +169,18 @@ func TestRefVarTransformer(t *testing.T) {
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
// arrange
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
tr := newRefVarTransformer(tc.given.varMap, tc.given.fs)
// act
err := tr.Transform(tc.given.res)
// assert
if tc.errMessage != "" {
if err == nil {
t.Fatalf("missing expected error %v", tc.errMessage)
} else if err.Error() != tc.errMessage {
t.Fatalf("actual error doesn't match expected error: \nACTUAL: %v\nEXPECTED: %v", err.Error(), tc.errMessage)
t.Fatalf(`actual error doesn't match expected error:
ACTUAL: %v
EXPECTED: %v`,
err.Error(), tc.errMessage)
}
} else {
if err != nil {
@@ -182,7 +190,13 @@ func TestRefVarTransformer(t *testing.T) {
a, e := tc.given.res, tc.expected.res
if !reflect.DeepEqual(a, e) {
err = e.ErrorIfNotEqualLists(a)
t.Fatalf("actual doesn't match expected: \nACTUAL:\n%v\nEXPECTED:\n%v\nERR: %v", a, e, err)
t.Fatalf(`actual doesn't match expected:
ACTUAL:
%v
EXPECTED:
%v
ERR: %v`,
a, e, err)
}
}
})

View File

@@ -41,13 +41,11 @@ func (ra *ResAccumulator) Vars() []types.Var {
return ra.varSet.AsSlice()
}
func (ra *ResAccumulator) AppendAll(
resources resmap.ResMap) error {
func (ra *ResAccumulator) AppendAll(resources resmap.ResMap) error {
return ra.resMap.AppendAll(resources)
}
func (ra *ResAccumulator) AbsorbAll(
resources resmap.ResMap) error {
func (ra *ResAccumulator) AbsorbAll(resources resmap.ResMap) error {
return ra.resMap.AbsorbAll(resources)
}
@@ -61,6 +59,15 @@ func (ra *ResAccumulator) GetTransformerConfig() *builtinconfig.TransformerConfi
return ra.tConfig
}
// MergeVars accumulates vars into ResAccumulator.
// A Var is a tuple of name, object reference and field reference.
// This func takes a list of vars from the current kustomization file and
// annotates the accumulated resources with the names of the vars that match
// those resources. E.g. if there's a var named "sam" that wants to get
// its data from a ConfigMap named "james", and the resource list contains a
// ConfigMap named "james", then that ConfigMap will be annotated with the
// var name "sam". Later this annotation is used to find the data for "sam"
// by digging into a particular fieldpath of "james".
func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
for _, v := range incoming {
targetId := resid.NewResIdWithNamespace(v.ObjRef.GVK(), v.ObjRef.Name, v.ObjRef.Namespace)
@@ -70,7 +77,7 @@ func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
// wildcard search on the namespace hence we still use GvknEquals
idMatcher = targetId.Equals
}
matched := ra.resMap.GetMatchingResourcesByOriginalId(idMatcher)
matched := ra.resMap.GetMatchingResourcesByAnyId(idMatcher)
if len(matched) > 1 {
return fmt.Errorf(
"found %d resId matches for var %s "+
@@ -106,12 +113,10 @@ func (ra *ResAccumulator) findVarValueFromResources(v types.Var) (interface{}, e
"field specified in var '%v' "+
"not found in corresponding resource", v)
}
return s, nil
}
}
}
return "", fmt.Errorf(
"var '%v' cannot be mapped to a field "+
"in the set of known resources", v)
@@ -127,10 +132,8 @@ func (ra *ResAccumulator) makeVarReplacementMap() (map[string]interface{}, error
if err != nil {
return nil, err
}
result[v.Name] = s
}
return result, nil
}
@@ -161,6 +164,6 @@ func (ra *ResAccumulator) FixBackReferences() (err error) {
if ra.tConfig.NameReference == nil {
return nil
}
return ra.Transform(newNameReferenceTransformer(
ra.tConfig.NameReference))
return ra.Transform(
newNameReferenceTransformer(ra.tConfig.NameReference))
}

View File

@@ -344,19 +344,20 @@ func TestResolveVarsWithNoambiguation(t *testing.T) {
},
},
}}).
// Make it seem like this resource
// went through a prefix transformer.
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "backendOne",
"name": "sub-backendOne",
"annotations": map[string]interface{}{
"config.kubernetes.io/previousNames": "backendOne",
"config.kubernetes.io/previousNamespaces": "default",
"config.kubernetes.io/prefixes": "sub-",
},
}}).ResMap()
// Make it seem like this resource
// went through a prefix transformer.
r := m.GetByIndex(1)
r.AddNamePrefix("sub-")
r.SetName("sub-backendOne") // original name remains "backendOne"
err = ra2.AppendAll(m)
if err != nil {
t.Fatalf("unexpected err: %v", err)

View File

@@ -21,6 +21,11 @@ func (c *smPatchMergeOnlyDetector) HasConflict(
return false, nil
}
// There's at least one case that doesn't work. Suppose one has a
// Deployment with a volume with the bizarre "emptyDir: {}" entry.
// If you want to get rid of this entry via a patch containing
// the entry "emptyDir: null", then the following won't work,
// because null entries are eliminated.
func (c *smPatchMergeOnlyDetector) MergePatches(
r, patch *resource.Resource) (*resource.Resource, error) {
err := r.ApplySmPatch(patch)

View File

@@ -1,40 +1,20 @@
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=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
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-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
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/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
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=
@@ -42,14 +22,10 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@@ -57,31 +33,18 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elastic/go-elasticsearch/v6 v6.8.5 h1:U2HtkBseC1FNBmDr0TR2tKltL6FxoY+niDAlj5M8TK8=
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
@@ -90,13 +53,11 @@ github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -110,7 +71,6 @@ github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCs
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
@@ -122,7 +82,6 @@ github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pL
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@@ -132,170 +91,66 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
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/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -307,183 +162,94 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190320223903-b7391e95e576/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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
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/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/sys v0.0.0-20170830134202-bb24a47a89ea/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c h1:Vco5b+cuG5NNfORVxZy6bYZQ7rsigisU1WQFkvQ0L5E=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/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-20190125232054-d66bd3c5d5a6/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-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/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-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
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/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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -491,50 +257,19 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg=
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/kyaml v0.9.4 h1:DDuzZtjIzFqp2IPy4DTyCI69Cl3bDgcJODjI6sjF9NY=
sigs.k8s.io/kustomize/kyaml v0.9.4/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/kustomize/kyaml v0.10.12 h1:1lUvuSVETthZspl4X+Xdic/FgPAfxUbc7MKtc1vcO2c=
sigs.k8s.io/kustomize/kyaml v0.10.12/go.mod h1:uD7q6dIrZV02fBV6D7FOgdOBcLfUmhG3ExxDIGbUM3w=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@@ -191,7 +191,8 @@ func (idx *index) Put(uniqueID string, doc interface{}) error {
}
if exists {
docBytes, err := json.Marshal(doc)
var docBytes []byte
docBytes, err = json.Marshal(doc)
if err != nil {
return err
}
@@ -204,12 +205,14 @@ func (idx *index) Put(uniqueID string, doc interface{}) error {
Body: bytes.NewReader(body),
DocumentID: uniqueID,
}
res, err := req.Do(idx.ctx, idx.client)
var res *esapi.Response
res, err = req.Do(idx.ctx, idx.client)
err = idx.responseErrorOrNil("could not update document",
res, err, ignoreResponseBody)
} else {
body, err := json.Marshal(doc)
var body []byte
body, err = json.Marshal(doc)
if err != nil {
return err
}
@@ -219,7 +222,8 @@ func (idx *index) Put(uniqueID string, doc interface{}) error {
Body: bytes.NewReader(body),
DocumentID: uniqueID,
}
res, err := req.Do(idx.ctx, idx.client)
var res *esapi.Response
res, err = req.Do(idx.ctx, idx.client)
err = idx.responseErrorOrNil("could not insert document",
res, err, ignoreResponseBody)

View File

@@ -4,7 +4,6 @@
package generators
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -38,14 +37,9 @@ func MakeConfigMap(
if err != nil {
return nil, err
}
for _, k := range filtersutil.SortedMapKeys(m) {
fldName, vrN := makeConfigMapValueRNode(m[k])
if _, err = rn.Pipe(
yaml.LookupCreate(yaml.MappingNode, fldName),
yaml.SetField(k, vrN)); err != nil {
return nil, err
}
if err = rn.LoadMapIntoConfigMapData(m); err != nil {
return nil, err
}
copyLabelsAndAnnotations(rn, args.Options)
return rn, err
return rn, nil
}

View File

@@ -4,7 +4,6 @@
package generators
import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -37,24 +36,23 @@ func MakeSecret(
if err != nil {
return nil, err
}
t := "Opaque"
if args.Type != "" {
t = args.Type
}
if _, err := rn.Pipe(
yaml.FieldSetter{
Name: "type",
Value: yaml.NewStringRNode("Opaque")}); err != nil {
Value: yaml.NewStringRNode(t)}); err != nil {
return nil, err
}
m, err := makeValidatedDataMap(ldr, args.Name, args.KvPairSources)
if err != nil {
return nil, err
}
for _, k := range filtersutil.SortedMapKeys(m) {
vrN := makeSecretValueRNode(m[k])
if _, err = rn.Pipe(
yaml.LookupCreate(yaml.MappingNode, yaml.DataField),
yaml.SetField(k, vrN)); err != nil {
return nil, err
}
if err = rn.LoadMapIntoSecretData(m); err != nil {
return nil, err
}
copyLabelsAndAnnotations(rn, args.Options)
return rn, err
return rn, nil
}

View File

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

View File

@@ -4,13 +4,9 @@
package generators
import (
"encoding/base64"
"fmt"
"strings"
"unicode/utf8"
"github.com/go-errors/errors"
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
@@ -66,13 +62,13 @@ func copyLabelsAndAnnotations(
if opts == nil {
return nil
}
for _, k := range filtersutil.SortedMapKeys(opts.Labels) {
for _, k := range yaml.SortedMapKeys(opts.Labels) {
v := opts.Labels[k]
if _, err := rn.Pipe(yaml.SetLabel(k, v)); err != nil {
return err
}
}
for _, k := range filtersutil.SortedMapKeys(opts.Annotations) {
for _, k := range yaml.SortedMapKeys(opts.Annotations) {
v := opts.Annotations[k]
if _, err := rn.Pipe(yaml.SetAnnotation(k, v)); err != nil {
return err
@@ -80,60 +76,3 @@ func copyLabelsAndAnnotations(
}
return nil
}
// In a secret, all data is base64 encoded, regardless of its conformance
// or lack thereof to UTF-8.
func makeSecretValueRNode(s string) *yaml.RNode {
yN := &yaml.Node{Kind: yaml.ScalarNode}
// Purposely don't use YAML tags to identify the data as being plain text or
// binary. It kubernetes Secrets the values in the `data` map are expected
// to be base64 encoded, and in ConfigMaps that same can be said for the
// values in the `binaryData` field.
yN.Tag = yaml.NodeTagString
yN.Value = encodeBase64(s)
if strings.Contains(yN.Value, "\n") {
yN.Style = yaml.LiteralStyle
}
return yaml.NewRNode(yN)
}
func makeConfigMapValueRNode(s string) (field string, rN *yaml.RNode) {
yN := &yaml.Node{Kind: yaml.ScalarNode}
yN.Tag = yaml.NodeTagString
if utf8.ValidString(s) {
field = yaml.DataField
yN.Value = s
} else {
field = yaml.BinaryDataField
yN.Value = encodeBase64(s)
}
if strings.Contains(yN.Value, "\n") {
yN.Style = yaml.LiteralStyle
}
return field, yaml.NewRNode(yN)
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines
// as appropriate for the resulting length.
func encodeBase64(s string) string {
const lineLen = 70
encLen := base64.StdEncoding.EncodedLen(len(s))
lines := encLen/lineLen + 1
buf := make([]byte, encLen*2+lines)
in := buf[0:encLen]
out := buf[encLen:]
base64.StdEncoding.Encode(in, []byte(s))
k := 0
for i := 0; i < len(in); i += lineLen {
j := i + lineLen
if j > len(in) {
j = len(in)
}
k += copy(out[k:], in[i:j])
if lines > 1 {
out[k] = '\n'
k++
}
}
return string(out[:k])
}

View File

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

View File

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

View File

@@ -1,68 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package configmapandsecret generates configmaps and secrets per generator rules.
package configmapandsecret
import (
"fmt"
"unicode/utf8"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/api/types"
)
func makeFreshConfigMap(
args *types.ConfigMapArgs) *corev1.ConfigMap {
cm := &corev1.ConfigMap{}
cm.APIVersion = "v1"
cm.Kind = "ConfigMap"
cm.Name = args.Name
cm.Namespace = args.Namespace
cm.Data = map[string]string{}
return cm
}
// MakeConfigMap returns a new ConfigMap, or nil and an error.
func (f *Factory) MakeConfigMap(args *types.ConfigMapArgs) (*corev1.ConfigMap, error) {
all, err := f.kvLdr.Load(args.KvPairSources)
if err != nil {
return nil, errors.Wrap(err, "loading KV pairs")
}
cm := makeFreshConfigMap(args)
for _, p := range all {
err = f.addKvToConfigMap(cm, p)
if err != nil {
return nil, errors.Wrap(err, "trouble mapping")
}
}
f.copyLabelsAndAnnotations(cm, args.Options)
return cm, nil
}
// addKvToConfigMap adds the given key and data to the given config map.
// Error if key invalid, or already exists.
func (f *Factory) addKvToConfigMap(configMap *corev1.ConfigMap, p types.Pair) error {
if err := f.kvLdr.Validator().ErrIfInvalidKey(p.Key); err != nil {
return err
}
// If the configmap data contains byte sequences that are all in the UTF-8
// range, we will write it to .Data
if utf8.Valid([]byte(p.Value)) {
if _, entryExists := configMap.Data[p.Key]; entryExists {
return fmt.Errorf(keyExistsErrorMsg, p.Key, configMap.Data)
}
configMap.Data[p.Key] = p.Value
return nil
}
// otherwise, it's BinaryData
if configMap.BinaryData == nil {
configMap.BinaryData = map[string][]byte{}
}
if _, entryExists := configMap.BinaryData[p.Key]; entryExists {
return fmt.Errorf(keyExistsErrorMsg, p.Key, configMap.BinaryData)
}
configMap.BinaryData[p.Key] = []byte(p.Value)
return nil
}

View File

@@ -1,189 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package configmapandsecret
import (
"path/filepath"
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/loader"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
func makeEnvConfigMap(name string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}
}
func makeFileConfigMap(name string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"app-init.ini": `FOO=bar
BAR=baz
`,
},
BinaryData: map[string][]byte{
"app.bin": {0xff, 0xfd},
},
}
}
func makeLiteralConfigMap(name string, labels, annotations map[string]string) *corev1.ConfigMap {
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"a": "x",
"b": "y",
"c": "Hello World",
"d": "true",
},
}
if labels != nil {
cm.SetLabels(labels)
}
if annotations != nil {
cm.SetAnnotations(annotations)
}
return cm
}
func TestConstructConfigMap(t *testing.T) {
type testCase struct {
description string
input types.ConfigMapArgs
expected *corev1.ConfigMap
}
testCases := []testCase{
{
description: "construct config map from env",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "envConfigMap",
KvPairSources: types.KvPairSources{
EnvSources: []string{
filepath.Join("configmap", "app.env"),
},
},
},
},
expected: makeEnvConfigMap("envConfigMap"),
},
{
description: "construct config map from file",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileConfigMap",
KvPairSources: types.KvPairSources{
FileSources: []string{
filepath.Join("configmap", "app-init.ini"),
filepath.Join("configmap", "app.bin"),
},
},
},
},
expected: makeFileConfigMap("fileConfigMap"),
},
{
description: "construct config map from literal",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalConfigMap",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
},
},
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
"foo": "bar",
}, nil),
},
{
description: "construct config map from literal with GeneratorOptions in ConfigMapArgs",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalConfigMap",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "changed",
"cat": "dog",
},
Annotations: map[string]string{
"foo": "changed",
"cat": "dog",
},
},
},
},
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
"foo": "changed",
"cat": "dog",
}, map[string]string{
"foo": "changed",
"cat": "dog",
}),
},
}
fSys := filesys.MakeFsInMemory()
fSys.WriteFile(
filesys.RootedPath("configmap", "app.env"),
[]byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile(
filesys.RootedPath("configmap", "app-init.ini"),
[]byte("FOO=bar\nBAR=baz\n"))
fSys.WriteFile(
filesys.RootedPath("configmap", "app.bin"),
[]byte{0xff, 0xfd})
kvLdr := kv.NewLoader(
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for _, tc := range testCases {
cm, err := NewFactory(kvLdr).MakeConfigMap(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(*cm, *tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, *cm, tc.expected)
}
}
}

View File

@@ -1,37 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package configmapandsecret
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/types"
)
// Factory makes ConfigMaps and Secrets.
type Factory struct {
kvLdr ifc.KvLoader
}
// NewFactory returns a new factory that makes ConfigMaps and Secrets.
func NewFactory(kvLdr ifc.KvLoader) *Factory {
return &Factory{kvLdr: kvLdr}
}
// copyLabelsAndAnnotations copies labels and annotations from
// GeneratorOptions into the given object.
func (f *Factory) copyLabelsAndAnnotations(
obj metav1.Object, opts *types.GeneratorOptions) {
if opts == nil {
return
}
if opts.Labels != nil {
obj.SetLabels(types.CopyMap(opts.Labels))
}
if opts.Annotations != nil {
obj.SetAnnotations(types.CopyMap(opts.Annotations))
}
}
const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v"

View File

@@ -1,54 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package configmapandsecret
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/api/types"
)
func makeFreshSecret(
args *types.SecretArgs) *corev1.Secret {
s := &corev1.Secret{}
s.APIVersion = "v1"
s.Kind = "Secret"
s.Name = args.Name
s.Namespace = args.Namespace
s.Type = corev1.SecretType(args.Type)
if s.Type == "" {
s.Type = corev1.SecretTypeOpaque
}
s.Data = map[string][]byte{}
return s
}
// MakeSecret returns a new secret.
func (f *Factory) MakeSecret(args *types.SecretArgs) (*corev1.Secret, error) {
all, err := f.kvLdr.Load(args.KvPairSources)
if err != nil {
return nil, err
}
s := makeFreshSecret(args)
for _, p := range all {
err = f.addKvToSecret(s, p.Key, p.Value)
if err != nil {
return nil, err
}
}
f.copyLabelsAndAnnotations(s, args.Options)
return s, nil
}
func (f *Factory) addKvToSecret(secret *corev1.Secret, keyName, data string) error {
if err := f.kvLdr.Validator().ErrIfInvalidKey(keyName); err != nil {
return err
}
if _, entryExists := secret.Data[keyName]; entryExists {
return fmt.Errorf(keyExistsErrorMsg, keyName, secret.Data)
}
secret.Data[keyName] = []byte(data)
return nil
}

View File

@@ -1,154 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package configmapandsecret
import (
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/loader"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
func makeEnvSecret(name string) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string][]byte{
"DB_PASSWORD": []byte("somepw"),
"DB_USERNAME": []byte("admin"),
},
Type: "Opaque",
}
}
func makeFileSecret(name string) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string][]byte{
"app-init.ini": []byte(`FOO=bar
BAR=baz
`),
},
Type: "Opaque",
}
}
func makeLiteralSecret(name string, labels, annotations map[string]string) *corev1.Secret {
s := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string][]byte{
"a": []byte("x"),
"b": []byte("y"),
},
Type: "Opaque",
}
if labels != nil {
s.SetLabels(labels)
}
if annotations != nil {
s.SetAnnotations(annotations)
}
return s
}
func TestConstructSecret(t *testing.T) {
type testCase struct {
description string
input types.SecretArgs
expected *corev1.Secret
}
testCases := []testCase{
{
description: "construct secret from env",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "envSecret",
KvPairSources: types.KvPairSources{
EnvSources: []string{"secret/app.env"},
},
},
},
expected: makeEnvSecret("envSecret"),
},
{
description: "construct secret from file",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileSecret",
KvPairSources: types.KvPairSources{
FileSources: []string{"secret/app-init.ini"},
},
},
},
expected: makeFileSecret("fileSecret"),
},
{
description: "construct secret from literal",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalSecret",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y"},
},
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
Annotations: map[string]string{
"fruit": "banana",
"pet": "dog",
},
},
},
},
expected: makeLiteralSecret("literalSecret", map[string]string{
"foo": "bar",
}, map[string]string{
"fruit": "banana",
"pet": "dog",
}),
},
}
fSys := filesys.MakeFsInMemory()
fSys.WriteFile("/secret/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
kvLdr := kv.NewLoader(
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for _, tc := range testCases {
f := NewFactory(kvLdr)
cm, err := f.MakeSecret(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(*cm, *tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, *cm, tc.expected)
}
}
}

View File

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

View File

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

View File

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

View File

@@ -10,8 +10,8 @@ import (
"sigs.k8s.io/kustomize/api/types"
)
// NameBackReferences is an association between a gvk.GVK and a list
// of FieldSpec instances that could refer to it.
// NameBackReferences is an association between a gvk.GVK (a ReferralTarget)
// and a list of Referrers that could refer to it.
//
// It is used to handle name changes, and can be thought of as a
// a contact list. If you change your own contact info (name,
@@ -19,16 +19,20 @@ import (
// know about the change.
//
// For example, ConfigMaps can be used by Pods and everything that
// contains a Pod; Deployment, Job, StatefulSet, etc. To change
// the name of a ConfigMap instance from 'alice' to 'bob', one
// must visit all objects that could refer to the ConfigMap, see if
// they mention 'alice', and if so, change the reference to 'bob'.
// 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',
// one must
// - visit all objects that could refer to the ConfigMap (the Referrers)
// - see if they mention 'alice',
// - if so, change the Referrer's name reference to 'bob'.
//
// The NameBackReferences instance to aid in this could look like
// {
// kind: ConfigMap
// version: v1
// FieldSpecs:
// fieldSpecs:
// - kind: Pod
// version: v1
// path: spec/volumes/configMap/name
@@ -39,13 +43,15 @@ import (
// (etc.)
// }
type NameBackReferences struct {
resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
FieldSpecs types.FsSlice `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"`
resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
// TODO: rename json 'fieldSpecs' to 'referrers' for clarity.
// This will, however, break anyone using a custom config.
Referrers types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
}
func (n NameBackReferences) String() string {
var r []string
for _, f := range n.FieldSpecs {
for _, f := range n.Referrers {
r = append(r, f.String())
}
return n.Gvk.String() + ": (\n" +
@@ -77,7 +83,7 @@ func (s nbrSlice) mergeOne(other NameBackReferences) (nbrSlice, error) {
found := false
for _, c := range s {
if c.Gvk.Equals(other.Gvk) {
c.FieldSpecs, err = c.FieldSpecs.MergeAll(other.FieldSpecs)
c.Referrers, err = c.Referrers.MergeAll(other.Referrers)
if err != nil {
return nil, err
}

View File

@@ -50,13 +50,13 @@ func TestMergeAll(t *testing.T) {
Gvk: resid.Gvk{
Kind: "ConfigMap",
},
FieldSpecs: fsSlice1,
Referrers: fsSlice1,
},
{
Gvk: resid.Gvk{
Kind: "Secret",
},
FieldSpecs: fsSlice2,
Referrers: fsSlice2,
},
}
nbrsSlice2 := nbrSlice{
@@ -64,13 +64,13 @@ func TestMergeAll(t *testing.T) {
Gvk: resid.Gvk{
Kind: "ConfigMap",
},
FieldSpecs: fsSlice1,
Referrers: fsSlice1,
},
{
Gvk: resid.Gvk{
Kind: "Secret",
},
FieldSpecs: fsSlice2,
Referrers: fsSlice2,
},
}
expected := nbrSlice{
@@ -78,13 +78,13 @@ func TestMergeAll(t *testing.T) {
Gvk: resid.Gvk{
Kind: "ConfigMap",
},
FieldSpecs: fsSlice1,
Referrers: fsSlice1,
},
{
Gvk: resid.Gvk{
Kind: "Secret",
},
FieldSpecs: fsSlice2,
Referrers: fsSlice2,
},
}
actual, err := nbrsSlice1.mergeAll(nbrsSlice2)

View File

@@ -24,7 +24,7 @@ func TestAddNamereferenceFieldSpec(t *testing.T) {
Gvk: resid.Gvk{
Kind: "KindA",
},
FieldSpecs: []types.FieldSpec{
Referrers: []types.FieldSpec{
{
Gvk: resid.Gvk{
Kind: "KindB",
@@ -89,7 +89,7 @@ func TestMerge(t *testing.T) {
Gvk: resid.Gvk{
Kind: "KindA",
},
FieldSpecs: []types.FieldSpec{
Referrers: []types.FieldSpec{
{
Gvk: resid.Gvk{
Kind: "KindB",
@@ -103,7 +103,7 @@ func TestMerge(t *testing.T) {
Gvk: resid.Gvk{
Kind: "KindA",
},
FieldSpecs: []types.FieldSpec{
Referrers: []types.FieldSpec{
{
Gvk: resid.Gvk{
Kind: "KindC",

View File

@@ -45,6 +45,7 @@ s/$BAR/bar baz/g
"argsFromFile": "sed-input.txt",
})
pluginConfig.RemoveBuildAnnotations()
p := NewExecPlugin(
pLdr.AbsolutePluginPath(
konfig.DisabledPluginConfig(),

View File

@@ -4,6 +4,7 @@
package utils
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
@@ -13,8 +14,8 @@ import (
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
@@ -135,9 +136,6 @@ func GetResMapWithIDAnnotation(rm resmap.ResMap) (resmap.ResMap, error) {
return nil, err
}
annotations := r.GetAnnotations()
if annotations == nil {
annotations = make(map[string]string)
}
annotations[idAnnotation] = string(idString)
r.SetAnnotations(annotations)
}
@@ -147,41 +145,65 @@ func GetResMapWithIDAnnotation(rm resmap.ResMap) (resmap.ResMap, error) {
// UpdateResMapValues updates the Resource value in the given ResMap
// with the emitted Resource values in output.
func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byte, rm resmap.ResMap) error {
outputRM, err := h.ResmapFactory().NewResMapFromBytes(output)
mapFactory := h.ResmapFactory()
resFactory := mapFactory.RF()
resources, err := resFactory.SliceFromBytes(output)
if err != nil {
return err
}
for _, r := range outputRM.Resources() {
// for each emitted Resource, find the matching Resource in the original ResMap
// using its id
annotations := r.GetAnnotations()
idString, ok := annotations[idAnnotation]
if !ok {
return fmt.Errorf("the transformer %s should not remove annotation %s",
pluginName, idAnnotation)
// Don't use resources here, or error message will be unfriendly to plugin builders
newMap, err := mapFactory.NewResMapFromBytes([]byte{})
if err != nil {
return err
}
for _, r := range resources {
removeIDAnnotation(r) // stale--not manipulated by plugin transformers
// Add to the new map, checking for duplicates
if err := newMap.Append(r); err != nil {
prettyID, err := json.Marshal(r.CurId())
if err != nil {
prettyID = []byte(r.CurId().String())
}
return fmt.Errorf("plugin %s generated duplicate resource: %s", pluginName, prettyID)
}
id := resid.ResId{}
err := yaml.Unmarshal([]byte(idString), &id)
// Add to or update the old map
oldIdx, err := rm.GetIndexOfCurrentId(r.CurId())
if err != nil {
return err
}
res, err := rm.GetByCurrentId(id)
if err != nil {
return fmt.Errorf("unable to find unique match to %s", id.String())
if oldIdx != -1 {
rm.GetByIndex(oldIdx).ResetPrimaryData(r)
} else {
if err := rm.Append(r); err != nil {
return err
}
}
// remove the annotation set by Kustomize to track the resource
delete(annotations, idAnnotation)
if len(annotations) == 0 {
annotations = nil
}
r.SetAnnotations(annotations)
// update the resource value with the transformed object
res.ResetPrimaryData(r)
}
// Remove items the transformer deleted from the old map
for _, id := range rm.AllIds() {
newIdx, _ := newMap.GetIndexOfCurrentId(id)
if newIdx == -1 {
rm.Remove(id)
}
}
return nil
}
func removeIDAnnotation(r *resource.Resource) {
// remove the annotation set by Kustomize to track the resource
annotations := r.GetAnnotations()
delete(annotations, idAnnotation)
if len(annotations) == 0 {
annotations = nil
}
r.SetAnnotations(annotations)
}
// UpdateResourceOptions updates the generator options for each resource in the
// given ResMap based on plugin provided annotations.
func UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {

View File

@@ -6,9 +6,9 @@ package target
import (
"encoding/json"
"fmt"
"path/filepath"
"strings"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/builtins"
"sigs.k8s.io/kustomize/api/ifc"
@@ -19,6 +19,7 @@ import (
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/yaml"
)
@@ -334,20 +335,15 @@ func (kt *KustTarget) accumulateResources(
for _, path := range paths {
// try loading resource as file then as base (directory or git repository)
if errF := kt.accumulateFile(ra, path); errF != nil {
ldr, errL := kt.ldr.New(path)
if errL != nil {
return nil, multierror.Append(
fmt.Errorf("accumulateFile error: %q", errF),
fmt.Errorf("loader.New error: %q", errL),
)
ldr, err := kt.ldr.New(path)
if err != nil {
return nil, errors.Wrapf(
err, "accumulation err='%s'", errF.Error())
}
var errD error
ra, errD = kt.accumulateDirectory(ra, ldr, false)
if errD != nil {
return nil, multierror.Append(
fmt.Errorf("accumulateFile error: %q", errF),
fmt.Errorf("accumulateDirector error: %q", errD),
)
ra, err = kt.accumulateDirectory(ra, ldr, false)
if err != nil {
return nil, errors.Wrapf(
err, "accumulation err='%s'", errF.Error())
}
}
}
@@ -382,6 +378,18 @@ func (kt *KustTarget) accumulateDirectory(
return nil, errors.Wrapf(
err, "couldn't make target for path '%s'", ldr.Root())
}
var bytes []byte
path := ldr.Root()
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
bytes, err = ldr.Load(filepath.Join(path, openApiPath))
if err != nil {
return nil, err
}
}
err = openapi.SetSchema(subKt.Kustomization().OpenAPI, bytes, false)
if err != nil {
return nil, err
}
if isComponent && subKt.kustomization.Kind != types.ComponentKind {
return nil, fmt.Errorf(
"expected kind '%s' for path '%s' but got '%s'", types.ComponentKind, ldr.Root(), subKt.kustomization.Kind)

View File

@@ -244,6 +244,7 @@ metadata:
t.Fatalf("unexpected error %v", err)
}
}
expected.RemoveBuildAnnotations()
expYaml, err := expected.AsYaml()
assert.NoError(t, err)
@@ -251,6 +252,7 @@ metadata:
assert.NoError(t, kt.Load())
actual, err := kt.MakeCustomizedResMap()
assert.NoError(t, err)
actual.RemoveBuildAnnotations()
actYaml, err := actual.AsYaml()
assert.NoError(t, err)
assert.Equal(t, expYaml, actYaml)

View File

@@ -42,6 +42,14 @@ func (o *multiTransformer) transform(m resmap.ResMap) error {
return err
}
}
for _, r := range m.Resources() {
if r.IsEmpty() {
err := m.Remove(r.CurId())
if err != nil {
return err
}
}
}
return nil
}

View File

@@ -1,25 +0,0 @@
// +build tools
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// This file exists to automatically trigger installs
// of the given tools, and is the official 'unofficial'
// way to declare a dependence on a Go binary until
// some better technique comes along.
package tools
import (
// for code generation
_ "golang.org/x/tools/cmd/stringer"
// for lint checks
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
// REMOVED pluginator from this process, and leaving
// this note to discourage its reintroduction,
// because pluginator depends on the api, forcing
// major version increments in pluginator with each
// api release to allow this trick to work and not
// introduce cycles.
// _ "sigs.k8s.io/kustomize/cmd/pluginator/v2"
)

View File

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

View File

@@ -0,0 +1,22 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils
import "strings"
// PathSplitter splits a slash delimited string, permitting escaped slashes.
func PathSplitter(path string) []string {
ps := strings.Split(path, "/")
var res []string
res = append(res, ps[0])
for i := 1; i < len(ps); i++ {
last := len(res) - 1
if strings.HasSuffix(res[last], `\`) {
res[last] = strings.TrimSuffix(res[last], `\`) + "/" + ps[i]
} else {
res = append(res, ps[i])
}
}
return res
}

View File

@@ -0,0 +1,49 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package utils_test
import (
"testing"
"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/api/internal/utils"
)
func TestPathSplitter(t *testing.T) {
for _, tc := range []struct {
exp []string
path string
}{
{
path: "",
exp: []string{""},
},
{
path: "s",
exp: []string{"s"},
},
{
path: "a/b/c",
exp: []string{"a", "b", "c"},
},
{
path: `a/b[]/c`,
exp: []string{"a", "b[]", "c"},
},
{
path: `a/b\/c/d\/e/f`,
exp: []string{"a", "b/c", "d/e", "f"},
},
{
// The actual reason for this.
path: `metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret`,
exp: []string{
"metadata",
"annotations",
"nginx.ingress.kubernetes.io/auth-secret"},
},
} {
assert.Equal(t, tc.exp, PathSplitter(tc.path))
}
}

View File

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

View File

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

View File

@@ -58,7 +58,7 @@ func (k *WNodeFactory) SliceFromBytes(bs []byte) ([]ifc.Kunstructured, error) {
// shouldDropObject returns true if the resource should not be accumulated.
func shouldDropObject(m yaml.ResourceMeta) bool {
_, y := m.ObjectMeta.Annotations[konfig.IgnoredByKustomizeResourceAnnotation]
_, y := m.ObjectMeta.Annotations[konfig.IgnoredByKustomizeAnnotation]
return y
}

View File

@@ -6,6 +6,8 @@ package wrappy
import (
"fmt"
"log"
"regexp"
"strconv"
"strings"
"sigs.k8s.io/kustomize/api/ifc"
@@ -43,6 +45,10 @@ func FromRNode(node *yaml.RNode) *WNode {
return &WNode{node: node}
}
func (wn *WNode) AsRNode() *yaml.RNode {
return wn.node
}
func (wn *WNode) demandMetaData(label string) yaml.ResourceMeta {
meta, err := wn.node.GetMeta()
if err != nil {
@@ -62,9 +68,35 @@ func (wn *WNode) GetAnnotations() map[string]string {
return wn.demandMetaData("GetAnnotations").Annotations
}
// convertSliceIndex traverses the items in `fields` and find
// if there is a slice index in the item and change it to a
// valid Lookup field path. For example, 'ports[0]' will be
// converted to 'ports' and '0'.
func convertSliceIndex(fields []string) []string {
var res []string
for _, s := range fields {
if !strings.HasSuffix(s, "]") {
res = append(res, s)
continue
}
re := regexp.MustCompile(`^(.*)\[(\d+)\]$`)
groups := re.FindStringSubmatch(s)
if len(groups) == 0 {
// no match, add to result
res = append(res, s)
continue
}
if groups[1] != "" {
res = append(res, groups[1])
}
res = append(res, groups[2])
}
return res
}
// GetFieldValue implements ifc.Kunstructured.
func (wn *WNode) GetFieldValue(path string) (interface{}, error) {
fields := strings.Split(path, ".")
fields := convertSliceIndex(strings.Split(path, "."))
rn, err := wn.node.Pipe(yaml.Lookup(fields...))
if err != nil {
return nil, err
@@ -91,14 +123,34 @@ func (wn *WNode) GetFieldValue(path string) (interface{}, error) {
// Return value as slice for SequenceNode kind
if yn.Kind == yaml.SequenceNode {
var result []interface{}
for _, node := range yn.Content {
result = append(result, node.Value)
if err := yn.Decode(&result); err != nil {
return nil, err
}
return result, nil
}
if yn.Kind != yaml.ScalarNode {
return nil, fmt.Errorf("expected ScalarNode, got Kind=%d", yn.Kind)
}
// Return value value directly for all other (ScalarNode) kinds
return yn.Value, nil
// TODO: When doing kustomize var replacement, which is likely a
// a primary use of this function and the reason it returns interface{}
// rather than string, we do conversion from Nodes to Go types and back
// to nodes. We should figure out how to do replacement using raw nodes,
// assuming we keep the var feature in kustomize.
// The other end of this is: refvar.go:updateNodeValue.
switch yn.Tag {
case yaml.NodeTagString:
return yn.Value, nil
case yaml.NodeTagInt:
return strconv.Atoi(yn.Value)
case yaml.NodeTagFloat:
return strconv.ParseFloat(yn.Value, 64)
case yaml.NodeTagBool:
return strconv.ParseBool(yn.Value)
default:
// Possibly this should be an error or log.
return yn.Value, nil
}
}
// GetGvk implements ifc.Kunstructured.
@@ -108,6 +160,26 @@ func (wn *WNode) GetGvk() resid.Gvk {
return resid.Gvk{Group: g, Version: v, Kind: meta.Kind}
}
// GetDataMap implements ifc.Kunstructured.
func (wn *WNode) GetDataMap() map[string]string {
return wn.node.GetDataMap()
}
// SetDataMap implements ifc.Kunstructured.
func (wn *WNode) SetDataMap(m map[string]string) {
wn.node.SetDataMap(m)
}
// GetBinaryDataMap implements ifc.Kunstructured.
func (wn *WNode) GetBinaryDataMap() map[string]string {
return wn.node.GetBinaryDataMap()
}
// SetBinaryDataMap implements ifc.Kunstructured.
func (wn *WNode) SetBinaryDataMap(m map[string]string) {
wn.node.SetBinaryDataMap(m)
}
// GetKind implements ifc.Kunstructured.
func (wn *WNode) GetKind() string {
return wn.demandMetaData("GetKind").Kind
@@ -149,12 +221,7 @@ func (wn *WNode) GetString(path string) (string, error) {
// Map implements ifc.Kunstructured.
func (wn *WNode) Map() map[string]interface{} {
var result map[string]interface{}
if err := wn.node.YNode().Decode(&result); err != nil {
// Log and die since interface doesn't allow error.
log.Fatalf("failed to decode ynode: %v", err)
}
return result
return wn.node.Map()
}
// MarshalJSON implements ifc.Kunstructured.
@@ -182,9 +249,7 @@ func (wn *WNode) SetAnnotations(annotations map[string]string) {
// SetGvk implements ifc.Kunstructured.
func (wn *WNode) SetGvk(gvk resid.Gvk) {
wn.setMapField(yaml.NewScalarRNode(gvk.Kind), yaml.KindField)
wn.setMapField(
yaml.NewScalarRNode(
fmt.Sprintf("%s/%s", gvk.Group, gvk.Version)), yaml.APIVersionField)
wn.setMapField(yaml.NewScalarRNode(gvk.ApiVersion()), yaml.APIVersionField)
}
// SetLabels implements ifc.Kunstructured.

View File

@@ -8,6 +8,7 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"sigs.k8s.io/kustomize/api/resid"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
@@ -32,6 +33,38 @@ const (
"area": "51",
"greeting": "Take me to your leader."
}
},
"spec": {
"template": {
"spec": {
"containers": [
{
"env": [
{
"name": "CM_FOO",
"valueFrom": {
"configMapKeyRef": {
"key": "somekey",
"name": "myCm"
}
}
},
{
"name": "SECRET_FOO",
"valueFrom": {
"secretKeyRef": {
"key": "someKey",
"name": "mySecret"
}
}
}
],
"image": "nginx:1.7.9",
"name": "nginx"
}
]
}
}
}
}
`
@@ -357,6 +390,51 @@ func TestGetFieldValueReturnsMap(t *testing.T) {
}
}
func TestGetFieldValueReturnsStuff(t *testing.T) {
wn := NewWNode()
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
t.Fatalf("unexpected unmarshaljson err: %v", err)
}
expected := []interface{}{
map[string]interface{}{
"env": []interface{}{
map[string]interface{}{
"name": "CM_FOO",
"valueFrom": map[string]interface{}{
"configMapKeyRef": map[string]interface{}{
"key": "somekey",
"name": "myCm",
},
},
},
map[string]interface{}{
"name": "SECRET_FOO",
"valueFrom": map[string]interface{}{
"secretKeyRef": map[string]interface{}{
"key": "someKey",
"name": "mySecret",
},
},
},
},
"image": string("nginx:1.7.9"),
"name": string("nginx"),
},
}
actual, err := wn.GetFieldValue("spec.template.spec.containers")
if err != nil {
t.Fatalf("error getting field value: %v", err)
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Fatalf("actual map does not deep equal expected map:\n%v", diff)
}
// Cannot go deeper yet.
_, err = wn.GetFieldValue("spec.template.spec.containers.env")
if err == nil {
t.Fatalf("expected err %v", err)
}
}
func TestGetFieldValueReturnsSlice(t *testing.T) {
bytes, err := yaml.Marshal(makeBigMap())
if err != nil {
@@ -377,6 +455,39 @@ func TestGetFieldValueReturnsSlice(t *testing.T) {
}
}
func TestGetFieldValueReturnsSliceOfMappings(t *testing.T) {
bytes, err := yaml.Marshal(makeBigMap())
if err != nil {
t.Fatalf("unexpected yaml.Marshal err: %v", err)
}
rNode, err := kyaml.Parse(string(bytes))
if err != nil {
t.Fatalf("unexpected yaml.Marshal err: %v", err)
}
wn := FromRNode(rNode)
expected := []interface{}{
map[string]interface{}{
"field1": "idx0foo",
"field2": "idx0bar",
},
map[string]interface{}{
"field1": "idx1foo",
"field2": "idx1bar",
},
map[string]interface{}{
"field1": "idx2foo",
"field2": "idx2bar",
},
}
actual, err := wn.GetFieldValue("those")
if err != nil {
t.Fatalf("error getting slice: %v", err)
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Fatalf("actual slice does not deep equal expected slice:\n%v", diff)
}
}
func TestGetFieldValueReturnsString(t *testing.T) {
wn := NewWNode()
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
@@ -447,6 +558,10 @@ func TestGetSlice(t *testing.T) {
}
}
func TestMapEmpty(t *testing.T) {
assert.Equal(t, 0, len(NewWNode().Map()))
}
func TestMap(t *testing.T) {
wn := NewWNode()
if err := wn.UnmarshalJSON([]byte(deploymentLittleJson)); err != nil {

View File

@@ -1,70 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// 2019 Nov 06 These notes are somewhat out of date, but left
// for historical purposes need to be updated (or simply removed
// with all the code). The kubectl integration plan described
// below is no longer the plan of record.
//
// --------
//
// It's possible that kustomize's features will be vendored into
// the kubernetes/kubernetes repo and made available to kubectl
// commands, while at the same time the kustomize program will
// continue to exist as an independent CLI. Vendoring snapshots
// would be taken just before a kubectl release.
//
// This creates a problem in that freestanding-kustomize depends on
// (for example):
//
// https://github.com/kubernetes/apimachinery/
// tree/master/pkg/util/yaml
//
// It vendors that package into
// sigs.k8s.io/kustomize/vendor/k8s.io/apimachinery/
//
// Whereas kubectl-kustomize would have to depend on the "staging"
// version of this code, located at
//
// https://github.com/kubernetes/kubernetes/
// blob/master/staging/src/k8s.io/apimachinery/pkg/util/yaml
//
// which is "vendored" via symlinks:
// k8s.io/kubernetes/vendor/k8s.io/apimachinery
// is a symlink to
// ../../staging/src/k8s.io/apimachinery
//
// The staging version is the canonical, under-development
// version of the code that kubectl depends on, whereas the packages
// at kubernetes/apimachinery are periodic snapshots of staging made
// for outside tools to depend on.
//
// apimachinery isn't the only package that poses this problem, just
// using it as a specific example.
//
// The kubectl binary cannot vendor in kustomize code that in
// turn vendors in the non-staging packages.
//
// One way to fix some of this would be to copy code - a hard fork.
// This has all the problems associated with a hard forking.
//
// Another way would be to break the kustomize repo into three:
//
// (1) kustomize - repo with the main() function,
// vendoring (2) and (3).
//
// (2) kustomize-libs - packages used by (1) with no
// apimachinery dependence.
//
// (3) kustomize-k8sdeps - A thin code layer that depends
// on (vendors) apimachinery to provide thin implementations
// to interfaces used in (2).
//
// The kubectl repo would then vendor from (2) only, and have
// a local implementation of (3). With that in mind, it's clear
// that (3) doesn't have to be a repo; the kustomize version of
// the thin layer can live directly in (1).
//
// This package is the code in (3), meant for kustomize.
package k8sdeps

View File

@@ -1,151 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kunstruct
import (
"bytes"
"fmt"
"io"
"strconv"
"strings"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/configmapandsecret"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types"
)
// KunstructuredFactoryImpl makes instances of UnstructAdapter.
// These instances in turn adapt structs in
// k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
// to implement ifc.Kunstructured.
// This factory is meant to implement ifc.KunstructuredFactory.
type KunstructuredFactoryImpl struct {
hasher *kustHash
}
var _ ifc.KunstructuredFactory = &KunstructuredFactoryImpl{}
// NewKunstructuredFactoryImpl returns a factory.
func NewKunstructuredFactoryImpl() ifc.KunstructuredFactory {
return &KunstructuredFactoryImpl{hasher: NewKustHash()}
}
// Hasher returns a kunstructured hasher
// input: kunstructured; output: string hash.
func (kf *KunstructuredFactoryImpl) Hasher() ifc.KunstructuredHasher {
return kf.hasher
}
// SliceFromBytes returns a slice of Kunstructured.
func (kf *KunstructuredFactoryImpl) SliceFromBytes(
in []byte) ([]ifc.Kunstructured, error) {
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
var result []ifc.Kunstructured
var err error
for err == nil || isEmptyYamlError(err) {
var out unstructured.Unstructured
err = decoder.Decode(&out)
if err == nil {
if len(out.Object) == 0 {
continue
}
err = kf.validate(out)
if err != nil {
return nil, err
}
if !kf.skipResource(out) {
result = append(result, &UnstructAdapter{Unstructured: out})
}
}
}
if err != io.EOF {
return nil, err
}
return result, nil
}
func isEmptyYamlError(err error) bool {
return strings.Contains(err.Error(), "is missing in 'null'")
}
// FromMap returns an instance of Kunstructured.
func (kf *KunstructuredFactoryImpl) FromMap(
m map[string]interface{}) ifc.Kunstructured {
return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}}
}
// MakeConfigMap returns an instance of Kunstructured for ConfigMap
func (kf *KunstructuredFactoryImpl) MakeConfigMap(
kvLdr ifc.KvLoader, args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(kvLdr).MakeConfigMap(args)
if err != nil {
return nil, err
}
return NewKunstructuredFromObject(o)
}
// MakeSecret returns an instance of Kunstructured for Secret
func (kf *KunstructuredFactoryImpl) MakeSecret(
kvLdr ifc.KvLoader, args *types.SecretArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(kvLdr).MakeSecret(args)
if err != nil {
return nil, err
}
return NewKunstructuredFromObject(o)
}
// validate validates that u has kind and name
// except for kind `List`, which doesn't require a name
func (kf *KunstructuredFactoryImpl) validate(u unstructured.Unstructured) error {
kind := u.GetKind()
if kind == "" {
return fmt.Errorf("missing kind in object %v", u)
} else if strings.HasSuffix(kind, "List") {
return nil
}
if u.GetName() == "" {
return fmt.Errorf("missing metadata.name in object %v", u)
}
if result, path := checkListItemNil(u.Object); result {
return fmt.Errorf("empty item at %v in object %v", path, u)
}
return nil
}
// skipResource returns true if the Resource should not be accumulated
func (kf *KunstructuredFactoryImpl) skipResource(u unstructured.Unstructured) bool {
an := u.GetAnnotations()
if an == nil {
// annotation unset
return false
}
// check if the Resource has opt-ed out of kustomize
_, found := an[konfig.IgnoredByKustomizeResourceAnnotation]
return found
}
func checkListItemNil(in interface{}) (bool, string) {
switch v := in.(type) {
case map[string]interface{}:
for key, s := range v {
if result, path := checkListItemNil(s); result {
return result, key + "/" + path
}
}
case []interface{}:
for index, s := range v {
if s == nil {
return true, ""
}
if result, path := checkListItemNil(s); result {
return result, "[" + strconv.Itoa(index) + "]/" + path
}
}
}
return false, ""
}

View File

@@ -1,237 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kunstruct
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/ifc"
)
func TestSliceFromBytes(t *testing.T) {
factory := NewKunstructuredFactoryImpl()
testConfigMap := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
},
})
testList := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "List",
"items": []interface{}{
testConfigMap.Map(),
testConfigMap.Map(),
},
})
testConfigMapList := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMapList",
"items": []interface{}{
testConfigMap.Map(),
testConfigMap.Map(),
},
})
tests := []struct {
name string
input []byte
expectedOut []ifc.Kunstructured
expectedErr bool
}{
{
name: "garbage",
input: []byte("garbageIn: garbageOut"),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
{
name: "noBytes",
input: []byte{},
expectedOut: []ifc.Kunstructured{},
expectedErr: false,
},
{
name: "goodJson",
input: []byte(`
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml1",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml2",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap},
expectedErr: false,
},
{
name: "localConfigYaml",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie-skip
annotations:
# this annotation causes the Resource to be ignored by kustomize
config.kubernetes.io/local-config: ""
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "garbageInOneOfTwoObjects",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
`),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
{
name: "emptyObjects",
input: []byte(`
---
#a comment
---
`),
expectedOut: []ifc.Kunstructured{},
expectedErr: false,
},
{
name: "Missing .metadata.name in object",
input: []byte(`
apiVersion: v1
kind: Namespace
metadata:
annotations:
foo: bar
`),
expectedOut: nil,
expectedErr: true,
},
{
name: "nil value in list",
input: []byte(`
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: kube100-site
labels:
app: web
testList:
- testA
-
`),
expectedOut: nil,
expectedErr: true,
},
{
name: "List",
input: []byte(`
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testList},
expectedErr: false,
},
{
name: "ConfigMapList",
input: []byte(`
apiVersion: v1
kind: ConfigMapList
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
- apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMapList},
expectedErr: false,
},
}
for _, test := range tests {
rs, err := factory.SliceFromBytes(test.input)
if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name)
}
if !test.expectedErr && err != nil {
t.Fatalf("%v: unexpected error: %s", test.name, err)
}
if len(rs) != len(test.expectedOut) {
t.Fatalf("%s: length mismatch %d != %d",
test.name, len(rs), len(test.expectedOut))
}
for i := range rs {
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
t.Fatalf("%s: Got: %v\nexpected:%v",
test.name, test.expectedOut[i], rs[i])
}
}
}
}

View File

@@ -1,27 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kunstruct
import (
"sigs.k8s.io/kustomize/api/hasher"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
)
// kustHash computes a hash of an unstructured object.
type kustHash struct{}
// NewKustHash returns a kustHash object
func NewKustHash() *kustHash {
return &kustHash{}
}
// Hash returns a hash of the given object
func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
node, err := filtersutil.GetRNode(m)
if err != nil {
return "", err
}
return hasher.HashRNode(node)
}

View File

@@ -1,34 +0,0 @@
package kunstruct
import (
"testing"
)
func TestHasher(t *testing.T) {
input := `
apiVersion: v1
kind: ConfigMap
metadata:
name: foo
data:
one: ""
binaryData:
two: ""
`
expect := "698h7c7t9m"
factory := NewKunstructuredFactoryImpl()
k, err := factory.SliceFromBytes([]byte(input))
if err != nil {
t.Fatal(err)
}
hasher := NewKustHash()
result, err := hasher.Hash(k[0])
if err != nil {
t.Fatal(err)
}
if result != expect {
t.Fatalf("expect %s but got %s", expect, result)
}
}

View File

@@ -1,95 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
import (
"fmt"
"strconv"
"strings"
)
// A PathSection contains a list of nested fields, which may end with an
// indexable value. For instance, foo.bar resolves to a PathSection with 2
// fields and no index, while foo[0].bar resolves to two path sections, the
// first containing the field foo and the index 0, and the second containing
// the field bar, with no index. The latter PathSection references the bar
// field of the first item in the foo list
type PathSection struct {
fields []string
idx int
}
func newPathSection() PathSection {
return PathSection{idx: -1}
}
func appendNonEmpty(section *PathSection, field string) {
if len(field) != 0 {
section.fields = append(section.fields, field)
}
}
func parseFields(path string) (result []PathSection, err error) {
section := newPathSection()
if !strings.Contains(path, "[") {
section.fields = strings.Split(path, ".")
result = append(result, section)
return result, nil
}
start := 0
insideParentheses := false
for i, c := range path {
switch c {
case '.':
if !insideParentheses {
appendNonEmpty(&section, path[start:i])
start = i + 1
}
case '[':
if !insideParentheses {
appendNonEmpty(&section, path[start:i])
start = i + 1
insideParentheses = true
} else {
return nil, fmt.Errorf("nested parentheses are not allowed: %s", path)
}
case ']':
if insideParentheses {
// Assign this index to the current
// PathSection, save it to the result, then begin
// a new PathSection
tmpIdx, err := strconv.Atoi(path[start:i])
if err == nil {
// We have detected an integer so an array.
section.idx = tmpIdx
} else {
// We have detected the downwardapi syntax
appendNonEmpty(&section, path[start:i])
}
result = append(result, section)
section = newPathSection()
start = i + 1
insideParentheses = false
} else {
return nil, fmt.Errorf("invalid field path %s", path)
}
}
}
if start < len(path)-1 {
appendNonEmpty(&section, path[start:])
result = append(result, section)
}
for _, section := range result {
for i, f := range section.fields {
if strings.HasPrefix(f, "\"") || strings.HasPrefix(f, "'") {
section.fields[i] = strings.Trim(f, "\"'")
}
}
}
return result, nil
}

View File

@@ -1,152 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kunstruct
import (
"reflect"
"testing"
)
type PathSectionSlice []PathSection
func buildPath(idx int, fields ...string) PathSectionSlice {
return PathSectionSlice{PathSection{fields: fields, idx: idx}}
}
func (a PathSectionSlice) addSection(idx int, fields ...string) PathSectionSlice {
return append(a, PathSection{fields: fields, idx: idx})
}
func TestParseField(t *testing.T) {
tests := []struct {
name string
pathToField string
expectedValue []PathSection
errorExpected bool
errorMsg string
}{
{
name: "oneField",
pathToField: "Kind",
expectedValue: buildPath(-1, "Kind"),
errorExpected: false,
},
{
name: "twoFields",
pathToField: "metadata.name",
expectedValue: buildPath(-1, "metadata", "name"),
errorExpected: false,
},
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: buildPath(-1, "spec", "ports", "port"),
errorExpected: false,
},
{
name: "empty",
pathToField: "",
expectedValue: buildPath(-1, ""),
errorExpected: false,
},
{
name: "validStringIndex",
pathToField: "that[1]",
expectedValue: buildPath(1, "that"),
errorExpected: false,
},
{
name: "sliceInSlice",
pathToField: "that[1][0]",
expectedValue: buildPath(1, "that").addSection(0),
errorExpected: false,
},
{
name: "validStructSubField",
pathToField: "those[1].field2",
expectedValue: buildPath(1, "those").addSection(-1, "field2"),
errorExpected: false,
},
{
name: "validStructSubFieldIndex",
pathToField: "these[1].field2[0]",
expectedValue: buildPath(1, "these").addSection(0, "field2"),
errorExpected: false,
},
{
name: "validStructSubFieldIndexSubfield",
pathToField: "complextree[1].field2[1].stringsubfield",
expectedValue: buildPath(1, "complextree").addSection(1, "field2").addSection(-1, "stringsubfield"),
errorExpected: false,
},
{
name: "validStructDownwardAPI",
pathToField: `metadata.labels["app.kubernetes.io/component"]`,
expectedValue: buildPath(-1, "metadata", "labels", "app.kubernetes.io/component"),
errorExpected: false,
},
{
name: "invalidIndexInIndex",
pathToField: "complextree[1[0]]",
errorExpected: true,
errorMsg: "nested parentheses are not allowed: complextree[1[0]]",
},
{
name: "invalidClosingBrackets",
pathToField: "complextree[1]]",
errorExpected: true,
errorMsg: "invalid field path complextree[1]]",
},
{
name: "validFieldsWithQuotes",
pathToField: "'complextree'[1].field2[1].'stringsubfield'",
expectedValue: buildPath(1, "complextree").addSection(1, "field2").addSection(-1, "stringsubfield"),
errorExpected: false,
},
}
for _, test := range tests {
s, err := parseFields(test.pathToField)
if test.errorExpected {
compareExpectedParserError(t, test.name, test.pathToField, err, test.errorMsg)
continue
}
if err != nil {
unExpectedParserError(t, test.name, test.pathToField, err)
}
compareParserValues(t, test.name, test.pathToField, test.expectedValue, s)
}
}
// unExpectedError function handles unexpected error
func unExpectedParserError(t *testing.T, name string, pathToField string, err error) {
t.Fatalf("%q; path %q - unexpected error %v", name, pathToField, err)
}
// compareExpectedError compares the expectedError and the actualError return by parseFields
func compareExpectedParserError(t *testing.T, name string, pathToField string, err error, errorMsg string) {
if err == nil {
t.Fatalf("%q; path %q - should return error, but no error returned",
name, pathToField)
}
if errorMsg != err.Error() {
t.Fatalf("%q; path %q - expected error: \"%s\", got error: \"%v\"",
name, pathToField, errorMsg, err.Error())
}
}
// compareValues compares the expectedValue and actualValue returned by parseFields
func compareParserValues(t *testing.T, name string, pathToField string, expectedValue PathSectionSlice, actualValue []PathSection) {
t.Helper()
if len(expectedValue) != len(actualValue) {
t.Fatalf("%q; Path: %s Got: %v Expected: %v", name, pathToField, actualValue, expectedValue)
}
for idx, expected := range expectedValue {
if !reflect.DeepEqual(expected, actualValue[idx]) {
t.Fatalf("%q; Path: %s idx: %v Fields Got: %v Expected: %v", name, pathToField, idx, actualValue[idx], expected)
}
}
}

View File

@@ -1,350 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
import (
"encoding/json"
"fmt"
jsonpatch "github.com/evanphx/json-patch"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/resid"
)
var _ ifc.Kunstructured = &UnstructAdapter{}
// UnstructAdapter wraps unstructured.Unstructured from
// https://github.com/kubernetes/apimachinery/blob/master/
// pkg/apis/meta/v1/unstructured/unstructured.go
// to isolate dependence on apimachinery.
type UnstructAdapter struct {
unstructured.Unstructured
}
// NewKunstructuredFromObject returns a new instance of Kunstructured.
func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
// Convert obj to a byte stream, then convert that to JSON (Unstructured).
marshaled, err := json.Marshal(obj)
if err != nil {
return &UnstructAdapter{}, err
}
var u unstructured.Unstructured
err = u.UnmarshalJSON(marshaled)
// creationTimestamp always 'null', remove it
u.SetCreationTimestamp(metav1.Time{})
return &UnstructAdapter{Unstructured: u}, err
}
// GetGvk returns the Gvk name of the object.
func (fs *UnstructAdapter) GetGvk() resid.Gvk {
x := fs.GroupVersionKind()
return resid.Gvk{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}
// SetGvk set the Gvk of the object to the input Gvk
func (fs *UnstructAdapter) SetGvk(g resid.Gvk) {
fs.SetGroupVersionKind(toSchemaGvk(g))
}
// Copy provides a copy behind an interface.
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
return &UnstructAdapter{*fs.DeepCopy()}
}
// Map returns the unstructured content map.
func (fs *UnstructAdapter) Map() map[string]interface{} {
return fs.Object
}
// SetMap overrides the unstructured content map.
func (fs *UnstructAdapter) SetMap(m map[string]interface{}) {
fs.Object = m
}
func (fs *UnstructAdapter) selectSubtree(path string) (map[string]interface{}, []string, bool, error) {
sections, err := parseFields(path)
if len(sections) == 0 || (err != nil) {
return nil, nil, false, err
}
content := fs.UnstructuredContent()
lastSectionIdx := len(sections)
// There are multiple sections to walk
for sectionIdx := 0; sectionIdx < lastSectionIdx; sectionIdx++ {
idx := sections[sectionIdx].idx
fields := sections[sectionIdx].fields
if idx == -1 {
// This section has no index
return content, fields, true, nil
}
// This section is terminated by an indexed field.
// Let's extract the slice first
indexedField, found, err := unstructured.NestedFieldNoCopy(content, fields...)
if !found || err != nil {
return content, fields, found, err
}
s, ok := indexedField.([]interface{})
if !ok {
return content, fields, false, fmt.Errorf("%v is of the type %T, expected []interface{}", indexedField, indexedField)
}
if idx >= len(s) {
return content, fields, false, fmt.Errorf("index %d is out of bounds", idx)
}
if sectionIdx == lastSectionIdx-1 {
// This is the last section. Let's build a fake map
// to let the rest of the field extraction to work.
idxstring := fmt.Sprintf("[%v]", idx)
newContent := map[string]interface{}{idxstring: s[idx]}
newFields := []string{idxstring}
return newContent, newFields, true, nil
}
newContent, ok := s[idx].(map[string]interface{})
if !ok {
// Only map are supported here
return content, fields, false,
fmt.Errorf("%#v is expected to be of type map[string]interface{}", s[idx])
}
content = newContent
}
// It seems to be an invalid path
return nil, []string{}, false, nil
}
// GetFieldValue returns the value at the given fieldpath.
func (fs *UnstructAdapter) GetFieldValue(path string) (interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedFieldNoCopy(
content, fields...)
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
}
// GetString returns value at the given fieldpath.
func (fs *UnstructAdapter) GetString(path string) (string, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return "", NoFieldError{Field: path}
}
s, found, err := unstructured.NestedString(
content, fields...)
if found || err != nil {
return s, err
}
return "", NoFieldError{Field: path}
}
// GetStringSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringSlice(path string) ([]string, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return []string{}, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedStringSlice(
content, fields...)
if found || err != nil {
return s, err
}
return []string{}, NoFieldError{Field: path}
}
// GetBool returns value at the given fieldpath.
func (fs *UnstructAdapter) GetBool(path string) (bool, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return false, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedBool(
content, fields...)
if found || err != nil {
return s, err
}
return false, NoFieldError{Field: path}
}
// GetFloat64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetFloat64(path string) (float64, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return 0, err
}
s, found, err := unstructured.NestedFloat64(
content, fields...)
if found || err != nil {
return s, err
}
return 0, NoFieldError{Field: path}
}
// GetInt64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetInt64(path string) (int64, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return 0, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedInt64(
content, fields...)
if found || err != nil {
return s, err
}
return 0, NoFieldError{Field: path}
}
// GetSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetSlice(path string) ([]interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedSlice(
content, fields...)
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
}
// GetStringMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringMap(path string) (map[string]string, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedStringMap(
content, fields...)
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
}
// GetMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
content, fields, found, err := fs.selectSubtree(path)
if !found || err != nil {
return nil, NoFieldError{Field: path}
}
s, found, err := unstructured.NestedMap(
content, fields...)
if found || err != nil {
return s, err
}
return nil, NoFieldError{Field: path}
}
func (fs *UnstructAdapter) MatchesLabelSelector(selector string) (bool, error) {
s, err := labels.Parse(selector)
if err != nil {
return false, err
}
return s.Matches(labels.Set(fs.GetLabels())), nil
}
func (fs *UnstructAdapter) MatchesAnnotationSelector(selector string) (bool, error) {
s, err := labels.Parse(selector)
if err != nil {
return false, err
}
return s.Matches(labels.Set(fs.GetAnnotations())), nil
}
func (fs *UnstructAdapter) Patch(patch ifc.Kunstructured) error {
versionedObj, err := scheme.Scheme.New(
toSchemaGvk(patch.GetGvk()))
merged := map[string]interface{}{}
saveName := fs.GetName()
switch {
case runtime.IsNotRegisteredError(err):
baseBytes, err := json.Marshal(fs.Map())
if err != nil {
return err
}
patchBytes, err := json.Marshal(patch.Map())
if err != nil {
return err
}
mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
if err != nil {
return err
}
err = json.Unmarshal(mergedBytes, &merged)
if err != nil {
return err
}
case err != nil:
return err
default:
// Use Strategic-Merge-Patch to handle types w/ schema
// TODO: Change this to use the new Merge package.
// Store the name of the target object, because this name may have been munged.
// Apply this name to the patched object.
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
if err != nil {
return err
}
merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
fs.Map(),
patch.Map(),
lookupPatchMeta)
if err != nil {
return err
}
}
fs.SetMap(merged)
if len(fs.Map()) != 0 {
// if the patch deletes the object
// don't reset the name
fs.SetName(saveName)
}
return nil
}
// toSchemaGvk converts to a schema.GroupVersionKind.
func toSchemaGvk(x resid.Gvk) schema.GroupVersionKind {
return schema.GroupVersionKind{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}
// NoFieldError is returned when a field is expected, but missing.
type NoFieldError struct {
Field string
}
func (e NoFieldError) Error() string {
return fmt.Sprintf("no field named '%s'", e.Field)
}

View File

@@ -1,559 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kunstruct
import (
"reflect"
"testing"
)
var kunstructured = NewKunstructuredFactoryImpl().FromMap(map[string]interface{}{
"Kind": "Service",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "application-name",
},
"name": "service-name",
},
"spec": map[string]interface{}{
"ports": map[string]interface{}{
"port": int64(80),
},
},
"this": map[string]interface{}{
"is": map[string]interface{}{
"aNumber": int64(1000),
"aFloat": float64(1.001),
"aNilValue": nil,
"aBool": true,
"anEmptyMap": map[string]interface{}{},
"anEmptySlice": []interface{}{},
"unrecognizable": testing.InternalExample{
Name: "fooBar",
},
},
},
"that": []interface{}{
"idx0",
"idx1",
"idx2",
"idx3",
},
"those": []interface{}{
map[string]interface{}{
"field1": "idx0foo",
"field2": "idx0bar",
},
map[string]interface{}{
"field1": "idx1foo",
"field2": "idx1bar",
},
map[string]interface{}{
"field1": "idx2foo",
"field2": "idx2bar",
},
},
"these": []interface{}{
map[string]interface{}{
"field1": []interface{}{"idx010", "idx011"},
"field2": []interface{}{"idx020", "idx021"},
},
map[string]interface{}{
"field1": []interface{}{"idx110", "idx111"},
"field2": []interface{}{"idx120", "idx121"},
},
map[string]interface{}{
"field1": []interface{}{"idx210", "idx211"},
"field2": []interface{}{"idx220", "idx221"},
},
},
"complextree": []interface{}{
map[string]interface{}{
"field1": []interface{}{
map[string]interface{}{
"stringsubfield": "idx1010",
"intsubfield": int64(1010),
"floatsubfield": float64(1.010),
"boolfield": true,
},
map[string]interface{}{
"stringsubfield": "idx1011",
"intsubfield": int64(1011),
"floatsubfield": float64(1.011),
"boolfield": false,
},
},
"field2": []interface{}{
map[string]interface{}{
"stringsubfield": "idx1020",
"intsubfield": int64(1020),
"floatsubfield": float64(1.020),
"boolfield": true,
},
map[string]interface{}{
"stringsubfield": "idx1021",
"intsubfield": int64(1021),
"floatsubfield": float64(1.021),
"boolfield": false,
},
},
},
map[string]interface{}{
"field1": []interface{}{
map[string]interface{}{
"stringsubfield": "idx1110",
"intsubfield": int64(1110),
"floatsubfield": float64(1.110),
"boolfield": true,
},
map[string]interface{}{
"stringsubfield": "idx1111",
"intsubfield": int64(1111),
"floatsubfield": float64(1.111),
"boolfield": false,
},
},
"field2": []interface{}{
map[string]interface{}{
"stringsubfield": "idx1120",
"intsubfield": int64(1120),
"floatsubfield": float64(1.1120),
"boolfield": true,
},
map[string]interface{}{
"stringsubfield": "idx1121",
"intsubfield": int64(1121),
"floatsubfield": float64(1.1121),
"boolfield": false,
},
},
},
},
})
func TestGetFieldValue(t *testing.T) {
tests := []struct {
name string
pathToField string
expectedValue interface{}
errorExpected bool
errorMsg string
}{
{
name: "oneField",
pathToField: "Kind",
expectedValue: "Service",
errorExpected: false,
},
{
name: "twoFields",
pathToField: "metadata.name",
expectedValue: "service-name",
errorExpected: false,
},
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: int64(80),
errorExpected: false,
},
{
name: "empty",
pathToField: "",
errorExpected: true,
errorMsg: "no field named ''",
},
{
name: "emptyDotEmpty",
pathToField: ".",
errorExpected: true,
errorMsg: "no field named '.'",
},
{
name: "twoFieldsOneMissing",
pathToField: "metadata.banana",
errorExpected: true,
errorMsg: "no field named 'metadata.banana'",
},
{
name: "deeperMissingField",
pathToField: "this.is.aDeep.field.that.does.not.exist",
errorExpected: true,
errorMsg: "no field named 'this.is.aDeep.field.that.does.not.exist'",
},
{
name: "emptyMap",
pathToField: "this.is.anEmptyMap",
errorExpected: false,
expectedValue: map[string]interface{}{},
},
{
name: "emptySlice",
pathToField: "this.is.anEmptySlice",
errorExpected: false,
expectedValue: []interface{}{},
},
{
name: "numberAsValue",
pathToField: "this.is.aNumber",
errorExpected: false,
expectedValue: int64(1000),
},
{
name: "floatAsValue",
pathToField: "this.is.aFloat",
errorExpected: false,
expectedValue: float64(1.001),
},
{
name: "boolAsValue",
pathToField: "this.is.aBool",
errorExpected: false,
expectedValue: true,
},
{
name: "nilAsValue",
pathToField: "this.is.aNilValue",
errorExpected: false,
expectedValue: nil,
},
{
name: "unrecognizable",
pathToField: "this.is.unrecognizable.Name",
errorExpected: true,
errorMsg: ".this.is.unrecognizable.Name accessor error: {fooBar <nil> false} is of the type testing.InternalExample, expected map[string]interface{}",
},
{
name: "validStringIndex",
pathToField: "that[2]",
expectedValue: "idx2",
errorExpected: false,
},
{
name: "outOfBoundIndex",
pathToField: "that[99]",
errorMsg: "no field named 'that[99]'",
errorExpected: true,
},
{
name: "accessorError",
pathToField: "that[downwardapi]",
errorMsg: ".that.downwardapi accessor error: [idx0 idx1 idx2 idx3] is of the type []interface {}, expected map[string]interface{}",
errorExpected: true,
},
{
name: "unknownSlice",
pathToField: "unknown[0]",
errorMsg: "no field named 'unknown[0]'",
errorExpected: true,
},
{
name: "sliceInSlice",
pathToField: "that[2][0]",
errorExpected: true,
errorMsg: "no field named 'that[2][0]'",
},
{
name: "validStructIndex",
pathToField: "those[1]",
errorExpected: false,
expectedValue: map[string]interface{}{"field1": "idx1foo", "field2": "idx1bar"},
},
{
name: "validStructSubField",
pathToField: "those[1].field2",
errorExpected: false,
expectedValue: "idx1bar",
},
{
name: "validStructSubFieldIndex",
pathToField: "these[1].field2[1]",
errorExpected: false,
expectedValue: "idx121",
},
{
name: "validStructSubFieldOutOfBoundIndex",
pathToField: "these[1].field2[99]",
errorExpected: true,
errorMsg: "no field named 'these[1].field2[99]'",
},
{
name: "validStructSubFieldIndexSubfield",
pathToField: "complextree[1].field2[1].stringsubfield",
errorExpected: false,
expectedValue: "idx1121",
},
{
name: "validStructSubFieldIndexInvalidName",
pathToField: "complextree[1].field2[1].invalidsubfield",
errorExpected: true,
errorMsg: "no field named 'complextree[1].field2[1].invalidsubfield'",
},
{
name: "validDownwardAPILabels",
pathToField: `metadata.labels["app"]`,
errorExpected: false,
expectedValue: "application-name",
},
{
name: "validDownwardAPISpecs",
pathToField: `spec.ports['port']`,
errorExpected: false,
expectedValue: int64(80),
},
{
name: "validDownwardAPIThis",
pathToField: `this.is[aFloat]`,
errorExpected: false,
expectedValue: float64(1.001),
},
{
name: "downwardAPIInvalidLabel",
pathToField: `metadata.labels["theisnotanint"]`,
errorExpected: true,
errorMsg: `no field named 'metadata.labels["theisnotanint"]'`,
},
{
name: "downwardAPIInvalidLabel2",
pathToField: `invalidfield.labels["app"]`,
errorExpected: true,
errorMsg: `no field named 'invalidfield.labels["app"]'`,
},
{
name: "invalidIndexInIndex",
pathToField: "complextree[1[0]]",
errorExpected: true,
errorMsg: "no field named 'complextree[1[0]]'",
},
{
name: "invalidClosingBrackets",
pathToField: "complextree[1]]",
errorExpected: true,
errorMsg: "no field named 'complextree[1]]'",
},
{
name: "validFieldsWithQuotes",
pathToField: "'complextree'[1].field2[1].'stringsubfield'",
errorExpected: false,
expectedValue: "idx1121",
},
}
for _, test := range tests {
s, err := kunstructured.GetFieldValue(test.pathToField)
if test.errorExpected {
compareExpectedError(t, test.name, test.pathToField, err, test.errorMsg)
continue
}
if err != nil {
unExpectedError(t, test.name, test.pathToField, err)
}
compareValues(t, test.name, test.pathToField, test.expectedValue, s)
}
}
func TestGetString(t *testing.T) {
tests := []struct {
name string
pathToField string
expectedValue string
errorExpected bool
errorMsg string
}{
{
name: "oneField",
pathToField: "Kind",
expectedValue: "Service",
errorExpected: false,
},
{
name: "twoFields",
pathToField: "metadata.name",
expectedValue: "service-name",
errorExpected: false,
},
{
name: "emptyMap",
pathToField: "this.is.anEmptyMap",
errorExpected: true,
errorMsg: ".this.is.anEmptyMap accessor error: map[] is of the type map[string]interface {}, expected string",
},
{
name: "twoFieldsOneMissing",
pathToField: "metadata.banana",
errorExpected: true,
errorMsg: "no field named 'metadata.banana'",
},
{
name: "emptySlice",
pathToField: "this.is.anEmptySlice",
errorExpected: true,
errorMsg: ".this.is.anEmptySlice accessor error: [] is of the type []interface {}, expected string",
},
{
name: "numberAsValue",
pathToField: "this.is.aNumber",
errorExpected: true,
errorMsg: ".this.is.aNumber accessor error: 1000 is of the type int64, expected string",
},
{
name: "nilAsValue",
pathToField: "this.is.aNilValue",
errorExpected: true,
errorMsg: ".this.is.aNilValue accessor error: <nil> is of the type <nil>, expected string",
},
{
name: "validStringIndex",
pathToField: "that[2]",
expectedValue: "idx2",
errorExpected: false,
},
{
name: "validStructIndex",
pathToField: "those[1]",
errorExpected: true,
errorMsg: ".[1] accessor error: map[field1:idx1foo field2:idx1bar] is of the type map[string]interface {}, expected string",
},
{
name: "validStructSubField",
pathToField: "those[1].field2",
errorExpected: false,
expectedValue: "idx1bar",
},
{
name: "validStructSubFieldIndex",
pathToField: "these[1].field2[1]",
errorExpected: false,
expectedValue: "idx121",
},
{
name: "validStructSubFieldIndexSubfield",
pathToField: "complextree[1].field2[1].stringsubfield",
errorExpected: false,
expectedValue: "idx1121",
},
{
name: "invalidIndexInMap",
pathToField: "this.is[1]",
errorExpected: true,
errorMsg: "no field named 'this.is[1]'",
},
{
name: "anotherInvalidIndexInMap",
pathToField: "this.is[1].aString",
errorExpected: true,
errorMsg: "no field named 'this.is[1].aString'",
},
{
name: "validDownwardAPIField",
pathToField: `metadata.labels["app"]`,
errorExpected: false,
expectedValue: "application-name",
},
}
for _, test := range tests {
s, err := kunstructured.GetString(test.pathToField)
if test.errorExpected {
compareExpectedError(t, test.name, test.pathToField, err, test.errorMsg)
continue
}
if err != nil {
unExpectedError(t, test.name, test.pathToField, err)
}
compareValues(t, test.name, test.pathToField, test.expectedValue, s)
}
}
func TestGetSlice(t *testing.T) {
tests := []struct {
name string
pathToField string
errorExpected bool
errorMsg string
}{
{
name: "validSlice1",
pathToField: "that",
errorExpected: false,
},
{
name: "validSlice2",
pathToField: "those",
errorExpected: false,
},
{
name: "validSlice3",
pathToField: "these",
errorExpected: false,
},
{
name: "validSlice4",
pathToField: "complextree",
errorExpected: false,
},
{
name: "twoFieldsOneMissing",
pathToField: "metadata.banana",
errorExpected: true,
errorMsg: "no field named 'metadata.banana'",
},
{
name: "validStructSubFieldOutOfBoundIndex",
pathToField: "these[1].field2[99]",
errorExpected: true,
errorMsg: "no field named 'these[1].field2[99]'",
},
}
for _, test := range tests {
_, err := kunstructured.GetSlice(test.pathToField)
if test.errorExpected {
compareExpectedError(t, test.name, test.pathToField, err, test.errorMsg)
continue
}
if err != nil {
unExpectedError(t, test.name, test.pathToField, err)
}
}
}
// unExpectedError function handles unexpected error
func unExpectedError(t *testing.T, name string, pathToField string, err error) {
t.Fatalf("%q; path %q - unexpected error %v", name, pathToField, err)
}
// compareExpectedError compares the expectedError and the actualError return by GetFieldValue
func compareExpectedError(t *testing.T, name string, pathToField string, err error, errorMsg string) {
if err == nil {
t.Fatalf("%q; path %q - should return error, but no error returned",
name, pathToField)
}
if errorMsg != err.Error() {
t.Fatalf("%q; path %q - expected error: \"%s\", got error: \"%v\"",
name, pathToField, errorMsg, err.Error())
}
}
// compareValues compares the expectedValue and actualValue returned by GetFieldValue
func compareValues(t *testing.T, name string, pathToField string, expectedValue interface{}, actualValue interface{}) {
t.Helper()
switch typedV := expectedValue.(type) {
case nil, string, bool, float64, int, int64:
if expectedValue != actualValue {
t.Fatalf("%q; Got: %v Expected: %v", name, actualValue, expectedValue)
}
case map[string]interface{}:
if !reflect.DeepEqual(expectedValue, actualValue) {
t.Fatalf("%q; Got: %v Expected: %v", name, actualValue, expectedValue)
}
case []interface{}:
if !reflect.DeepEqual(expectedValue, actualValue) {
t.Fatalf("%q; Got: %v Expected: %v", name, actualValue, expectedValue)
}
default:
t.Logf("%T value at `%s`", typedV, pathToField)
}
}

View File

@@ -1,105 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package validator provides functions to validate labels, annotations,
// namespaces and configmap/secret keys using apimachinery functions.
package validator
import (
"errors"
"fmt"
"strings"
apivalidation "k8s.io/apimachinery/pkg/api/validation"
v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"sigs.k8s.io/kustomize/api/ifc"
)
// KustValidator validates Labels and annotations by apimachinery
type KustValidator struct{}
var _ ifc.Validator = (*KustValidator)(nil)
// NewKustValidator returns a KustValidator object
func NewKustValidator() *KustValidator {
return &KustValidator{}
}
func (v *KustValidator) ErrIfInvalidKey(k string) error {
if errs := validation.IsConfigMapKey(k); len(errs) != 0 {
return fmt.Errorf(
"%q is not a valid key name: %s",
k, strings.Join(errs, ";"))
}
return nil
}
func (v *KustValidator) IsEnvVarName(k string) error {
if errs := validation.IsEnvVarName(k); len(errs) != 0 {
return fmt.Errorf(
"%q is not a valid key name: %s",
k, strings.Join(errs, ";"))
}
return nil
}
// MakeAnnotationValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeAnnotationValidator() func(map[string]string) error {
return func(x map[string]string) error {
errs := apivalidation.ValidateAnnotations(x, field.NewPath("field"))
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// MakeAnnotationNameValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeAnnotationNameValidator() func([]string) error {
return func(x []string) error {
errs := field.ErrorList{}
fldPath := field.NewPath("field")
for _, k := range x {
for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) {
errs = append(errs, field.Invalid(fldPath, k, msg))
}
}
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// MakeLabelValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeLabelValidator() func(map[string]string) error {
return func(x map[string]string) error {
errs := v1validation.ValidateLabels(x, field.NewPath("field"))
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// MakeLabelNameValidator returns a ArrayValidatorFunc using apimachinery.
func (v *KustValidator) MakeLabelNameValidator() func([]string) error {
return func(x []string) error {
errs := field.ErrorList{}
fldPath := field.NewPath("field")
for _, k := range x {
errs = append(errs, v1validation.ValidateLabelName(k, fldPath)...)
}
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// ValidateNamespace validates a string is a valid namespace using apimachinery.
func (v *KustValidator) ValidateNamespace(s string) []string {
return validation.IsDNS1123Label(s)
}

View File

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

View File

@@ -3,6 +3,9 @@
package builtinpluginconsts
// TODO: rename 'fieldSpecs' to 'referrers' for clarity.
// This will, however, break anyone using a custom config.
const (
nameReferenceFieldSpecs = `
nameReference:
@@ -121,6 +124,12 @@ nameReference:
kind: CronJob
- path: spec/configSource/configMap
kind: Node
- path: rules/resourceNames
kind: Role
- path: rules/resourceNames
kind: ClusterRole
- path: metadata/annotations/nginx.ingress.kubernetes.io\/fastcgi-params-configmap
kind: Ingress
- kind: Secret
version: v1

View File

@@ -32,8 +32,7 @@ const (
// FlagEnableKyamlDefaultValue is the default value for the --enable_kyaml
// flag. This value is also used in unit tests. See provider.DepProvider.
//
// TODO(#3304): eliminate branching on this constant.
// Details: https://github.com/kubernetes-sigs/kustomize/issues/3304
// TODO(#3588): Delete this constant.
//
// All tests should pass for either true or false values
// of this constant, without having to check its value.
@@ -43,7 +42,7 @@ const (
// Historically, tests passed for enable_kyaml == false, i.e. using
// apimachinery libs. This doesn't mean the code was better, it just
// means regression tests preserved those outcomes.
FlagEnableKyamlDefaultValue = false
FlagEnableKyamlDefaultValue = true
// An environment variable to consult for kustomization
// configuration data. See:
@@ -56,8 +55,11 @@ const (
// A program name, for use in help, finding the XDG_CONFIG_DIR, etc.
ProgramName = "kustomize"
// ConfigAnnoDomain is configuration-related annotation namespace.
ConfigAnnoDomain = "config.kubernetes.io"
// If a resource has this annotation, kustomize will drop it.
IgnoredByKustomizeResourceAnnotation = "config.kubernetes.io/local-config"
IgnoredByKustomizeAnnotation = ConfigAnnoDomain + "/local-config"
// Label key that indicates the resources are built from Kustomize
ManagedbyLabelKey = "app.kubernetes.io/managed-by"

View File

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

View File

@@ -15,19 +15,19 @@ import (
func TestTargetMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("/app/service.yaml", `
th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: aService
`)
th.WriteF("/app/deeper/service.yaml", `
th.WriteF("deeper/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: anotherService
`)
err := th.RunWithErr("/app", th.MakeDefaultOptions())
err := th.RunWithErr(".", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
@@ -39,27 +39,27 @@ metadata:
func TestTargetMustHaveOnlyOneKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
for _, n := range konfig.RecognizedKustomizationFileNames() {
th.WriteF(filepath.Join("/app", n), `
th.WriteF(filepath.Join(".", n), `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`)
}
err := th.RunWithErr("/app", th.MakeDefaultOptions())
err := th.RunWithErr(".", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
if !strings.Contains(err.Error(), "Found multiple kustomization files under: /app") {
if !strings.Contains(err.Error(), "Found multiple kustomization files") {
t.Fatalf("unexpected error: %q", err)
}
}
func TestBaseMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
th.WriteK(".", `
resources:
- base
`)
th.WriteF("/app/base/service.yaml", `
th.WriteF("base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
@@ -70,7 +70,7 @@ spec:
ports:
- port: 7002
`)
err := th.RunWithErr("/app", th.MakeDefaultOptions())
err := th.RunWithErr(".", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
@@ -81,11 +81,11 @@ spec:
func TestResourceNotFound(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
th.WriteK(".", `
resources:
- deployment.yaml
`)
err := th.RunWithErr("/app", th.MakeDefaultOptions())
err := th.RunWithErr(".", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
@@ -93,3 +93,70 @@ resources:
t.Fatalf("unexpected error: %q", err)
}
}
func TestResourceHasAnchor(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- ingress.yaml
`)
th.WriteF("ingress.yaml", `
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog
spec:
tls:
- hosts:
- xyz.me
- www.xyz.me
secretName: cert-tls
rules:
- host: xyz.me
http: &xxx_rules
paths:
- path: /
pathType: Prefix
backend:
service:
name: service
port:
number: 80
- host: www.xyz.me
http: *xxx_rules
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog
spec:
rules:
- host: xyz.me
http:
paths:
- backend:
service:
name: service
port:
number: 80
path: /
pathType: Prefix
- host: www.xyz.me
http:
paths:
- backend:
service:
name: service
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- xyz.me
- www.xyz.me
secretName: cert-tls
`)
}

View File

@@ -10,7 +10,7 @@ import (
)
func writeMediumBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
th.WriteK("base", `
namePrefix: baseprefix-
commonLabels:
foo: bar
@@ -20,7 +20,7 @@ resources:
- deployment/deployment.yaml
- service/service.yaml
`)
th.WriteF("/app/base/service/service.yaml", `
th.WriteF("base/service/service.yaml", `
apiVersion: v1
kind: Service
metadata:
@@ -33,7 +33,7 @@ spec:
selector:
app: mungebot
`)
th.WriteF("/app/base/deployment/deployment.yaml", `
th.WriteF("base/deployment/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -61,7 +61,7 @@ spec:
func TestMediumBase(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeMediumBase(th)
m := th.Run("/app/base", th.MakeDefaultOptions())
m := th.Run("base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -115,7 +115,7 @@ spec:
func TestMediumOverlay(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeMediumBase(th)
th.WriteK("/app/overlay", `
th.WriteK("overlay", `
namePrefix: test-infra-
commonLabels:
app: mungebot
@@ -140,24 +140,24 @@ images:
- name: nginx
newTag: 1.8.0`)
th.WriteF("/app/overlay/configmap/db.env", `
th.WriteF("overlay/configmap/db.env", `
DB_USERNAME=admin
DB_PASSWORD=somepw
`)
th.WriteF("/app/overlay/configmap/units.ini", `
th.WriteF("overlay/configmap/units.ini", `
LENGTH=kilometer
ENERGY=electronvolt
`)
th.WriteF("/app/overlay/configmap/food.ini", `
th.WriteF("overlay/configmap/food.ini", `
FRUIT=banana
LEGUME=chickpea
`)
th.WriteF("/app/overlay/configmap/dummy.txt",
th.WriteF("overlay/configmap/dummy.txt",
`Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
`)
th.WriteF("/app/overlay/deployment/deployment.yaml", `
th.WriteF("overlay/deployment/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -190,7 +190,7 @@ spec:
name: app-env
name: app-env
`)
m := th.Run("/app/overlay", th.MakeDefaultOptions())
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -14,7 +14,7 @@ import (
func TestOrderPreserved(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
th.WriteK("base", `
namePrefix: b-
resources:
- namespace.yaml
@@ -22,50 +22,50 @@ resources:
- service.yaml
- deployment.yaml
`)
th.WriteF("/app/base/service.yaml", `
th.WriteF("base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: myService
`)
th.WriteF("/app/base/namespace.yaml", `
th.WriteF("base/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
name: myNs
`)
th.WriteF("/app/base/role.yaml", `
th.WriteF("base/role.yaml", `
apiVersion: v1
kind: Role
metadata:
name: myRole
`)
th.WriteF("/app/base/deployment.yaml", `
th.WriteF("base/deployment.yaml", `
apiVersion: v1
kind: Deployment
metadata:
name: myDep
`)
th.WriteK("/app/prod", `
th.WriteK("prod", `
namePrefix: p-
resources:
- ../base
- service.yaml
- namespace.yaml
`)
th.WriteF("/app/prod/service.yaml", `
th.WriteF("prod/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: myService2
`)
th.WriteF("/app/prod/namespace.yaml", `
th.WriteF("prod/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
name: myNs2
`)
m := th.Run("/app/prod", th.MakeDefaultOptions())
m := th.Run("prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Namespace
@@ -101,17 +101,17 @@ metadata:
func TestBaseInResourceList(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/prod", `
th.WriteK("prod", `
namePrefix: b-
resources:
- ../base
`)
th.WriteK("/app/base", `
th.WriteK("base", `
namePrefix: a-
resources:
- service.yaml
`)
th.WriteF("/app/base/service.yaml", `
th.WriteF("base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
@@ -120,7 +120,7 @@ spec:
selector:
backend: bungie
`)
m := th.Run("/app/prod", th.MakeDefaultOptions())
m := th.Run("prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
@@ -181,7 +181,7 @@ spec:
}
func writeSmallBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
th.WriteK("base", `
namePrefix: a-
commonLabels:
app: myApp
@@ -189,7 +189,7 @@ resources:
- deployment.yaml
- service.yaml
`)
th.WriteF("/app/base/service.yaml", `
th.WriteF("base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
@@ -200,7 +200,7 @@ spec:
ports:
- port: 7002
`)
th.WriteF("/app/base/deployment.yaml", `
th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -220,7 +220,7 @@ spec:
func TestSmallBase(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
m := th.Run("/app/base", th.MakeDefaultOptions())
m := th.Run("base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -260,7 +260,7 @@ spec:
func TestSmallOverlay(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
th.WriteK("overlay", `
namePrefix: b-
commonLabels:
env: prod
@@ -275,15 +275,15 @@ images:
newTag: 1.8.0
`)
th.WriteF("/app/overlay/configmap/app.env", `
th.WriteF("overlay/configmap/app.env", `
DB_USERNAME=admin
DB_PASSWORD=somepw
`)
th.WriteF("/app/overlay/configmap/app-init.ini", `
th.WriteF("overlay/configmap/app-init.ini", `
FOO=bar
BAR=baz
`)
th.WriteF("/app/overlay/deployment/deployment.yaml", `
th.WriteF("overlay/deployment/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -291,7 +291,7 @@ metadata:
spec:
replicas: 1000
`)
m := th.Run("/app/overlay", th.MakeDefaultOptions())
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -347,7 +347,7 @@ spec:
func TestSharedPatchDisAllowed(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
th.WriteK("overlay", `
commonLabels:
env: prod
resources:
@@ -355,7 +355,7 @@ resources:
patchesStrategicMerge:
- ../shared/deployment-patch.yaml
`)
th.WriteF("/app/shared/deployment-patch.yaml", `
th.WriteF("shared/deployment-patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -363,14 +363,14 @@ metadata:
spec:
replicas: 1000
`)
err := th.RunWithErr("/app/overlay", func() Options {
err := th.RunWithErr("overlay", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsRootOnly
return o
}())
if !strings.Contains(
err.Error(),
"security; file '/app/shared/deployment-patch.yaml' is not in or below '/app/overlay'") {
"security; file '/shared/deployment-patch.yaml' is not in or below '/overlay'") {
t.Fatalf("unexpected error: %s", err)
}
}
@@ -378,7 +378,7 @@ spec:
func TestSharedPatchAllowed(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
th.WriteK("overlay", `
commonLabels:
env: prod
resources:
@@ -386,7 +386,7 @@ resources:
patchesStrategicMerge:
- ../shared/deployment-patch.yaml
`)
th.WriteF("/app/shared/deployment-patch.yaml", `
th.WriteF("shared/deployment-patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -394,7 +394,7 @@ metadata:
spec:
replicas: 1000
`)
m := th.Run("/app/overlay", func() Options {
m := th.Run("overlay", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsNone
return o
@@ -444,7 +444,7 @@ spec:
func TestSmallOverlayJSONPatch(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
th.WriteK("overlay", `
resources:
- ../base
patchesJson6902:
@@ -455,12 +455,12 @@ patchesJson6902:
path: service-patch.yaml
`)
th.WriteF("/app/overlay/service-patch.yaml", `
th.WriteF("overlay/service-patch.yaml", `
- op: add
path: /spec/selector/backend
value: beagle
`)
m := th.Run("/app/overlay", th.MakeDefaultOptions())
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -41,37 +41,37 @@ import (
func TestBaseReuseNameConflict(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/component1/base", `
th.WriteK("component1/base", `
resources:
- ../../shared
namePrefix: component1-
`)
th.WriteK("/app/component1/overlay", `
th.WriteK("component1/overlay", `
resources:
- ../base
namePrefix: overlay-
`)
th.WriteK("/app/component2/base", `
th.WriteK("component2/base", `
resources:
- ../../shared
namePrefix: component2-
`)
th.WriteK("/app/component2/overlay", `
th.WriteK("component2/overlay", `
resources:
- ../base
namePrefix: overlay-
`)
th.WriteK("/app/shared", `
th.WriteK("shared", `
resources:
- resources.yaml
`)
th.WriteF("/app/shared/resources.yaml", `
th.WriteF("shared/resources.yaml", `
---
kind: PersistentVolumeClaim
apiVersion: v1
@@ -111,13 +111,13 @@ spec:
claimName: postgres
`)
th.WriteK("/app", `
th.WriteK(".", `
resources:
- component1/overlay
- component2/overlay
`)
m := th.Run("/app", th.MakeDefaultOptions())
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: PersistentVolumeClaim

102
api/krusty/basic_io_test.go Normal file
View File

@@ -0,0 +1,102 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestBasicIO_1(t *testing.T) {
th := kusttest_test.MakeHarness(t)
opts := th.MakeDefaultOptions()
if !opts.UseKyaml {
// This test won't pass under apimachinery, because in the bowels of
// that code (see GetAnnotations in v0.17.0 of
// k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go)
// an error returned from NestedStringMap is discarded, and an
// empty annotation map is silently returned, making this test fail
// The swallowed error arises from code like:
// var v interface{}
// v = true
// if str, ok := v.(string); ok {
// save the value in a map (doesn't happen)
// } else {
// return an error (that is then ignored by GetAnnotations)
// }
// The error happens when any annotation value can be interpreted as
// a boolean or number. Such annotations cannot be successfully applied
// to an object in a cluster unless they are quoted.
t.SkipNow()
}
th.WriteK(".", `
resources:
- service.yaml
`)
th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
annotations:
port: 8080
happy: true
color: green
name: demo
spec:
clusterIP: None
`)
m := th.Run(".", opts)
// The annotations are sorted by key, hence the order change.
// Quotes are added intentionally.
th.AssertActualEqualsExpected(
m, `
apiVersion: v1
kind: Service
metadata:
annotations:
color: green
happy: "true"
port: "8080"
name: demo
spec:
clusterIP: None
`)
}
func TestBasicIO_2(t *testing.T) {
th := kusttest_test.MakeHarness(t)
opts := th.MakeDefaultOptions()
th.WriteK(".", `
resources:
- service.yaml
`)
// All the annotation values are quoted in the input.
th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
annotations:
port: "8080"
happy: "true"
color: green
name: demo
spec:
clusterIP: None
`)
m := th.Run(".", opts)
// The annotations are sorted by key, hence the order change.
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
metadata:
annotations:
color: green
happy: "true"
port: "8080"
name: demo
spec:
clusterIP: None
`)
}

View File

@@ -32,13 +32,13 @@ func TestChartInflatorPlugin(t *testing.T) {
PrepExecPlugin("someteam.example.com", "v1", "ChartInflator")
defer th.Reset()
th.WriteK("/app", `
th.WriteK(".", `
generators:
- chartInflator.yaml
namePrefix: LOOOOOOOONG-
`)
th.WriteF("/app/chartInflator.yaml", `
th.WriteF("./chartInflator.yaml", `
apiVersion: someteam.example.com/v1
kind: ChartInflator
metadata:
@@ -46,7 +46,7 @@ metadata:
chartName: minecraft
`)
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
m := th.Run(".", th.MakeOptionsPluginsEnabled())
chartName := regexp.MustCompile("chart: minecraft-[0-9.]+")
th.AssertActualEqualsExpectedWithTweak(m,
func(x []byte) []byte {

View File

@@ -27,11 +27,11 @@ spec:
`
func writeStatefulSetBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
th.WriteK("base", `
resources:
- statefulset.yaml
`)
th.WriteF("/app/base/statefulset.yaml", `
th.WriteF("base/statefulset.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
@@ -56,15 +56,15 @@ spec:
}
func writeHTTPSOverlay(th kusttest_test.Harness) {
th.WriteK("/app/https", `
th.WriteK("https", `
resources:
- ../base
- https-svc.yaml
patchesStrategicMerge:
- sts-patch.yaml
`)
th.WriteF("/app/https/https-svc.yaml", httpsService)
th.WriteF("/app/https/sts-patch.yaml", `
th.WriteF("https/https-svc.yaml", httpsService)
th.WriteF("https/sts-patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
@@ -75,8 +75,8 @@ spec:
}
func writeHTTPSTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/https/service/https-svc.yaml", httpsService)
th.WriteF("/app/https/transformer/transformer.yaml", `
th.WriteF("https/service/https-svc.yaml", httpsService)
th.WriteF("https/transformer/transformer.yaml", `
apiVersion: builtin
kind: PatchTransformer
metadata:
@@ -97,11 +97,11 @@ patch: |-
}
func writeHTTPSTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/https/service", `
th.WriteK("https/service", `
resources:
- https-svc.yaml
`)
th.WriteK("/app/https/transformer", `
th.WriteK("https/transformer", `
resources:
- transformer.yaml
`)
@@ -109,7 +109,7 @@ resources:
}
func writeConfigFromEnvOverlay(th kusttest_test.Harness) {
th.WriteK("/app/config", `
th.WriteK("config", `
resources:
- ../base
configMapGenerator:
@@ -121,7 +121,7 @@ generatorOptions:
patchesStrategicMerge:
- sts-patch.yaml
`)
th.WriteF("/app/config/sts-patch.yaml", `
th.WriteF("config/sts-patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
@@ -138,7 +138,7 @@ spec:
}
func writeConfigFromEnvTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/config/map/generator.yaml", `
th.WriteF("config/map/generator.yaml", `
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
@@ -148,7 +148,7 @@ options:
literals:
- MY_ENV=foo
`)
th.WriteF("/app/config/transformer/transformer.yaml", `
th.WriteF("config/transformer/transformer.yaml", `
apiVersion: builtin
kind: PatchTransformer
metadata:
@@ -174,11 +174,11 @@ patch: |-
`)
}
func writeConfigFromEnvTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/config/map", `
th.WriteK("config/map", `
resources:
- generator.yaml
`)
th.WriteK("/app/config/transformer", `
th.WriteK("config/transformer", `
resources:
- transformer.yaml
`)
@@ -186,13 +186,13 @@ resources:
}
func writeTolerationsOverlay(th kusttest_test.Harness) {
th.WriteK("/app/tolerations", `
th.WriteK("tolerations", `
resources:
- ../base
patchesStrategicMerge:
- sts-patch.yaml
`)
th.WriteF("/app/tolerations/sts-patch.yaml", `
th.WriteF("tolerations/sts-patch.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
@@ -208,7 +208,7 @@ spec:
}
func writeTolerationsTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/tolerations/transformer.yaml", `
th.WriteF("tolerations/transformer.yaml", `
apiVersion: builtin
kind: PatchTransformer
metadata:
@@ -234,7 +234,7 @@ patch: |-
}
func writeTolerationsTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/tolerations", `
th.WriteK("tolerations", `
resources:
- transformer.yaml
`)
@@ -242,7 +242,7 @@ resources:
}
func writeStorageOverlay(th kusttest_test.Harness) {
th.WriteK("/app/storage", `
th.WriteK("storage", `
resources:
- ../base
patchesJson6902:
@@ -253,13 +253,13 @@ patchesJson6902:
name: my-sts
path: sts-patch.json
`)
th.WriteF("/app/storage/sts-patch.json", `
th.WriteF("storage/sts-patch.json", `
[{"op": "replace", "path": "/spec/volumeClaimTemplates/0/spec/storageClassName", "value": "my-sc"}]
`)
}
func writeStorageTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/storage/transformer.yaml", `
th.WriteF("storage/transformer.yaml", `
apiVersion: builtin
kind: PatchTransformer
metadata:
@@ -275,7 +275,7 @@ patch: |-
}
func writeStorageTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/storage", `
th.WriteK("storage", `
resources:
- transformer.yaml
`)
@@ -358,12 +358,12 @@ func TestComplexComposition_Dev_Failure(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingOverlays(th)
th.WriteK("/app/dev", `
th.WriteK("dev", `
resources:
- ../storage
- ../config
`)
err := th.RunWithErr("/app/dev", th.MakeDefaultOptions())
err := th.RunWithErr("dev", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected resource accumulation error")
}
@@ -410,7 +410,7 @@ func TestComplexComposition_Dev_SuccessWithRawTransformers(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformersRaw(th)
th.WriteK("/app/dev", `
th.WriteK("dev", `
resources:
- ../base
generators:
@@ -419,7 +419,7 @@ transformers:
- ../config/transformer/transformer.yaml
- ../storage/transformer.yaml
`)
m := th.Run("/app/dev", func() Options {
m := th.Run("dev", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsNone
return o
@@ -431,7 +431,7 @@ func TestComplexComposition_Dev_SuccessWithBaseTransformers(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformerBases(th)
th.WriteK("/app/dev", `
th.WriteK("dev", `
resources:
- ../base
generators:
@@ -440,7 +440,7 @@ transformers:
- ../config/transformer
- ../storage
`)
m := th.Run("/app/dev", th.MakeDefaultOptions())
m := th.Run("dev", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, devDesiredResult)
}
@@ -448,13 +448,13 @@ func TestComplexComposition_Prod_Failure(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingOverlays(th)
th.WriteK("/app/prod", `
th.WriteK("prod", `
resources:
- ../config
- ../tolerations
- ../https
`)
err := th.RunWithErr("/app/prod", th.MakeDefaultOptions())
err := th.RunWithErr("prod", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected resource accumulation error")
}
@@ -517,7 +517,7 @@ func TestComplexComposition_Prod_SuccessWithRawTransformers(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformersRaw(th)
th.WriteK("/app/prod", `
th.WriteK("prod", `
resources:
- ../base
- ../https/service/https-svc.yaml
@@ -528,7 +528,7 @@ transformers:
- ../https/transformer/transformer.yaml
- ../tolerations/transformer.yaml
`)
m := th.Run("/app/prod", func() Options {
m := th.Run("prod", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsNone
return o
@@ -540,7 +540,7 @@ func TestComplexComposition_Prod_SuccessWithBaseTransformers(t *testing.T) {
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformerBases(th)
th.WriteK("/app/prod", `
th.WriteK("prod", `
resources:
- ../base
- ../https/service
@@ -551,6 +551,6 @@ transformers:
- ../https/transformer
- ../tolerations
`)
m := th.Run("/app/prod", th.MakeDefaultOptions())
m := th.Run("prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, prodDesiredResult)
}

View File

@@ -33,16 +33,16 @@ func writeK(path string, content string) FileGen {
}
func writeTestBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
th.WriteK("base", `
resources:
- deploy.yaml
configMapGenerator:
- name: my-configmap
literals:
- testValue=1
- otherValue=10
- testValue=purple
- otherValue=green
`)
th.WriteF("/app/base/deploy.yaml", `
th.WriteF("base/deploy.yaml", `
apiVersion: v1
kind: Deployment
metadata:
@@ -53,7 +53,7 @@ spec:
}
func writeTestComponent(th kusttest_test.Harness) {
th.WriteC("/app/comp", `
th.WriteC("comp", `
namePrefix: comp-
replicas:
- name: storefront
@@ -64,10 +64,10 @@ configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- testValue=2
- compValue=5
- testValue=blue
- compValue=red
`)
th.WriteF("/app/comp/stub.yaml", `
th.WriteF("comp/stub.yaml", `
apiVersion: v1
kind: Deployment
metadata:
@@ -78,7 +78,7 @@ spec:
}
func writeOverlayProd(th kusttest_test.Harness) {
th.WriteK("/app/prod", `
th.WriteK("prod", `
resources:
- ../base
- db
@@ -90,7 +90,7 @@ components:
}
func writeDB(th kusttest_test.Harness) {
deployment("db", "/app/prod/db")(th)
deployment("db", "prod/db")(th)
}
func deployment(name string, path string) FileGen {
@@ -114,7 +114,7 @@ func TestComponent(t *testing.T) {
// resources that come before it in the resources list of the parent Kustomization.
"basic-component": {
input: []FileGen{writeTestBase, writeTestComponent, writeOverlayProd},
runPath: "/app/prod",
runPath: "prod",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -125,14 +125,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "10"
testValue: "2"
compValue: red
otherValue: green
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-kc6k2kmkh9
name: comp-my-configmap-97647ckcmg
---
apiVersion: v1
kind: Deployment
@@ -151,14 +149,14 @@ spec:
},
"multiple-components": {
input: []FileGen{writeTestBase, writeTestComponent, writeDB,
writeC("/app/additionalcomp", `
writeC("additionalcomp", `
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
writeK("/app/prod", `
writeK("prod", `
resources:
- ../base
- db
@@ -168,7 +166,7 @@ components:
- ../additionalcomp
`),
},
runPath: "/app/prod",
runPath: "prod",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -179,14 +177,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "9"
testValue: "2"
compValue: red
otherValue: orange
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-55249mf5kb
name: comp-my-configmap-g486mb229k
---
apiVersion: v1
kind: Deployment
@@ -205,16 +201,16 @@ spec:
},
"nested-components": {
input: []FileGen{writeTestBase, writeTestComponent, writeDB,
writeC("/app/additionalcomp", `
writeC("additionalcomp", `
components:
- ../comp
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
writeK("/app/prod", `
writeK("prod", `
resources:
- ../base
- db
@@ -223,7 +219,7 @@ components:
- ../additionalcomp
`),
},
runPath: "/app/prod",
runPath: "prod",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -234,14 +230,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "9"
testValue: "2"
compValue: red
otherValue: orange
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-55249mf5kb
name: comp-my-configmap-g486mb229k
---
apiVersion: v1
kind: Deployment
@@ -262,13 +256,13 @@ spec:
// without being affected by the component in another branch of the resource tree
"basic-component-with-repeated-base": {
input: []FileGen{writeTestBase, writeTestComponent, writeOverlayProd,
writeK("/app/repeated", `
writeK("repeated", `
resources:
- ../base
- ../prod
`),
},
runPath: "/app/repeated",
runPath: "repeated",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -279,11 +273,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "10"
testValue: "1"
otherValue: green
testValue: purple
kind: ConfigMap
metadata:
name: my-configmap-2g9c94mhb8
name: my-configmap-9cd648hm8f
---
apiVersion: v1
kind: Deployment
@@ -294,14 +288,12 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "10"
testValue: "2"
compValue: red
otherValue: green
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: comp-my-configmap-kc6k2kmkh9
name: comp-my-configmap-97647ckcmg
---
apiVersion: v1
kind: Deployment
@@ -320,18 +312,18 @@ spec:
},
"applying-component-directly-should-be-same-as-kustomization": {
input: []FileGen{writeTestBase, writeTestComponent,
writeC("/app/direct-component", `
writeC("direct-component", `
resources:
- ../base
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- compValue=5
- testValue=2
- compValue=red
- testValue=blue
`),
},
runPath: "/app/direct-component",
runPath: "direct-component",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -342,28 +334,26 @@ spec:
---
apiVersion: v1
data:
compValue: "5"
otherValue: "10"
testValue: "2"
compValue: red
otherValue: green
testValue: blue
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: my-configmap-kc6k2kmkh9
name: my-configmap-97647ckcmg
`,
},
"missing-optional-component-api-version": {
input: []FileGen{writeTestBase, writeOverlayProd,
writeF("/app/comp/"+konfig.DefaultKustomizationFileName(), `
writeF("comp/"+konfig.DefaultKustomizationFileName(), `
kind: Component
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
},
runPath: "/app/prod",
runPath: "prod",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -374,13 +364,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "9"
testValue: "1"
otherValue: orange
testValue: purple
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: my-configmap-5g7gh5mgt5
name: my-configmap-6hhdg8gkdg
---
apiVersion: v1
kind: Deployment
@@ -394,25 +382,25 @@ spec:
// accumulator when "comp-b" is accumulated. In practice we could use simple Kustomizations for this example.
"components-can-add-the-same-base-if-the-first-renames-resources": {
input: []FileGen{writeTestBase,
deployment("proxy", "/app/comp-a/proxy.yaml"),
writeC("/app/comp-a", `
deployment("proxy", "comp-a/proxy.yaml"),
writeC("comp-a", `
resources:
- ../base
nameSuffix: "-a"
`),
writeC("/app/comp-b", `
writeC("comp-b", `
resources:
- ../base
nameSuffix: "-b"
`),
writeK("/app/prod", `
writeK("prod", `
components:
- ../comp-a
- ../comp-b`),
},
runPath: "/app/prod",
runPath: "prod",
expectedOutput: `
apiVersion: v1
kind: Deployment
@@ -423,11 +411,11 @@ spec:
---
apiVersion: v1
data:
otherValue: "10"
testValue: "1"
otherValue: green
testValue: purple
kind: ConfigMap
metadata:
name: my-configmap-a-b-2g9c94mhb8
name: my-configmap-a-b-9cd648hm8f
---
apiVersion: v1
kind: Deployment
@@ -438,44 +426,44 @@ spec:
---
apiVersion: v1
data:
otherValue: "10"
testValue: "1"
otherValue: green
testValue: purple
kind: ConfigMap
metadata:
name: my-configmap-b-2g9c94mhb8
name: my-configmap-b-9cd648hm8f
`,
},
"multiple-bases-can-add-the-same-component-if-it-doesn-not-define-named-entities": {
input: []FileGen{
writeC("/app/comp", `
writeC("comp", `
namespace: prod
`),
writeK("/app/base-a", `
writeK("base-a", `
resources:
- proxy.yaml
components:
- ../comp
`),
deployment("proxy-a", "/app/base-a/proxy.yaml"),
writeK("/app/base-b", `
deployment("proxy-a", "base-a/proxy.yaml"),
writeK("base-b", `
resources:
- proxy.yaml
components:
- ../comp
`),
deployment("proxy-b", "/app/base-b/proxy.yaml"),
writeK("/app/prod", `
deployment("proxy-b", "base-b/proxy.yaml"),
writeK("prod", `
resources:
- proxy.yaml
- ../base-a
- ../base-b
`),
deployment("proxy-prod", "/app/prod/proxy.yaml"),
deployment("proxy-prod", "prod/proxy.yaml"),
},
runPath: "/app/prod",
runPath: "prod",
// Note that the namepsace has not been applied to proxy-prod because it was not in scope when the
// component was applied
expectedOutput: `
@@ -525,30 +513,30 @@ func TestComponentErrors(t *testing.T) {
}{
"components-cannot-be-added-to-resources": {
input: []FileGen{writeTestBase, writeTestComponent,
writeK("/app/compinres", `
writeK("compinres", `
resources:
- ../base
- ../comp
`),
},
runPath: "app/compinres",
expectedError: "expected kind != 'Component' for path '/app/comp'",
runPath: "compinres",
expectedError: "expected kind != 'Component' for path '/comp'",
},
"kustomizations-cannot-be-added-to-components": {
input: []FileGen{writeTestBase, writeTestComponent,
writeK("/app/kustincomponents", `
writeK("kustincomponents", `
components:
- ../base
- ../comp
`),
},
runPath: "/app/kustincomponents",
runPath: "kustincomponents",
expectedError: "accumulating components: accumulateDirectory: \"expected kind 'Component' for path " +
"'/app/base' but got 'Kustomization'",
"'/base' but got 'Kustomization'",
},
"files-cannot-be-added-to-components-list": {
input: []FileGen{writeTestBase,
writeF("/app/filesincomponents/stub.yaml", `
writeF("filesincomponents/stub.yaml", `
apiVersion: v1
kind: Deployment
metadata:
@@ -556,43 +544,43 @@ metadata:
spec:
replicas: 1
`),
writeK("/app/filesincomponents", `
writeK("filesincomponents", `
components:
- stub.yaml
- ../comp
`),
},
runPath: "/app/filesincomponents",
expectedError: "'/app/filesincomponents/stub.yaml' must be a directory to be a root",
runPath: "filesincomponents",
expectedError: "'/filesincomponents/stub.yaml' must be a directory to be a root",
},
"invalid-component-api-version": {
input: []FileGen{writeTestBase, writeOverlayProd,
writeF("/app/comp/"+konfig.DefaultKustomizationFileName(), `
writeF("comp/"+konfig.DefaultKustomizationFileName(), `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Component
configMapGenerator:
- name: my-configmap
behavior: merge
literals:
- otherValue=9
- otherValue=orange
`),
},
runPath: "/app/prod",
runPath: "prod",
expectedError: "apiVersion for Component should be kustomize.config.k8s.io/v1alpha1",
},
"components-cannot-add-the-same-resource": {
input: []FileGen{writeTestBase,
writeC("/app/comp-a", `
writeC("comp-a", `
resources:
- proxy.yaml
`),
deployment("proxy", "/app/comp-a/proxy.yaml"),
writeC("/app/comp-b", `
deployment("proxy", "comp-a/proxy.yaml"),
writeC("comp-b", `
resources:
- proxy.yaml
`),
deployment("proxy", "/app/comp-b/proxy.yaml"),
writeK("/app/prod", `
deployment("proxy", "comp-b/proxy.yaml"),
writeK("prod", `
resources:
- ../base
@@ -600,49 +588,49 @@ components:
- ../comp-a
- ../comp-b`),
},
runPath: "/app/prod",
runPath: "prod",
expectedError: "may not add resource with an already registered id: ~G_v1_Deployment|~X|proxy",
},
"components-cannot-add-the-same-base": {
input: []FileGen{writeTestBase,
deployment("proxy", "/app/comp-a/proxy.yaml"),
writeC("/app/comp-a", `
deployment("proxy", "comp-a/proxy.yaml"),
writeC("comp-a", `
resources:
- ../base
`),
writeC("/app/comp-b", `
writeC("comp-b", `
resources:
- ../base
`),
writeK("/app/prod", `
writeK("prod", `
components:
- ../comp-a
- ../comp-b`),
},
runPath: "/app/prod",
runPath: "prod",
expectedError: "may not add resource with an already registered id: ~G_v1_Deployment|~X|storefront",
},
"components-cannot-add-bases-containing-the-same-resource": {
input: []FileGen{writeTestBase,
writeC("/app/comp-a", `
writeC("comp-a", `
resources:
- ../base-a
`),
writeK("/app/base-a", `
writeK("base-a", `
resources:
- proxy.yaml
`),
deployment("proxy", "/app/base-a/proxy.yaml"),
writeC("/app/comp-b", `
deployment("proxy", "base-a/proxy.yaml"),
writeC("comp-b", `
resources:
- ../base-b
`),
writeK("/app/base-b", `
writeK("base-b", `
resources:
- proxy.yaml
`),
deployment("proxy", "/app/base-b/proxy.yaml"),
writeK("/app/prod", `
deployment("proxy", "base-b/proxy.yaml"),
writeK("prod", `
resources:
- ../base
@@ -650,7 +638,7 @@ components:
- ../comp-a
- ../comp-b`),
},
runPath: "/app/prod",
runPath: "prod",
expectedError: "may not add resource with an already registered id: ~G_v1_Deployment|~X|proxy",
},
}

View File

@@ -4,16 +4,126 @@
package krusty_test
import (
"fmt"
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// Numbers and booleans are quoted
func TestGeneratorIntVsStringNoMerge(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- service.yaml
configMapGenerator:
- name: bob
literals:
- fruit=Indian Gooseberry
- year=2020
- crisis=true
`)
th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: demo
spec:
clusterIP: None
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(
m, `
apiVersion: v1
kind: Service
metadata:
name: demo
spec:
clusterIP: None
---
apiVersion: v1
data:
crisis: "true"
fruit: Indian Gooseberry
year: "2020"
kind: ConfigMap
metadata:
name: bob-79t79mt227
`)
}
func TestGeneratorIntVsStringWithMerge(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
configMapGenerator:
- name: bob
literals:
- fruit=Indian Gooseberry
- year=2020
- crisis=true
`)
th.WriteK("overlay", `
resources:
- ../base
configMapGenerator:
- name: bob
behavior: merge
literals:
- month=12
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `apiVersion: v1
data:
crisis: "true"
fruit: Indian Gooseberry
month: "12"
year: "2020"
kind: ConfigMap
metadata:
name: bob-bk46gm59c6
`)
}
func TestGeneratorFromProperties(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
configMapGenerator:
- name: test-configmap
behavior: create
envs:
- properties
`)
th.WriteF("base/properties", `
VAR1=100
`)
th.WriteK("overlay", `
resources:
- ../base
configMapGenerator:
- name: test-configmap
behavior: "merge"
envs:
- properties
`)
th.WriteF("overlay/properties", `
VAR2=200
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `apiVersion: v1
data:
VAR1: "100"
VAR2: "200"
kind: ConfigMap
metadata:
name: test-configmap-hdghb5ddkg
`)
}
// Generate a Secret and a ConfigMap from the same data
// to compare the result.
func TestGeneratorBasics(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
th.WriteK(".", `
namePrefix: blah-
configMapGenerator:
- name: bob
@@ -44,25 +154,24 @@ secretGenerator:
- passphrase=phrase.dat
- forces.txt
`)
th.WriteF("/app/foo.env", `
th.WriteF("foo.env", `
MOUNTAIN=everest
OCEAN=pacific
`)
th.WriteF("/app/phrase.dat", `
th.WriteF("phrase.dat", `
Life is short.
But the years are long.
Not while the evil days come not.
`)
th.WriteF("/app/forces.txt", `
th.WriteF("forces.txt", `
gravitational
electromagnetic
strong nuclear
weak nuclear
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
opts := th.MakeDefaultOptions()
m := th.Run(".", opts)
expFmt := `apiVersion: v1
data:
MOUNTAIN: everest
OCEAN: pacific
@@ -95,21 +204,36 @@ apiVersion: v1
data:
MOUNTAIN: ZXZlcmVzdA==
OCEAN: cGFjaWZpYw==
forces.txt: CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbnVjbGVhcgo=
forces.txt: %s
fruit: YXBwbGU=
passphrase: CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aGUgZXZpbCBkYXlzIGNvbWUgbm90Lgo=
passphrase: %s
vegetable: YnJvY2NvbGk=
kind: Secret
metadata:
name: blah-bob-ftht6hfgmb
name: blah-bob-%s
type: Opaque
`)
`
th.AssertActualEqualsExpected(
m,
// TODO(#3304): DECISION - kyaml better; not a bug.
opts.IfApiMachineryElseKyaml(
fmt.Sprintf(
expFmt,
`CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbnVjbGVhcgo=`,
`CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aGUgZXZpbCBkYXlzIGNvbWUgbm90Lgo=`,
`ftht6hfgmb`),
fmt.Sprintf(
expFmt, `|
CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbn
VjbGVhcgo=`, `|
CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aG
UgZXZpbCBkYXlzIGNvbWUgbm90Lgo=`, `9t25t44gg4`)))
}
// TODO: These should be errors instead.
func TestGeneratorRepeatsInKustomization(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
th.WriteK(".", `
namePrefix: blah-
configMapGenerator:
- name: bob
@@ -125,13 +249,13 @@ configMapGenerator:
files:
- nobles=nobility.txt
`)
th.WriteF("/app/forces.txt", `
th.WriteF("forces.txt", `
gravitational
electromagnetic
strong nuclear
weak nuclear
`)
th.WriteF("/app/nobility.txt", `
th.WriteF("nobility.txt", `
helium
neon
argon
@@ -139,7 +263,7 @@ krypton
xenon
radon
`)
m := th.Run("/app", th.MakeDefaultOptions())
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -159,9 +283,120 @@ metadata:
`)
}
func TestIssue3393(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
resources:
- cm.yaml
configMapGenerator:
- name: project
behavior: merge
literals:
- ANOTHER_ENV_VARIABLE="bar"
`)
th.WriteF("cm.yaml", `
apiVersion: v1
kind: ConfigMap
metadata:
name: project
data:
A_FIRST_ENV_VARIABLE: "foo"
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
A_FIRST_ENV_VARIABLE: foo
ANOTHER_ENV_VARIABLE: bar
kind: ConfigMap
metadata:
name: project
`)
}
func TestGeneratorSimpleOverlay(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("base", `
namePrefix: p-
configMapGenerator:
- name: cm
behavior: create
literals:
- fruit=apple
`)
th.WriteK("overlay", `
resources:
- ../base
configMapGenerator:
- name: cm
behavior: merge
literals:
- veggie=broccoli
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
fruit: apple
veggie: broccoli
kind: ConfigMap
metadata:
name: p-cm-877mt5hc89
`)
}
var binaryHello = []byte{
0xff, // non-utf8
0x68, // h
0x65, // e
0x6c, // l
0x6c, // l
0x6f, // o
}
func manyHellos(count int) (result []byte) {
for i := 0; i < count; i++ {
result = append(result, binaryHello...)
}
return
}
func TestGeneratorOverlaysBinaryData(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("base/data.bin", string(manyHellos(30)))
th.WriteK("base", `
namePrefix: p1-
configMapGenerator:
- name: com1
behavior: create
files:
- data.bin
`)
th.WriteK("overlay", `
resources:
- ../base
configMapGenerator:
- name: com1
behavior: merge
`)
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
binaryData:
data.bin: |
/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbG
xv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hl
bGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2
hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv
kind: ConfigMap
metadata:
name: p1-com1-96gmmt6gt5
`)
}
func TestGeneratorOverlays(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base1", `
th.WriteK("base1", `
namePrefix: p1-
configMapGenerator:
- name: com1
@@ -169,7 +404,7 @@ configMapGenerator:
literals:
- from=base
`)
th.WriteK("/app/base2", `
th.WriteK("base2", `
namePrefix: p2-
configMapGenerator:
- name: com2
@@ -177,7 +412,7 @@ configMapGenerator:
literals:
- from=base
`)
th.WriteK("/app/overlay/o1", `
th.WriteK("overlay/o1", `
resources:
- ../../base1
configMapGenerator:
@@ -186,7 +421,7 @@ configMapGenerator:
literals:
- from=overlay
`)
th.WriteK("/app/overlay/o2", `
th.WriteK("overlay/o2", `
resources:
- ../../base2
configMapGenerator:
@@ -195,7 +430,7 @@ configMapGenerator:
literals:
- from=overlay
`)
th.WriteK("/app/overlay", `
th.WriteK("overlay", `
resources:
- o1
- o2
@@ -206,7 +441,7 @@ configMapGenerator:
- foo=bar
- baz=qux
`)
m := th.Run("/app/overlay", th.MakeDefaultOptions())
m := th.Run("overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -215,8 +450,6 @@ data:
from: overlay
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: p1-com1-8tc62428t2
---
apiVersion: v1
@@ -224,8 +457,6 @@ data:
from: overlay
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: p2-com2-87mcggf7d7
`)
}
@@ -233,24 +464,24 @@ metadata:
func TestConfigMapGeneratorMergeNamePrefix(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
th.WriteK("base", `
configMapGenerator:
- name: cm
behavior: create
literals:
- foo=bar
`)
th.WriteK("/app/o1", `
th.WriteK("o1", `
resources:
- ../base
namePrefix: o1-
`)
th.WriteK("/app/o2", `
th.WriteK("o2", `
resources:
- ../base
nameSuffix: -o2
`)
th.WriteK("/app", `
th.WriteK(".", `
resources:
- o1
- o2
@@ -264,7 +495,7 @@ configMapGenerator:
literals:
- big=crunch
`)
m := th.Run("/app", th.MakeDefaultOptions())
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -272,8 +503,6 @@ data:
foo: bar
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: o1-cm-ft9mmdc8c6
---
apiVersion: v1
@@ -282,8 +511,43 @@ data:
foo: bar
kind: ConfigMap
metadata:
annotations: {}
labels: {}
name: cm-o2-5k95kd76ft
`)
}
func TestConfigMapGeneratorLiteralNewline(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK(".", `
generators:
- configmaps.yaml
`)
th.WriteF("configmaps.yaml", `
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: testing
literals:
- |
initial.txt=greetings
everyone
- |
final.txt=different
behavior
---
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(
m, `
apiVersion: v1
data:
final.txt: |
different
behavior
initial.txt: |
greetings
everyone
kind: ConfigMap
metadata:
name: testing-tt4769fb52
`)
}

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