Compare commits

..

151 Commits

Author SHA1 Message Date
jingfangliu
9b3a0c971a update client-go version 2019-08-15 16:55:44 -07:00
Jeff Regan
e0bac6ad19 Merge pull request #1302 from mmb/nginx-auth-tls-secret
Add support for nginx.ingress.kubernetes.io/auth-tls-secret
2019-07-03 11:01:14 -07:00
Kubernetes Prow Robot
d841d1bb36 Merge pull request #1270 from sunny0826/master
Chinese localization & fix fields.md
2019-07-03 09:00:35 -07:00
Matthew M. Boedicker
0d87cd6ba1 Add support for nginx.ingress.kubernetes.io/auth-tls-secret 2019-07-02 20:17:16 -07:00
郭旭东
28ad36b02c Merge remote-tracking branch 'upstream/master' 2019-07-03 09:38:44 +08:00
郭旭东
cad8a7bd3f fix zh/fields.md 2019-07-03 09:21:33 +08:00
Jeff Regan
60a990d660 Merge pull request #1297 from arrikto/feature-complex-overlay-composition
Add complex overlay composition test
2019-07-02 13:41:52 -07:00
Kubernetes Prow Robot
cb3751cea6 Merge pull request #1293 from monopole/fix1281
Fix 1281
2019-07-02 09:45:09 -07:00
Ioannis Androulidakis
5ad012e6d9 Add complex overlay composition test
Signed-off-by: Ioannis Androulidakis <ioannis@arrikto.com>
Signed-off-by: Alex Pyrgiotis <apyrgio@arrikto.com>
2019-07-02 19:26:04 +03:00
Jeffrey Regan
8a454de8f9 Fix 1281 2019-07-01 18:09:48 -07:00
Jeff Regan
57b18b7caa Merge pull request #1294 from monopole/repo1281
Add a test combining imagetag and jsonpatch
2019-07-01 18:05:47 -07:00
Jeffrey Regan
701d2c9597 Add a test combining imagetag and jsonpatch 2019-07-01 17:58:46 -07:00
Kubernetes Prow Robot
e7e844bc95 Merge pull request #1291 from monopole/addTest
Add another resmap test.
2019-07-01 11:55:22 -07:00
Jeffrey Regan
0fe95a2f74 Add another resmap test. 2019-07-01 11:17:46 -07:00
Jeff Regan
eb93d8c389 Merge pull request #1289 from monopole/moreTests
Add more json transformer examples.
2019-07-01 09:14:43 -07:00
jregan
8b373ab587 Add more json transformer examples. 2019-07-01 08:52:55 -07:00
Jeff Regan
c352003f3e Merge pull request #1290 from arrikto/feature-diamond-test-harden
Update the diamond composition test case
2019-07-01 08:34:23 -07:00
Alex Pyrgiotis
79d0de7000 Update the diamond composition test case
Refactor the existing base, so that one of the overlays patches an
already present field of the base resource. Previously, all overlays
added a new field in the base deployment, which made this case easier to
solve, with a merge of the produced YAMLs from each overlay.

Also, fix a typo in the comments.

Signed-off-by: Alex Pyrgiotis <apyrgio@arrikto.com>
Signed-off-by: Ioannis Androulidakis <ioannis@arrikto.com>
2019-07-01 14:57:59 +00:00
Jeff Regan
a32d5ce7ab Merge pull request #1288 from monopole/inlineJson
Push json transform code down to plugin.
2019-06-30 17:49:24 -07:00
jregan
5de0673db1 Push json transform code down to plugin. 2019-06-30 17:30:52 -07:00
Jeff Regan
c2b0b6f781 Merge pull request #1286 from monopole/anotherTest
Stacked patching example
2019-06-30 08:58:08 -07:00
jregan
116b37813a stackedOverlays 2019-06-30 08:45:37 -07:00
Jeff Regan
27f0d29734 Merge pull request #1287 from monopole/defineConstants
Define some constants in a test for later reuse.
2019-06-30 08:44:16 -07:00
jregan
f62af4ebf3 Define some constants in a test for later reuse. 2019-06-30 08:42:15 -07:00
Jeff Regan
faa6d0fd0a Merge pull request #1285 from monopole/v1App
Switch Deployment apiVersion to apps/v1 in a couple of tests.
2019-06-30 07:51:53 -07:00
jregan
0554da9d6e Switch to apps/v1 in various tests. 2019-06-30 07:45:29 -07:00
Jeff Regan
fa1fd9fbd7 Merge pull request #1283 from arrikto/feature-diamond-composition-test
Add diamond composition test with multiple patches
2019-06-30 06:56:56 -07:00
Jeff Regan
3dffc30e83 Merge pull request #1280 from sethpollack/generator_metadata
use ObjectMeta
2019-06-30 06:55:52 -07:00
Seth Pollack
2126b6cf23 use ObjectMeta instead of name and namespace fields 2019-06-29 23:30:50 -04:00
Ioannis Androulidakis
2b052fdd55 Add diamond composition test with multiple patches
The purpose of this commit is to demonstrate a composition use case,
that combines multiple overlays that patch the same base resource.

Signed-off-by: Ioannis Androulidakis <ioannis@arrikto.com>
Signed-off-by: Alex Pyrgiotis <apyrgio@arrikto.com>
2019-06-29 22:05:30 +03:00
Jeff Regan
58faa762cb Merge pull request #1275 from Liujingfang1/patches
add function to find all matched patch targets
2019-06-29 09:36:53 -07:00
jingfangliu
349cfff1cb add function to find all matched patch targets 2019-06-28 17:12:02 -07:00
Jeff Regan
558be8b923 Merge pull request #1284 from monopole/objectmeta
Add ObjectMeta type.
2019-06-28 14:56:45 -07:00
Jeffrey Regan
233b3613ae Add ObjectMeta type. 2019-06-28 14:39:56 -07:00
Jeff Regan
615a41d6be Merge pull request #1282 from monopole/repoBug1044
Repo bug 1044
2019-06-28 13:08:39 -07:00
Jeffrey Regan
0ceefcf39d Repo bug 1044 2019-06-28 11:29:48 -07:00
Jeff Regan
16ae64a722 Merge pull request #1279 from monopole/fix972
Fix JSON patch targetting issue.
2019-06-27 17:43:54 -07:00
Jeff Regan
3f239fb4a5 Update bugs.md 2019-06-27 17:40:34 -07:00
Jeffrey Regan
a60d99fdc9 Fix 972 2019-06-27 17:37:12 -07:00
Kubernetes Prow Robot
dd0334536b Merge pull request #1278 from monopole/addDiamondTest
Add diamond base test, improve patching error messages.
2019-06-27 16:53:21 -07:00
Jeffrey Regan
3cef37bdb2 Add diamond base test. 2019-06-27 16:10:58 -07:00
Jeff Regan
ac27e94dff Update README.md 2019-06-27 16:04:15 -07:00
Jeff Regan
0877aa7e0b Merge pull request #1277 from monopole/deleteGetById
Delete deprecated GetById
2019-06-27 15:28:34 -07:00
Jeffrey Regan
07e5a544fe Delete deprecated GetById 2019-06-27 15:26:03 -07:00
Kubernetes Prow Robot
60c04a5f33 Merge pull request #1271 from etiennecoutaud/support_azure_tfs_url
Add suport for _git in git  url
2019-06-27 11:51:22 -07:00
Jeff Regan
b9b9fb1dd2 Merge pull request #1274 from monopole/plainerPluginSecurityDiscussion
Plainer plugin security discussion.
2019-06-27 11:09:08 -07:00
Jeffrey Regan
e1233a0fbc Plainer plugin security discussion. 2019-06-27 11:08:26 -07:00
Etienne Coutaud
cc8203032c Add suport for _git in git url 2019-06-27 11:54:37 +02:00
郭旭东
7117961234 Chinese localization & fix fields.md 2019-06-27 16:52:00 +08:00
Jeff Regan
d410252cf8 Update goPluginCaveats.md 2019-06-26 16:56:46 -07:00
Jeff Regan
4235c57657 Update goPluginCaveats.md 2019-06-26 16:55:33 -07:00
Jeff Regan
e34c1ce192 Merge pull request #1263 from monopole/pluginsDocs
More plugin docs.
2019-06-26 16:38:53 -07:00
Jeffrey Regan
4d399ad89c More plugin docs. 2019-06-26 16:37:26 -07:00
Jeff Regan
9d6ab24388 Merge pull request #1260 from monopole/gomodtidy
A round of go mod tidy.
2019-06-26 13:27:20 -07:00
Jeffrey Regan
ee9f35d451 A round of go mod tidy. 2019-06-26 13:24:40 -07:00
Jeff Regan
45c11ec733 Update README.md 2019-06-26 13:22:22 -07:00
Jeff Regan
0519df4ad5 Merge pull request #1259 from monopole/releasing
Update notes for releasing.
2019-06-26 13:19:03 -07:00
Jeffrey Regan
55585d8da5 Update notes for releasing. 2019-06-26 13:10:41 -07:00
Jeff Regan
b8b49c3124 Merge pull request #1244 from Liujingfang1/patches
add type for extended patches
2019-06-26 11:21:22 -07:00
Jeff Regan
a41471d895 Merge pull request #1254 from monopole/nonnamespace
Fix some minor nits around namespace code.
2019-06-26 10:25:16 -07:00
Jeffrey Regan
877e9ecf64 Fix some minor nits around namespace code. 2019-06-26 10:02:22 -07:00
Kubernetes Prow Robot
150985bb9c Merge pull request #1200 from sunny0826/master
Chinese configGeneration.md dosc
2019-06-26 09:11:16 -07:00
jingfangliu
039f7669df add type for extended patches 2019-06-26 09:01:17 -07:00
Jeff Regan
6caa042b05 Merge pull request #1255 from monopole/fixNits
Fix some random Go nits.
2019-06-25 21:03:38 -07:00
jregan
cc0fffc67b Fix some random Go nits. 2019-06-25 20:46:56 -07:00
郭旭东
50d40ef941 fix zh/configGeneration.md 2019-06-26 09:57:46 +08:00
Jeff Regan
69d40bd740 Merge pull request #1221 from keleustes/mergens
ConfigMap Generators with identical name in different namespaces
2019-06-25 16:31:18 -07:00
Jerome Brette
4272611593 Change key used sort "not namespaceable objects.
- Use "%no_namespace% instead of "cluster-wide"
- Ensure will be no conflict with a kubernetes valid namespace name.
2019-06-25 17:04:55 -05:00
Jerome Brette
74f5e74b89 Consolidate IsClusterKind and IsNamespaceableKind method to avoid duplication 2019-06-25 13:46:49 -05:00
Jerome Brette
2bba0a6aa3 Support for ConfigMap generator with identical names in different namespaces.
- Attempt to account, at build time, for subsequent kubectl apply behavior.
  (empty or no namespace means default).
- Account for the fact that not all objects have a namespace.
- Add new Equal method to ResId address merge name conflict
- Add GroupByName to resources by namespaces to resolve filenames conflict
- Added corresponding unit tests.
- Change the fail test for issue #1155
2019-06-25 13:39:32 -05:00
Jeff Regan
762d3143eb Merge pull request #1242 from taxpon/add-patch-remover
Add patch remover
2019-06-25 09:51:44 -07:00
Jeff Regan
7f22e25dfe Merge pull request #1239 from sethpollack/fix_plugins
allow reuse of plugins
2019-06-25 09:10:05 -07:00
Kubernetes Prow Robot
41c162a65f Merge pull request #1204 from zeusro/master
Chinese translation:jsonpatch.md
2019-06-25 09:02:40 -07:00
Zeusro
ca521946a5 add missing text 2019-06-25 16:50:27 +08:00
Zeusro
b0e53d2b39 Chinese translation:jsonpatch.md 2019-06-25 16:49:41 +08:00
Takuro Wada
5c93722db8 Update pkg structure to avoid circular import 2019-06-25 11:46:01 +09:00
Takuro Wada
d34c82c905 move globPatterns to edit pkg and make it public 2019-06-25 11:21:29 +09:00
Takuro Wada
f11d083b0a Apply goimports 2019-06-25 11:05:56 +09:00
Takuro Wada
f1a5a7703c Update Copyright to shorter one 2019-06-25 11:05:43 +09:00
Seth Pollack
9cc2c90a4b allow reuse of plugins 2019-06-24 21:09:13 -04:00
Jeff Regan
bc31fa9120 Merge pull request #1247 from monopole/updateReleaseNotes
Update versioning policy.
2019-06-24 17:27:44 -07:00
Jeffrey Regan
7a67645558 Update versioning policy. 2019-06-24 17:26:42 -07:00
Jeff Regan
b0f59358d9 Update v3.0.0.md 2019-06-24 16:17:36 -07:00
Jeff Regan
0e6c7d8af7 Update v3.0.0.md 2019-06-24 16:15:54 -07:00
Jeff Regan
9c20085ca9 Update goPluginGuidedExample.md 2019-06-24 15:27:14 -07:00
Jeff Regan
d48a52055a Update goPluginGuidedExample.md 2019-06-24 15:25:03 -07:00
Jeff Regan
dc433e12fb Merge pull request #1246 from monopole/pluginDocGetsOwnDir
Add another detailed plugin example.
2019-06-24 15:21:04 -07:00
Jeffrey Regan
1740ca6a16 Add another detailed plugin example. 2019-06-24 15:19:49 -07:00
Takuro Wada
2ae8ca1d63 Fix help message to align other cmd 2019-06-24 21:28:44 +09:00
Takuro Wada
674cd89ac9 Add patch remover 2019-06-24 21:25:01 +09:00
Takuro Wada
6ed70add4a Add Delete function to patch pkg 2019-06-24 21:14:26 +09:00
Jeff Regan
ae5ebccec7 Merge pull request #1241 from monopole/hackPluginTesting
Hack for local testing of isolated plugins.
2019-06-23 18:05:23 -07:00
jregan
19c8e23425 Hack for local testing of isolated plugins. 2019-06-23 18:04:20 -07:00
Jeff Regan
b878cd050d Merge pull request #1240 from monopole/v3
Starting v3 release for plugin developers.
2019-06-23 15:18:18 -07:00
jregan
a7df00c07a Starting v3 release for plugin developers.
[doc]: https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher

Per this Go modules [doc] a repo or branch that's
already tagged v2 or higher should increment the major
version (e.g. go to v3) when releasing their first Go
module-based packages.

At the moment, the kustomize repo has these top level
packages in the sigs.k8s.io/kustomize module:

 - `cmd` - holds main program for kustomize

	 Conceivably someone can depend on this
	 package for integration tests.

 - `internal` - intentionally unreleased subpackages

 - `k8sdeps` - an adapter wrapping k8s dependencies

	 This exists only for use in pre-Go-modules kustomize-into-kubectl
	 integration and won't live much longer (as everything involved is
	 switching to Go modules).

 - `pkg` - kustomize packages for export

	 This should shrink in later versions, since
	 the surface area is too large, containing
	 sub-packages that should be in 'internal'.

 - `plugin` - holds main programs for plugins

This PR changes the top level go.mod file from

```
module sigs.k8s.io/kustomize
```

to

```
module sigs.k8s.io/kustomize/v3
```

and adjusts all import statements to
reflect the change.
2019-06-23 15:05:59 -07:00
Jeff Regan
3127f1adc6 Merge pull request #1238 from monopole/removeSopsEncodedSecretsPlugin
Remove SopsEncodedSecretsPlugin
2019-06-23 10:02:15 -07:00
jregan
a722cca80a Remove SopsEncodedSecretsPlugin 2019-06-23 09:46:45 -07:00
Jeff Regan
0ffd78eab6 Merge pull request #1224 from keleustes/varset
Change the backing data structure of VarSet from slice to map
2019-06-23 09:03:48 -07:00
Jeff Regan
694c868048 Merge pull request #1231 from arnodel/fix-1228
Iterate over fieldspecs for name tranformations (fixes #1228)
2019-06-23 09:02:54 -07:00
Jeff Regan
2da2006e2a Merge pull request #1237 from taxpon/add-metadata-remover
Add metadata remover
2019-06-23 08:56:03 -07:00
Jeff Regan
0bc83ca065 Merge pull request #1227 from leoxiongdev/patch-1
Fix typo
2019-06-23 08:36:08 -07:00
Takuro Wada
ab2643ef14 Fix FakeValidator 2019-06-23 19:59:01 +09:00
Takuro Wada
297812ec11 Fix lint 2019-06-23 19:43:49 +09:00
Takuro Wada
158f754f18 Add remove annotation command 2019-06-23 18:43:52 +09:00
Takuro Wada
da3504105e Add remove label command 2019-06-23 18:43:52 +09:00
Arnaud Delobelle
d3f50695b4 Fix configmap name in test 2019-06-22 08:46:22 +01:00
Arnaud Delobelle
5a9a6ab0f6 Fix typo in test 2019-06-22 08:27:23 +01:00
Arnaud Delobelle
b86e78b7a9 Add test for regression 2019-06-22 08:09:39 +01:00
Ian Howell
b1cdf581d0 Change the backing data structure of VarSet from slice to map
This will speed up most operations performed on a large set of Vars
2019-06-21 17:28:57 -05:00
Jeff Regan
8bf20527be Merge pull request #1232 from monopole/moreVarTestCoverage
More var test coverage.
2019-06-21 14:14:53 -07:00
Jeffrey Regan
3eedc40595 More var test coverage. 2019-06-21 13:53:58 -07:00
Arnaud Delobelle
93db0ef3e9 Iterate over fieldspecs for name tranformations 2019-06-21 21:08:59 +01:00
Jeff Regan
6922dbbc70 Merge pull request #1225 from keleustes/fix/compiler
Fixed unit test failures when GOROOT was unset
2019-06-21 09:52:39 -07:00
Jeff Regan
f1b9b27a15 Merge pull request #1220 from keleustes/downwardapi
FieldPath syntax backward compatibility
2019-06-21 09:36:52 -07:00
Leo Xiong
a755558beb Fix typo 2019-06-21 12:29:31 +12:00
Ian Howell
b8423d0f5f Fixed unit test failures when GOROOT was unset 2019-06-20 16:37:20 -05:00
Jeff Regan
42ef4fbcc1 Merge pull request #1222 from monopole/linuxIn30
Another plugin demo.
2019-06-20 11:47:34 -07:00
Jeffrey Regan
69c11780eb Another plugin demo. 2019-06-20 11:45:26 -07:00
Jerome Brette
c925b43090 FieldSpec Backward Compatibility with K8s Downward API 2019-06-20 09:22:47 -05:00
Kubernetes Prow Robot
a5b97cbd9b Merge pull request #1214 from monopole/sops
A secret generator using sops.
2019-06-19 19:50:48 -07:00
Jeffrey Regan
bcb844663f A secret generator using sops. 2019-06-19 18:55:50 -07:00
Jeff Regan
0905ee293c Merge pull request #1213 from monopole/commitGenerated
Commit generated code for image and namespace transformers.
2019-06-19 18:53:02 -07:00
Jeffrey Regan
3325852aab Commit generated code for image and namespace transformers. 2019-06-19 18:52:24 -07:00
Jeff Regan
c437d99c5f Merge pull request #1210 from monopole/pushTagTransformCodeToPlugin
Push image tag transform code to plugin.
2019-06-19 18:26:31 -07:00
Jeff Regan
cacafc63e8 Merge pull request #1211 from monopole/pushNamespaceTransformerCodeToPlugin
Push namespace transformer code to plugin.
2019-06-19 18:26:05 -07:00
Jeff Regan
b08f3383b8 Merge pull request #1206 from jbrette/namespace
Addresses issue discovered in attempting to patch K8s objects across different namespaces.
2019-06-19 13:07:50 -07:00
Jeffrey Regan
2eccf67b1c Push namespace transformer code to plugin. 2019-06-19 12:57:02 -07:00
Kubernetes Prow Robot
293c8bef54 Merge pull request #1202 from mamoit/patch-1
Typo correction in 2.1.0 release notes
2019-06-19 12:38:19 -07:00
Kubernetes Prow Robot
00c7ae0542 Merge pull request #1199 from ramnar/master
Corrected spelling mistake
2019-06-19 12:36:21 -07:00
Jeffrey Regan
cd656faadf Push image tag transform code to plugin. 2019-06-19 12:24:00 -07:00
Kubernetes Prow Robot
056b95ffa9 Merge pull request #1201 from yujunz/fix-typo
Fix typo in docs
2019-06-19 11:28:34 -07:00
Kubernetes Prow Robot
d211df1e73 Merge pull request #1205 from pyaillet/fix-typo
Fix typo in comment
2019-06-19 08:56:36 -07:00
Jerome Brette
934e036b99 Attempting to patch K8s objects across different namespaces.
- Return an error when findTarget fails.
- Add unit test testing the change.
2019-06-19 08:42:12 -05:00
Zeusro
9fc86f92fa Chinese translation:jsonpatch.md 2019-06-19 21:16:40 +08:00
Pierre-Yves Aillet
49c6bd4141 Fix typo in comment 2019-06-19 14:53:29 +02:00
Miguel Almeida
24011cf2a5 Simple flag typo correction
The flag is load_restrictor and not load_restrictions.
2019-06-19 11:35:33 +01:00
郭旭东
83b284dfde fix configGeneration.md 2019-06-19 17:21:07 +08:00
Yujun Zhang
7c9181317f Fix typo in docs 2019-06-19 15:09:31 +08:00
郭旭东
01b410fe9c Chinese configGeneration.md dosc 2019-06-19 14:36:21 +08:00
ramnar
56ac98468d Corrected spelling mistake
Corrected spelling mistake
2019-06-19 08:22:55 +05:30
Jeff Regan
658ebeaa21 Merge pull request #1197 from keleustes/showcasevariables
Demonstrate new capabilities in pkg/target testing
2019-06-18 19:22:27 -07:00
Jeff Regan
59aa898533 Merge pull request #1198 from sunny0826/master
update docs/zh/README.md
2019-06-18 19:21:37 -07:00
Jeff Regan
c88f87cee2 Merge pull request #1196 from keleustes/helperimprovment
Improve robutness of helper code
2019-06-18 18:59:15 -07:00
郭旭东
cc663bb08c update docs/zh/README.md 2019-06-19 09:26:44 +08:00
Jeff Regan
63d647df18 Update secretGeneratorPlugin.md 2019-06-18 16:50:48 -07:00
Jerome Brette
e3a46cb6ce Leverage new variables during testing
Extract the HTTP port (int) from the container section end
use it in the service definition.

Also enable variable replacement for Service object.
2019-06-18 18:37:20 -05:00
Jerome Brette
4556eb3a0c Improve robutness of helper code
As per request, changed usage of pointer to int into plain int.
Use -1 value where nil use to be used.
2019-06-18 18:06:38 -05:00
Jeff Regan
26ed9b7c58 Fix date of release v2.1.0 2019-06-18 15:30:37 -07:00
Jeff Regan
8ff0b5423d Update v2.1.0.md 2019-06-18 15:27:27 -07:00
Jeff Regan
0fbced95a8 Merge pull request #1195 from monopole/updateReleaseLinks
Update release note links.
2019-06-18 15:25:09 -07:00
Jeffrey Regan
66b816aabc Update release note links. 2019-06-18 15:24:10 -07:00
259 changed files with 7500 additions and 3052 deletions

View File

@@ -7,7 +7,7 @@ untouched and usable as is.
`kustomize` targets kubernetes; it understands and can
patch [kubernetes style] API objects. It's like
[`make`], in that what it does is declared in a file,
and it's like [`sed`], in that it emits editted text.
and it's like [`sed`], in that it emits edited text.
This tool is sponsored by [sig-cli] ([KEP]), and
inspired by [DAM].
@@ -22,7 +22,7 @@ these [instructions](docs/INSTALL.md).
Browse the [docs](docs) or jump right into the
tested [examples](examples).
kustomize [v2.0.3] is available in [kubectl v1.14][kubectl].
kustomize [v2.0.3] is available in [kubectl v1.15][kubectl].
## Usage
@@ -171,4 +171,5 @@ is governed by the [Kubernetes Code of Conduct].
[variant]: docs/glossary.md#variant
[variants]: docs/glossary.md#variant
[v2.0.3]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.0.3
[v2.1.0]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.1.0
[workflows]: docs/workflows.md

View File

@@ -1,43 +0,0 @@
[releases page]: https://github.com/kubernetes-sigs/kustomize/releases
[`cloud-build-local`]: https://github.com/GoogleCloudPlatform/cloud-build-local
[Google Cloud Build]: https://cloud.google.com/cloud-build
Scripts and configuration files for publishing a
`kustomize` release on the [releases page].
### Build a release locally
Install [`cloud-build-local`], then run
```
./build/localbuild.sh
```
to build artifacts under `./dist`.
### Publish a Release
Get on an up-to-date master branch:
```
git checkout master
git fetch upstream
git rebase upstream/master
```
Define the version (see [semver principles](https://semver.org)), e.g.:
```
version=v1.0.3
```
Tag the repo:
```
git tag -a $version -m "$version release"
```
Push the tag upstream:
```
git push upstream $version
```
The new tag will trigger a job in [Google Cloud
Build] to put a new release on the [releases page].

View File

@@ -6,7 +6,7 @@ package main
import (
"os"
"sigs.k8s.io/kustomize/pkg/commands"
"sigs.k8s.io/kustomize/v3/pkg/commands"
)
func main() {

View File

@@ -12,8 +12,8 @@ import (
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/plugins"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/plugins"
)
func main() {

View File

@@ -23,17 +23,8 @@ kustomization file, and refering to this directory as a
wants to use it. This encourages modularity and
relocatability.
At the moment (in v2.0.3), however, there's no
(released) analogous way to share patch files and other
transformer configuration data between kustomizations.
As a stop-gap until we add base-like behavior for
transformers, we've added a flag to disable the check:
To disable this, use v3, and the `load_restrictor` flag:
```
kustomize build --load_restrictor none $target
```
This flag is not in v2.0.3, but is available from head
(`go install sigs.k8s.io/kustomize`).

View File

@@ -1,13 +1,15 @@
[release page]: https://github.com/kubernetes-sigs/kustomize/releases
[Go]: https://golang.org
## Installation
# Installation
For linux, macOs and Windows,
download a binary from the
[release page].
Binaries at various versions for linux, macOs and Windows
are available on the [release page].
Or...
## Quickly curl the latest
Or try this command:
```
opsys=linux # or darwin, or windows
curl -s https://api.github.com/repos/kubernetes-sigs/kustomize/releases/latest |\
@@ -19,17 +21,19 @@ mv kustomize_*_${opsys}_amd64 kustomize
chmod u+x kustomize
```
To install from head with [Go] v1.12 or higher:
## Install from the HEAD of master branch
Requires [Go] v1.12 or higher:
<!-- @installkustomize @test -->
```
go install sigs.k8s.io/kustomize/cmd/kustomize
go install sigs.k8s.io/kustomize/v3/cmd/kustomize
```
### Other methods
#### macOS
```
brew install kustomize
```
@@ -44,4 +48,3 @@ For support on the chocolatey package
and prior releases, see:
- [Choco Package](https://chocolatey.org/packages/kustomize)
- [Package Source](https://github.com/kenmaglio/choco-kustomize)

View File

@@ -12,7 +12,7 @@ English | [简体中文](zh/README.md)
* [Kustomize Fields](fields.md) - explanations of the fields
in a [kustomization](glossary.md#kustomization) file.
* [Plugins](plugins.md) - extending kustomize with
* [Plugins](plugins) - extending kustomize with
custom generators and transformers.
* [Workflows](workflows.md) - steps one might take in
@@ -23,12 +23,14 @@ English | [简体中文](zh/README.md)
## Release notes
* [2.1](v_2.1.0.md) - Date TBD, target late May 2019
* [3.0](v3.0.0.md) - Late June 2019. Plugin developer release.
* [2.0](v_2.0.0.md) - Mar 2019.
* [2.1](v2.1.0.md) - 18 June 2019. Plugins, ordered resources, etc.
* [2.0](v2.0.0.md) - Mar 2019.
kustomize [v2.0.3] is available in [kubectl v1.14][kubectl].
* [1.0](v_1.0.1.md) - May 2018. Initial release after development
* [1.0](v1.0.1.md) - May 2018. Initial release after development
in the [kubectl repository].

View File

@@ -20,7 +20,10 @@ following to improve response time.
kustomize has a simple test harness in the
[target package] for specifying a kustomization's
input and the expected output.
See this [example of a target test].
See this [example of a target test], and contribution
[#971](https://github.com/kubernetes-sigs/kustomize/pull/971),
which does exactly the right thing.
The pattern is
* call `NewKustTestHarness`

1
docs/execPluginIn30sec.md Symbolic link
View File

@@ -0,0 +1 @@
plugins/execPluginGuidedExample.md

View File

@@ -21,7 +21,7 @@ What things should be created (and optionally subsequently customized)?
|[configMapGenerator](#configmapgenerator)| list |Each entry in this list results in the creation of one ConfigMap resource (it's a generator of n maps).|
|[secretGenerator](#secretgenerator)| list |Each entry in this list results in the creation of one Secret resource (it's a generator of n secrets)|
|[generatorOptions](#generatoroptions)|string|generatorOptions modify behavior of all ConfigMap and Secret generators|
|[generators](#generators)|list|[plugin](plugins.md) configuration files|
|[generators](#generators)|list|[plugin](plugins) configuration files|
## Transformers
@@ -40,7 +40,7 @@ What transformations (customizations) should be applied?
| [replicas](#replicas) | list | Replicas modifies the number of replicas of a resource. |
|[patchesStrategicMerge](#patchesstrategicmerge)| list |Each entry in this list should resolve to a partial or complete resource definition file.|
|[patchesJson6902](#patchesjson6902)| list |Each entry in this list should resolve to a kubernetes object and a JSON patch that will be applied to the object.|
|[transformers](#transformers)|list|[plugin](plugins.md) configuration files|
|[transformers](#transformers)|list|[plugin](plugins) configuration files|
## Meta
@@ -173,7 +173,7 @@ generatorOptions:
### generators
A list of generator [plugin](plugins.md) configuration files.
A list of generator [plugin](plugins) configuration files.
```
generators:
@@ -307,12 +307,14 @@ The content in this patch file can be either in JSON format as
or in YAML format as
```
- op: add
path: /some/new/path
value: value
- op:replace
- op: replace
path: /some/existing/path
value: new value
```
```
patchesJson6902:
@@ -356,6 +358,7 @@ be modified at the same time.
#### Limitation
As this declaration does not take in a `kind:` nor a `group:`
it will match any `group` and `kind` that has a matching name and
that is one of:

View File

@@ -405,7 +405,7 @@ A chunk of code used by kustomize, but not necessarily
compiled into kustomize, to generate and/or transform a
kubernetes resource as part of a kustomization.
Details [here](plugins.md).
Details [here](plugins).
## resource

View File

@@ -30,7 +30,7 @@ The _inventory_ ConfigMap contains two special annotations:
struct that contains following information
- all objects within this kustomization target
- all objects that reference within this kustomization target
Here is an example of an Inventory object
```json
{
@@ -49,11 +49,11 @@ The _inventory_ ConfigMap contains two special annotations:
],
"~G_v1_Service|default|mysql":null
}
}
}
```
- kustomize.config.k8s.io/InventoryHash
The value of this annotation is a hash that is
The value of this annotation is a hash that is
computed from the list of items in the Inventory
Basically, this inventory object acts a record of objects that are applied as a group.
@@ -150,7 +150,7 @@ metadata:
annotations:
kustomize.config.k8s.io/Inventory: '{"current":{"apps_v1_Deployment|default|mysql":null,"~G_v1_Secret|default|pass-dfg7h97cf6":[{"group":"apps","version":"v1","kind":"Deployment","name":"mysql","namespace":"default"}],"~G_v1_Service|default|mysql":null}}'
kustomize.config.k8s.io/InventoryHash: 7mgt867b75
name: haha
name: root-cm
namespace: default
```

View File

@@ -1,11 +1,16 @@
# kustomize plugins
Quick guides:
* [linux exec plugin in 60 sec](execPluginGuidedExample.md)
* [linux Go plugin in 60 sec](goPluginGuidedExample.md)
Kustomize offers a plugin framework allowing
people to write their own resource _generators_
and _transformers_.
[generator options]: ../examples/generatorOptions.md
[transformer configs]: ../examples/transformerconfigs
[generator options]: ../../examples/generatorOptions.md
[transformer configs]: ../../examples/transformerconfigs
Write a plugin when changing [generator options]
or [transformer configs] doesn't meet your needs.
@@ -21,9 +26,9 @@ or [transformer configs] doesn't meet your needs.
* A _transformer_ plugin might perform special
container command line edits, or any other
transformation that exceeds the power of the
builtin transformations (`namePrefix`,
`commonLabels`, etc.).
transformation beyond those provided by the
builtin (`namePrefix`, `commonLabels`, etc.)
transformers.
## Specification in `kustomization.yaml`
@@ -43,26 +48,21 @@ Each field accepts a string list:
> - {as above}
> ```
This is exactly like the syntax of the `resources`
field.
The value of each entry in a `generators` or
`transformers` list must be a relative path to a
YAML file, or a path or URL to a [kustomization].
This is the same format as demanded by the
`resources` field.
The value of each entry in a `resources`,
`generators` or `transformers` list must be a
relative path to a YAML file, or a path or URL
to a [kustomization].
[kustomization]: ../glossary.md#kustomization
[kustomization]: glossary.md#kustomization
In the former case the YAML is read from disk directly,
and in the latter case a kustomization is performed,
and its YAML output is merged with the YAML read
directly from files. The net result in all three cases
is a set of YAML objects.
Each object resulting from a `generators` or
`transformers` field is now further interpreted by
YAML files are read from disk directly. Paths or
URLs leading to kustomizations trigger an
in-process kustomization run. Each of the
resulting objects is now further interpreted by
kustomize as a _plugin configuration_ object.
## Configuration
A kustomization file could have the following lines:
@@ -72,11 +72,12 @@ generators:
- chartInflator.yaml
```
Given this, the kustomization process would expect to
find a file called `chartInflator.yaml` in the
kustomization [root](glossary.md#kustomization-root).
Given this, the kustomization process would expect
to find a file called `chartInflator.yaml` in the
kustomization [root](../glossary.md#kustomization-root).
This is the _plugin's configuration file_.
This is the plugin's configuration file;
it contains a YAML configuration object.
The file `chartInflator.yaml` could contain:
@@ -91,19 +92,19 @@ chartName: minecraft
__The `apiVersion` and `kind` fields are
used to locate the plugin.__
[k8s object]: glossary.md#kubernetes-style-object
[k8s object]: ../glossary.md#kubernetes-style-object
> Thus, these fields are required. They are also
> required because a kustomize plugin
> configuration object is also a [k8s object].
Thus, these fields are required. They are also
required because a kustomize plugin configuration
object is also a [k8s object].
To get the plugin ready to generator or transform,
To get the plugin ready to generate or transform,
it is given the entire contents of the
configuration file.
[NameTransformer]: ../plugin/builtin/prefixsuffixtransformer/PrefixSuffixTransformer_test.go
[ChartInflator]: ../plugin/someteam.example.com/v1/chartinflator/ChartInflator_test.go
[plugins]: ../plugin/builtin
[NameTransformer]: ../../plugin/builtin/prefixsuffixtransformer/PrefixSuffixTransformer_test.go
[ChartInflator]: ../../plugin/someteam.example.com/v1/chartinflator/ChartInflator_test.go
[plugins]: ../../plugin/builtin
For more examples of plugin configuration YAML,
browse the unit tests below the [plugins] root,
@@ -115,16 +116,18 @@ e.g. the tests for [ChartInflator] or
Each plugin gets its own dedicated directory named
[`XDG_CONFIG_HOME`]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
```
$XDG_CONFIG_HOME/kustomize/plugin
/${apiVersion}/LOWERCASE(${kind})
```
The default value of `XDG_CONFIG_HOME` is
The default value of [`XDG_CONFIG_HOME`] is
`$HOME/.config`.
The one-plugin-per-directory requirement eases
creation of a plugin tarball (source, test, plugin
creation of a plugin bundle (source, tests, plugin
data files, etc.) for sharing.
In the case of a [Go plugin](#go-plugins), it also
@@ -154,9 +157,8 @@ Plugins are only used during a run of the
`kustomize build` command.
Generator plugins are run after processing the
`resources` field (which itself is in some sense a
generator in that it emits resources for further
processing).
`resources` field (which itself can be viewed as a
generator, simply reading objects from disk).
The full set of resources is then passed into the
transformation pipeline, wherein builtin
@@ -166,28 +168,38 @@ in the kustomization file), followed by the
user-specified transformers in the `transformers`
field.
The specified order of transformers in the
`transformers` field should be respected, as
transformers cannot be expected to be commutative.
The order specified in the `transformers` field is
respected, as transformers cannot be expected to
be commutative.
#### No Security
Kustomize plugins do not run in any kind of
kustomize-provided sandbox. There's no notion
of _"plugin security"_.
A `kustomize build` that tries to use plugins but
omits the flag
> `--enable_alpha_plugins`
will fail with a warning about plugin use.
will not load plugins and will fail with a
warning about plugin use.
Flag use is an opt-in acknowledging the absence of
plugin provenance. It's meant to give pause to
someone who blindly downloads a kustomization from
the internet and attempts to run it, without
realizing that it might attempt to run 3rd party
code in plugin form. The plugin would have to be
installed already, but nevertheless the flag is a
reminder.
The use of this flag is an opt-in acknowledging
the unstable (alpha) plugin API, the absence of
plugin provenance, and the fact that a plugin
is not part of kustomize.
To be clear, some kustomize plugin downloaded
from the internet might wonderfully transform
k8s config in a desired manner, while also
quietly doing anything the user could do to the
system running `kustomize build`.
## Writing plugins
## Authoring
There are two kinds of plugins, [exec](#exec-plugins) and [Go](#go-plugins).
### Exec plugins
@@ -196,20 +208,21 @@ single argument on its command line - the name of
a YAML file containing its configuration (the file name
provided in the kustomization file).
> TODO: more restrictions on plugin to allow the same exec
> plugin to be specified in a config under both the
> TODO: restrictions on plugin to allow the _same exec
> plugin_ to be targetted by both the
> `generators` and `transformers` fields.
>
> - first arg could be the fixed string
> `generate` or `transform`,
> (the name of the configuration file moves to
> the 2nd arg), or
> - by default an exec plugin behaves as a tranformer
> - or by default an exec plugin behaves as a tranformer
> unless a flag `-g` is provided, switching the
> exec plugin to behave as a generator.
[helm chart inflator]: ../plugin/someteam.example.com/v1/chartinflator
[bashed config map]: ../plugin/someteam.example.com/v1/bashedconfigmap
[sed transformer]: ../plugin/someteam.example.com/v1/sedtransformer
[helm chart inflator]: ../../plugin/someteam.example.com/v1/chartinflator
[bashed config map]: ../../plugin/someteam.example.com/v1/bashedconfigmap
[sed transformer]: ../../plugin/someteam.example.com/v1/sedtransformer
#### Examples
@@ -232,16 +245,27 @@ marshalled resources on `stdin` and capture
### Go plugins
Be sure to read [Go plugin caveats](goPluginCaveats.md).
[Go plugin]: https://golang.org/pkg/plugin/
A [Go plugin] for kustomize looks like this:
A `.go` file can be a [Go plugin] if it declares
'main' as it's package, and exports a symbol to
which useful functions are attached.
It can further be used as a _kustomize_ plugin if
the symbol is named 'KustomizePlugin' and the
attached functions implement the `Configurable`,
`Generator` and `Transformer` interfaces.
A Go plugin for kustomize looks like this:
> ```
> package main
>
> import (
> "sigs.k8s.io/kustomize/pkg/ifc"
> "sigs.k8s.io/kustomize/pkg/resmap"
> "sigs.k8s.io/kustomize/v3/pkg/ifc"
> "sigs.k8s.io/kustomize/v3/pkg/resmap"
> ...
> )
>
@@ -269,27 +293,28 @@ file to be added to the `generators` or
`transformers` field in the kustomization file.
Do one or the other or both as desired.
[secret generator]: ../plugin/someteam.example.com/v1/secretsfromdatabase
[service generator]: ../plugin/someteam.example.com/v1/someservicegenerator
[string prefixer]: ../plugin/someteam.example.com/v1/stringprefixer
[date prefixer]: ../plugin/someteam.example.com/v1/dateprefixer
[secret generator]: ../../plugin/someteam.example.com/v1/secretsfromdatabase
[service generator]: ../../plugin/someteam.example.com/v1/someservicegenerator
[string prefixer]: ../../plugin/someteam.example.com/v1/stringprefixer
[date prefixer]: ../../plugin/someteam.example.com/v1/dateprefixer
[sops encoded secrets]: https://github.com/monopole/sopsencodedsecrets
#### Examples
* [secret generator] - Generate secrets from a database.
* [service generator] - Generate a service from a name and port argument.
* [service generator] - generate a service from a name and port argument.
* [string prefixer] - uses the value in `metadata/name` as the prefix.
This particular example exists to show how a plugin can
transform the behavior of a plugin. See the
`TestTransformedTransformers` test in the `target` package.
* [date prefixer] - prefix the current date to resource names, a simple
example used to modify the string prefixer plugin just mentioned.
* All the builtin plugins [here](../plugin/builtin).
* [secret generator] - generate secrets from a toy database.
* [sops encoded secrets] - a more complex secret generator.
* [All the builtin plugins](../../plugin/builtin).
User authored plugins are
on the same footing as builtin operations.
A plugin can be both a generator and a
A Go plugin can be both a generator and a
transformer. The `Generate` method will run along
with all the other generators before the
`Transform` method runs.
@@ -306,43 +331,3 @@ go build -buildmode plugin \
-o $d/${kind}.so $d/${kind}.go
```
#### Caveats
Go plugins allow kustomize extensions that run
without the cost marshalling/unmarshalling all
resource data to/from a subprocess for each plugin
run.
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
Go plugins work as [defined][Go plugin], but fall
short of common notions associated with the word
_plugin_. Go plugin compilation creates an [ELF]
formatted `.so` file, which by definition has no
information about the provenance of the object
code. Skew between the compilation conditions
(versions of package dependencies, `GOOS`,
`GOARCH`) of the main program ELF and the plugin
ELF will cause plugin load failure.
Exec plugins also lack provenance, but won't
complain about compilation skew.
In either case, a sensible way to share a plugin
is as a tar file of source code, tests and
associated data, unpackable under
`$XDG_CONFIG_HOME/kustomize/plugin` (exactly where
one would develop a plugin).
[Go modules]: https://github.com/golang/go/wiki/Modules
In the case of a Go plugin, an end user accepting
a shared plugin must compile both kustomize and
the plugin. Tooling could be built to make Go
_plugin sharing_ easier, but this requires some
critical mass of _plugin authoring_, which in turn
is hampered by confusion around sharing.
[Go modules], once they are more widely adopted,
will solve one of the biggest plugin sharing
difficulties - ambiguous plugin vs host
dependencies.

View File

@@ -0,0 +1,229 @@
# Exec plugin on linux in 60 seconds
This is a (no reading allowed!) 60 second copy/paste guided
example. Full plugin docs [here](README.md).
This demo writes and uses a somewhat ridiculous
_exec_ plugin (written in bash) that generates a
`ConfigMap`.
This is a guide to try it without damaging your
current setup.
#### requirements
* linux, git, curl, Go 1.12
## Make a place to work
```
DEMO=$(mktemp -d)
```
## Create a kustomization
Make a kustomization directory to
hold all your config:
```
MYAPP=$DEMO/myapp
mkdir -p $MYAPP
```
Make a deployment config:
```
cat <<'EOF' >$MYAPP/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: the-deployment
spec:
replicas: 3
template:
spec:
containers:
- name: the-container
image: monopole/hello:1
command: ["/hello",
"--port=8080",
"--date=$(THE_DATE)",
"--enableRiskyFeature=$(ENABLE_RISKY)"]
ports:
- containerPort: 8080
env:
- name: THE_DATE
valueFrom:
configMapKeyRef:
name: the-map
key: today
- name: ALT_GREETING
valueFrom:
configMapKeyRef:
name: the-map
key: altGreeting
- name: ENABLE_RISKY
valueFrom:
configMapKeyRef:
name: the-map
key: enableRisky
EOF
```
Make a service config:
```
cat <<EOF >$MYAPP/service.yaml
kind: Service
apiVersion: v1
metadata:
name: the-service
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 8666
targetPort: 8080
EOF
```
Now make a config file for the plugin
you're about to write.
This config file is just another k8s resource
object. The values of its `apiVersion` and `kind`
fields are used to _find_ the plugin code on your
filesystem (more on this later).
```
cat <<'EOF' >$MYAPP/cmGenerator.yaml
apiVersion: myDevOpsTeam
kind: SillyConfigMapGenerator
metadata:
name: whatever
argsOneLiner: Bienvenue true
EOF
```
Finally, make a kustomization file
referencing all of the above:
```
cat <<EOF >$MYAPP/kustomization.yaml
commonLabels:
app: hello
resources:
- deployment.yaml
- service.yaml
generators:
- cmGenerator.yaml
EOF
```
Review the files
```
ls -C1 $MYAPP
```
## Make a home for plugins
Plugins must live in a particular place for
kustomize to find them.
This demo will use the ephemeral directory:
```
PLUGIN_ROOT=$DEMO/kustomize/plugin
```
The plugin config defined above in
`$MYAPP/cmGenerator.yaml` specifies:
> ```
> apiVersion: myDevOpsTeam
> kind: SillyConfigMapGenerator
> ```
This means the plugin must live in a directory
named:
```
MY_PLUGIN_DIR=$PLUGIN_ROOT/myDevOpsTeam/sillyconfigmapgenerator
mkdir -p $MY_PLUGIN_DIR
```
The directory name is the plugin config's
_apiVersion_ followed by its lower-cased _kind_.
A plugin gets its own directory to hold itself,
its tests and any supplemental data files it
might need.
## Create the plugin
There are two kinds of plugins, _exec_ and _Go_.
Make an _exec_ plugin, installing it to the
correct directory and file name. The file name
must match the plugin's _kind_ (in this case,
`SillyConfigMapGenerator`):
```
cat <<'EOF' >$MY_PLUGIN_DIR/SillyConfigMapGenerator
#!/bin/bash
# Skip the config file name argument.
shift
today=`date +%F`
echo "
kind: ConfigMap
apiVersion: v1
metadata:
name: the-map
data:
today: $today
altGreeting: "$1"
enableRisky: "$2"
"
EOF
```
By definition, an _exec_ plugin must be executable:
```
chmod a+x $MY_PLUGIN_DIR/SillyConfigMapGenerator
```
## Download kustomize 3.0.0
```
mkdir -p $DEMO/bin
gh=https://github.com/kubernetes-sigs/kustomize/releases/download
url=$gh/v3.0.0-pre/kustomize_3.0.0-pre_linux_amd64
curl -o $DEMO/bin/kustomize -L $url
chmod u+x $DEMO/bin/kustomize
```
## Review the layout
```
tree $DEMO
```
## Build your app, using the plugin:
```
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
```
Above, if you had set
> ```
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
> ```
there would be no need to use `XDG_CONFIG_HOME` in the
_kustomize_ command above.

View File

@@ -0,0 +1,117 @@
[plugin package]: https://golang.org/pkg/plugin
[Go modules]: https://github.com/golang/go/wiki/Modules
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
[tensorflow plugin]: https://www.tensorflow.org/guide/extend/op
# Go plugin Caveats
A _Go plugin_ is a compilation artifact described
by the Go [plugin package]. It is built with
special flags and cannot run on its own.
It must be loaded into a running Go program.
> A normal program written in Go might be usable
> as _exec plugin_, but is not a _Go plugin_.
Go plugins allow kustomize extensions that run
without the cost marshalling/unmarshalling all
resource data to/from a subprocess for each plugin
run. The Go plugin API assures a certain level of
consistency to avoid confusing downstream
transformers.
Go plugins work as described in the [plugin
package], but fall short of common notions
associated with the word _plugin_.
## The skew problem
Go plugin compilation creates an [ELF] formatted
`.so` file, which by definition has no information
about the provenance of the object code.
Skew between the compilation conditions (versions
of package dependencies, `GOOS`, `GOARCH`) of the
main program ELF and the plugin ELF will cause
plugin load failure, with non-helpful error
messages.
Exec plugins also lack provenance, but won't fail
due to compilation skew.
In either case, the only sensible way to share a
plugin is as some kind of _bundle_ (a git repo
URL, a git archive file, a tar file, etc.)
containing source code, tests and associated data,
unpackable under
`$XDG_CONFIG_HOME/kustomize/plugin`.
In the case of a Go plugin, an _end user_
accepting a shared plugin _must compile both
kustomize and the plugin_.
This means a one-time run of
```
GOPATH=${whatever} go get \
sigs.k8s.io/kustomize/cmd/kustomize@${releaseVersion}
```
and then a normal development cycle using
```
go build -buildmode plugin \
-o ${wherever}/${kind}.so ${wherever}/${kind}.go
```
with paths and the release version tag (e.g. `v3.0.0`)
adjusted as needed.
For comparison, consider what one
must do to write a [tensorflow plugin].
## Why support Go plugins?
### Safety
The Go plugin developer sees the same API offered
to native kustomize operations, assuring certain
semantics, invariants, checks, etc. An exec
plugin sub-process dealing with this via
stdin/stdout will have an easier time screwing
things up for downstream transformers and
consumers.
Minor point: if the plugin reads files via
the kustomize-provided file `Loader` interface, it
will be constrained by kustomize file loading
restrictions. Of course, nothing but a code audit
prevents a Go plugin from importing the `io` package
and doing whatever it wants.
### Debugging
A Go plugin developer can debug the plugin _in
situ_, setting breakpoints inside the plugin and
elsewhere while running a plugin in feature tests.
To get the best of both worlds (shareability and safety),
a developer can write an `.go` program that functions
as an _exec plugin_, but can be processed by `go generate`
to emit a _Go plugin_ (or vice versa).
### Unit of contribution
All the builtin generators and transformers
are themselves Go plugins. This means that
the kustomize maintainers can promote a contributed
plugin to a builtin without needing code changes
(beyond those mandated by normal code review).
### Ecosystems grow through use
Tooling could ease Go plugin _sharing_, but this
requires some critical mass of Go plugin
_authoring_, which in turn is hampered by
confusion around sharing. [Go modules], once they
are more widely adopted, will solve the
biggest plugin sharing difficulty: ambiguous
plugin vs host dependencies.

View File

@@ -0,0 +1,308 @@
# Go Plugin Guided Example for Linux
This is a (no reading allowed!) 60 second copy/paste guided
example. Full plugin docs [here](README.md).
[SopsEncodedSecrets repository]: https://github.com/monopole/sopsencodedsecrets
[Go plugin]: https://golang.org/pkg/plugin
This demo uses a Go plugin, `SopsEncodedSecrets`,
that lives in the [sopsencodedsecrets repository].
This is an inprocess [Go plugin], not an
sub-process exec plugin that happens to be written
in Go (which is another option for Go authors).
This is a guide to try it without damaging your
current setup.
#### requirements
* linux, git, curl, Go 1.12
* Google cloud (gcloud) install
* a Google account (will use Google kms -
volunteers needed to convert to a GPG example).
## Make a place to work
```
DEMO=$(mktemp -d)
```
## Install kustomize
Need v3.0.0 for what follows:
```
GOBIN=$DEMO/bin go get sigs.k8s.io/kustomize/v3/cmd/kustomize@v3.0.0-pre
```
## Make a home for plugins
A kustomize plugin is fully determined by
its configuration file and source code.
[required fields]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
Kustomize plugin configuration files are formatted
as kubernetes resource objects, meaning
`apiVersion`, `kind` and `metadata` are [required
fields] in these config files.
The kustomize program reads the config file
(because the config file name appears in the
`generators` or `transformers` field in the
kustomization file), then locates the Go plugin's
object code at the following location:
> ```
> $XGD_CONFIG_HOME/kustomize/plugin/$apiVersion/$lKind/$kind.so
> ```
where `lKind` holds the lowercased kind. The
plugin is then loaded and fed its config, and the
plugin's output becomes part of the overall
`kustomize build` process.
The same plugin might be used multiple times in
one kustomize build, but with different config
files. Also, kustomize might customize config
data before sending it to the plugin, for whatever
reason. For these reasons, kustomize owns the
mapping between plugins and config data; it's not
left to plugins to find their own config.
This demo will house the plugin it uses at the
ephemeral directory
```
PLUGIN_ROOT=$DEMO/kustomize/plugin
```
and ephemerally set `XGD_CONFIG_HOME` on a command
line below.
### What apiVersion and kind?
At this stage in the development of kustomize
plugins, plugin code doesn't know or care what
`apiVersion` or `kind` appears in the config file
sent to it.
The plugin could check these fields, but it's the
remaining fields that provide actual configuration
data, and at this point the successful parsing of
these other fields are the only thing that matters
to a plugin.
This demo uses a plugin called _SopsEncodedSecrets_,
and it lives in the [SopsEncodedSecrets repository].
Somewhat arbitrarily, we'll chose to install
this plugin with
```
apiVersion=mygenerators
kind=SopsEncodedSecrets
```
### Define the plugin's home dir
By convention, the ultimate home of the plugin
code and supplemental data, tests, documentation,
etc. is the lowercase form of its kind.
```
lKind=$(echo $kind | awk '{print tolower($0)}')
```
### Download the SopsEncodedSecrets plugin
In this case, the repo name matches the lowercase
kind already, so we just clone the repo and get
the proper directory name automatically:
```
mkdir -p $PLUGIN_ROOT/${apiVersion}
cd $PLUGIN_ROOT/${apiVersion}
git clone git@github.com:monopole/sopsencodedsecrets.git
```
Remember this directory:
```
MY_PLUGIN_DIR=$PLUGIN_ROOT/${apiVersion}/${lKind}
```
### Try the plugin's own test
Plugins may come with their own tests.
This one does, and it hopefully passes:
```
cd $MY_PLUGIN_DIR
go test SopsEncodedSecrets_test.go
```
Build the object code for use by kustomize:
```
cd $MY_PLUGIN_DIR
go build -buildmode plugin -o ${kind}.so ${kind}.go
```
This step may succeed, but kustomize might
ultimately fail to load the plugin because of
dependency [skew].
[skew]: https://github.com/kubernetes-sigs/kustomize/blob/master/docs/plugins/README.md#caveats
[used in this demo]: #install-kustomize
On load failure
* be sure to build the plugin with the same
version of Go (_go1.12_) on the same `$GOOS`
(_linux_) and `$GOARCH` (_amd64_) used to build
the kustomize being [used in this demo].
* change the plugin's dependencies in its `go.mod`
to match the versions used by kustomize (check
kustomize's `go.mod` used in its tagged commit).
Lacking tools and metadata to allow this to be
automated, there won't be a Go plugin ecosystem.
Kustomize has adopted a Go plugin architecture as
to ease accept new generators and transformers
(just write a plugin), and to be sure that native
operations (also constructed and tested as
plugins) are compartmentalized, orderable and
reusable instead of bizarrely woven throughout the
code as a individual special cases.
## Create a kustomization
Make a kustomization directory to
hold all your config:
```
MYAPP=$DEMO/myapp
mkdir -p $MYAPP
```
Make a config file for the SopsEncodedSecrets plugin.
Its `apiVersion` and `kind` allow the plugin to be
found:
```
cat <<EOF >$MYAPP/secGenerator.yaml
apiVersion: ${apiVersion}
kind: ${kind}
metadata:
name: forbiddenValues
namespace: production
file: myEncryptedData.yaml
keys:
- ROCKET
- CAR
EOF
```
This plugin expects to find more data in
`myEncryptedData.yaml`; we'll get to that shortly.
Make a kustomization file referencing the plugin
config:
```
cat <<EOF >$MYAPP/kustomization.yaml
commonLabels:
app: hello
generators:
- secGenerator.yaml
EOF
```
Now for the hard part. Generate the real encrypted data.
### Assure you have a Google Cloud sops key ring.
We're going to use [sops](https://github.com/mozilla/sops) to encode a file.
Try this:
```
gcloud kms keys list --location global --keyring sops
```
If it succeeds, presumably you've already
created keys and placed them in a keyring called `sops`.
If not, do this:
```
gcloud kms keyrings create sops --location global
gcloud kms keys create sops-key --location global \
--keyring sops --purpose encryption
```
Extract your keyLocation for use below:
```
keyLocation=$(\
gcloud kms keys list --location global --keyring sops |\
grep GOOGLE | cut -d " " -f1)
echo $keyLocation
```
### Install `sops`
```
GOBIN=$DEMO/bin go install go.mozilla.org/sops/cmd/sops
```
### Create data encrypted with your Google Cloud key
Create raw data to encrypt:
```
cat <<EOF >$MYAPP/myClearData.yaml
VEGETABLE: carrot
ROCKET: saturn-v
FRUIT: apple
CAR: dymaxion
EOF
```
Encrypt the data into file the plugin wants to read:
```
$DEMO/bin/sops --encrypt \
--gcp-kms $keyLocation \
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
```
Review the files
```
tree $DEMO
```
## Build your app, using the plugin:
```
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
```
This should emit a kubernetes secret, with
encrypted data for the names `ROCKET` and `CAR`.
Above, if you had set
> ```
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
> ```
there would be no need to use `XDG_CONFIG_HOME` in the
_kustomize_ command above.

View File

@@ -13,6 +13,6 @@ History
* Oct 2017: s/kexpand/kinflate/
* Sep 2017: kexpand [starts](https://github.com/kubernetes/kubectl/pull/65)
in [github.com/kubernetes/kubectl]
* Aug 2018: [DAM] authored by Brian Grant
* Aug 2017: [DAM] authored by Brian Grant
[DAM]: https://docs.google.com/document/d/1cLPGweVEYrVqQvBLJg6sxV-TrE5Rm2MNOBA_cxZP2WU

View File

@@ -1,6 +1,5 @@
# kustomize 2.1.0
[Go modules]: https://github.com/golang/go/wiki/Modules
[generator options]: ../examples/generatorOptions.md
[imgModules]: images/goModules.png
@@ -14,7 +13,7 @@
[bases]: glossary.md#base
[_base_]: glossary.md#base
[kustomize inventory object documentation]: inventory_object.md
[kustomize plugin documentation]: plugins.md
[kustomize plugin documentation]: plugins
[root]: glossary.md#kustomization-root
[transformer configs]: ../examples/transformerconfigs
[v1.0.9]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v1.0.9
@@ -26,6 +25,8 @@ Go modules, resource ordering respected, generator and transformer plugins, ease
loading restrictions, the notion of inventory, eased replica count modification.
About ~90 issues closed since [v2.0.3] in ~400 commits.
Download [here][v2.1.0].
## Go modules
![gopher with boxes][imgModules]
@@ -123,7 +124,7 @@ For more information, see the
The following usage:
```
kustomize build --load_restrictions none $target
kustomize build --load_restrictor none $target
```
allows a `kustomization.yaml` file used in this

242
docs/v2.1.0_changelog.md Normal file
View File

@@ -0,0 +1,242 @@
e1b59c93 2.1 release notes
2cf8371a Add --force flag to modify annotations and labels
0fa2d9c3 Add --reorder flag.
2d70526e Add ConfigMapGenerator and test.
4df57686 Add SedTransformerTest
68f6b0be Add Webhookconfiguration in default name references
1545e07d Add a plugin loader test.
449175e3 Add a sorting plugin.
aafc23a6 Add annotation transformer.
9bd456c6 Add bug report page.
0df58838 Add builtin JSON patch transformer
621bb7c6 Add builtin NameTransformer plugin.
45901219 Add builtin label transformer.
79906d73 Add builtin namespace transformer plugin
d9b0c4c8 Add copy method to VarSet
798b61c8 Add copy method to VarSet
d9259397 Add documentation for the replicas transform
2744e058 Add entry for inventory in fields.md
3f2acc90 Add faq
99391157 Add goplugin KV generator example.
3b8c5ee9 Add load_restrictor flag.
8f413f52 Add name reference of storageClass
5e054c9d Add originalName field to resource.
bb9b3163 Add script to run cloud build 'locally'.
ffc16d51 Add secret generator.
755dd3d0 Add some utilities.
c9d903cc Add support for escaping characters in Doc
2825888f Add test for builtin secretgenerator plugin.
e6c1b141 Add test for transformers/image custom config
644dc4b9 Add test showing shared patches disallowed.
96707645 Add test showing shared patches disallowed.
8d9897d5 Add the rmBuilder test helper.
000f81b2 Added test to verify usage of multiline strip chomp in configMapGenerator
5e7ddc86 Adds precommit for windows + documentation
5e33ac4a Allow nil label and annotaion
f38d0c69 Apply LimitRange resources before workloads
b28aaae6 Break a bad dep.
76d370a8 Chart last mile example
f621543d Cleanup kusttarget.
16fe7ced Cleanup plugin builds.
d4842ebd Cleanup the replica plugin implementation.
8991bcb3 Collect existing internal pkgs under one roof.
d0cf0473 Convert image transformer test to a more readable format
81c98c85 Convert inventory transformer to plugin, reduce k8sdeps.
c9a5c03e Convert legacy file based test to in-memory
2e71a3b8 Convert plugins to accept bytes instead of unstruct.
52faa01e Cover #1155 with a test.
fe67bcdb Cut more ties to k8sdeps
e1389649 Cut more ties to k8sdeps
175c754f Define a plugin compiler.
9a850710 Delete kustomizationerror.
6a106546 Delete the KV plugin code.
9a4cb6c9 Delete unused code.
cc531af6 Deprecate 'bases:' field.
939de0cd Dogfood the plugin framework.
267eec55 Fix 918
3a44508d Fix error message
0f571b91 Fix field names
9a4692e6 Fix function comments based on best practices from Effective Go
e207ae4c Fix incorrect default varrefs for CronJob volumeMounts
3d0e2907 Fix markdownlint warnings
31091a8d Fix missing varrefs for CronJob, Job, ReplicaSet
cefb64b6 Fix path
a9145702 Fix some comment nits.
7295a9b3 Fix some nits.
b92ee256 Fix some nits.
57eecd74 Fix test broken by the change in ordering.
e079c20c Fix typo
559efd64 Fix typo in namereference path for cronjobs initContainers.
a7a2589e Fix yaml in generator examples.
9b6f8f0c Format generated code.
2545ea10 Helm chart generator exec plugin
02f37953 Idiom fixes.
5000a2e5 Implement replica transformer as patch alternative
9c36ac28 Improve comments in name transform code.
58d9a510 Improve plugin doc.
529db049 Introduce envs field.
6d309b52 Introduce stacked transformers.
abf538d8 Keep backward compatibility for image transformer
7e12918f Keep var refernce in resources
7130e3ff Leave defautconfig empty for images
3e85c458 Load default config for image transformer
4162dbc2 Maintain resources in order loaded.
3a7c8a03 Make builtin the default pluginType
bcc7412e Make kusttestharness shareable.
cfb0c5ef Make plugin dir match Go conventions.
8d4b6452 Make the replica transformer `kind` aware.
3f8b1fe0 Make the replica transformer `kind` aware.
c470982c Make transformer configs array-aware
cd19d426 Merge remote-tracking branch 'upstream/master'
0b555e1b Modify tests to present expected data in unsorted order.
f17698a8 More release note tweaks.
9a12b551 Move accumulator code to its own package.
ee728d58 Move hashing code out of k8sdeps.
fd2248e7 Move hashing transformer out of k8sdeps.
d2c93065 Move kustomize main to cmd directory.
4bc31f4b Move pluginator to cmd directory.
5653ae69 One plugin per dir.
a09b42b3 Order ValidatingWebhookConfig last.
c63ebbdf Preserve order when merging.
11bb176a Push suffix/prefix code to plugin.
103c1b3a Put goplugins behind flag.
2796e545 Put windows test script next to pre-commit.sh
47c96548 Reduce k8ds deps
4f429d6b Reduce time required for cloning remote bases
b67d713b Remove dependency on ghodss/yaml
78cdff6d Remove kv plugins from docs.
3c58c9d1 Remove local load restrictions.
8767495b Remove some duped code.
b32e041b Remove some duped code.
8c133ef0 Removes mdrip testing for Windows
a2e4f6cf Rename ./bin dir to ./travis.
0e4f9acb Rename ErrorIfNotEqual to ErrorIfNotEqualSets
49d94f53 Rename the prefix/suffix transformer.
c06b9507 Secret/configmap factory cleanup.
3a01a63a Simplify code base.
76a31798 Simplify plugin loader code.
3a85fcd3 Simplify some of the plugin testing code.
3011f180 Sort default varReference config by kind, path
44ac9a9f Standalone ChartInflator plugin test.
5614649d Standalone service generator test
f311ba8d Support custom config for image transformer
e191ff53 Switch to vgo
a5660415 Tell homebrew to update.
ed03818e This commit enhances the UnstructAdapter
e0d2fa57 Translated kustomization.yaml into markdown in fields.md. Updated links to point to fields.md
a352ff39 True and false are mysterious.
7971ac1c Tweak secret docs.
852e7ed5 Typo Fix
1dd448e6 Update 2.1 release notes before release.
0f50be87 Update ChartInflatorExec
72fd31fd Update FAQ.md
185ae510 Update README.md
fa4dc14c Update all.go
ae0510f6 Update chartinflatorexecplugin_test.go
08b6f6f4 Update golinter to 1.17.1
4502e8ff Update inventory_object.md
ca478016 Update minecraft version in example.
efcf8757 Update order of resources to include psps
64bd0692 Update plugins.md
0045d7b7 Update plugins.md
54d1c557 Update plugins.md
86534869 Update remoteBuild.md
2ec8189c Update remoteBuild.md
1afc6c77 Update strategic-merge link
c1dea667 Update travis file.
9edecffc Update v_2.1.0.md
f2295acf Update v_2.1.0.md
71f44d64 Update v_2.1.0.md
bb69e9e7 Updates documentation for support and source
2490e605 Updates in image transformer (#911)
c6476d16 Upgrade version of minecraft used in tests.
af2b101f Use go modules in cloud builder.
5be42092 Vars should expand in ingress/spec/tls/secretName
9203478a Write individual files to output path if it is a directory
942e36e1 a few more changes
5b18c4de add ItemId type
6f4b104c add admission webhook types in the default cluster-scoped resource list
9fc4d388 add builtin envfiles plugin
a8465c95 add builtin files plugin
388d5c2d add builtin plugins
7fa02ce5 add document to explain inventory field (#997)
142879ec add example for transformer plugin
74937321 add generator plugins
deaf0779 add generators/transformers fields in kusotmization.yaml
ba43ecbc add goplugin for exec generators and transformers
d5abe39d add inventory package and refactor inventory transformer
f7cd44be add job initcontainer to varreference config
53a22cbe add note for availability in kubectl
2675bf4b add older release notes
ca6228b5 add remove resource subcommand
18f63282 add secret and configmap generator plugins
f6e01cfd add support for exec plugins
dd59eb38 add test case
c724cb71 add test for empty patch file
445f7392 add test for ensuirng the loader root is correctly passed
a8c476f7 add the Chhinese translation of docs list & install (#1022)
fb9e00bf add the unstructured to ENV of exec plugins
4f1a2350 add transformer plugins
237c54f4 add tutorial for custom images transformer
b4dbac1b add validation transformer
89243aed add zh dir
b07bea40 added field tables
3168b2a1 added link to examples
7a54d998 added links to section headings
e9a3f9f5 address comments
86f0f9a4 address comments
e5d730e1 address comments
ad7ca697 address comments
65886f12 address comments
1d65f24b adds documentation for choco package
e4159d94 allow to set image without a tag
b4fc1e43 change field name: prune -> inventory
404884e2 chinese helloworld doc
7b82154c correct spelling, minor word ordering
ca4aea17 doc/glossary updates for v2.1
3ff5c793 docs add kubectl command
c250f75d enable go module in the integration test (#1153)
3e6ee23a fix README
70def866 fix a link
e6d1de0d fix commonLabels spec for volumeClaimTemplates
4848987a fix configmap/secret name references for cronjobs with projected volumes
fa552d77 fix help msg for set image cmd
a64baed4 fix link
1bd7afe6 fix linter
822420e4 fix mergeFlags
bcb697eb fix namespace transformer for cluster-scoped resources
7765bdd9 fix some doc
a889f97f fix some example ptrs
56965a00 fix test
927b497f fix tests
61d46c26 fix the boilerplate copyright header (#1064)
03751372 fix the bug for patching CRDs
93908602 fix the bug for setting annotations when triggering transformers
21a0cba4 fix the regression of building remote url (#935)
7ab4d284 fix translation
62d3200e fix typo in namereference where serviceaccount name would not resolve
826affb8 generate configmap for pruning
cd9572e0 hey
5c471965 honor XDG_CONFIG_HOME
2aa7e30a minimize test
29cbec37 move parse helpers to util
fc8063f7 pass loader root to exec plugins
c1e2b27c pass resources to transformer plugin all together
e287f615 readded kustomization.yaml
f850ca63 remove extra comment
e17d3033 reorganize the examples layout
bfc3655b skip adding namespace when the object is empty
440d0361 some transformer plugins
61cf67fb start v2.1 release notes
403ede78 tests: demonstrate issue with JSON patch when base adds name prefix
b4efc833 translate example list
16924d79 translate kustomization.yaml
faaf6002 translate kustomization.yaml & update zh/README
540e4023 typo in README
748c88c2 update PruneString for resources
b60fca05 update edit add secrets/configmaps to use plugins
c836de5c update error msg
e4956c55 update examples/README.md
b2c87522 update validation transformer example text
d2103dbf updated grouping and added brief descriptions of sections

72
docs/v3.0.0.md Normal file
View File

@@ -0,0 +1,72 @@
# kustomize 3.0.0
This release is basically [v2.1.0](v2.1.0.md),
with some post-v2.1.0 bugs fixed and a `v3` in Go
package paths.
[plugin]: https://github.com/kubernetes-sigs/kustomize/tree/master/docs/plugins
The major version increment to `v3` puts a new
floor on a stable API for [plugin] developers
(both _Go_ plugin developers and _exec_ plugin
developers who happen to use Go), to carry them
through the coming series of minor releases and
patches.
### Why so soon after v2.1.0?
[semantic versioning]: https://semver.org
[Go modules doc]: https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher
[versioning policy]: versioningPolicy.md
We made a mistake - v2.1.0 should have been
v3.0.0. Per the [Go modules doc] (which have
improved a great deal recently), a release that's
already tagged v2 or higher should increment the
major version when performing their first Go
module-based release.
This advice applies to kustomize, since it was
already at major version 2 when it began using Go
modules to state _its own_ dependencies in v2.1.0.
But the more important reason for `v3` is a change
to the kustomize [versioning policy], forced by
the introduction of plugins.
Historically, kustomize's [versioning policy]
didn't involve Go modules and addressed _only_ the
command line tool's behavior and the fields in a
kustomization file. The underlying packages were
an implementation detail, not under semantic
versioning, because they weren't intended for
export (and should have all been under
`internal`). Thus although the v2.1.0 CLI is
backward compatible with v2.0.3, the underlying
package APIs are not.
[minimal version selection]: https://research.swtch.com/vgo-mvs
With Go modules, the `go` tool must assume that Go
packages respect [semantic versioning], so it can
perform [minimal version selection].
With the introduction of alpha plugins, kustomize
sub-packages - in particular `loader` and
`resmap` - become part of an API formally exposed
to plugin authors, and so must be semantically
versioned. This allows plugins defined in other
repositories to clarify that they depend on
kustomize v3.0.0, and not see confusing errors
arising from incompatibilities between v2.1.0 and
v2.0.3. Hence, the jump to v3.
Aside - the set of kustomize packages outside
`internal` is too large, and over time, informed
by package use, this API surface must shrink.
Such shrinkage will trigger a major version
increment.

View File

@@ -1,13 +1,15 @@
# Versioning
Running `kustomize` means one is running a
particular version of a program, reading a
particular version of a [kustomization] file.
particular version of a program, using a
particular version of underlying packages, and
reading a particular version of a [kustomization]
file.
## Program Versioning
The command `kustomize version` prints a three
field version tag (e.g. `1.0.11`) that aspires to
field version tag (e.g. `v3.0.0`) that aspires to
[semantic versioning].
When enough changes have accumulated to
@@ -15,6 +17,27 @@ warrant a new release, a [release process]
is followed, and the fields in the version
number are bumped per semver.
## Kustomize packages
At the time of writing, the kustomize program and
the packages it uses (and exports) are in the same
Go module (see the top level `go.mod` file in the
repo).
[trailing major version indicator]: https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher
Thus, they share the module's version number, per
its git tag (e.g. `v3.0.0`), whose major verion
number matches the [trailing major version
indicator] in the module name (e.g. the `/v3` in
`sigs.k8s.io/kustomize/v3`).
The non-internal packages in the Go module
`sigs.k8s.io/kustomize/v3`, introduced in
[v3.0.0](v3.0.0.md), conform to [semantic
versioning].
## Kustomization File Versioning
At the time of writing (circa release of v2.0.0):
@@ -212,7 +235,7 @@ moment forward.
[special]: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#resources
[k8s API]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[conventions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[release process]: ../build/README.md
[release process]: ../releasing/README.md
[kustomization]: glossary.md#kustomization
[`kind`]: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#types-kinds
[`apiVersion`]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning

View File

@@ -35,5 +35,5 @@ chmod u+x kustomize
<!-- @installkustomize @test -->
```
go get sigs.k8s.io/kustomize
go install sigs.k8s.io/kustomize/v3/cmd/kustomize
```

View File

@@ -8,10 +8,9 @@
* [术语表](../glossary.md) - 用于消除术语歧义。
* [kustomization.yaml](kustomization.yaml) - 包含
[kustomization](../glossary.md#kustomization) 所有字段的示例文件。
* [Kustomize 字段](fields.md) - 介绍 [kustomization](../glossary.md#kustomization) 文件中各字段的含义。
* [插件](../plugins.md) - 使用自定义的资源生成器和资源转换器来拓展 kustomize 功能。
* [插件](../plugins) - 使用自定义的资源生成器和资源转换器来拓展 kustomize 功能。
* [工作流](workflows.md) - 使用定制及使用现成配置使用的一些步骤。
@@ -20,16 +19,19 @@
## 发行说明
* [2.1](../v_2.1.0.md) - 日期待定,预计2019年5月下旬。
* [3.0](../v3.0.0.md) - 2019年6月下旬,插件开发者发布
* [2.0](../v_2.0.0.md) - 2019年3月
* [2.1](../v2.1.0.md) - 2019年6月18日
插件、有序资源等。
* [2.0](../v2.0.0.md) - 2019年3月
可以在 [kubectl v1.14][kubectl] 中使用 kustomize [v2.0.3] 。
* [1.0](../v_1.0.1.md) - 2018年5月
* [1.0](../v1.0.1.md) - 2018年5月
于 [kubectl repository] 开发后的首发版本。
## 政策
## 行为守则
* [版本控制](../versioningPolicy.md) - kustomize 代码及 kustomization 文件的版本控制策略。

436
docs/zh/fields.md Normal file
View File

@@ -0,0 +1,436 @@
# Kustomization 文件字段
介绍 [kustomization](../glossary.md#kustomization) 文件中各字段的含义。
## Resources
现有可定制对象。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
|[resources](#resources) | list | 包含 k8s API 对象的文件,或其他包含 kustomizations 文件的目录。 |
|[CRDs](#crds)| list | CDR 文件,以允许在资源列表中指定自定义资源。 |
## Generators
生成可定制的对象。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
|[configMapGenerator](#configmapgenerator)| list | 列表中的每个条目都将创建一个 ConfigMap 它是n个 ConfigMap 的生成器)。 |
|[secretGenerator](#secretgenerator)| list | 此列表中的每个条目都将创建一个 Secret 资源它是n个 secrets 的生成器)。 |
|[generatorOptions](#generatoroptions)| string | generatorOptions 可以修改所有 ConfigMapGenerator 和 SecretGenerator 的行为。 |
|[generators](#generators)| list | [插件](../plugins)配置文件。 |
## Transformers
可用的转换。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| [commonLabels](#commonlabels) | string | 为所有资源和 selectors 增加 Labels 。 |
| [commonAnnotations](#commonannotations) | string | 为所有资源增加 Annotations 。 |
| [images](#images) | list | 修改镜像的名称、tag 或 image digest ,而无需使用 patches 。 |
| [inventory](#inventory) | struct | 用于生成一个包含清单信息的对象。 |
| [namespace](#namespace) | string | 为所有 resources 添加 namespace 。 |
| [namePrefix](#nameprefix) | string | 该字段的值将添加在所有资源的名称之前。 |
| [nameSuffix](#namesuffix) | string | 该字段的值将添加在所有资源的名称后面。 |
| [replicas](#replicas) | list | 修改资源的副本数。 |
| [patchesStrategicMerge](#patchesstrategicmerge) | list | 此列表中的每个条目都应可以解析为部分或完整的资源定义文件。 |
| [patchesJson6902](#patchesjson6902) | list | 列表中的每个条目都应可以解析为 kubernetes 对象和将应用于该对象的 JSON patch 。 |
| [transformers](#transformers) | list | [插件](../plugins)配置文件。 |
## Meta
[k8s metadata]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| [vars](#vars) | string | 获取一个对象中的字段并插入到另外的对象中。 |
| [apiVersion](#apiversion) | string | [k8s metadata] 字段。 |
| [kind](#kind) | string | [k8s metadata] 字段。 |
----
### apiVersion
该字段默认值为:
```
apiVersion: kustomize.config.k8s.io/v1beta1
```
### bases
`bases` 字段在 v2.1.0 中已被弃用。
该条目已被移动到 [resources](#resources) 字段中。
### commonLabels
为所有资源和 selectors 增加 Labels
```
commonLabels:
someName: someValue
owner: alice
app: bingo
```
### commonAnnotations
为所有资源增加 Annotations ,和 labels 一样是 key:value 的键值对。
```
commonAnnotations:
oncallPager: 800-555-1212
```
### configMapGenerator
列表中的每个条目都将创建一个 ConfigMap 它是n个 ConfigMap 的生成器)。
下面的示例创建了两个 ConfigMaps
- 一个具有给定文件的名称和内容
- 另一个包含 key/value 键值对数据
每个 configMapGenerator 项都可以使用 `behavior: [create|replace|merge]` 参数。
允许 overlay 从父级修改或替换现有的 configMap。
```
configMapGenerator:
- name: myJavaServerProps
files:
- application.properties
- more.properties
- name: myJavaServerEnvVars
literals:
- JAVA_HOME=/opt/java/jdk
- JAVA_TOOL_OPTIONS=-agentlib:hprof
```
### crds
此列表中的每个条目都应该是自定义资源定义CRD文件的相对路径。
该字段的存在是为了让 kustomize 知道用户自定义的 CRD ,并对这些类型中的对象应用适当的转换。
典型用例CRD 引用 ConfigMap 对象
在 kustomization 中ConfigMap 对象名称可能会通过 namePrefix 、nameSuffix 或 hashing 来更改 CRD 对象中此 ConfigMap 对象的名称,
引用时需要以相同的方式使用 namePrefix 、 nameSuffix 或 hashing 来进行更新。
Annotations 可以放入 openAPI 的定义中:
- "x-kubernetes-annotation": ""
- "x-kubernetes-label-selector": ""
- "x-kubernetes-identity": ""
- "x-kubernetes-object-ref-api-version": "v1",
- "x-kubernetes-object-ref-kind": "Secret",
- "x-kubernetes-object-ref-name-key": "name",
```
crds:
- crds/typeA.yaml
- crds/typeB.yaml
```
### generatorOptions
generatorOptions 修改所有 [ConfigMapGenerator](#configmapgenerator) 和 [SecretGenerator](#secretgenerator) 的行为。
```
generatorOptions:
# 为所有生成的资源添加 labels
labels:
kustomize.generated.resources: somevalue
# 为所有生成的资源添加 annotations
annotations:
kustomize.generated.resource: somevalue
# disableNameSuffixHash 为 true 时将禁止默认的在名称后添加哈希值后缀的行为
disableNameSuffixHash: true
```
### generators
[插件](../plugins)生成器配置文件列表。
```
generators:
- mySecretGeneratorPlugin.yaml
- myAppGeneratorPlugin.yaml
```
### images
修改镜像的名称、tag 或 image digest ,而无需使用 patches 。例如,对于这种 kubernetes Deployment 片段:
```
containers:
- name: mypostgresdb
image: postgres:8
- name: nginxapp
image: nginx:1.7.9
- name: myapp
image: my-demo-app:latest
- name: alpine-app
image: alpine:3.7
```
可以通过以下方式更改 `image`
- `postgres:8` to `my-registry/my-postgres:v1`,
- nginx tag `1.7.9` to `1.8.0`,
- image name `my-demo-app` to `my-app`,
- alpine's tag `3.7` to a digest value
可以在 *kustomization* 中添加以下内容:
```
images:
- name: postgres
newName: my-registry/my-postgres
newTag: v1
- name: nginx
newTag: 1.8.0
- name: my-demo-app
newName: my-app
- name: alpine
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
```
### inventory
详见 [inventory object](inventory_object.md)。
### kind
该字段默认值为:
```
kind: Kustomization
```
### namespace
为所有 resources 添加 namespace 。
```
namespace: my-namespace
```
### namePrefix
该字段的值将添加在所有资源的名称之前,例如 将资源名称 `wordpress` 变为 `alices-wordpress`
```
namePrefix: alices-
```
### nameSuffix
该字段的值将添加在所有资源的名称后面,例如 将资源名称 `wordpress` 变为 `wordpress-v2`
如果资源类型为 ConfigMap 或 Secret ,则在哈希值之前附加后缀。
```
nameSuffix: -v2
```
### patchesStrategicMerge
此列表中的每个条目都应可以解析为部分或完整的资源定义文件。
这些(也可能是部分的)资源文件中的 name 必须与已经通过 `resources` 加载的 name 字段匹配,或者通过 `bases` 中的 name 字段匹配。这些条目将用于 _patch_(修改)已知资源。
推荐使用小的 patches例如修改内存的 request/limit更改 ConfigMap 中的 env 变量等小的 patches 易于维护和查看,并且易于在 overlays 中混合使用。
```
patchesStrategicMerge:
- service_port_8888.yaml
- deployment_increase_replicas.yaml
- deployment_increase_memory.yaml
```
### patchesJson6902
patchesJson6902 列表中的每个条目都应可以解析为 kubernetes 对象和将应用于该对象的 JSON patch
JSON patch 的文档地址https://tools.ietf.org/html/rfc6902
目标字段指向的 kubernetes 对象的 group、 version、 kind、 name 和 namespace 在同一 kustomization 内 path 字段内容是 JSON patch 文件的相对路径。
patch 文件中的内容可以如下这种 JSON 格式:
```
[
{"op": "add", "path": "/some/new/path", "value": "value"},
{"op": "replace", "path": "/some/existing/path", "value": "new value"}
]
```
也可以使用 YAML 格式表示:
```
- op: add
path: /some/new/path
value: value
- op: replace
path: /some/existing/path
value: new value
```
```
patchesJson6902:
- target:
version: v1
kind: Deployment
name: my-deployment
path: add_init_container.yaml
- target:
version: v1
kind: Service
name: my-service
path: add_service_annotation.yaml
```
### replicas
修改资源的副本数。
例如:对于如下 kubernetes Deployment 片段:
```
kind: Deployment
metadata:
name: deployment-name
spec:
replicas: 3
```
在 kustomization 中添加以下内容将副本数更改为5
```
replicas:
- name: deployment-name
count: 5
```
该字段内容为列表,所以可以同时修改许多资源。
#### Limitation
由于这个声明无法设置 `kind:` 或 `group:` 它将匹配任何可以匹配名称的 `group` 和 `kind` ,并且它是以下之一:
- `Deployment`
- `ReplicationController`
- `ReplicaSet`
- `StatefulSet`
对于更复杂的用例,请使用 patch 。
### resources
该条目可以是指向本地目录的相对路径,也可以是指向远程仓库中的目录的 URL例如
```
resource:
- myNamespace.yaml
- sub-dir/some-deployment.yaml
- ../../commonbase
- github.com/kubernetes-sigs/kustomize//examples/multibases?ref=v1.0.6
- deployment.yaml
- github.com/kubernets-sigs/kustomize//examples/helloWorld?ref=test-branch
```
将以深度优先的顺序读取和处理资源。
文件应包含 YAML 格式的 k8s 资源。一个资源描述文件可以含有多个由(“---”)分隔的资源。
应该包含 `resources` 字段的 kustomization 文件的指定文件目录的相对路径。
[hashicorp URL]: https://github.com/hashicorp/go-getter#url-format
目录规范可以是相对、绝对或部分的 URL。URL 规范应遵循 [hashicorp URL] 格式。该目录必须包含 `kustomization.yaml` 文件。
### secretGenerator
此列表中的每个条目都将创建一个 Secret 资源它是n个 secrets 的生成器)。
```
secretGenerator:
- name: app-tls
files:
- secret/tls.cert
- secret/tls.key
type: "kubernetes.io/tls"
- name: app-tls-namespaced
# you can define a namespace to generate secret in, defaults to: "default"
namespace: apps
files:
- tls.crt=catsecret/tls.cert
- tls.key=secret/tls.key
type: "kubernetes.io/tls"
- name: env_file_secret
envs:
- env.txt
type: Opaque
```
### vars
Vars 用于从一个 resource 字段中获取文本,并将该文本插入指定位置 - 反射功能。
例如,假设需要在容器的 command 中指定了 Service 对象的名称,并在容器的 env 中指定了 Secret 对象的名称来确保以下内容可以正常工作:
```
containers:
- image: myimage
command: ["start", "--host", "$(MY_SERVICE_NAME)"]
env:
- name: SECRET_TOKEN
value: $(SOME_SECRET_NAME)
```
则可以在 `vars` 中添加如下内容:
```
vars:
- name: SOME_SECRET_NAME
objref:
kind: Secret
name: my-secret
apiVersion: v1
- name: MY_SERVICE_NAME
objref:
kind: Service
name: my-service
apiVersion: v1
fieldref:
fieldpath: metadata.name
- name: ANOTHER_DEPLOYMENTS_POD_RESTART_POLICY
objref:
kind: Deployment
name: my-deployment
apiVersion: apps/v1
fieldref:
fieldpath: spec.template.spec.restartPolicy
```
var 是包含该对象的变量名、对象引用和字段引用的元组。
字段引用是可选的,默认为 `metadata.name`,这是正常的默认值,因为 kustomize 用于生成或修改 resources 的名称。
在撰写本文档时,仅支持字符串类型字段,不支持 intsboolsarrays 等。例如在某些pod模板的容器编号2中提取镜像的名称是不可能的。
变量引用,即字符串 '$(FOO)' ,只能放在 kustomize 配置指定的特定对象的特定字段中。
关于 vars 的默认配置数据可以查看:
https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/transformers/config/defaultconfig/varreference.go
默认目标是所有容器 command args 和 env 字段。
Vars _不应该_ 被用于 kustomize 已经处理过的配置中插入 names 。
例如, Deployment 可以通过 name 引用 ConfigMap ,如果 kustomize 更改 ConfigMap 的名称,则知道更改 Deployment 中的引用的 name 。

View File

@@ -1,287 +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.
#
# ----------------------------------------------------
# Example kustomization.yaml content.
#
# This file declares the customization provided by
# the kustomize program.
#
# Since customization is, by definition, _custom_,
# there are no sensible default values for the fields
# in this file.
#
# The field values used below are merely examples, not
# to be copied literally. The values won't work if
# they happen to be references to external files that
# don't exist.
#
# In practice, fields with no value should simply be
# omitted from kustomization.yaml to reduce the content
# visible in configuration reviews.
# ----------------------------------------------------
# Kustomization 的 apiVersion 和 kind
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 为所有 resources 添加 namespace
namespace: my-namespace
# 该字段的值将添加在所有资源的名称之前
# 例如 将资源名称 “wordpress” 变为 “alices-wordpress”
namePrefix: alices-
# 该字段的值将添加在所有资源的名称后面
# 例如 将资源名称 “wordpress” 变为 “wordpress-v2”
# 如果资源类型为 ConfigMap 或 Secret ,则在哈希值之前附加后缀
nameSuffix: -v2
# 为所有资源和 selectors 增加 Labels
commonLabels:
someName: someValue
owner: alice
app: bingo
# 和 Labels 一样, 增加 Annotations
# 为 key:value 键值对
commonAnnotations:
oncallPager: 800-555-1212
# 此列表中的每条记录都必须是一个存在的 YAML 资源描述文件
# 一个 YAML 资源描述文件可以含有多个由(“---”)分隔的资源。
# kustomize 将读取这些YAML文件中的资源对其进行修改并
# 发布在 kustomize 的输出中。
#
# 此列表中的每个条目都应解析为包含 kustomization 文件的目录,否则定制将失败
#
# 该条目可以是指向本地目录的相对路径
# 也可以是指向远程仓库中的目录的 URL
# URL 应该遵循 hashicorp/go-getter 中的 URL 格式
# https://github.com/hashicorp/go-getter#url-format
#
# 此字段的存在意味着此文件(您正在阅读的文件)是 _overlay_
# 它将进一步定制这些来自 _bases_ 文件中的配置
#
# 典型用例:开发,演示和生产环境
# 这些环境大部分相同但有些关键方式存在差异(镜像标签,一些服务器参数等,与公共 base 不同的配置)
resources:
- some-service.yaml
- sub-dir/some-deployment.yaml
- ../../base
- github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6
- github.com/Liujingfang1/mysql
- github.com/Liujingfang1/kustomize/examples/helloWorld?ref=test-branch
# 列表中的每个条目都将创建一个 ConfigMap 它是n个 ConfigMap 的生成器)
# 下面的示例创建了两个 ConfigMaps
# 一个具有给定文件的名称和内容
# 另一个包含 key/value 键值对数据
# 每个 configMapGenerator 项都可以使用 [create | replace | merge] 参数
# 允许 overlay 从父级修改或替换现有的 configMap
configMapGenerator:
- name: myJavaServerProps
files:
- application.properties
- more.properties
- name: myJavaServerEnvVars
literals:
- JAVA_HOME=/opt/java/jdk
- JAVA_TOOL_OPTIONS=-agentlib:hprof
# 此列表中的每个条目都会导致创建一个Secret资源n个 secrets 的生成器)
secretGenerator:
- name: app-tls
files:
- secret/tls.cert
- secret/tls.key
type: "kubernetes.io/tls"
- name: app-tls-namespaced
# 你可以给生成的 secret 定义一个 namespace ,默认为 ”default“
namespace: apps
files:
- tls.crt=catsecret/tls.cert
- tls.key=secret/tls.key
type: "kubernetes.io/tls"
- name: env_file_secret
# 文件路径以 k=v 键值对的形式,每行一个键值对
envs:
- env.txt
type: Opaque
# generatorOptions 修改所有 ConfigMapGenerator 和 SecretGenerator 的行为
generatorOptions:
# 为所有生成的资源添加 labels
labels:
kustomize.generated.resources: somevalue
# 为所有生成的资源添加 annotations
annotations:
kustomize.generated.resource: somevalue
# disableNameSuffixHash 为 true 时将禁止默认的在名称后添加哈希值后缀的行为
disableNameSuffixHash: true
# 此列表中的每个条目都应可以解析为部分或完整的资源定义文件
#
# 这些(也可能是部分的)资源文件中的 name 必须与已经通过 `resources` 加载的 name 字段匹配
# 或者通过 `bases` 中的 name 字段匹配
# 这些条目将用于 _patch_修改已知资源
#
# 推荐使用小的 patches
# 例如:修改内存的 request/limit更改 ConfigMap 中的 env 变量等
# 小的 patches 易于维护和查看,并且易于在 overlays 中混合使用
patchesStrategicMerge:
- service_port_8888.yaml
- deployment_increase_replicas.yaml
- deployment_increase_memory.yaml
# patchesJson6902 列表中的每个条目都应可以解析为 kubernetes 对象和将应用于该对象的 JSON patch
# JSON patch 的文档地址https://tools.ietf.org/html/rfc6902
#
# 目标字段指向的 kubernetes 对象的 group、 version、 kind、 name 和 namespace 在同一 kustomization 内
# path 字段内容是 JSON patch 文件的相对路径
# patch 文件中的内容可以如下这种 JSON 格式:
#
# [
# {"op": "add", "path": "/some/new/path", "value": "value"},
# {"op": "replace", "path": "/some/existing/path", "value": "new value"}
# ]
#
# 也可以使用 YAML 格式表示:
#
# - op: add
# path: /some/new/path
# value: value
# - op:replace
# path: /some/existing/path
# value: new value
#
patchesJson6902:
- target:
version: v1
kind: Deployment
name: my-deployment
path: add_init_container.yaml
- target:
version: v1
kind: Service
name: my-service
path: add_service_annotation.yaml
# 此列表中的每个条目都应该是 openAPI 定义中自定义资源定义CRD文件的相对路径
#
# 该字段的存在是为了让 kustomize 知道用户自定义的 CRD
# 并对这些类型中的对象应用适当的转换
#
# 典型用例CRD 引用 ConfigMap 对象
# 在 kustomization 中ConfigMap 对象名称可能会通过 namePrefix 、nameSuffix 或 hashing 来更改 CRD 对象中此 ConfigMap 对象的名称
# 引用时需要以相同的方式使用 namePrefix 、 nameSuffix 或 hashing 来进行更新
#
# Annotations 可以放入 openAPI 的定义中:
# "x-kubernetes-annotation": ""
# "x-kubernetes-label-selector": ""
# "x-kubernetes-identity": ""
# "x-kubernetes-object-ref-api-version": "v1",
# "x-kubernetes-object-ref-kind": "Secret",
# "x-kubernetes-object-ref-name-key": "name",
crds:
- crds/typeA.json
- crds/typeB.json
# Vars 用于从一个 resource 字段中获取文本
# 并将该文本插入指定位置
#
# 例如,假设需要在容器的 command 中指定了 Service 对象的名称
# 并在容器的 env 中指定了 Secret 对象的名称
# 来确保以下内容可以正常工作:
# ```
# containers:
# - image: myimage
# command: ["start", "--host", "$(MY_SERVICE_NAME)"]
# env:
# - name: SECRET_TOKEN
# value: $(SOME_SECRET_NAME)
# ```
#
# 则可以在 `vars` 中添加如下内容:
#
vars:
- name: SOME_SECRET_NAME
objref:
kind: Secret
name: my-secret
apiVersion: v1
- name: MY_SERVICE_NAME
objref:
kind: Service
name: my-service
apiVersion: v1
fieldref:
fieldpath: metadata.name
- name: ANOTHER_DEPLOYMENTS_POD_RESTART_POLICY
objref:
kind: Deployment
name: my-deployment
apiVersion: apps/v1
fieldref:
fieldpath: spec.template.spec.restartPolicy
#
# var 是包含该对象的变量名、对象引用和字段引用的元组
#
# 字段引用是可选的,默认为 `metadata.name`
# 这是正常的默认值,因为 kustomize 用于生成或修改 resources 的名称
#
# 在撰写本文档时,仅支持字符串类型字段
# 不支持 intsboolsarrays 等
#
# 变量引用,即字符串 '$(FOO)' ,只能放在 kustomize 配置指定的特定对象的特定字段中
#
# 关于 vars 的默认配置数据可以查看:
# https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/transformers/config/defaultconfig/varreference.go
# 默认目标是所有容器 command args 和 env 字段
#
# Vars _不应该_ 被用于 kustomize 已经处理过的配置中插入 names
# 例如, Deployment 可以通过 name 引用 ConfigMap
# 如果 kustomize 更改 ConfigMap 的名称,则知道更改 Deployment 中的引用的 name
# 修改镜像的名称、tag 或 image digest ,而无需使用 patches
# 例如,对于这种 kubernetes Deployment 片段:
# ```
# containers:
# - name: mypostgresdb
# image: postgres:8
# - name: nginxapp
# image: nginx:1.7.9
# - name: myapp
# image: my-demo-app:latest
# - name: alpine-app
# image: alpine:3.7
#```
# 想对 `image` 完成以下修改:
#
# - 将 `postgres:8` 修改为 `my-registry/my-postgres:v1`,
# - 将 nginx 的 tag 从 `1.7.9` 修改为 `1.8.0`,
# - 将 镜像名称从 `my-demo-app` 修改为 `my-app`,
# - 将 alpine 的 tag 从 `3.7` 修改为 digest 值
#
# 可以在 *kustomization* 中添加以下内容:
images:
- name: postgres
newName: my-registry/my-postgres
newTag: v1
- name: nginx
newTag: 1.8.0
- name: my-demo-app
newName: my-app
- name: alpine
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3

View File

@@ -9,7 +9,7 @@ tests, and should work with HEAD
<!-- @installkustomize @test -->
```
go get sigs.k8s.io/kustomize/cmd/kustomize
go get sigs.k8s.io/kustomize/v3/cmd/kustomize
```
Basic Usage

View File

@@ -4,7 +4,7 @@
[stable chart]: https://github.com/helm/charts/tree/master/stable
[Helm charts]: https://github.com/helm/charts
[_minecraft_]: https://github.com/helm/charts/tree/master/stable/minecraft
[plugin]: ../docs/plugins.md
[plugin]: ../docs/plugins
[Helm charts] aren't natively read by kustomize, but
kustomize has a [plugin] system that allows one to

View File

@@ -125,10 +125,8 @@ them, etc.
## Secret values from anywhere
> New _alpha_ behavior at HEAD, for v2.1+
A general alternative is to enshrine secret
value generation in a [plugin](../docs/plugins.md).
value generation in a [plugin](../docs/plugins).
The values can then come in via, say, an
authenticated and authorized RPC to a password

View File

@@ -2,7 +2,7 @@
[base]: ../../docs/glossary.md#base
[kubeval]: https://github.com/instrumenta/kubeval
[plugin]: ../../docs/plugins.md
[plugin]: ../../docs/plugins
kustomize doesn't validate either its input or
output beyond the validation provided by the

View File

@@ -7,12 +7,12 @@
这些示例通过了 [pre-commit](../../travis/pre-commit.sh) 测试,并且应该与 HEAD 一起使用。
```
go get sigs.k8s.io/kustomize
go get sigs.k8s.io/kustomize/v3/cmd/kustomize
```
基本用法
* [configGenerations](../configGeneration.md) - 当 ConfigMapGenerator 修改时进行滚动更新。
* [configGenerations](configGeneration.md) - 当 ConfigMapGenerator 修改时进行滚动更新。
* [combineConfigs](../combineConfigs.md) - 融合来自不同用户的配置数据(例如来自 devops/SRE 和 developers
@@ -24,7 +24,7 @@ go get sigs.k8s.io/kustomize
* [remote target](../remoteBuild.md) - 通过 github URL 来构建 kustomization 。
* [json patch](../jsonpatch.md) -在 kustomization 中应用 json patch 。
* [json patch](jsonpatch.md) -在 kustomization 中应用 json patch 。
高级用法

View File

@@ -0,0 +1,184 @@
[patch]: ../../docs/glossary.md#patch
[resource]: ../../docs/glossary.md#resource
[variant]: ../../docs/glossary.md#variant
## ConfigMap 的生成和滚动更新
kustomize 提供了两种添加 ConfigMap 的方法:
- 将 ConfigMap 声明为 [resource]
- 通过 ConfigMapGenerator 声明 ConfigMap
`kustomization.yaml` 中,这两种方法的格式分别如下:
> ```
> # 将 ConfigMap 声明为 resource
> resources:
> - configmap.yaml
>
> # 在 ConfigMapGenerator 中声明 ConfigMap
> configMapGenerator:
> - name: a-configmap
> files:
> - configs/configfile
> - configs/another_configfile
> ```
声明为 [resource] 的 ConfigMaps 的处理方式与其他 resource 相同Kustomize 不会在为 ConfigMap 的名称添加哈希后缀。而在 ConfigMapGenerator 中声明 ConfigMap 的处理方式则与之前不同默认将为名称添加哈希后缀ConfigMap 中的任何更改都将触发滚动更新。
在 [hello_world](helloWorld.md) 示例中,使用 ConfigmapGenerator 来替换将 ConfigMap 声明为 [resource] 的方法。由此生成的 ConfigMap 中的更改将导致哈希值更改和滚动更新。
### 建立 base 和 staging
使用 configMapGenerator 建立 base
<!-- @establishBase @test -->
```
DEMO_HOME=$(mktemp -d)
BASE=$DEMO_HOME/base
mkdir -p $BASE
curl -s -o "$BASE/#1.yaml" "https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/helloWorld\
/{deployment,service}.yaml"
cat <<'EOF' >$BASE/kustomization.yaml
commonLabels:
app: hello
resources:
- deployment.yaml
- service.yaml
configMapGenerator:
- name: the-map
literals:
- altGreeting=Good Morning!
- enableRisky="false"
EOF
```
通过应用 ConfigMap patch 的方式建立 staging
<!-- @establishStaging @test -->
```
OVERLAYS=$DEMO_HOME/overlays
mkdir -p $OVERLAYS/staging
cat <<'EOF' >$OVERLAYS/staging/kustomization.yaml
namePrefix: staging-
nameSuffix: -v1
commonLabels:
variant: staging
org: acmeCorporation
commonAnnotations:
note: Hello, I am staging!
resources:
- ../../base
patchesStrategicMerge:
- map.yaml
EOF
cat <<EOF >$OVERLAYS/staging/map.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: the-map
data:
altGreeting: "Have a pineapple!"
enableRisky: "true"
EOF
```
### Review
在集群中运行的 _hello-world_ 的 deployment 配置了来自 configMap 的数据。
deployment 按照名称引用此 ConfigMap
<!-- @showDeployment @test -->
```
grep -C 2 configMapKeyRef $BASE/deployment.yaml
```
当 ConfigMap 中的数据需要更新时,更改群集中的实时 ConfigMap 的数据并不是一个好的做法。 由于 Deployment 无法知道其引用的 ConfigMap 已更改,这类更新是无效。
更改 Deployment 配置的推荐方法是:
1. 使用新名称创建一个新的 configMap
2. 为_deployment_ 添加 patch修改相应 `configMapKeyRef` 字段的名称值。
后一种更改会启动对 deployment 中的 pod 的滚动更新。旧的 configMap 在不再被任何其他资源引用时最终会被[垃圾回收](https://github.com/kubernetes-sigs/kustomize/issues/242)。
### 如何使用 kustomize
_staging_ 的 [variant] 包含一个 configMap 的 [patch]
<!-- @showMapPatch @test -->
```
cat $OVERLAYS/staging/map.yaml
```
根据定义,此 patch 是一个命名但不一定是完整的资源规范,旨在修改完整的资源规范。
在 ConfigMapGenerator 中声明 ConfigMap 的修改。
<!-- @showMapBase @test -->
```
grep -C 4 configMapGenerator $BASE/kustomization.yaml
```
要使这个 patch 正常工作,`metadata/name` 字段中的名称必须匹配。
但是文件中指定的名称值不是群集中使用的名称值。根据设计kustomize 修改从 ConfigMapGenerator 声明的 ConfigMaps 的名称。要查看最终在群集中使用的名称,只需运行 kustomize
<!-- @grepStagingName @test -->
```
kustomize build $OVERLAYS/staging |\
grep -B 8 -A 1 staging-the-map
```
根据 `$OVERLAYS/staging/kustomization.yaml` 中的 `namePrefix` 字段configMap 名称以 _staging-_ 为前缀。
根据 `$OVERLAYS/staging/kustomization.yaml` 中的 `nameSuffix` 字段configMap 名称以 _-v1_ 为后缀。
configMap 名称的后缀是由 map 内容的哈希生成的 - 在这种情况下,名称后缀是 _k25m8k5k5m_
<!-- @grepStagingHash @test -->
```
kustomize build $OVERLAYS/staging | grep k25m8k5k5m
```
现在修改 map patch ,更改该服务将使用的问候消息:
<!-- @changeMap @test -->
```
sed -i.bak 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
```
查看新的问候消息:
```
kustomize build $OVERLAYS/staging |\
grep -B 2 -A 3 kiwi
```
再次运行 kustomize 查看新的 configMap 名称:
<!-- @grepStagingName @test -->
```
kustomize build $OVERLAYS/staging |\
grep -B 8 -A 1 staging-the-map
```
确认 configMap 内容的更改将会生成以 _cd7kdh48fd_ 结尾的三个新名称 - 一个在 configMap 的名称中,另两个在使用 ConfigMap 的 deployment 中:
<!-- @countHashes @test -->
```
test 3 == \
$(kustomize build $OVERLAYS/staging | grep cd7kdh48fd | wc -l); \
echo $?
```
将这些资源应用于群集将导致 deployment pod 的滚动更新,将它们从 _k25m8k5k5m_ map 重新定位到 _cd7kdh48fd_ map 。系统稍后将垃圾收集未使用的 map。
## 回滚
回滚,可以撤消对源码配置所做的任何编辑,然后在还原的配置上重新运行 kustomize 并将其应用于群集。

124
examples/zh/jsonpatch.md Normal file
View File

@@ -0,0 +1,124 @@
# 例子: 应用 json patchjson补丁
kustomization文件支持通过[JSON patches](https://tools.ietf.org/html/rfc6902)来修改已有的资源.
下面的例子将会使用这个功能对`Ingress`加以修改.
首先,创建一个包含`ingress``kustomization`文件.
<!-- @createIngress @test -->
```bash
DEMO_HOME=$(mktemp -d)
cat <<EOF >$DEMO_HOME/kustomization.yaml
resources:
- ingress.yaml
EOF
cat <<EOF >$DEMO_HOME/ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: my-api
servicePort: 80
EOF
```
定义一个JSON patch文件以更新`Ingress`对象的2个字段:
- 把 host 从 `foo.bar.com` 改为 `foo.bar.io`
- 把 servicePort 从 `80` 改为 `8080`
<!-- @addJsonPatch @test -->
```bash
cat <<EOF >$DEMO_HOME/ingress_patch.json
[
{"op": "replace", "path": "/spec/rules/0/host", "value": "foo.bar.io"},
{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/servicePort", "value": 8080}
]
EOF
```
JSON patch 也可以写成 YAML 的格式.该例子顺便展示了“添加”操作:
<!-- @addYamlPatch @test -->
```bash
cat <<EOF >$DEMO_HOME/ingress_patch.yaml
- op: replace
path: /spec/rules/0/host
value: foo.bar.io
- op: add
path: /spec/rules/0/http/paths/-
value:
path: '/test'
backend:
serviceName: my-test
servicePort: 8081
EOF
```
在kustomization.yaml文件中增加 _patchesJson6902_ 字段,以应用该补丁
<!-- @applyJsonPatch @test -->
```bash
cat <<EOF >>$DEMO_HOME/kustomization.yaml
patchesJson6902:
- target:
group: extensions
version: v1beta1
kind: Ingress
name: my-ingress
path: ingress_patch.json
EOF
```
运行 `kustomize build $DEMO_HOME`, 在输出那里确认 host 已经被正确更新.
<!-- @confirmHost @test -->
```bash
test 1 == \
$(kustomize build $DEMO_HOME | grep "host: foo.bar.io" | wc -l); \
echo $?
```
运行 `kustomize build $DEMO_HOME`, 在输出那里确认 servicePort 已经被正确更新.
<!-- @confirmServicePort @test -->
```bash
test 1 == \
$(kustomize build $DEMO_HOME | grep "servicePort: 8080" | wc -l); \
echo $?
```
如果 patch 是YAML格式的就能正确解析:
<!-- @applyYamlPatch @test -->
```bash
cat <<EOF >>$DEMO_HOME/kustomization.yaml
patchesJson6902:
- target:
group: extensions
version: v1beta1
kind: Ingress
name: my-ingress
path: ingress_patch.yaml
EOF
```
运行 `kustomize build $DEMO_HOME`, 在输出那里确认有 `/test` 这个路径.
<!-- @confirmYamlPatch @test -->
```bash
test 1 == \
$(kustomize build $DEMO_HOME | grep "path: /test" | wc -l); \
echo $?
```

44
go.mod
View File

@@ -1,38 +1,26 @@
module sigs.k8s.io/kustomize
module sigs.k8s.io/kustomize/v3
go 1.12
require (
github.com/PuerkitoBio/purell v1.1.0 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/emicklei/go-restful v2.9.3+incompatible // indirect
github.com/evanphx/json-patch v3.0.0+incompatible
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa // indirect
github.com/go-openapi/jsonreference v0.0.0-20180322222742-3fb327e6747d // indirect
github.com/go-openapi/spec v0.0.0-20180415031709-bcff419492ee
github.com/go-openapi/swag v0.0.0-20180405201759-811b1089cde9 // indirect
github.com/gogo/protobuf v1.0.0 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
github.com/googleapis/gnostic v0.1.0 // indirect
github.com/emicklei/go-restful v2.9.6+incompatible // indirect
github.com/evanphx/json-patch v4.5.0+incompatible
github.com/go-openapi/spec v0.19.2
github.com/golang/protobuf v1.3.1 // indirect
github.com/googleapis/gnostic v0.3.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/json-iterator/go v0.0.0-20180315132816-ca39e5af3ece // indirect
github.com/mailru/easyjson v0.0.0-20180606163543-3fdea8d05856 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v0.0.0-20180228065516-1df9eeb2bb81 // indirect
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect
github.com/mailru/easyjson v0.0.0-20190620125010-da37f6c1e481 // indirect
github.com/pkg/errors v0.8.1
github.com/spf13/cobra v0.0.2
github.com/spf13/pflag v1.0.1
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3 // indirect
github.com/spf13/pflag v1.0.3
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
golang.org/x/sys v0.0.0-20190621203818-d432491b9138 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.2.1
k8s.io/api v0.0.0-20180510062335-53d615ae3f44
k8s.io/apimachinery v0.0.0-20180510061931-13b73596e4b6
k8s.io/client-go v7.0.0+incompatible
k8s.io/kube-openapi v0.0.0-20180510204742-b3f03f553288
gopkg.in/yaml.v2 v2.2.2
k8s.io/api v0.0.0-20190809220925-3ab596449d6f
k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010
k8s.io/client-go v0.0.0-20190812221009-4f902818859a
k8s.io/klog v0.3.3 // indirect
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058
sigs.k8s.io/yaml v1.1.0
)

200
go.sum
View File

@@ -1,99 +1,201 @@
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.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/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful v2.9.3+incompatible h1:2OwhVdhtzYUp5P5wuGsVDPagKSRd9JK72sJCHVCXh5g=
github.com/emicklei/go-restful v2.9.3+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v3.0.0+incompatible h1:l91aby7TzBXBdmF8heZqjskeH9f3g7ZOL8/sSe+vTlU=
github.com/evanphx/json-patch v3.0.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
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/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
github.com/emicklei/go-restful v2.9.6+incompatible/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/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 v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa h1:hr8WVDjg4JKtQptZpzyb196TmruCs7PIsdJz8KAOZp8=
github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20180322222742-3fb327e6747d h1:k3UQ7Z8yFYq0BNkYykKIheY0HlZBl1Hku+pO9HE9FNU=
github.com/go-openapi/jsonreference v0.0.0-20180322222742-3fb327e6747d/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20180415031709-bcff419492ee h1:eo0HQoNFtbiEc7+1gRF9pgW6azx8a1cO2fXcqq1MuD0=
github.com/go-openapi/spec v0.0.0-20180415031709-bcff419492ee/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20180405201759-811b1089cde9 h1:+vsw187FKvA2QUGAcE+vQSfyxqLbUXixPYRRMAzwu04=
github.com/go-openapi/swag v0.0.0-20180405201759-811b1089cde9/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/gogo/protobuf v1.0.0 h1:2jyBKDKU/8v3v2xVR2PtiWQviFUyiaGk2rpfyFT8rTM=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2 h1:A9+F4Dc/MCNB5jibxf6rRvOvR/iFgQdyNx9eIhnGqq0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.2 h1:SStNd1jRcYtfKCN7R0laGNs80WYYvn5CbBjM2sOmCrE=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
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/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
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/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/json-iterator/go v0.0.0-20180315132816-ca39e5af3ece h1:3HJXp/18JmMk5sjBP3LDUBtWjczCvynxaeAF6b6kWp8=
github.com/json-iterator/go v0.0.0-20180315132816-ca39e5af3ece/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/mailru/easyjson v0.0.0-20180606163543-3fdea8d05856 h1:hOnidOuIWNsFRPcxxStGeN3NNm4n4+w6KJ9cVJIh70o=
github.com/mailru/easyjson v0.0.0-20180606163543-3fdea8d05856/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3 h1:/UewZcckqhvnnS0C6r3Sher2hSEbVmM6Ogpcjen08+Y=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/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/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190620125010-da37f6c1e481 h1:IaSjLMT6WvkoZZjspGxy3rdaTEmWLoRm49WbtVUi9sA=
github.com/mailru/easyjson v0.0.0-20190620125010-da37f6c1e481/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
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-20180228065516-1df9eeb2bb81 h1:ImOHKpmdLPXWX5KSYquUWXKaopEPuY7TPPUo18u9aOI=
github.com/modern-go/reflect2 v0.0.0-20180228065516-1df9eeb2bb81/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da h1:ZQGIPjr1iTtUPXZFk8WShqb5G+Qg65VHFLtSvmHh+Mw=
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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
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.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/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.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
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/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE=
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190225153610-fe579d43d832 h1:2IdId8zoI92l1bUzjAOygcAOkmCe13HY1j0rqPPPzB8=
golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/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-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-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-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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 h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190621203818-d432491b9138 h1:t8BZD9RDjkm9/h7yYN6kE8oaeov5r9aztkB7zKA5Tkg=
golang.org/x/sys v0.0.0-20190621203818-d432491b9138/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 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d h1:bt+R27hbE7uVf7PY9S6wpNg9Xo2WRe/XQT0uGq9RQQw=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3 h1:sU3tSV6wDhWsvf9NjL0FzRjgAmYnQL5NEhdmcN16UEg=
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
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-20161028155119-f51c12702a4d/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-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-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
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.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
k8s.io/api v0.0.0-20180510062335-53d615ae3f44 h1:zQ8YhMpuc1QJoor+Vm1moP9iEOyaQgOjSj3bo/zUEXE=
k8s.io/api v0.0.0-20180510062335-53d615ae3f44/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/apimachinery v0.0.0-20180510061931-13b73596e4b6 h1:pJrzRmry9HLPxkVGMk57cfeGRy/WG0oYXuji9t4zD1M=
k8s.io/apimachinery v0.0.0-20180510061931-13b73596e4b6/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/client-go v7.0.0+incompatible h1:kiH+Y6hn+pc78QS/mtBfMJAMIIaWevHi++JvOGEEQp4=
k8s.io/client-go v7.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/kube-openapi v0.0.0-20180510204742-b3f03f553288 h1:AhFqcaw5JbAAaZHxTe1fT+Jtek0pZmIwwt6FbsMA9to=
k8s.io/kube-openapi v0.0.0-20180510204742-b3f03f553288/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
k8s.io/api v0.0.0-20190313235455-40a48860b5ab h1:DG9A67baNpoeweOy2spF1OWHhnVY5KR7/Ek/+U1lVZc=
k8s.io/api v0.0.0-20190313235455-40a48860b5ab/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/api v0.0.0-20190809220925-3ab596449d6f h1:Ica1a7bw1U7AKaTDYgumijQa95BxzapaG9F7g8h2bjs=
k8s.io/api v0.0.0-20190809220925-3ab596449d6f/go.mod h1:3Iy+myeAORNCLgjd/Xu9ebwN7Vh59Bw0vh9jhoX+V58=
k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1 h1:IS7K02iBkQXpCeieSiyJjGoLSdVOv2DbPaWHJ+ZtgKg=
k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010 h1:pyoq062NftC1y/OcnbSvgolyZDJ8y4fmUPWMkdA6gfU=
k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8=
k8s.io/client-go v0.0.0-20190812221009-4f902818859a h1:Q6MWhZhFJehn507QasOhePysGew/kq+cCeei+M9L1t8=
k8s.io/client-go v0.0.0-20190812221009-4f902818859a/go.mod h1:2rTYlEIRnJeJ+Y2va8HpkQBKyWjf+Uo3A8KVGcf+eMA=
k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=
k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
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 v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c=
k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208 h1:5sW+fEHvlJI3Ngolx30CmubFulwH28DhKjGf70Xmtco=
k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058 h1:di3XCwddOR9cWBNpfgXaskhh6cgJuwcK54rvtwUaC10=
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -6,11 +6,11 @@ package loadertest
import (
"log"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
// FakeLoader encapsulates the delegate Loader and the fake file system.

View File

@@ -9,7 +9,7 @@ import (
"unicode/utf8"
"k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
func makeFreshConfigMap(

View File

@@ -9,10 +9,10 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
func makeEnvConfigMap(name string) *corev1.ConfigMap {

View File

@@ -4,8 +4,8 @@
package configmapandsecret
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// Factory makes ConfigMaps and Secrets.

View File

@@ -7,7 +7,7 @@ import (
"fmt"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
func makeFreshSecret(

View File

@@ -9,10 +9,10 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
func makeEnvSecret(name string) *corev1.Secret {

View File

@@ -11,9 +11,9 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/k8sdeps/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/k8sdeps/configmapandsecret"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// KunstructuredFactoryImpl hides construction using apimachinery types.

View File

@@ -20,7 +20,7 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
func TestSliceFromBytes(t *testing.T) {

View File

@@ -9,8 +9,8 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/kustomize/pkg/hasher"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/hasher"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
// kustHash computes a hash of an unstructured object.

View File

@@ -1,18 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
@@ -31,7 +18,11 @@ import (
// field of the first item in the foo list
type PathSection struct {
fields []string
idx *int
idx int
}
func newPathSection() PathSection {
return PathSection{idx: -1}
}
func appendNonEmpty(section *PathSection, field string) {
@@ -40,13 +31,12 @@ func appendNonEmpty(section *PathSection, field string) {
}
}
func parseFields(path string) ([]PathSection, error) {
section := PathSection{}
sectionset := []PathSection{}
func parseFields(path string) (result []PathSection, err error) {
section := newPathSection()
if !strings.Contains(path, "[") {
section.fields = strings.Split(path, ".")
sectionset = append(sectionset, section)
return sectionset, nil
result = append(result, section)
return result, nil
}
start := 0
@@ -69,15 +59,18 @@ func parseFields(path string) ([]PathSection, error) {
case ']':
if insideParentheses {
// Assign this index to the current
// PathSection, save it to the set, then begin
// PathSection, save it to the result, then begin
// a new PathSection
tmpIdx, err := strconv.Atoi(path[start:i])
if err != nil {
return nil, fmt.Errorf("invalid index %s", path)
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])
}
section.idx = &tmpIdx
sectionset = append(sectionset, section)
section = PathSection{}
result = append(result, section)
section = newPathSection()
start = i + 1
insideParentheses = false
@@ -88,15 +81,15 @@ func parseFields(path string) ([]PathSection, error) {
}
if start < len(path)-1 {
appendNonEmpty(&section, path[start:])
sectionset = append(sectionset, section)
result = append(result, section)
}
for _, section := range sectionset {
for _, section := range result {
for i, f := range section.fields {
if strings.HasPrefix(f, "\"") || strings.HasPrefix(f, "'") {
section.fields[i] = strings.Trim(f, "\"'")
}
}
}
return sectionset, nil
return result, nil
}

View File

@@ -1,18 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kunstruct
@@ -23,20 +10,15 @@ import (
type PathSectionSlice []PathSection
func buildPath(idx *int, fields ...string) PathSectionSlice {
func buildPath(idx int, fields ...string) PathSectionSlice {
return PathSectionSlice{PathSection{fields: fields, idx: idx}}
}
func (a PathSectionSlice) addSection(idx *int, fields ...string) PathSectionSlice {
func (a PathSectionSlice) addSection(idx int, fields ...string) PathSectionSlice {
return append(a, PathSection{fields: fields, idx: idx})
}
func TestParseField(t *testing.T) {
i := 1
var one *int = &i
j := 0
var zero *int = &j
tests := []struct {
name string
pathToField string
@@ -47,62 +29,62 @@ func TestParseField(t *testing.T) {
{
name: "oneField",
pathToField: "Kind",
expectedValue: buildPath(nil, "Kind"),
expectedValue: buildPath(-1, "Kind"),
errorExpected: false,
},
{
name: "twoFields",
pathToField: "metadata.name",
expectedValue: buildPath(nil, "metadata", "name"),
expectedValue: buildPath(-1, "metadata", "name"),
errorExpected: false,
},
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: buildPath(nil, "spec", "ports", "port"),
expectedValue: buildPath(-1, "spec", "ports", "port"),
errorExpected: false,
},
{
name: "empty",
pathToField: "",
expectedValue: buildPath(nil, ""),
expectedValue: buildPath(-1, ""),
errorExpected: false,
},
{
name: "validStringIndex",
pathToField: "that[1]",
expectedValue: buildPath(one, "that"),
expectedValue: buildPath(1, "that"),
errorExpected: false,
},
{
name: "sliceInSlice",
pathToField: "that[1][0]",
expectedValue: buildPath(one, "that").addSection(zero),
expectedValue: buildPath(1, "that").addSection(0),
errorExpected: false,
},
{
name: "validStructSubField",
pathToField: "those[1].field2",
expectedValue: buildPath(one, "those").addSection(nil, "field2"),
expectedValue: buildPath(1, "those").addSection(-1, "field2"),
errorExpected: false,
},
{
name: "validStructSubFieldIndex",
pathToField: "these[1].field2[0]",
expectedValue: buildPath(one, "these").addSection(zero, "field2"),
expectedValue: buildPath(1, "these").addSection(0, "field2"),
errorExpected: false,
},
{
name: "validStructSubFieldIndexSubfield",
pathToField: "complextree[1].field2[1].stringsubfield",
expectedValue: buildPath(one, "complextree").addSection(one, "field2").addSection(nil, "stringsubfield"),
expectedValue: buildPath(1, "complextree").addSection(1, "field2").addSection(-1, "stringsubfield"),
errorExpected: false,
},
{
name: "validStructSubFieldNoneIntIndex",
pathToField: "complextree[thisisnotanint]",
errorExpected: true,
errorMsg: "invalid index complextree[thisisnotanint]",
name: "validStructDownwardAPI",
pathToField: `metadata.labels["app.kubernetes.io/component"]`,
expectedValue: buildPath(-1, "metadata", "labels", "app.kubernetes.io/component"),
errorExpected: false,
},
{
name: "invalidIndexInIndex",
@@ -119,7 +101,7 @@ func TestParseField(t *testing.T) {
{
name: "validFieldsWithQuotes",
pathToField: "'complextree'[1].field2[1].'stringsubfield'",
expectedValue: buildPath(one, "complextree").addSection(one, "field2").addSection(nil, "stringsubfield"),
expectedValue: buildPath(1, "complextree").addSection(1, "field2").addSection(-1, "stringsubfield"),
errorExpected: false,
},
}

View File

@@ -20,13 +20,15 @@ package kunstruct
import (
"encoding/json"
"fmt"
"sigs.k8s.io/kustomize/pkg/types"
"k8s.io/apimachinery/pkg/labels"
"sigs.k8s.io/kustomize/v3/pkg/types"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
var _ ifc.Kunstructured = &UnstructAdapter{}
@@ -92,7 +94,7 @@ func (fs *UnstructAdapter) selectSubtree(path string) (map[string]interface{}, [
idx := sections[sectionIdx].idx
fields := sections[sectionIdx].fields
if idx == nil {
if idx == -1 {
// This section has no index
return content, fields, true, nil
}
@@ -107,24 +109,24 @@ func (fs *UnstructAdapter) selectSubtree(path string) (map[string]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 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]}
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{})
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])
fmt.Errorf("%#v is expected to be of type map[string]interface{}", s[idx])
}
content = newContent
}
@@ -267,3 +269,19 @@ func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
}
return nil, types.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
}

View File

@@ -24,14 +24,14 @@ import (
var kunstructured = NewKunstructuredFactoryImpl().FromMap(map[string]interface{}{
"Kind": "Service",
"metadata": map[string]interface{}{
"labels": map[string]string{
"labels": map[string]interface{}{
"app": "application-name",
},
"name": "service-name",
},
"spec": map[string]interface{}{
"ports": map[string]interface{}{
"port": "80",
"port": int64(80),
},
},
"this": map[string]interface{}{
@@ -168,7 +168,7 @@ func TestGetFieldValue(t *testing.T) {
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: "80",
expectedValue: int64(80),
errorExpected: false,
},
{
@@ -249,6 +249,12 @@ func TestGetFieldValue(t *testing.T) {
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]",
@@ -298,16 +304,34 @@ func TestGetFieldValue(t *testing.T) {
errorMsg: "no field named 'complextree[1].field2[1].invalidsubfield'",
},
{
name: "validStructSubFieldNoneIntIndex",
pathToField: "complextree[thisisnotanint]",
errorExpected: true,
errorMsg: "no field named 'complextree[thisisnotanint]'",
name: "validDownwardAPILabels",
pathToField: `metadata.labels["app"]`,
errorExpected: false,
expectedValue: "application-name",
},
{
name: "invalidNoneIntIndex",
pathToField: "complextree[thisisnotanint]",
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 'complextree[thisisnotanint]'",
errorMsg: `no field named 'metadata.labels["theisnotanint"]'`,
},
{
name: "downwardAPIInvalidLabel2",
pathToField: `invalidfield.labels["app"]`,
errorExpected: true,
errorMsg: `no field named 'invalidfield.labels["app"]'`,
},
{
name: "invalidIndexInIndex",
@@ -362,12 +386,6 @@ func TestGetString(t *testing.T) {
expectedValue: "service-name",
errorExpected: false,
},
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: "80",
errorExpected: false,
},
{
name: "emptyMap",
pathToField: "this.is.anEmptyMap",
@@ -440,6 +458,12 @@ func TestGetString(t *testing.T) {
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 {
@@ -487,6 +511,12 @@ func TestGetInt64(t *testing.T) {
errorExpected: true,
errorMsg: "no field named 'these[1].field2[99]'",
},
{
name: "validDownwardAPISpecs",
pathToField: `spec.ports['port']`,
errorExpected: false,
expectedValue: int64(80),
},
}
for _, test := range tests {
@@ -522,6 +552,12 @@ func TestGetFloat64(t *testing.T) {
errorExpected: false,
expectedValue: float64(1.1121),
},
{
name: "validDownwardAPIThis",
pathToField: `this.is[aFloat]`,
errorExpected: false,
expectedValue: float64(1.001),
},
{
name: "twoFieldsOneMissing",
pathToField: "metadata.banana",

View File

@@ -5,9 +5,9 @@
package transformer
import (
"sigs.k8s.io/kustomize/k8sdeps/transformer/patch"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer/patch"
"sigs.k8s.io/kustomize/v3/pkg/resource"
"sigs.k8s.io/kustomize/v3/pkg/transformers"
)
// FactoryImpl makes patch transformer and name hash transformer

View File

@@ -10,7 +10,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/mergepatch"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/v3/pkg/resource"
)
type conflictDetector interface {

View File

@@ -12,11 +12,10 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resource"
"sigs.k8s.io/kustomize/v3/pkg/transformers"
)
// transformer applies strategic merge patches.
@@ -44,7 +43,10 @@ func (tf *transformer) Transform(m resmap.ResMap) error {
return err
}
for _, patch := range patches.Resources() {
target, err := tf.findPatchTarget(m, patch.OrgId())
target, err := m.GetById(patch.OrgId())
if err != nil {
return err
}
merged := map[string]interface{}{}
versionedObj, err := scheme.Scheme.New(
toSchemaGvk(patch.OrgId().Gvk))
@@ -93,20 +95,6 @@ func (tf *transformer) Transform(m resmap.ResMap) error {
return nil
}
func (tf *transformer) findPatchTarget(
m resmap.ResMap, id resid.ResId) (*resource.Resource, error) {
match, err := m.GetByOriginalId(id)
if err == nil {
return match, nil
}
match, err = m.GetByCurrentId(id)
if err == nil {
return match, nil
}
return nil, fmt.Errorf(
"failed to find target for patch %s", id.GvknString())
}
// mergePatches merge and index patches by OrgId.
// It errors out if there is conflict between patches.
func (tf *transformer) mergePatches() (resmap.ResMap, error) {

View File

@@ -8,9 +8,9 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/pkg/resmaptest"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
"sigs.k8s.io/kustomize/v3/pkg/resource"
)
var rf = resource.NewFactory(
@@ -326,6 +326,65 @@ func TestMultiplePatchesWithConflict(t *testing.T) {
}
}
func TestPatchesWithWrongNamespace(t *testing.T) {
base := resmaptest_test.NewRmBuilder(t, rf).
Add(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
"namespace": "namespace1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx",
},
},
},
},
},
}).ResMap()
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
"namespace": "namespace2",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}),
}
lt, err := NewTransformer(patch, rf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = lt.Transform(base)
if err == nil {
t.Fatalf("did not get expected error")
}
if !strings.Contains(err.Error(), "failed to find unique target for patch") {
t.Fatalf("expected error to contain %q but get %v", "failed to find target for patch", err)
}
}
func TestNoSchemaOverlayRun(t *testing.T) {
base := resmaptest_test.NewRmBuilder(t, rf).
Add(map[string]interface{}{

View File

@@ -53,6 +53,23 @@ func (v *KustValidator) MakeAnnotationValidator() func(map[string]string) error
}
}
// 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 {
@@ -64,6 +81,21 @@ func (v *KustValidator) MakeLabelValidator() func(map[string]string) error {
}
}
// 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

@@ -8,11 +8,11 @@ import (
"log"
"strings"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/resid"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/transformers"
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// ResAccumulator accumulates resources and the rules
@@ -28,7 +28,7 @@ func MakeEmptyAccumulator() *ResAccumulator {
ra := &ResAccumulator{}
ra.resMap = resmap.New()
ra.tConfig = &config.TransformerConfig{}
ra.varSet = types.VarSet{}
ra.varSet = types.NewVarSet()
return ra
}

View File

@@ -10,14 +10,14 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
. "sigs.k8s.io/kustomize/pkg/accumulator"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resmaptest"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
. "sigs.k8s.io/kustomize/v3/pkg/accumulator"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
"sigs.k8s.io/kustomize/v3/pkg/resource"
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
func makeResAccumulator(t *testing.T) (*ResAccumulator, *resource.Factory) {

View File

@@ -4,22 +4,22 @@
package build
import (
"fmt"
"io"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/ifc/transformer"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/plugins"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/target"
"sigs.k8s.io/kustomize/plugin/builtin"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/ifc/transformer"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/plugins"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resource"
"sigs.k8s.io/kustomize/v3/pkg/target"
"sigs.k8s.io/kustomize/v3/plugin/builtin"
"sigs.k8s.io/yaml"
)
@@ -202,23 +202,38 @@ func NewCmdBuildPrune(
func writeIndividualFiles(
fSys fs.FileSystem, folderPath string, m resmap.ResMap) error {
for _, res := range m.Resources() {
filename := filepath.Join(
folderPath,
fmt.Sprintf(
"%s_%s.yaml",
strings.ToLower(res.GetGvk().String()),
strings.ToLower(res.GetName()),
),
)
out, err := yaml.Marshal(res.Map())
if err != nil {
return err
byNamespace := m.GroupedByNamespace()
for namespace, resList := range byNamespace {
for _, res := range resList {
fName := fileName(res)
if len(byNamespace) > 1 {
fName = strings.ToLower(namespace) + "_" + fName
}
err := writeFile(fSys, folderPath, fName, res)
if err != nil {
return err
}
}
err = fSys.WriteFile(filename, out)
}
for _, res := range m.NonNamespaceable() {
err := writeFile(fSys, folderPath, fileName(res), res)
if err != nil {
return err
}
}
return nil
}
func fileName(res *resource.Resource) string {
return strings.ToLower(res.GetGvk().String()) +
"_" + strings.ToLower(res.GetName()) + ".yaml"
}
func writeFile(
fSys fs.FileSystem, path, fName string, res *resource.Resource) error {
out, err := yaml.Marshal(res.Map())
if err != nil {
return err
}
return fSys.WriteFile(filepath.Join(path, fName), out)
}

View File

@@ -19,7 +19,7 @@ package build
import (
"testing"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
)
func TestNewOptionsToSilenceCodeInspectionError(t *testing.T) {

View File

@@ -9,16 +9,16 @@ import (
"os"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/k8sdeps/transformer"
"sigs.k8s.io/kustomize/k8sdeps/validator"
"sigs.k8s.io/kustomize/pkg/commands/build"
"sigs.k8s.io/kustomize/pkg/commands/edit"
"sigs.k8s.io/kustomize/pkg/commands/misc"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
"sigs.k8s.io/kustomize/v3/k8sdeps/validator"
"sigs.k8s.io/kustomize/v3/pkg/commands/build"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit"
"sigs.k8s.io/kustomize/v3/pkg/commands/misc"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/resmap"
"sigs.k8s.io/kustomize/v3/pkg/resource"
)
// NewDefaultCommand returns the default (aka root) command for kustomize command.

View File

@@ -22,8 +22,8 @@ import (
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
type addBaseOptions struct {

View File

@@ -20,8 +20,8 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
const (

View File

@@ -21,10 +21,10 @@ import (
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// kindOfAdd is the kind of metadata being added: label or annotation

View File

@@ -20,10 +20,10 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
func makeKustomization(t *testing.T) *types.Kustomization {

View File

@@ -21,9 +21,10 @@ import (
"log"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/patch"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/patch"
)
type addPatchOptions struct {
@@ -70,7 +71,7 @@ func (o *addPatchOptions) Complete(cmd *cobra.Command, args []string) error {
// RunAddPatch runs addPatch command (do real work).
func (o *addPatchOptions) RunAddPatch(fSys fs.FileSystem) error {
patches, err := globPatterns(fSys, o.patchFilePaths)
patches, err := util.GlobPatterns(fSys, o.patchFilePaths)
if err != nil {
return err
}

View File

@@ -21,7 +21,7 @@ import (
"strings"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
const (

View File

@@ -21,8 +21,9 @@ import (
"log"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
type addResourceOptions struct {
@@ -69,7 +70,7 @@ func (o *addResourceOptions) Complete(cmd *cobra.Command, args []string) error {
// RunAddResource runs addResource command (do real work).
func (o *addResourceOptions) RunAddResource(fSys fs.FileSystem) error {
resources, err := globPatterns(fSys, o.resourceFilePaths)
resources, err := util.GlobPatterns(fSys, o.resourceFilePaths)
if err != nil {
return err
}

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
const (

View File

@@ -5,8 +5,8 @@ package add
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
// NewCmdAdd returns an instance of 'add' subcommand.

View File

@@ -5,10 +5,10 @@ package add
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// newCmdAddConfigMap returns a new command.

View File

@@ -6,10 +6,10 @@ package add
import (
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
func TestNewAddConfigMapIsNotNil(t *testing.T) {

View File

@@ -20,7 +20,8 @@ import (
"fmt"
"strings"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
// flagsAndArgs encapsulates the options for add secret/configmap commands.
@@ -85,7 +86,7 @@ func (a *flagsAndArgs) ExpandFileSource(fSys fs.FileSystem) error {
} else {
patterns = append(patterns, s[0])
}
result, err := globPatterns(fSys, patterns)
result, err := util.GlobPatterns(fSys, patterns)
if err != nil {
return err
}

View File

@@ -20,7 +20,7 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func TestDataValidation_NoName(t *testing.T) {

View File

@@ -5,10 +5,10 @@ package add
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// newCmdAddSecret returns a new command.

View File

@@ -6,10 +6,10 @@ package add
import (
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
func TestNewCmdAddSecretIsNotNil(t *testing.T) {

View File

@@ -1,39 +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 add
import (
"log"
"sigs.k8s.io/kustomize/pkg/fs"
)
func globPatterns(fsys fs.FileSystem, patterns []string) ([]string, error) {
var result []string
for _, pattern := range patterns {
files, err := fsys.Glob(pattern)
if err != nil {
return nil, err
}
if len(files) == 0 {
log.Printf("%s has no match", pattern)
continue
}
result = append(result, files...)
}
return result, nil
}

View File

@@ -5,13 +5,13 @@ package edit
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/edit/add"
"sigs.k8s.io/kustomize/pkg/commands/edit/fix"
"sigs.k8s.io/kustomize/pkg/commands/edit/remove"
"sigs.k8s.io/kustomize/pkg/commands/edit/set"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/add"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/fix"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/remove"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/set"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/loader"
)
// NewCmdEdit returns an instance of 'edit' subcommand.
@@ -38,7 +38,7 @@ func NewCmdEdit(
add.NewCmdAdd(fSys, loader.NewFileLoaderAtCwd(v, fSys), kf),
set.NewCmdSet(fSys, v),
fix.NewCmdFix(fSys),
remove.NewCmdRemove(fSys),
remove.NewCmdRemove(fSys, loader.NewFileLoaderAtCwd(v, fSys)),
)
return c
}

View File

@@ -18,8 +18,8 @@ package fix
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
// NewCmdFix returns an instance of 'fix' subcommand.

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func TestFix(t *testing.T) {

View File

@@ -18,11 +18,14 @@ package remove
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
// NewCmdRemove returns an instance of 'remove' subcommand.
func NewCmdRemove(fsys fs.FileSystem) *cobra.Command {
func NewCmdRemove(
fsys fs.FileSystem,
ldr ifc.Loader) *cobra.Command {
c := &cobra.Command{
Use: "remove",
Short: "Removes items from the kustomization file.",
@@ -31,11 +34,23 @@ func NewCmdRemove(fsys fs.FileSystem) *cobra.Command {
# Removes resources from the kustomization file
kustomize edit remove resource {filepath} {filepath}
kustomize edit remove resource {pattern}
# Removes one or more patches from the kustomization file
kustomize edit remove patch <filepath>
# Removes one or more commonLabels from the kustomization file
kustomize edit remove label {labelKey1},{labelKey2}
# Removes one or more commonAnnotations from the kustomization file
kustomize edit remove annotation {annotationKey1},{annotationKey2}
`,
Args: cobra.MinimumNArgs(1),
}
c.AddCommand(
newCmdRemoveResource(fsys),
newCmdRemoveLabel(fsys, ldr.Validator().MakeLabelNameValidator()),
newCmdRemoveAnnotation(fsys, ldr.Validator().MakeAnnotationNameValidator()),
newCmdRemovePatch(fsys),
)
return c
}

View File

@@ -0,0 +1,174 @@
/*
Copyright 2019 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 remove
import (
"fmt"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/types"
"strings"
)
// kindOfAdd is the kind of metadata being added: label or annotation
type kindOfAdd int
const (
annotation kindOfAdd = iota
label
)
func (k kindOfAdd) String() string {
kinds := [...]string{
"annotation",
"label",
}
if k < 0 || k > 1 {
return "Unknown metadatakind"
}
return kinds[k]
}
type removeMetadataOptions struct {
ignore bool
metadata []string
arrayValidator func([]string) error
kind kindOfAdd
}
// newCmdRemoveLabel removes one or more commonAnnotations from the kustomization file.
func newCmdRemoveAnnotation(fSys fs.FileSystem, v func([]string) error) *cobra.Command {
var o removeMetadataOptions
o.kind = label
o.arrayValidator = v
cmd := &cobra.Command{
Use: "annotation",
Short: "Removes one or more commonAnnotations from " + pgmconfig.KustomizationFileNames[0],
Example: `
remove annotation {annotationKey1},{annotationKey2}`,
RunE: func(cmd *cobra.Command, args []string) error {
return o.runE(args, fSys, o.removeAnnotations)
},
}
cmd.Flags().BoolVarP(&o.ignore, "ignore-non-existence", "i", false,
"ignore error if the given label doesn't exist",
)
return cmd
}
// newCmdRemoveLabel removes one or more commonLabels from the kustomization file.
func newCmdRemoveLabel(fSys fs.FileSystem, v func([]string) error) *cobra.Command {
var o removeMetadataOptions
o.kind = label
o.arrayValidator = v
cmd := &cobra.Command{
Use: "label",
Short: "Removes one or more commonLabels from " + pgmconfig.KustomizationFileNames[0],
Example: `
remove label {labelKey1},{labelKey2}`,
RunE: func(cmd *cobra.Command, args []string) error {
return o.runE(args, fSys, o.removeLabels)
},
}
cmd.Flags().BoolVarP(&o.ignore, "ignore-non-existence", "i", false,
"ignore error if the given label doesn't exist",
)
return cmd
}
func (o *removeMetadataOptions) runE(
args []string, fSys fs.FileSystem, remover func(*types.Kustomization) error) error {
err := o.validateAndParse(args)
if err != nil {
return err
}
kf, err := kustfile.NewKustomizationFile(fSys)
if err != nil {
return err
}
m, err := kf.Read()
if err != nil {
return err
}
err = remover(m)
if err != nil {
return err
}
return kf.Write(m)
}
// validateAndParse validates `remove` commands and parses them into o.metadata
func (o *removeMetadataOptions) validateAndParse(args []string) error {
if len(args) < 1 {
return fmt.Errorf("must specify %s", o.kind)
}
if len(args) > 1 {
return fmt.Errorf("%ss must be comma-separated, with no spaces", o.kind)
}
m, err := o.convertToArray(args[0])
if err != nil {
return err
}
if err = o.arrayValidator(m); err != nil {
return err
}
o.metadata = m
return nil
}
func (o *removeMetadataOptions) convertToArray(arg string) ([]string, error) {
inputs := strings.Split(arg, ",")
result := make([]string, 0, len(inputs))
for _, input := range inputs {
if len(input) == 0 {
return nil, o.makeError(input, "name is empty")
}
result = append(result, input)
}
return result, nil
}
func (o *removeMetadataOptions) removeAnnotations(m *types.Kustomization) error {
if m.CommonAnnotations == nil && !o.ignore {
return fmt.Errorf("commonAnnotations is not defined in kustomization file")
}
return o.removeFromMap(m.CommonAnnotations, annotation)
}
func (o *removeMetadataOptions) removeLabels(m *types.Kustomization) error {
if m.CommonLabels == nil && !o.ignore {
return fmt.Errorf("commonLabels is not defined in kustomization file")
}
return o.removeFromMap(m.CommonLabels, label)
}
func (o *removeMetadataOptions) removeFromMap(m map[string]string, kind kindOfAdd) error {
for _, k := range o.metadata {
if _, ok := m[k]; !ok && !o.ignore {
return fmt.Errorf("%s %s is not defined in kustomization file", kind, k)
}
delete(m, k)
}
return nil
}
func (o *removeMetadataOptions) makeError(input string, message string) error {
return fmt.Errorf("invalid %s: '%s' (%s)", o.kind, input, message)
}

View File

@@ -0,0 +1,351 @@
/*
Copyright 2019 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 remove
import (
"fmt"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/validators"
"strings"
"testing"
)
func makeKustomizationFS() fs.FileSystem {
fakeFS := fs.MakeFakeFS()
commonLabels := []string{"label1: val1", "label2: val2"}
commonAnnotations := []string{"annotation1: val1", "annotation2: val2"}
fakeFS.WriteTestKustomizationWith([]byte(
fmt.Sprintf("commonLabels:\n %s\ncommonAnnotations:\n %s",
strings.Join(commonLabels, "\n "), strings.Join(commonAnnotations, "\n "))))
return fakeFS
}
func readKustomizationFS(t *testing.T, fakeFS fs.FileSystem) *types.Kustomization {
kf, err := kustfile.NewKustomizationFile(fakeFS)
if err != nil {
t.Errorf("unexpected new error %v", err)
}
m, err := kf.Read()
if err != nil {
t.Errorf("unexpected read error %v", err)
}
return m
}
func makeKustomization(t *testing.T) *types.Kustomization {
fakeFS := makeKustomizationFS()
return readKustomizationFS(t, fakeFS)
}
func TestRemoveAnnotation(t *testing.T) {
var o removeMetadataOptions
o.metadata = []string{"annotation1"}
m := makeKustomization(t)
err := o.removeAnnotations(m)
if err != nil {
t.Errorf("unexpected error: could not write to kustomization file")
}
// adding the same test input should not work
err = o.removeAnnotations(m)
if err == nil {
t.Errorf("expected not exist in kustomization file error")
}
_, exists := m.CommonAnnotations["annotation1"]
if exists {
t.Errorf("annotation1 must be deleted")
}
_, exists = m.CommonAnnotations["annotation2"]
if !exists {
t.Errorf("annotation2 must exist")
}
}
func TestRemoveAnnotationIgnore(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveAnnotation(fakeFS, v.ValidatorArray)
cmd.Flag("ignore-non-existence").Value.Set("true")
args := []string{"annotation3"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error %v", err)
}
}
func TestRemoveAnnotationNoDefinition(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteTestKustomizationWith([]byte(""))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveAnnotation(fakeFS, v.ValidatorArray)
args := []string{"annotation1,annotation2"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "commonAnnotations is not defined in kustomization file" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveAnnotationNoDefinitionIgnore(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteTestKustomizationWith([]byte(""))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
cmd.Flag("ignore-non-existence").Value.Set("true")
args := []string{"annotation1,annotation2"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error %v", err)
}
}
func TestRemoveAnnotationNoArgs(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveAnnotation(fakeFS, v.ValidatorArray)
err := cmd.Execute()
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "must specify label" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveAnnotationInvalidFormat(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeSadMapValidator(t)
cmd := newCmdRemoveAnnotation(fakeFS, v.ValidatorArray)
args := []string{"nospecialchars%^=@"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != validators.SAD {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveAnnotationMultipleArgs(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveAnnotation(fakeFS, v.ValidatorArray)
args := []string{"annotation1,annotation2"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
splitArgs := strings.Split(args[0], ",")
for _, k := range splitArgs {
if _, exist := m.CommonAnnotations[k]; exist {
t.Errorf("%s must be deleted", k)
}
}
}
func TestRemoveAnnotationMultipleArgsInvalidFormat(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeSadMapValidator(t)
cmd := newCmdRemoveAnnotation(fakeFS, v.ValidatorArray)
args := []string{"annotation1", "annotation2"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "labels must be comma-separated, with no spaces" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveLabel(t *testing.T) {
var o removeMetadataOptions
o.metadata = []string{"label1"}
m := makeKustomization(t)
err := o.removeLabels(m)
if err != nil {
t.Errorf("unexpected error: could not write to kustomization file")
}
// adding the same test input should not work
err = o.removeLabels(m)
if err == nil {
t.Errorf("expected not exist in kustomization file error")
}
_, exists := m.CommonLabels["label1"]
if exists {
t.Errorf("label1 must be deleted")
}
_, exists = m.CommonLabels["label2"]
if !exists {
t.Errorf("label2 must exist")
}
}
func TestRemoveLabelIgnore(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
cmd.Flag("ignore-non-existence").Value.Set("true")
args := []string{"label3"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error %v", err)
}
}
func TestRemoveLabelNoDefinition(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteTestKustomizationWith([]byte(""))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
args := []string{"label1,label2"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "commonLabels is not defined in kustomization file" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveLabelNoDefinitionIgnore(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteTestKustomizationWith([]byte(""))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
cmd.Flag("ignore-non-existence").Value.Set("true")
args := []string{"label1,label2"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error %v", err)
}
}
func TestRemoveLabelNoArgs(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
err := cmd.Execute()
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "must specify label" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveLabelInvalidFormat(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeSadMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
args := []string{"exclamation!"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != validators.SAD {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRemoveLabelMultipleArgs(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
args := []string{"label1,label2"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
splitArgs := strings.Split(args[0], ",")
for _, k := range splitArgs {
if _, exist := m.CommonLabels[k]; exist {
t.Errorf("%s must be deleted", k)
}
}
}
func TestRemoveLabelMultipleArgsInvalidFormat(t *testing.T) {
fakeFS := makeKustomizationFS()
v := validators.MakeSadMapValidator(t)
cmd := newCmdRemoveLabel(fakeFS, v.ValidatorArray)
args := []string{"label1", "label2"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "labels must be comma-separated, with no spaces" {
t.Errorf("incorrect error: %v", err.Error())
}
}

View File

@@ -0,0 +1,91 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package remove
import (
"log"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/patch"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
)
type removePatchOptions struct {
patchFilePaths []string
}
// newCmdRemovePatch removes the name of a file containing a patch from the kustomization file.
func newCmdRemovePatch(fsys fs.FileSystem) *cobra.Command {
var o removePatchOptions
cmd := &cobra.Command{
Use: "patch",
Short: "Removes one or more patches from " + pgmconfig.KustomizationFileNames[0],
Example: `
remove patch {filepath}`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
if err != nil {
return err
}
err = o.Complete(cmd, args)
if err != nil {
return err
}
return o.RunRemovePatch(fsys)
},
}
return cmd
}
// Validate validates removePatch command.
func (o *removePatchOptions) Validate(args []string) error {
if len(args) == 0 {
return errors.New("must specify a patch file")
}
o.patchFilePaths = args
return nil
}
// Complete completes removePatch command.
func (o *removePatchOptions) Complete(cmd *cobra.Command, args []string) error {
return nil
}
// RunRemovePatch runs removePatch command (do real work).
func (o *removePatchOptions) RunRemovePatch(fSys fs.FileSystem) error {
patches, err := util.GlobPatterns(fSys, o.patchFilePaths)
if err != nil {
return err
}
if len(patches) == 0 {
return nil
}
mf, err := kustfile.NewKustomizationFile(fSys)
if err != nil {
return err
}
m, err := mf.Read()
if err != nil {
return err
}
var removePatches []string
for _, p := range patches {
if !patch.Exist(m.PatchesStrategicMerge, p) {
log.Printf("patch %s doesn't exist in kustomization file", p)
continue
}
removePatches = append(removePatches, p)
}
m.PatchesStrategicMerge = patch.Delete(m.PatchesStrategicMerge, removePatches...)
return mf.Write(m)
}

View File

@@ -0,0 +1,136 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package remove
import (
"fmt"
"strings"
"testing"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/patch"
)
const (
patchFileContent = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
`
)
func makeKustomizationPatchFS() fs.FileSystem {
fakeFS := fs.MakeFakeFS()
patches := []string{"patch1.yaml", "patch2.yaml"}
fakeFS.WriteTestKustomizationWith([]byte(
fmt.Sprintf("patchesStrategicMerge:\n - %s",
strings.Join(patches, "\n - "))))
for _, p := range patches {
fakeFS.WriteFile(p, []byte(patchFileContent))
}
fakeFS.WriteFile("patch3.yaml", []byte(patchFileContent))
return fakeFS
}
func TestRemovePatch(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch1.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range args {
if patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must be deleted", k)
}
}
}
func TestRemovePatchMultipleArgs(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch1.yaml", "patch2.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range args {
if patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must be deleted", k)
}
}
}
func TestRemovePatchGlob(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch*.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
if len(m.PatchesStrategicMerge) != 0 {
t.Errorf("all patch must be deleted")
}
}
func TestRemovePatchNotDefinedInKustomization(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch3.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range []string{"patch1.yaml", "patch2.yaml"} {
if !patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must exist", k)
}
}
}
func TestRemovePatchNotExist(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch4.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range []string{"patch1.yaml", "patch2.yaml"} {
if !patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must exist", k)
}
}
}
func TestRemovePatchNoArgs(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
err := cmd.RunE(cmd, nil)
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "must specify a patch file" {
t.Errorf("incorrect error: %v", err.Error())
}
}

View File

@@ -19,10 +19,11 @@ package remove
import (
"errors"
"path/filepath"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
type removeResourceOptions struct {
@@ -35,7 +36,7 @@ func newCmdRemoveResource(fsys fs.FileSystem) *cobra.Command {
cmd := &cobra.Command{
Use: "resource",
Short: "Remove resource file paths to the kustomization file.",
Short: "Removes one or more resource file paths from " + pgmconfig.KustomizationFileNames[0],
Example: `
remove resource my-resource.yml
remove resource resource1.yml resource2.yml resource3.yml

View File

@@ -22,7 +22,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func TestRemoveResources(t *testing.T) {

View File

@@ -18,8 +18,8 @@ package set
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
// NewCmdSet returns an instance of 'set' subcommand.

View File

@@ -20,8 +20,8 @@ import (
"errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
type setNamePrefixOptions struct {

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
const (

View File

@@ -20,8 +20,8 @@ import (
"errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
type setNameSuffixOptions struct {

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
const (

View File

@@ -23,9 +23,9 @@ import (
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/image"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/image"
)
type setImageOptions struct {
@@ -133,7 +133,7 @@ func (o *setImageOptions) RunSetImage(fSys fs.FileSystem) error {
return err
}
// append only new images from ksutomize file
// append only new images from kustomize file
for _, im := range m.Images {
if _, ok := o.imageMap[im.Name]; ok {
continue

View File

@@ -21,7 +21,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func TestSetImage(t *testing.T) {

View File

@@ -22,9 +22,9 @@ import (
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/ifc"
)
type setNamespaceOptions struct {

View File

@@ -21,8 +21,8 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/validators"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/validators"
)
const (

View File

@@ -0,0 +1,26 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package util
import (
"log"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func GlobPatterns(fsys fs.FileSystem, patterns []string) ([]string, error) {
var result []string
for _, pattern := range patterns {
files, err := fsys.Glob(pattern)
if err != nil {
return nil, err
}
if len(files) == 0 {
log.Printf("%s has no match", pattern)
continue
}
result = append(result, files...)
}
return result, nil
}

View File

@@ -26,9 +26,9 @@ import (
"regexp"
"strings"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/types"
"sigs.k8s.io/yaml"
)

View File

@@ -21,9 +21,9 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
func TestFieldOrder(t *testing.T) {

View File

@@ -22,8 +22,8 @@ import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/transformers/config/defaultconfig"
)
// NewCmdConfig returns an instance of 'config' subcommand.

View File

@@ -22,7 +22,7 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func TestValidate(t *testing.T) {

View File

@@ -20,7 +20,7 @@ import (
"fmt"
"testing"
. "sigs.k8s.io/kustomize/pkg/expansion"
. "sigs.k8s.io/kustomize/v3/pkg/expansion"
)
type expected struct {

View File

@@ -22,7 +22,7 @@ import (
"sort"
"strings"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
)
var _ FileSystem = &fakeFs{}

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