Compare commits

...

733 Commits

Author SHA1 Message Date
Jeff Regan
865348695f Update remoteBuild.md 2019-04-29 10:06:41 -07:00
Jeff Regan
2ec8189c1c Update remoteBuild.md 2019-04-29 09:59:00 -07:00
Kubernetes Prow Robot
a5dfc65440 Merge pull request #828 from kenmaglio/add-choco-documentation
Adds documentation for choco package for windows
2019-04-29 08:26:21 -07:00
Kubernetes Prow Robot
45302f0790 Merge pull request #1021 from max-sixty/patch-1
Update strategic-merge link
2019-04-29 08:24:25 -07:00
Maximilian Roos
1afc6c775b Update strategic-merge link
The existing link has been deprecated
2019-04-26 21:44:30 -04:00
Kubernetes Prow Robot
ca4d5ed42b Merge pull request #1019 from monopole/addIfToInflator
Mods to chart inflator plugin
2019-04-26 15:56:22 -07:00
Jeffrey Regan
cd9572e0bb hey 2019-04-26 15:48:41 -07:00
Jeff Regan
ac3ea4d6f3 Merge pull request #1014 from rohitsardesai83/replace_ghodss_yaml_with_sigsk8sio_yaml_dep
Remove dependency on ghodss/yaml
2019-04-26 09:50:51 -07:00
Jeff Regan
030824b196 Merge pull request #1016 from monopole/frog
Make plugin dir match Go conventions.
2019-04-26 09:07:19 -07:00
jregan
cfb0c5efad Make plugin dir match Go conventions. 2019-04-25 20:30:10 -07:00
rohitsardesai83
b67d713bc0 Remove dependency on ghodss/yaml 2019-04-25 23:47:01 +05:30
Kubernetes Prow Robot
0ac48f60a5 Merge pull request #1011 from Liujingfang1/execdir
pass loader root to exec plugins
2019-04-24 19:46:44 -07:00
Jingfang Liu
445f739234 add test for ensuirng the loader root is correctly passed 2019-04-24 18:32:03 -07:00
Jingfang Liu
fc8063f752 pass loader root to exec plugins 2019-04-24 12:09:25 -07:00
Kubernetes Prow Robot
520acc7d97 Merge pull request #1008 from Liujingfang1/resid
add ItemId type
2019-04-23 17:30:00 -07:00
Jeff Regan
ae0510f648 Update chartinflatorexecplugin_test.go 2019-04-23 17:23:55 -07:00
Jeff Regan
0f50be877c Update ChartInflatorExec 2019-04-23 17:05:12 -07:00
Jingfang Liu
5b18c4de0c add ItemId type 2019-04-23 16:31:48 -07:00
Jeff Regan
72fd31fd20 Update FAQ.md 2019-04-23 16:29:32 -07:00
Jeff Regan
256ffdb932 Merge pull request #1007 from monopole/collectInternal
Collect existing internal pkgs under one roof.
2019-04-23 12:01:40 -07:00
Jeffrey Regan
8991bcb399 Collect existing internal pkgs under one roof. 2019-04-23 11:53:50 -07:00
Jeff Regan
185ae510e8 Update README.md 2019-04-23 11:24:14 -07:00
Kubernetes Prow Robot
40303cb329 Merge pull request #1005 from monopole/addLoaderTest
Add a plugin loader test.
2019-04-22 15:40:06 -07:00
Kubernetes Prow Robot
38ec207609 Merge pull request #1004 from Liujingfang1/prune
change field name: prune -> inventory
2019-04-22 15:14:07 -07:00
Jeffrey Regan
1545e07dd6 Add a plugin loader test. 2019-04-22 15:00:32 -07:00
Kubernetes Prow Robot
f123380917 Merge pull request #1003 from monopole/simplifyPluginLoader
Simplify plugin loader code.
2019-04-22 11:27:45 -07:00
Jingfang Liu
b4fc1e4357 change field name: prune -> inventory 2019-04-22 11:25:14 -07:00
jregan
76a3179868 Simplify plugin loader code.
* use one place to build plugin file names,
 * use one loader instance,
 * test for plugin enabled flag in just one place to
   avoid errors and reduce if statements,
 * don't return private objects,
 * factor goplugin loading to a method,
 * fix a related test that was commented out.
2019-04-22 10:13:40 -07:00
Kubernetes Prow Robot
c9bf70fd4b Merge pull request #1002 from monopole/deleteKustomizationError
Delete kustomizationerror.
2019-04-22 09:53:45 -07:00
jregan
9a85071085 Delete kustomizationerror.
Do a longstanding TODO to remove kustomizationerror.

It wasn't used much, and it wasn't used consistently,
because it's complicated to decided when it's worth
proceeding to accumulate errors when one already knows
that one has a fatal error in the kustomization.  Its
use was blocking refactoring for simplicity and making
tests harder to write.

Removing it lets us reinstate the cyclomatic complexity
check in KustTarget.

Also added more info to the affected error messages.
2019-04-21 16:10:58 -07:00
Jeff Regan
a6f41bb96d Merge pull request #1000 from monopole/faq
Add faq
2019-04-20 07:50:10 -07:00
Jeffrey Regan
3f2acc90aa Add faq 2019-04-20 07:47:31 -07:00
Jeff Regan
aba9f7d1e5 Merge pull request #998 from monopole/addLoadRestrictorFlag
Add load_restrictor flag.
2019-04-20 07:09:01 -07:00
Jeffrey Regan
3b8c5ee96d Add load_restrictor flag. 2019-04-19 17:33:51 -07:00
Kubernetes Prow Robot
a5bb5479fb Merge pull request #995 from monopole/removeLocalLoadRestrictions
Remove local load restrictions.
2019-04-19 16:27:54 -07:00
Jeffrey Regan
3c58c9d132 Remove local load restrictions. 2019-04-19 15:47:13 -07:00
Kubernetes Prow Robot
1b1f91580e Merge pull request #996 from monopole/addTestShowingSharedPatchesDisallowed
Add test showing shared patches disallowed
2019-04-19 14:59:55 -07:00
Jeffrey Regan
644dc4b9a7 Add test showing shared patches disallowed. 2019-04-19 14:42:30 -07:00
Jeffrey Regan
96707645e2 Add test showing shared patches disallowed. 2019-04-19 14:39:02 -07:00
Jeff Regan
b878e5f10d Merge pull request #993 from monopole/fixNits
Fix some comment nits.
2019-04-19 09:29:18 -07:00
Jeffrey Regan
a914570240 Fix some comment nits. 2019-04-19 09:26:54 -07:00
Kubernetes Prow Robot
b3d2ab29e9 Merge pull request #992 from sunny0826/master
docs add kubectl command
2019-04-19 09:09:55 -07:00
郭旭东
3ff5c793e3 docs add kubectl command 2019-04-19 18:09:01 +08:00
Kubernetes Prow Robot
c752660aa6 Merge pull request #990 from monopole/removeSomeDupes
Remove some duped code.
2019-04-18 11:51:27 -07:00
Jeff Regan
efded10e26 Merge pull request #971 from pohly/base-renaming-json-patch
tests: demonstrate issue with JSON patch when base adds name prefix
2019-04-18 11:48:55 -07:00
Jeffrey Regan
8767495b5a Remove some duped code. 2019-04-18 11:37:42 -07:00
Patrick Ohly
403ede788c tests: demonstrate issue with JSON patch when base adds name prefix
The expectation is that the base entity can be referenced by its name
with prefix, because the overlay shouldn't have to know how the base
is generated. But currently the entity is only found when using the
name without prefix.

Related-To: #972
2019-04-18 20:36:39 +02:00
Jeff Regan
c444f93eb5 Merge pull request #960 from zeeZ/individual-output
Write individual files to output path if it is a directory
2019-04-18 11:26:14 -07:00
Kubernetes Prow Robot
ed146f656e Merge pull request #988 from mengqiy/nscluster
fix namespace transformer for cluster-scoped resources
2019-04-18 11:16:04 -07:00
Mengqi Yu
bcb697eb0b fix namespace transformer for cluster-scoped resources 2019-04-18 11:03:19 -07:00
Kubernetes Prow Robot
3ac66049c7 Merge pull request #989 from Liujingfang1/prune
update PruneString for resources
2019-04-18 10:54:02 -07:00
Kubernetes Prow Robot
7a1a231041 Merge pull request #984 from afirth/20190516_vars_for_secretName
Vars should expand in ingress/spec/tls/secretName
2019-04-18 10:52:06 -07:00
Jingfang Liu
748c88c276 update PruneString for resources 2019-04-18 10:39:22 -07:00
Mengqi Yu
6f4b104c9e add admission webhook types in the default cluster-scoped resource list 2019-04-18 10:30:04 -07:00
Kubernetes Prow Robot
867201a075 Merge pull request #980 from monopole/helmChartInflatorExec
Helm chart generator exec plugin
2019-04-18 08:54:09 -07:00
Jeffrey Regan
2545ea1019 Helm chart generator exec plugin 2019-04-17 19:07:20 -07:00
Alastair Firth
5be42092af Vars should expand in ingress/spec/tls/secretName
https://github.com/kubernetes-sigs/kustomize/issues/799
2019-04-16 23:36:05 +02:00
Kubernetes Prow Robot
50c076eb3f Merge pull request #983 from Liujingfang1/exec
add the unstructured to ENV of exec plugins
2019-04-16 13:49:10 -07:00
Jingfang Liu
fb9e00bf33 add the unstructured to ENV of exec plugins 2019-04-16 13:12:42 -07:00
Kubernetes Prow Robot
b9007fcc29 Merge pull request #974 from Liujingfang1/exec
add support for exec plugins
2019-04-16 10:39:09 -07:00
Jingfang Liu
f6e01cfda7 add support for exec plugins 2019-04-16 09:26:38 -07:00
Christian
9203478a8a Write individual files to output path if it is a directory 2019-04-13 09:46:43 +02:00
Kubernetes Prow Robot
28cb6daec7 Merge pull request #968 from monopole/switchToVGo
Switch to vgo
2019-04-12 09:38:47 -07:00
Jeffrey Regan
e191ff53dd Switch to vgo 2019-04-11 22:25:37 -07:00
Kubernetes Prow Robot
177297c0ef Merge pull request #959 from Liujingfang1/execplugins
add goplugin for exec generators and transformers
2019-04-09 15:48:11 -07:00
Jingfang Liu
e5d730e1fe address comments 2019-04-09 15:42:08 -07:00
Jingfang Liu
ba43ecbcb7 add goplugin for exec generators and transformers 2019-04-09 13:13:21 -07:00
Kubernetes Prow Robot
ee68a9c450 Merge pull request #957 from monopole/justTheFactsMaam
Define a plugin compiler.
2019-04-08 18:33:04 -07:00
jregan
175c754f61 Define a plugin compiler. 2019-04-08 18:05:31 -07:00
Kubernetes Prow Robot
e8eed838b5 Merge pull request #926 from Liujingfang1/prune
generate configmap for pruning
2019-04-08 15:24:27 -07:00
Jingfang Liu
e9a3f9f5f6 address comments 2019-04-08 15:17:18 -07:00
Jingfang Liu
826affb8dd generate configmap for pruning 2019-04-08 14:10:49 -07:00
Kubernetes Prow Robot
4937b1c75e Merge pull request #955 from monopole/addSecretGenerator
Add secret generator.
2019-04-08 09:02:30 -07:00
jregan
ffc16d51e0 Add secret generator. 2019-04-06 18:38:22 -07:00
Jeff Regan
1623f1e4c0 Merge pull request #954 from monopole/genGen
Consolidate some generator and transformer code.
2019-04-06 18:38:04 -07:00
jregan
b32e041bfe Remove some duped code. 2019-04-06 16:14:12 -07:00
Kubernetes Prow Robot
38029d1836 Merge pull request #951 from Liujingfang1/generatorplugins
add support for generator go-plugins
2019-04-06 13:40:26 -07:00
Jeff Regan
b2dd74ab97 Merge pull request #953 from monopole/cleanPluginBuilds
Cleanup plugin builds.
2019-04-06 13:23:16 -07:00
jregan
16fe7ced6a Cleanup plugin builds. 2019-04-06 13:16:46 -07:00
Kubernetes Prow Robot
cb4af7a9d4 Merge pull request #950 from 2opremio/564-add-force-flag-to-annotations-and-labels
Add --force flag to modify annotations and labels
2019-04-05 14:05:52 -07:00
Jingfang Liu
7493732176 add generator plugins 2019-04-05 13:51:56 -07:00
Alfonso Acosta
2cf8371add Add --force flag to modify annotations and labels
This change adds a new flag (`--force`) to commands `edit add annotation` and
`edit add label` so that annotations and labels are modified if they already
existed.
2019-04-05 22:49:28 +02:00
Jeff Regan
a575c24a24 Merge pull request #948 from bells17/fix-path
Fix path
2019-04-05 12:56:15 -07:00
Kubernetes Prow Robot
9e8d06e7ce Merge pull request #946 from Liujingfang1/moreplugins
add support for transformer goplugins
2019-04-05 11:25:20 -07:00
Jingfang Liu
4f1a2350ce add transformer plugins 2019-04-05 10:16:10 -07:00
Daiki Hayakawa
cefb64b6a9 Fix path 2019-04-05 18:02:37 +09:00
jregan
440d036176 some transformer plugins 2019-04-04 13:23:41 -07:00
Kubernetes Prow Robot
53f0deec8f Merge pull request #941 from Liujingfang1/gentran
add generators/transformers fields in kusotmization.yaml
2019-04-03 16:44:48 -07:00
Kubernetes Prow Robot
3c495e3b23 Merge pull request #939 from kbhawkey/doc-images-take2
add tutorial for custom images transformer
2019-04-03 14:36:49 -07:00
Jingfang Liu
deaf0779a1 add generators/transformers fields in kusotmization.yaml 2019-04-03 14:05:25 -07:00
Jeff Regan
fd7a353df6 Merge pull request #938 from monopole/tweakDoc
Expound on plugin caveats
2019-04-01 09:40:53 -07:00
Karen Bradshaw
927b497feb fix tests 2019-03-31 19:05:35 -04:00
Karen Bradshaw
237c54f47e add tutorial for custom images transformer 2019-03-31 16:29:52 -04:00
Kubernetes Prow Robot
8c23db47a7 Merge pull request #936 from Liujingfang1/note
add note for availability in kubectl
2019-03-30 18:38:34 -07:00
jregan
7971ac1cb8 Tweak secret docs. 2019-03-30 18:22:43 -07:00
Yujun Zhang
2490e605c3 Updates in image transformer (#911)
- Decouple `mutateImage` from `updateContainers` to be reused as `mutateFunc`
- Ignore default image transform error for CRD which may contain non-array type `containers` field

Related to #890, #904, fixes #890
2019-03-29 13:11:07 -07:00
Jingfang Liu
21a0cba43e fix the regression of building remote url (#935) 2019-03-29 13:10:11 -07:00
Kubernetes Prow Robot
42d9287985 Merge pull request #931 from michaelheyvaert/fix-cronjob-projected-volume-namerefs
fix configmap/secret name references for cronjobs with projected volumes
2019-03-29 09:28:23 -07:00
Michael Heyvaert
4848987a1f fix configmap/secret name references for cronjobs with projected volumes 2019-03-29 09:00:00 +01:00
Jingfang Liu
53a22cbe9b add note for availability in kubectl 2019-03-28 15:22:49 -07:00
Jeff Regan
c3700e0c88 Merge pull request #934 from monopole/tweakPluginDoc
Improve plugin doc.
2019-03-28 12:51:49 -07:00
Jeffrey Regan
58d9a51040 Improve plugin doc. 2019-03-28 12:50:19 -07:00
Jeff Regan
8f395ad86f Merge pull request #925 from monopole/addGoPluginExample
Add goplugin KV generator example.
2019-03-28 10:24:06 -07:00
Jeffrey Regan
99391157ec Add goplugin KV generator example. 2019-03-28 09:55:44 -07:00
Jeff Regan
99406d4412 Merge pull request #933 from monopole/fixTravisMaybe
Update travis file.
2019-03-28 09:54:30 -07:00
Jeffrey Regan
c1dea6676f Update travis file. 2019-03-28 09:42:18 -07:00
Kubernetes Prow Robot
afa4664511 Merge pull request #920 from monopole/fix918
fix a bool check
2019-03-26 11:03:22 -07:00
Jeffrey Regan
267eec5509 Fix 918 2019-03-26 10:47:31 -07:00
Jeff Regan
9764eb2f83 Merge pull request #919 from monopole/accumulatorPkg
Move accumulator code to its own package.
2019-03-26 10:04:46 -07:00
Jeffrey Regan
9a12b55139 Move accumulator code to its own package. 2019-03-26 09:53:52 -07:00
Kubernetes Prow Robot
f8cffef977 Merge pull request #889 from sethpollack/edit_add_plugins
update edit add secrets/configmaps to use plugins
2019-03-21 13:51:37 -07:00
Seth Pollack
822420e4ab fix mergeFlags 2019-03-21 14:58:06 -04:00
Seth Pollack
b60fca05bd update edit add secrets/configmaps to use plugins 2019-03-20 09:24:10 -04:00
Kubernetes Prow Robot
1a35071672 Merge pull request #895 from Liujingfang1/patchnamespace
skip adding namespace when the object is empty
2019-03-19 15:42:22 -07:00
Jingfang Liu
bfc3655bad skip adding namespace when the object is empty 2019-03-19 15:34:29 -07:00
Kubernetes Prow Robot
2c0c0c9497 Merge pull request #841 from yujunz/transformers/image
Support custom configuration for image transformer
2019-03-19 14:08:22 -07:00
Kubernetes Prow Robot
46bd38e89d Merge pull request #891 from sethpollack/envfiles
add builtin envfiles plugin
2019-03-18 12:58:21 -07:00
Seth Pollack
9fc4d388ce add builtin envfiles plugin 2019-03-18 13:58:38 -04:00
Jeff Regan
2965134f89 Merge pull request #892 from monopole/defaultToBuiltin
Make builtin the default pluginType
2019-03-18 10:29:22 -07:00
Jeffrey Regan
3a7c8a03f4 Make builtin the default pluginType 2019-03-18 10:21:24 -07:00
Kubernetes Prow Robot
449b1b68e0 Merge pull request #888 from sethpollack/files
add builtin files plugin
2019-03-18 09:46:20 -07:00
Seth Pollack
dd59eb38d0 add test case 2019-03-17 20:44:07 -04:00
Seth Pollack
a8465c95e1 add builtin files plugin 2019-03-17 17:22:52 -04:00
Kubernetes Prow Robot
df2f67b191 Merge pull request #883 from sethpollack/builtins
add builtin plugin for literals
2019-03-17 14:05:09 -07:00
Seth Pollack
7764dee59d Merge branch 'master' into builtins 2019-03-17 17:01:06 -04:00
Jeff Regan
6465a36176 Merge pull request #887 from monopole/addNannyFlag
Put goplugins behind flag.
2019-03-17 13:46:03 -07:00
jregan
103c1b3a4f Put goplugins behind flag. 2019-03-17 13:39:48 -07:00
Seth Pollack
29cbec37b8 move parse helpers to util 2019-03-17 12:34:52 -04:00
Kubernetes Prow Robot
2c9e4507a7 Merge pull request #861 from kbhawkey/fix-spelling-transformerconfig
correct spelling, minor word ordering
2019-03-17 06:38:55 -07:00
Kubernetes Prow Robot
d5d5c076a7 Merge pull request #882 from sethpollack/xdg_home
honor XDG_CONFIG_HOME
2019-03-17 06:36:55 -07:00
Kubernetes Prow Robot
f09bbff35c Merge pull request #884 from vreon/fix-varrefs
Fix incorrect and missing varReferences
2019-03-17 06:12:56 -07:00
Kubernetes Prow Robot
2627e2507b Merge pull request #885 from yujunz/imagetransformer/test
Convert image transformer test to a more readable format
2019-03-17 06:08:55 -07:00
Seth Pollack
1bd7afe6e7 fix linter 2019-03-17 08:53:49 -04:00
Yujun Zhang
e6c1b14108 Add test for transformers/image custom config 2019-03-17 16:59:41 +08:00
Yujun Zhang
7130e3ff1d Leave defautconfig empty for images
`containers` and `initContainers` of *ANY* kind in *ANY*
path are builtin supported in code
2019-03-17 16:43:31 +08:00
Yujun Zhang
abf538d80d Keep backward compatibility for image transformer 2019-03-17 16:43:31 +08:00
Yujun Zhang
f311ba8d4f Support custom config for image transformer 2019-03-17 16:43:31 +08:00
Yujun Zhang
3e85c4589b Load default config for image transformer 2019-03-17 16:43:31 +08:00
Yujun Zhang
d0cf047381 Convert image transformer test to a more readable format 2019-03-17 16:41:42 +08:00
Jesse Dubay
31091a8df2 Fix missing varrefs for CronJob, Job, ReplicaSet 2019-03-16 19:15:56 -07:00
Jesse Dubay
e207ae4c01 Fix incorrect default varrefs for CronJob volumeMounts 2019-03-16 19:12:58 -07:00
Jesse Dubay
3011f18047 Sort default varReference config by kind, path 2019-03-16 19:11:42 -07:00
Seth Pollack
388d5c2d7c add builtin plugins 2019-03-16 21:21:15 -04:00
Seth Pollack
5c4719651e honor XDG_CONFIG_HOME 2019-03-16 20:46:37 -04:00
Karen Bradshaw
f850ca63f4 remove extra comment 2019-03-16 16:49:16 -04:00
Karen Bradshaw
65886f1258 address comments 2019-03-16 16:40:30 -04:00
Karen Bradshaw
942e36e19f a few more changes 2019-03-16 16:40:29 -04:00
Karen Bradshaw
7b82154c4c correct spelling, minor word ordering 2019-03-16 16:40:29 -04:00
Kubernetes Prow Robot
284efc709c Merge pull request #760 from sethpollack/plugins
add secret and configmap generator plugins
2019-03-15 18:00:58 -07:00
Seth Pollack
56965a0046 fix test 2019-03-15 17:33:17 -04:00
Seth Pollack
18f6328284 add secret and configmap generator plugins 2019-03-15 14:28:18 -04:00
Jeff Regan
e7be999bc9 Merge pull request #879 from monopole/removeTheSet
Secret/configmap factory cleanup.
2019-03-15 10:17:29 -07:00
jregan
c06b95077d Secret/configmap factory cleanup. 2019-03-15 09:25:59 -07:00
Kubernetes Prow Robot
c4da063934 Merge pull request #877 from YP28/fix-typo-in-namereference
fix typo in namereference where serviceaccount name would not resolve
2019-03-14 08:46:29 -07:00
Yordi Pauptit
62d3200e4f fix typo in namereference where serviceaccount name would not resolve 2019-03-14 09:36:21 +01:00
Kubernetes Prow Robot
9a419824ae Merge pull request #874 from CodeLingoBot/rewrite
Fix function comments based on best practices from Effective Go
2019-03-12 14:50:39 -07:00
Kubernetes Prow Robot
a94eab0398 Merge pull request #867 from yujunz/docs/versioning-policy
Fix field names
2019-03-12 14:48:39 -07:00
Kubernetes Prow Robot
01b8ab8524 Merge pull request #872 from kbhawkey/fix-set-image-help-msg
fix help msg for set image cmd
2019-03-11 14:44:37 -07:00
Karen Bradshaw
fa552d7773 fix help msg for set image cmd 2019-03-11 17:23:30 -04:00
Kubernetes Prow Robot
7acbd4d3e0 Merge pull request #870 from YP28/job-initctr-varref
Add Job initContainer to varreference config
2019-03-11 10:39:29 -07:00
Kubernetes Prow Robot
9811123e2e Merge pull request #866 from yujunz/edit-fix
Fix error message
2019-03-11 10:13:28 -07:00
Yordi Pauptit
f7cd44be42 add job initcontainer to varreference config 2019-03-11 15:13:58 +01:00
CodeLingo Bot
9a4692e6ee Fix function comments based on best practices from Effective Go
Signed-off-by: CodeLingo Bot <bot@codelingo.io>
2019-03-11 00:45:21 +00:00
Yujun Zhang
3d0e29075d Fix markdownlint warnings 2019-03-09 17:02:39 +08:00
Yujun Zhang
0f571b9120 Fix field names 2019-03-09 16:58:32 +08:00
Yujun Zhang
3a44508d6f Fix error message
Closes #862
2019-03-09 16:43:32 +08:00
Kubernetes Prow Robot
5294355c98 Merge pull request #864 from mnatsu31/fix-typo-namereference
Fix typo in namereference path for cronjobs initContainers.
2019-03-08 09:25:30 -08:00
mnatsu31
559efd6477 Fix typo in namereference path for cronjobs initContainers. 2019-03-08 13:20:34 +09:00
Kubernetes Prow Robot
a59577c08d Merge pull request #857 from pst/fastergitclone
Reduce time required for cloning remote bases
2019-03-06 21:24:57 -08:00
Philipp Strube
4f429d6b86 Reduce time required for cloning remote bases
This commit changes git/cloner.go from cloning the whole history
and then checking out the desired ref to a implementation that
only downloads the history for the desired ref.

It does so by first initializing an empty repository, setting the
source repository as a remote, fetching just the desired ref and
then hard resetting the empty local repo to that ref.

This reduces the time it takes to build the multibases example
as a remote base at ref v2.0.3 from an avg of 8s with the
current implementation to an avg of 2s out of 10 runs each, by
drastically decreasing the data transferred.

The improvement should increase as repositories grow.
2019-03-06 19:31:24 +01:00
Jeff Regan
a6f6514412 Merge pull request #842 from narayanan/annotation-with-colon
Fix for #818 - Added support for quoted values
2019-03-04 17:40:12 -08:00
Jeff Regan
31ee38b1a1 Merge pull request #833 from Liujingfang1/crd_errmsg
improve error message for loading files listed under crds
2019-03-04 17:36:43 -08:00
Jeff Regan
46c7d6d39a Merge pull request #832 from Liujingfang1/jsonpatch
improve error message in json patch transformer
2019-03-04 17:35:37 -08:00
Jingfang Liu
78cbff16ef improve error message in json patch transformer 2019-03-04 16:43:24 -08:00
Jingfang Liu
28cefb3bd1 improve error message for loading files listed under crds 2019-03-04 16:32:01 -08:00
Narayanan Singaram
e666630d36 Simplify map conversion logic 2019-03-04 13:50:49 -08:00
Narayanan Singaram
ed2ad860c6 Move trim quotes logic to separate function 2019-03-04 13:19:18 -08:00
Kubernetes Prow Robot
a341c24b2a Merge pull request #837 from narayanan/image-with-port
Fix for #831 - Ignore domain when finding the image tag
2019-03-04 11:21:14 -08:00
Kubernetes Prow Robot
0101d6e393 Merge pull request #844 from yujunz/configmaps/test
Add configmaps test for json string
2019-03-04 11:04:39 -08:00
Kubernetes Prow Robot
e429d8ca10 Merge pull request #835 from pwittrock/master
Run kustomize tests on OSx
2019-03-04 10:03:00 -08:00
Yujun Zhang
45ba785641 Add configmaps test for json string 2019-03-03 10:21:03 +08:00
Narayanan Singaram
ea3d5e68db Fix for #818 - Added support for quoted values 2019-03-02 12:23:55 -08:00
Narayanan Singaram
eb75203926 Fix for #831 - Ignore domain when finding the image tag 2019-03-01 23:23:32 -08:00
Phillip Wittrock
1303ea3969 Run kustomize tests on OSX 2019-02-28 20:03:23 -08:00
Ken Maglio
bb69e9e70b Updates documentation for support and source 2019-02-28 21:45:40 -06:00
Kubernetes Prow Robot
16d1b20ed6 Merge pull request #830 from Liujingfang1/doc
update transformerconfigs/crd example
2019-02-27 15:05:00 -08:00
Jingfang Liu
b0c3cd75e1 update the doc for crds: the files in this list should be openAPI definition 2019-02-27 14:11:15 -08:00
Jingfang Liu
f4eef1dc0b update transformerconfigs/crd example 2019-02-27 13:26:58 -08:00
Kubernetes Prow Robot
76c6655520 Merge pull request #829 from monopole/fix317
Log warning about well-defined but unused variables.
2019-02-27 11:18:39 -08:00
Kubernetes Prow Robot
d5c8734555 Merge pull request #822 from Liujingfang1/webhooks
Add webhooks to order list of gvk
2019-02-26 21:55:10 -08:00
Kubernetes Prow Robot
62ee138173 Merge pull request #825 from PrasadG193/update-dep-golang/x/net
Update golang/x/net dependency to release-branch.go1.11
2019-02-26 21:49:37 -08:00
Jeffrey Regan
ff6cd3ca55 Report unused variables. 2019-02-26 21:04:36 -08:00
Ken Maglio
852e7ed5aa Typo Fix 2019-02-26 17:19:33 -06:00
Jeff Regan
b7e8042a02 Merge pull request #827 from monopole/fix826
Improve error handling during var resolution.
2019-02-26 14:14:14 -08:00
jregan
6bfd7cff72 Improve error handling during var resolution. 2019-02-26 14:05:38 -08:00
Prasad Ghangal
9d77cbea8c Update golang/x/net dependency to release-branch.go1.11 2019-02-27 00:44:10 +05:30
Jingfang Liu
8bbe147c14 Add webhooks to order list of gvk 2019-02-26 10:39:23 -08:00
Kubernetes Prow Robot
b67179e951 Merge pull request #820 from st1t/remove-imagetag
Change imagetag to image in docs/eschewedFeatures.md
2019-02-25 08:50:55 -08:00
Kubernetes Prow Robot
47237aa7a2 Merge pull request #813 from yujunz/varref
Add Pod initContainer to var reference
2019-02-25 08:48:49 -08:00
Shota Ito
5e6c06fb61 Change imagetag to image in docs/eschewedFeatures.md 2019-02-25 20:23:36 +09:00
Yujun Zhang
901455eb0b Add Pod initContainer to var reference 2019-02-24 11:36:09 +08:00
Jeff Regan
f8c80b7335 Merge pull request #812 from monopole/moreGeneratorTests
More generator tests.
2019-02-23 04:48:37 -08:00
Kubernetes Prow Robot
8db82d27e9 Merge pull request #811 from narg95/fix_new_tmp_confirmdir
fix absolute path for temp folder in MacOs
2019-02-22 17:31:12 -08:00
Nestor
1eab47b63f fix abs path with symlinks
Signed-off-by: Nestor <nesterran@gmail.com>
2019-02-22 18:29:53 +01:00
Kubernetes Prow Robot
c4656b71e5 Merge pull request #786 from ChrsMark/master
Change ExpandFileSource to work with key=val patterns
2019-02-22 07:14:07 -08:00
Kubernetes Prow Robot
711d3d3515 Merge pull request #809 from narg95/prevent_panic_image_trasformer
prevent panic on image transformer
2019-02-22 07:05:16 -08:00
Jeffrey Regan
0488f570cb More generator tests. 2019-02-22 06:52:41 -08:00
Nestor
0e459ebac8 prevent panic on image transformer
Signed-off-by: Nestor <nesterran@gmail.com>
2019-02-22 08:55:38 +01:00
Ken Maglio
1d65f24b04 adds documentation for choco package 2019-02-21 19:54:48 -06:00
Kubernetes Prow Robot
70719a8f65 Merge pull request #807 from Agilicus/add-generator-options
Add doc indicating existing of 'behavior' in configMapGenerator
2019-02-21 09:20:31 -08:00
Don Bowman
773c1f2199 Make requested wording changes from PR for behavior document
Signed-off-by: Don Bowman <don@agilicus.com>
2019-02-21 11:53:12 -05:00
Don Bowman
bf1c801a5e Add doc indicating existing of 'behavior' in configMapGenerator
It appears from the code that configMapGenerator can take
a parameter of 'behavior' which is 'merge','create','replace'.
Add note to the 'docs/kustomization.yaml' indicating so.

Signed-off-by: Don Bowman <don@agilicus.com>
2019-02-21 11:31:54 -05:00
Kubernetes Prow Robot
e1420b408c Merge pull request #762 from dimitropoulos/patch-1
typo: makes verb number agree with subject
2019-02-19 16:26:03 -08:00
Kubernetes Prow Robot
88a7471039 Merge pull request #796 from monopole/moreResIDTests
Add more resid test coverage.
2019-02-19 13:44:12 -08:00
Kubernetes Prow Robot
3c58cf0bf0 Merge pull request #789 from mrbrownt/runtime-version
Pulling goos and goarch from runtime
2019-02-19 09:07:27 -08:00
Chris Mark
77eebb89fd Review changes
Signed-off-by: Chris Mark <chrismarkou92@gmail.com>
2019-02-18 09:28:04 +02:00
jregan
d4d993a53c Add more resid test coverage. 2019-02-16 14:26:43 -08:00
Jeff Regan
ef3b0672c5 Merge pull request #795 from monopole/deleteExtraCopyright
Delete extraneous copyright.
2019-02-16 11:56:40 -08:00
jregan
0f30c09cbf Delete extraneous copyright. 2019-02-16 11:52:12 -08:00
Kubernetes Prow Robot
6f670a8f38 Merge pull request #782 from narg95/varref_in_maps_values
add support for varref in maps values
2019-02-15 14:53:21 -08:00
Nestor
8c93f7ba74 add support for varref in maps values 2019-02-14 08:02:32 +01:00
Todd Brown
7d3735b19e Adding goos and goarch from runtime 2019-02-13 10:59:35 -06:00
Chris Mark
f5f8e49fa3 Add explanatory comments and format
Signed-off-by: Chris Mark <chrismarkou92@gmail.com>
2019-02-13 09:38:13 +02:00
Chris
1382d87d7f Change ExpandFileSource to work with key=val patterns
Signed-off-by: Chris <chrismarkou92@gmail.com>
2019-02-13 09:30:06 +02:00
Kubernetes Prow Robot
e65b45f969 Merge pull request #790 from laverya/allow-all-kind-List-types
Allow all kind list types
2019-02-12 15:18:33 -08:00
Andrew Lavery
d72b16235a add a test for a list with no 'items:' provided 2019-02-12 15:07:46 -08:00
Andrew Lavery
3118ccfd05 add tests for *List kinds and empty lists 2019-02-12 12:45:28 -08:00
Andrew Lavery
fdba7df3c1 if the kind matches '*List$', treat it as a list 2019-02-12 12:28:08 -08:00
Kubernetes Prow Robot
02d753027a Merge pull request #788 from Liujingfang1/doc
fix invalid relative path in kustomization.yaml
2019-02-12 09:22:32 -08:00
Jingfang Liu
1a43759ac3 fix invalid relative path in kustomization.yaml 2019-02-12 08:57:56 -08:00
Kubernetes Prow Robot
7574f07be3 Merge pull request #785 from monopole/blackBoxTests
Switch to black box testing of KustTarget and Resource
2019-02-11 18:36:51 -08:00
Jeffrey Regan
48717f3f30 Switch to black box testing of KustTarget and Resource 2019-02-11 16:40:09 -08:00
Jeff Regan
74d3e92b55 Merge pull request #783 from monopole/testKustFileMissingMessage
Test missing kust file message
2019-02-11 10:18:54 -08:00
Kubernetes Prow Robot
f66024b1c1 Merge pull request #781 from saromanov/loop-refactoring
transformers/image: loop refactoring
2019-02-11 10:15:11 -08:00
Kubernetes Prow Robot
bf4e09a400 Merge pull request #761 from narg95/varref_mountpath
add volumeMounts/mountPath to varreference
2019-02-11 08:16:36 -08:00
Nestor
d968c0b4b1 add varref mountpath test case 2019-02-11 07:52:45 +01:00
Nestor
9837b5b429 add volumeMounts/mountPath to varreference
Signed-off-by: Nestor <nesterran@gmail.com>
2019-02-11 07:52:45 +01:00
jregan
1a03dcabde Test missing file report 2019-02-10 15:37:11 -08:00
Kubernetes Prow Robot
6fb11493ad Merge pull request #780 from monopole/addGitUrl
Add more git url regression coverage
2019-02-08 15:08:29 -08:00
Jeffrey Regan
1f063d6712 Add more git url regression coverage 2019-02-08 14:58:34 -08:00
Sergey
cebcd8a44d transformers/image: loop refactoring 2019-02-08 18:42:47 +05:00
Kubernetes Prow Robot
ce7e5ee2c3 Merge pull request #771 from alexbrand/fix-error-msg
Improve error msg returned when no kustomization file is found
2019-02-07 15:01:49 -08:00
Alexander Brand
242b9209d8 Improve error msg returned when no kustomization file is found
Signed-off-by: Alexander Brand <alexbrand09@gmail.com>
2019-02-07 17:09:57 -05:00
Kubernetes Prow Robot
92bd809bc8 Merge pull request #779 from monopole/bitbucket
Add nil ptr check
2019-02-07 10:28:04 -08:00
Jeffrey Regan
ccc4461827 Fix nil ptr bug 2019-02-07 10:11:45 -08:00
Kubernetes Prow Robot
9de524da7d Merge pull request #773 from monopole/kvpairToPair
Rename kv.KVPair to kv.Pair
2019-02-07 09:43:31 -08:00
Jeffrey Regan
7c8db24656 Rename kv.KVPair to kv.Pair 2019-02-06 16:45:44 -08:00
Jeff Regan
d720e9ef49 Fix some typos in versioning policy 2019-02-06 12:36:48 -08:00
Jeff Regan
9e69b9dcc4 Typos in versioning 2019-02-06 10:59:44 -08:00
Jeff Regan
4f7b0c1a21 Merge pull request #752 from Liujingfang1/doc
add documentation for kustomize 2.0.0
2019-02-05 17:22:09 -08:00
Jingfang Liu
fc5c7264cf add documentation for kustomize 2.0.0 2019-02-05 16:27:41 -08:00
Jeff Regan
ede407e6a2 Merge pull request #764 from sethpollack/kv
refactor kv pairs
2019-02-05 13:02:50 -08:00
Seth Pollack
e41ca934ac move package and add tests 2019-02-05 15:38:52 -05:00
Kubernetes Prow Robot
0184d5b697 Merge pull request #763 from Liujingfang1/kversion
allow apiVersion and Kind to be empty or specific values
2019-02-05 09:46:34 -08:00
Seth Pollack
e14ebc0adf refactor kv pairs 2019-02-04 17:19:57 -05:00
Jingfang Liu
e905704b0c allow apiVersion and Kind to be empty or specific values 2019-02-04 13:08:09 -08:00
Jeff Regan
f8060f3575 Merge pull request #753 from monopole/versionPolicy
Versioning policy.
2019-02-04 13:04:33 -08:00
Jeffrey Regan
120e7b5744 Versioning policy 2019-02-04 13:01:49 -08:00
Dimitri Mitropoulos
b15b20467c typo: changes verb number to agree with subject 2019-02-04 14:48:43 -05:00
Dimitri Mitropoulos
1d005d47b5 typo: makes verb number agree with subject
also changed `one` to `someone` to be more English-as-a-Second-Language friendly
2019-02-04 14:44:04 -05:00
Jingfang Liu
d8585334cc minor fix: incorrect apiVersion and add NoOpTransformer for vars (#757) 2019-02-04 09:44:33 -08:00
Kubernetes Prow Robot
6444981796 Merge pull request #751 from laverya/fix-invalid-type-encountered-nil
Accept a wider variety of kubernetes yaml values
2019-02-01 14:09:22 -08:00
Kubernetes Prow Robot
713c06354f Merge pull request #748 from Liujingfang1/version
add group name as kustomize.config.k8s.io
2019-02-01 13:54:36 -08:00
Jeff Regan
5e2c947cf8 Merge pull request #755 from Liujingfang1/generators
Combine generatorArgs and generatorOptions into options of Resource
2019-02-01 13:31:21 -08:00
Jeff Regan
92ede0d3c9 Merge pull request #754 from mgoodness/apiservice-nameref
Add Service nameReference to APIService
2019-01-31 15:33:23 -08:00
Jingfang Liu
84057436d6 Combine generatorArgs and generatorOptions into options of Resource 2019-01-31 15:32:32 -08:00
Michael Goodness
bf18cf2d9e Add Service nameReference to APIService
Signed-off-by: Michael Goodness <mgoodness@gmail.com>
2019-01-31 09:20:49 -06:00
Kubernetes Prow Robot
7913e5f5bc Merge pull request #749 from rndstr/document-smp-crd
Document SMP behavior for custom resources
2019-01-30 16:11:06 -08:00
Roli Schilter
f550540318 Document SMP behavior for custom resources
Documents how strategic merge patches are treated as json merge patches
when dealing with custom resources.
2019-01-30 15:59:01 -08:00
Andrew Lavery
1d263d24dd replaceVars returns nil on nil input, not error
includes  an integration test for 'null' args inputs
2019-01-30 15:40:53 -08:00
Jingfang Liu
199763dec8 add group name to kustomize.config.k8s.io 2019-01-30 09:48:12 -08:00
Kubernetes Prow Robot
093801479c Merge pull request #745 from greut/patch-1
examples: typo
2019-01-30 08:48:09 -08:00
Yoan Blanc
cdcc0052a6 examples: typo 2019-01-30 16:45:17 +01:00
Kubernetes Prow Robot
b6d4101808 Merge pull request #744 from laverya/skip-empty-object-validation
Skip empty object validation
2019-01-29 14:37:52 -08:00
Kubernetes Prow Robot
83f4fa2190 Merge pull request #743 from monopole/deleteDeadCode
Delete some dead code and fix nits.
2019-01-29 14:36:04 -08:00
jregan
35daae1715 Delete some dead code and fix nits. 2019-01-29 14:13:46 -08:00
Andrew Lavery
1997606372 add empty objects test for kunstruct SliceFromBytes 2019-01-29 13:17:03 -08:00
Andrew Lavery
209b115b7c ignore yaml files that do not include any entries 2019-01-29 13:17:03 -08:00
Kubernetes Prow Robot
93515517b8 Merge pull request #728 from monopole/disallowDownloadedKustomizationsFromLocalBases
Disallow cloned kustomization from using a local base outside the clone dir.
2019-01-29 11:49:03 -08:00
Jeffrey Regan
8c2bff2c91 Disallow cloned kustomization from using a local base outside the clone dir. 2019-01-29 10:31:52 -08:00
Jeff Regan
00e9657025 Merge pull request #740 from monopole/replaceStringWithRepoSpec
Replace all repo uri strings with git.RepoSpec.
2019-01-28 16:48:44 -08:00
Jeffrey Regan
31691f0330 Replace all repo uri strings with git.RepoSpec. 2019-01-28 15:31:42 -08:00
Kubernetes Prow Robot
bb74a42e04 Merge pull request #737 from monopole/moreGitUrlParsingCoverage
Add better error reporting to NewRepoSpecFromUrl
2019-01-28 14:48:00 -08:00
Jeffrey Regan
731a2a683e add another hostname to test 2019-01-28 14:27:59 -08:00
Kubernetes Prow Robot
95fd0c5530 Merge pull request #717 from asauber/remove-namespace-prefix-message
Remove warning for using prefix/suffix in conjunction with a Namespace
2019-01-28 11:48:54 -08:00
Andrew Sauber
79d357b460 remove warning for using prefix/suffix in conjunction with a Namespace 2019-01-28 14:42:04 -05:00
jregan
3ddc20f72c Increase git url parsing coverage. 2019-01-28 10:27:49 -08:00
Kubernetes Prow Robot
4179b8e6c8 Merge pull request #734 from FaKod/master
added DaemonSet for Var
2019-01-28 09:10:34 -08:00
Kubernetes Prow Robot
da23b6fce1 Merge pull request #733 from PascalBourdier/typo-doc
typo in doc
2019-01-28 09:01:16 -08:00
Christopher Schmidt
feb0502cb4 added DaemonSet 2019-01-28 12:39:44 +01:00
Pascal Bourdier
af8a169619 typo in doc
fix it
2019-01-28 11:57:43 +01:00
Jeff Regan
68ca28879d Merge pull request #731 from monopole/introRepoSpec
Introduce RepoSpec.
2019-01-27 08:24:49 -08:00
jregan
ad400cd13d Introduce RepoSpec.
This PR closes a TODO in the fileLoader type to
replace the string representing a git repo url
with a struct called holding validated fields.

New struct is called RepoSpec.

It holds what we need in coming PRs for remote
repo base containment checks, and will also allow
the overlay cycle prevention code to take into
account different host schemes or branches.

The struct is in a new file called repospec.go.
The new file is mostly just a code move of url
parsing code that was in cloner.go.  Git "blame"
history preserved through the move.

No change in execution (see final commit by itself).
2019-01-27 07:47:52 -08:00
jregan
90b863d124 Move cloner_tmp back to cloner. 2019-01-27 07:26:30 -08:00
jregan
9b7ddd6684 Merge in cloner_tmp, preserving blame history. 2019-01-27 07:26:30 -08:00
jregan
bcb939c19d Move cloner to repospec. 2019-01-27 07:26:30 -08:00
jregan
e2102dec3c Move cloner to cloner_tmp. 2019-01-27 07:26:30 -08:00
Jeff Regan
2ef16dce90 Merge pull request #730 from monopole/initializeGitPackage
Move git code to its own pkg.
2019-01-26 17:11:03 -08:00
jregan
1d9a20b391 Move git code to its own pkg. 2019-01-26 17:06:48 -08:00
Jeff Regan
d953eca630 Merge pull request #726 from monopole/refactorLoader
Add more coverage for loader and strengthen type safety
2019-01-25 16:11:38 -08:00
Jeff Regan
6651e488d6 Merge pull request #709 from sethpollack/secret
add add secret command
2019-01-25 16:10:24 -08:00
Jeffrey Regan
fd3cd47562 Fix copyright, add TODOs 2019-01-25 16:05:40 -08:00
jregan
dcb5682594 Add more coverage for loader and strengthen type safety. 2019-01-25 14:43:28 -08:00
Kubernetes Prow Robot
0bd2a1e232 Merge pull request #722 from Liujingfang1/removeDeprecates
remove patches and imageTags from kustomization.yaml
2019-01-25 14:41:06 -08:00
Jeff Regan
4d77c9f940 Merge pull request #721 from Liujingfang1/filename
support different filenames for kustomization file
2019-01-25 14:34:06 -08:00
Jingfang Liu
c461f1f766 remove patches and imageTags from kustomization.yaml 2019-01-25 14:26:17 -08:00
Jeff Regan
fbcae2b770 Merge pull request #724 from monopole/moveCleanedAbs
Cover CleanedAbs with tests.
2019-01-25 12:51:16 -08:00
Jeffrey Regan
c21dfefbdf Cover CleanedAbs 2019-01-25 12:21:03 -08:00
Seth Pollack
a0c22b8216 add add secret command 2019-01-25 12:32:14 -05:00
Jingfang Liu
f7a59178a8 support different filenames for kustomization file 2019-01-24 15:08:28 -08:00
Jeff Regan
028724df08 Merge pull request #718 from monopole/tweakVarDoc
Tweak documentation on 'vars' directive.
2019-01-23 17:26:11 -08:00
Jeffrey Regan
51bbf57e95 Tweak documentation on directive. 2019-01-23 17:23:29 -08:00
Jeff Regan
3e4ec3a12c Merge pull request #715 from narg95/feature/add-images-docu
add 'images' documentation
2019-01-23 15:07:48 -08:00
Jeff Regan
a9dff35a24 Merge pull request #707 from narg95/feature/add-set-image-command
add set image command
2019-01-23 09:29:57 -08:00
Kubernetes Prow Robot
1cf8156c0c Merge pull request #716 from Deepomatic/fix-typo_generatorOptions_doc
Fix typo in generatorOptions example doc
2019-01-23 08:51:46 -08:00
Thomas Riccardi
f1b8fdec7f Fix typo in generatorOptions example doc 2019-01-23 10:49:39 +01:00
Nestor
62d096e57d add 'images' documentation
deprecate 'imageTags' documentation
2019-01-23 09:32:04 +01:00
Nestor
e49bd3ab1d improve image command messages 2019-01-23 08:03:19 +01:00
Jeff Regan
1edfdea5e8 Merge pull request #714 from monopole/deleteField
DataSources is now common to Secrets and ConfigMaps.
2019-01-22 19:09:59 -08:00
jregan
d141b2421c DataSources is now common to Secrets and ConfigMaps. 2019-01-22 18:57:11 -08:00
Kubernetes Prow Robot
244b3a2c59 Merge pull request #713 from monopole/moreTestOnLoader
Add more loader tests.
2019-01-22 15:45:46 -08:00
Jeffrey Regan
2e6bdd4041 Add more loader tests. 2019-01-22 14:08:28 -08:00
Kubernetes Prow Robot
077d554b76 Merge pull request #712 from monopole/readmeFix
Add bug writing instructions to README.
2019-01-22 13:28:12 -08:00
Kubernetes Prow Robot
4e058f8ece Merge pull request #711 from Liujingfang1/kind
add apiversion and kind to docs/kustomization.yaml
2019-01-22 12:57:14 -08:00
Jeffrey Regan
d4b90c8f4e Add bug writing instructions to README. 2019-01-22 11:30:55 -08:00
Jingfang Liu
fed8195eb2 add apiversion and kind to docs/kustomization.yaml 2019-01-22 11:02:35 -08:00
Nestor
b22e43a4a7 add set image command 2019-01-21 11:01:15 +01:00
Kubernetes Prow Robot
2c1be17fe7 Merge pull request #704 from narg95/feature/add-image-transformer
Add image transformer
2019-01-18 09:17:06 -08:00
Kubernetes Prow Robot
56ce6b8ba4 Merge pull request #706 from monopole/explicitlyCallOutEschewedSedBehavior
Add sed-like behavior to the eschewed feature list.
2019-01-18 09:00:27 -08:00
jregan
78bac973f7 Add sed-like behavior to the eschewed feature list. 2019-01-17 16:38:41 -08:00
Kubernetes Prow Robot
bfd61a7605 Merge pull request #699 from Liujingfang1/fix657
Allow namespaced object to refer cluster level object
2019-01-17 14:04:47 -08:00
Kubernetes Prow Robot
c40e3d12e8 Merge pull request #674 from ryane/binaryData
configmap binarydata support
2019-01-17 13:37:29 -08:00
Kubernetes Prow Robot
7568531118 Merge pull request #679 from Liujingfang1/options
make BuildOptions exported
2019-01-17 11:49:34 -08:00
ryane
87411590c5 configmap binarydata comments and small tweaks
the BinaryData map is nil until the generator finds a file with contents that
needs injected into the BinaryData field of the configmap
2019-01-17 13:19:06 -05:00
ryane
d4170797ae configmap binarydata support 2019-01-17 13:12:46 -05:00
Nestor
6616b25d66 fix comment 2019-01-17 16:02:14 +01:00
Nestor
6d56c1750f fix issues from code review 2019-01-17 15:50:34 +01:00
Kubernetes Prow Robot
4e2c4b94e3 Merge pull request #703 from Liujingfang1/changeSecretG
replace commands/envcommand by DataSource in SecretGenerator
2019-01-16 13:47:59 -08:00
Kubernetes Prow Robot
0be9815d27 Merge pull request #690 from fassmus/CloneBaseFromPrivateGit
Remove git:: prefix for all git URLs not only GitLab
2019-01-16 13:40:20 -08:00
Jingfang Liu
f7c34ccb52 Remove filesystem from ConfigMapGenerator and SecretGenerator 2019-01-16 13:33:06 -08:00
Kubernetes Prow Robot
549290c447 Merge pull request #700 from monopole/restrictLoading
Restrict loading to root or below.
2019-01-16 11:48:01 -08:00
Jingfang Liu
2fa4a34589 replace commands/envcommand by DataSource in SecretGenerator 2019-01-16 11:17:34 -08:00
Jeffrey Regan
14af70d148 Restrict loading to root or below. 2019-01-16 11:13:37 -08:00
Nestor
6dd599a983 Add image transformer 2019-01-16 16:32:53 +01:00
Florian Assmus
176ad74a1c Add unit test for additional git url patterns 2019-01-15 22:53:36 +01:00
Jingfang Liu
38f0ca9f03 Allow namespaced object to refer cluster level object 2019-01-14 15:54:09 -08:00
Jeff Regan
4d60f9229b Merge pull request #698 from monopole/cleanup
Small cleanups, no change in exec.
2019-01-14 15:44:20 -08:00
Jeffrey Regan
ea1dd08a8c Small cleanups, no change in exec. 2019-01-14 15:35:03 -08:00
Kubernetes Prow Robot
73624da253 Merge pull request #697 from grodrigues3/remove-grod
remove myself from maintainers
2019-01-14 15:10:31 -08:00
Garrett Rodrigues
78a2884b79 remove myself from maintainers 2019-01-14 14:06:02 -08:00
Kubernetes Prow Robot
e24968c679 Merge pull request #691 from monopole/fix606
Don't force all config to be explicit.
2019-01-11 15:22:55 -08:00
Jeffrey Regan
60dc3aa09d Don't force all config to be explicit. 2019-01-11 11:34:12 -08:00
Florian Assmus
94be867a54 Remove git:: prefix for all urls not only GitLab 2019-01-11 13:41:29 +01:00
Jingfang Liu
b9ab948ef2 make BuildOptions exported 2019-01-07 13:52:52 -08:00
Jeff Regan
a5c6938c65 Fix link 2019-01-07 13:02:05 -08:00
Jeff Regan
5d0c7aa6a9 Merge pull request #678 from monopole/drainMoreCode
Drain more code from kusttarget.
2019-01-06 14:51:34 -08:00
jregan
032fffe111 Drain more code from kusttarget. 2019-01-06 14:44:46 -08:00
Kubernetes Prow Robot
1b726b26cd Merge pull request #673 from monopole/introduceResAccumulator
Introduce ResAccumulator to carry data up customization stack.
2019-01-04 19:26:56 -08:00
jregan
50a8b27854 Introduce ResAccumulator. 2019-01-04 15:26:07 -08:00
Kubernetes Prow Robot
aeb2adbcfb Merge pull request #668 from monopole/deleteFileBasedTestCode
Delete deprecated file-based build test code.
2019-01-04 10:59:06 -08:00
Jeff Regan
746c7b0b5b Merge pull request #671 from monopole/fixCommentNits
Fix some comments and format nits.
2018-12-30 07:44:39 -08:00
jregan
93ad371400 Fix some comments and format nits. 2018-12-30 07:40:30 -08:00
jregan
d98afdc229 Delete deprecated file-based build test code. 2018-12-29 15:12:09 -08:00
Jeff Regan
80f3afc1ff Merge pull request #667 from monopole/convertGeneratorsNamespaceTest
Convert namespaced generators to in-memory.
2018-12-29 15:08:02 -08:00
jregan
b16a7364fd Convert namespaced generators to in-memory. 2018-12-29 15:03:26 -08:00
Jeff Regan
4b543169c8 Merge pull request #666 from monopole/convertConfigMapTests
Convert configmap tests to in-memory.
2018-12-29 14:56:39 -08:00
jregan
b7e1f8da72 Convert configmap tests to in-memory. 2018-12-29 14:51:59 -08:00
Jeff Regan
97507a92a3 Merge pull request #665 from monopole/convertCrd
Convert CRD tests to in-memory.
2018-12-29 14:30:27 -08:00
jregan
a838b85426 Convert CRD tests to in-memory. 2018-12-29 14:26:28 -08:00
Jeff Regan
92fc368ede Merge pull request #664 from monopole/fix658
Check for config merge conflicts and duplication.
2018-12-29 08:42:53 -08:00
jregan
8c994725cb Check for config merge conflicts and duplication. 2018-12-29 08:31:59 -08:00
Jeff Regan
20b13a03e0 Merge pull request #663 from monopole/convertGeneratorTests
Convert generator merge and replace tests to in-memory.
2018-12-28 09:14:28 -08:00
jregan
9dcbee1d48 Convert generator merge and replace tests to in-memory. 2018-12-28 09:09:26 -08:00
Jeff Regan
77ac84c468 Merge pull request #661 from monopole/convertVarTests
Convert variable tests to in-memory.
2018-12-28 08:31:32 -08:00
jregan
8b76799dd9 Convert variable tests to in-memory. 2018-12-28 08:24:29 -08:00
Jeff Regan
bab0421c6c Merge pull request #660 from monopole/convertMultiPatchTest
Convert multi-patch test to in-memory.
2018-12-28 07:43:21 -08:00
jregan
95203c58c4 Convert multi-patch test to in-memory. 2018-12-28 07:39:21 -08:00
Jeff Regan
ad7c90b904 Merge pull request #659 from monopole/moreConfigTests
More custom transform coverage.
2018-12-28 06:43:47 -08:00
jregan
4583c4a9de More custom transform coverage. 2018-12-28 06:38:05 -08:00
Jeff Regan
428cef54c1 Merge pull request #655 from monopole/makeTestHarness
Make KustTarget test harness to reduce boilerplate.
2018-12-24 11:42:36 -08:00
jregan
037f898f81 Make KustTarget test harness to reduce boilerplate. 2018-12-24 11:38:49 -08:00
Kubernetes Prow Robot
541754df8d Merge pull request #654 from Liujingfang1/v1beta1
change current version from v1 to v1beta1
2018-12-20 15:57:45 -08:00
Jingfang Liu
1cd99ab68e change current version from v1 to v1beta1 2018-12-20 15:32:06 -08:00
Jingfang Liu
6f566d7a38 Revert "add apiVersion and kind to docs and examples" (#653) 2018-12-20 15:19:39 -08:00
hyww
4b25963c93 List of strategic merge patches (#637)
* support List of strategic merge patches

* add test for List of patches

* handle List in SliceFromBytes

* add test for List of patches with anchor/reference

* reorganize kunstruct validate
2018-12-20 10:08:18 -08:00
Kubernetes Prow Robot
900152f724 Merge pull request #644 from Liujingfang1/kind
add apiVersion and kind to docs and examples
2018-12-19 15:20:00 -08:00
Jeff Regan
048c1dde97 Merge pull request #647 from monopole/yaTest
Yet another kusttarget test.
2018-12-18 17:09:45 -08:00
Jeffrey Regan
949fd51463 Yet another kusttarget test. 2018-12-18 17:04:46 -08:00
Jingfang Liu
dd17174b35 fix typos (#645) 2018-12-18 12:51:30 -08:00
Jingfang Liu
0d14e89549 add apiVersion and kind in README.md for examples 2018-12-18 11:22:18 -08:00
Jingfang Liu
64372a786b add apiVersion and kind to example kustomizations 2018-12-18 11:21:42 -08:00
Jingfang Liu
819b2e99d0 add apiVersion and kind to docs/kustomization.yaml 2018-12-18 11:00:50 -08:00
Kubernetes Prow Robot
d8e703d0f5 Merge pull request #643 from monopole/moarTests
More fully in-memory integration tests.
2018-12-18 10:49:46 -08:00
Jeffrey Regan
47a04f2648 More fully in-memory integration tests. 2018-12-18 10:26:19 -08:00
Jeff Regan
4af125fa2d Merge pull request #631 from monopole/addKustTargetGetAllVarsTest
Forbid Var name collisions in a kustomization stack
2018-12-17 15:37:41 -08:00
jregan
0665371590 Forbid Var name collisions in a kustomization stack 2018-12-17 15:19:58 -08:00
Jeffrey Regan
ecb83c6ae1 Add KustTarget.getAllVars Test 2018-12-17 14:54:55 -08:00
Jeff Regan
c4264daf6a Merge pull request #640 from monopole/someLargeKustTargetTests
Convert file system based test to in-memory.
2018-12-17 14:45:59 -08:00
jregan
243cbae411 Convert file system based test to in-memory. 2018-12-17 12:45:50 -08:00
Kubernetes Prow Robot
186dd20ad6 Merge pull request #639 from monopole/addSecretFactoryTest
Add secret factory test
2018-12-17 12:29:16 -08:00
Jeffrey Regan
d4ba22191a Avoid unnecessary shell execution in secretFactory. 2018-12-17 11:01:18 -08:00
Jeffrey Regan
29694e5b6a Add test for secretfactory. 2018-12-17 10:56:22 -08:00
Jeff Regan
a99f415f36 Merge pull request #636 from monopole/simplifyRefVars
Simplify refvar transformer.
2018-12-16 09:29:04 -08:00
jregan
54d6cf7087 Simplify refvar transformer. 2018-12-16 09:27:58 -08:00
Jeff Regan
e487e494f9 Merge pull request #635 from monopole/nameTransformerDocs
Improve name transformer docs.
2018-12-16 09:26:26 -08:00
jregan
11a19906b9 Improve name transformer docs. 2018-12-16 09:21:54 -08:00
Jeff Regan
65100e13b3 Merge pull request #632 from Liujingfang1/editfix
add apiVersiond and kind in tests to reduce test noise
2018-12-15 17:28:14 -08:00
Jeff Regan
3b52fd5019 Merge pull request #633 from Liujingfang1/giturl
improve url parsing function in gitcloner
2018-12-15 17:26:09 -08:00
Jingfang Liu
20e37eaf65 improve url parsing function in gitcloner 2018-12-14 15:26:39 -08:00
Jingfang Liu
b6b2fb9c62 add apiVersiond and kind in tests to reduce test noise 2018-12-14 14:58:13 -08:00
Kubernetes Prow Robot
b971e6a1da Merge pull request #630 from Liujingfang1/editfix
fix the missing fields in all edit commands
2018-12-14 14:47:06 -08:00
Kubernetes Prow Robot
087c4976b6 Merge pull request #625 from monopole/fix602
Reduce log messages.
2018-12-14 13:26:33 -08:00
Jingfang Liu
d0e4db74b7 fix the missing fields in all edit commands 2018-12-14 13:11:04 -08:00
Jeff Regan
f7414fec08 Merge pull request #628 from babiel/cronjob-jobtemplate-labels
Add spec/jobTemplate/metadata/labels to common labels transformer
2018-12-14 09:25:27 -08:00
Maximilian Gaß
8cecccbc88 Add spec/jobTemplate/metadata/labels to common labels transformer 2018-12-14 14:52:25 +01:00
Kubernetes Prow Robot
441f45e1cc Merge pull request #626 from monopole/fix616
Fix incorrect use of filepath.Separator
2018-12-13 16:45:27 -08:00
Jeffrey Regan
48e8a3aec3 Fix incorrect use of filepath.Separator 2018-12-13 16:38:39 -08:00
Kubernetes Prow Robot
3fe07888ce Merge pull request #624 from monopole/fix596
Allow directory substrings in cycle check.
2018-12-13 16:35:06 -08:00
Jeffrey Regan
77b44f570a Reduce log noise. 2018-12-13 16:29:11 -08:00
Jeffrey Regan
352ec69556 Allow directory substrings in cycle check. 2018-12-13 15:57:49 -08:00
Kubernetes Prow Robot
bd83773a1e Merge pull request #622 from monopole/meddling
Add some resId tests to support refactor.
2018-12-13 14:44:01 -08:00
Kubernetes Prow Robot
bf8b435457 Merge pull request #621 from Liujingfang1/editfix
Add subcommand: edit fix
2018-12-13 14:42:31 -08:00
Jeffrey Regan
e9b19281b2 Add some resId tests to support refactor. 2018-12-13 14:19:04 -08:00
Jingfang Liu
986c85e728 Add subcommand: edit fix 2018-12-13 14:09:55 -08:00
Kubernetes Prow Robot
8e72931a8b Merge pull request #619 from Seth-Karlo/small_typo_fix
Tiny but noticeable typo fix
2018-12-13 13:01:16 -08:00
Kubernetes Prow Robot
aeda4172e4 Merge pull request #620 from monopole/reduceSizeOfEmptyFieldMarkers
Reduce size of missing field markers.
2018-12-13 11:35:33 -08:00
Jeffrey Regan
d40f52e953 Reduce size of missing field markers. 2018-12-13 11:12:51 -08:00
Kubernetes Prow Robot
3e47a2c0a7 Merge pull request #618 from Liujingfang1/version
Add enforcement message for apiVersion and kind
2018-12-13 10:10:21 -08:00
Andy Repton
3b9cd6bedd Tiny but noticeable typo fix 2018-12-13 18:26:53 +01:00
Jingfang Liu
0759136d3f Add enforcement message for apiVersion and kind 2018-12-12 15:25:59 -08:00
Kubernetes Prow Robot
f0f8aad2bb Merge pull request #612 from Liujingfang1/gitloader
add handling function for remote url hostname
2018-12-12 10:11:51 -08:00
Jingfang Liu
259cecd4b8 add handling function for remote url hostname 2018-12-11 14:33:10 -08:00
Kubernetes Prow Robot
38873aa0fa Merge pull request #614 from richardmarshall/projected_volume_secrets
Add projected secret path to transformer config
2018-12-10 14:35:01 -08:00
Richard Marshall
506c4a330d Add projected secret path to transformer config
Projected volumes can include values sourced from secrets that might be
managed by kustomize. To support this use case this patch updates the
name reference transformer configuration to include a field spec for
projected secrets.
2018-12-10 12:41:58 -08:00
Kubernetes Prow Robot
63e4e5ccaa Merge pull request #609 from monopole/typeFix
Extract common generator args to common type.
2018-12-07 13:41:51 -08:00
Jeffrey Regan
cbcc976828 Extract common generator args to common type. 2018-12-07 13:27:19 -08:00
Jeff Regan
1ce1b82f6f Merge pull request #599 from tomaszkiewicz/generators-namespace
Add namespace for config map and secret generators
2018-12-07 12:48:11 -08:00
Kubernetes Prow Robot
b92e9ab075 Merge pull request #608 from monopole/fixNits
Require relocatable kustomizations and fix some nits.
2018-12-07 11:19:39 -08:00
Kubernetes Prow Robot
cfdae37ef5 Merge pull request #600 from Liujingfang1/apiservice
add APIService to cluster level kinds
2018-12-07 11:12:40 -08:00
Jeffrey Regan
108b3e497b Require relocatable kustomizations and fix some nits. 2018-12-07 10:46:35 -08:00
Kubernetes Prow Robot
bff228815f Merge pull request #584 from brushmate/vars-for-ingress
Add support for variable subsitution in Ingress hosts
2018-12-07 10:31:52 -08:00
Steffen Kreutz
252cf3723c Add support for variable subsitution in Ingress hosts 2018-12-07 10:02:08 +01:00
Jingfang Liu
5b88179406 add APIService to cluster level kinds 2018-12-05 10:50:24 -08:00
luktom
6ad5d9f55b Add namespace for config map and secret generators 2018-12-05 11:36:23 +01:00
Jeff Regan
8a8331bf57 Merge pull request #592 from Liujingfang1/namereference
resolve namereference in an array
2018-12-04 15:51:00 -08:00
Jingfang Liu
931f43f8d7 resolve namereference in an array 2018-12-04 15:42:26 -08:00
Jeff Regan
3c1e52bf94 Merge pull request #591 from Liujingfang1/msg
improve error message when failing to find an object to patch
2018-12-04 13:46:43 -08:00
Jingfang Liu
a62d15e746 improve error message when failing to find an object to patch 2018-12-03 09:30:31 -08:00
k8s-ci-robot
8f701a0041 Merge pull request #565 from zoncoen/name-suffix-3
Update docs, examples, comments, and test data for nameSuffix
2018-11-29 08:13:42 -08:00
k8s-ci-robot
593f9231ae Merge pull request #583 from monopole/fix560
Ignore empty fields targeted by transformations.
2018-11-29 08:07:01 -08:00
zoncoen
59df8a0dda update docs, examples, comments 2018-11-29 22:29:52 +09:00
Jeffrey Regan
6b93973bad Fix #560 (kinda/sorta) 2018-11-28 16:46:10 -08:00
k8s-ci-robot
df3ec571fb Merge pull request #582 from monopole/preFix560
Add test for mutatefield
2018-11-28 16:38:31 -08:00
k8s-ci-robot
f03fad7a96 Merge pull request #563 from Liujingfang1/crdexample
update crd example by using configurations file list
2018-11-28 14:59:22 -08:00
Jeff Regan
f714e9faf3 another tweak 2018-11-28 14:55:48 -08:00
Jeff Regan
3e1a3d83da Minor tweaks 2018-11-28 14:53:33 -08:00
Jeffrey Regan
8ba2ea9ca7 Add test for mutatefield 2018-11-28 11:01:50 -08:00
zoncoen
7dc8ef1028 update build command testdata 2018-11-26 14:00:26 +09:00
Jeff Regan
ef51cceff5 Merge pull request #579 from monopole/deleteHashicorpCloner
Delete hashicorp cloner.
2018-11-22 17:11:12 -08:00
jregan
a40c2502de Delete hashicorp cloner. 2018-11-22 16:58:59 -08:00
Jeff Regan
0201f9cba8 Merge pull request #578 from monopole/turnOnSimpleCloner
Turn off hashicorp cloner, turn on simple cloner.
2018-11-22 16:56:56 -08:00
jregan
7c1277f24c Turn off hashicorp cloner. 2018-11-22 16:48:24 -08:00
Jeff Regan
29f03dfb55 Merge pull request #577 from monopole/fixCloner
Deal with branch spec in simpleGitCloner.
2018-11-22 16:47:51 -08:00
jregan
02d2d38c21 Deal with branch spec in simpleGitCloner. 2018-11-22 16:42:28 -08:00
k8s-ci-robot
6757efe290 Merge pull request #547 from Liujingfang1/base_var
POC: allow accessing labels and annotations in vars
2018-11-22 15:32:36 -08:00
Jeff Regan
5990af8ced Merge pull request #576 from monopole/removeStrayComment
Remove stray comment.
2018-11-22 10:39:39 -08:00
jregan
6cddc25f0e Remove stray comment. 2018-11-22 10:39:18 -08:00
Jeff Regan
8bd773b536 Merge pull request #574 from monopole/simpleGitCloner
Introduce simple git cloner.
2018-11-22 10:33:43 -08:00
jregan
d9ba209543 Introduce simple git cloner. 2018-11-22 10:24:35 -08:00
Jeff Regan
c51646e3db Merge pull request #573 from monopole/enforceRelocatability
Enforce relocatable kustomizations.
2018-11-22 09:15:08 -08:00
jregan
4f9d00c021 Enforce relocatabile kustomizations. 2018-11-22 09:07:05 -08:00
Jeff Regan
0042c4be54 Merge pull request #571 from monopole/fileRename
Rename gitloader to gitcloner.
2018-11-22 08:46:41 -08:00
jregan
910eb322e0 Rename gitloader to gitcloner. 2018-11-22 08:41:59 -08:00
Jeff Regan
064b768176 Merge pull request #570 from monopole/hotYoga
Add test coverage to gitloader.
2018-11-22 08:37:20 -08:00
jregan
4daa655516 Add test coverage to gitloader. 2018-11-22 08:27:25 -08:00
Jeff Regan
d6910e9788 Merge pull request #569 from monopole/fsRemoveAll
Add removeAll to fakeFs
2018-11-22 06:59:21 -08:00
jregan
eed16afb00 Add removeAll to fakeFs 2018-11-22 06:53:44 -08:00
Jingfang Liu
6ec77b27da update crd example by using configurations file list 2018-11-20 10:31:44 -08:00
k8s-ci-robot
621ed52bab Merge pull request #556 from zoncoen/name-suffix-2
Add nameSuffix field to kustomization.yaml
2018-11-20 08:50:22 -08:00
zoncoen
b8c2ed20d1 fix the command usage 2018-11-20 17:09:40 +09:00
k8s-ci-robot
19ad9c2d46 Merge pull request #544 from Liujingfang1/config
Remove -t flag in build and add configurations field in kustomization file
2018-11-19 16:04:44 -08:00
k8s-ci-robot
41cc210fa0 Merge pull request #546 from Liujingfang1/var
update docs for vars
2018-11-19 10:29:59 -08:00
zoncoen
3488b542ac add edit command option for editing name suffix 2018-11-19 12:09:54 +09:00
zoncoen
04a030bcf0 enable nameSuffix field of kustomization.yaml 2018-11-19 12:09:47 +09:00
Jingfang Liu
25415c5501 Remove -t flag in build and add configurations field in kustomization.yaml 2018-11-16 13:44:18 -08:00
Jingfang Liu
a094be45d9 update vendor_kustomize.sh with run-in-gopath.sh (#545) 2018-11-16 13:27:20 -08:00
k8s-ci-robot
fdb8a7d74a Merge pull request #550 from zoncoen/name-suffix-1
Enable namePrefixTransformer to append name suffix
2018-11-16 09:07:44 -08:00
zoncoen
d481dbad62 combine transformers 2018-11-15 18:49:36 +09:00
zoncoen
c1e7f1b957 fix the order of YAMLs
If suffix is empty string, ResId.String() retuns name with "noSuffix".
2018-11-15 18:29:11 +09:00
zoncoen
93094c78eb add transformer for appending suffix 2018-11-14 12:46:58 +09:00
zoncoen
a14609f730 add suffix field to ResId 2018-11-14 12:44:33 +09:00
zoncoen
a8984578e4 refactor test code for readability 2018-11-14 12:36:28 +09:00
Jingfang Liu
51e9fec65d allow accessing labels and annotations in vars 2018-11-13 15:56:06 -08:00
k8s-ci-robot
38b7f42f9e Merge pull request #543 from giannello/patch-1
Add StorageClass to the list of ordered objects
2018-11-13 11:38:12 -08:00
Jingfang Liu
e574948577 update docs for vars 2018-11-13 11:32:10 -08:00
Giuseppe Iannello
ebf1efe07e Add StorageClass to the list of ordered objects
StorageClasses can be configured as `default`, so that PVCs can use them without an explicit reference.
This change adds StorageClasses close to the beginning of the compiled output.
2018-11-13 14:51:48 +01:00
Jingfang Liu
83bc67c8ad remove glog dependency from kustomize code (#542) 2018-11-12 11:35:00 -08:00
k8s-ci-robot
1648eceb47 Merge pull request #541 from mooncak/fix_typos
Fix typos: expectd->expected, cluser->cluster
2018-11-12 08:23:30 -08:00
mooncake
538aaaf217 Fix typos: expectd->expected, cluser->cluster
Signed-off-by: mooncake <xcoder@tenxcloud.com>
2018-11-11 00:14:25 +08:00
k8s-ci-robot
5b35443533 Merge pull request #537 from Liujingfang1/vendor
update vendor_kustomize.sh
2018-11-07 19:21:03 -08:00
k8s-ci-robot
e089a56e05 Merge pull request #536 from Liujingfang1/mergenil
Update TransformerConfig.Merge function to handle nil
2018-11-07 19:19:33 -08:00
k8s-ci-robot
5c4a778e6a Merge pull request #535 from monopole/deleteSomeDeps
Simplify some code and add a de-looping TODO.
2018-11-07 14:28:11 -08:00
Jingfang Liu
e0ec8028eb Update TransformerConfig.Merge function to handle nil 2018-11-07 14:05:40 -08:00
Jeff Regan
578ff2e45c Merge pull request #533 from Liujingfang1/config
fix incorrect path in default namereference configs
2018-11-07 14:02:10 -08:00
Jeffrey Regan
d04877a9e7 Simplify some code and add TODOs. 2018-11-07 13:58:14 -08:00
Jingfang Liu
727b5ebd7f update vendor_kustomize.sh 2018-11-07 13:45:38 -08:00
Jeff Regan
af1e1e6942 Merge pull request #534 from monopole/typoRepair
Add/fix some documentation and vars names.
2018-11-07 12:42:59 -08:00
Jeffrey Regan
d05bb6b199 Add/fix some documentation and vars names. 2018-11-07 12:36:25 -08:00
Jeff Regan
ba953484bf Merge pull request #522 from Liujingfang1/name
make sure the objects loaded have name and kind
2018-11-07 12:18:50 -08:00
Jeff Regan
fdf78b1d7d Merge pull request #501 from Liujingfang1/generatoroptions
Add example for generatorOptions
2018-11-07 10:55:30 -08:00
Jeff Regan
95fed47c1c Update generatorOptions.md 2018-11-07 10:53:46 -08:00
Jingfang Liu
4cf916e6f4 fix incorrect path in default namereference configs 2018-11-07 10:04:49 -08:00
k8s-ci-robot
23bf326d93 Merge pull request #530 from twz123/patch-1
Update default var reference link
2018-11-05 11:12:04 -08:00
k8s-ci-robot
bcd4d185a7 Merge pull request #529 from pst/patch-1
Fix typo in namereference path for cronjobs
2018-11-05 11:10:38 -08:00
Tom Wieczorek
57a5fa593c Update default var reference link
It has moved recently.
2018-11-05 18:15:04 +01:00
Philipp Strube
421ca3fb3c Fix typo in namereference path for cronjobs
Fix namereference for CronJob `path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/configMapKeyRef/name`
2018-11-05 14:07:32 +01:00
k8s-ci-robot
29945c2c7a Merge pull request #528 from laverya/fallback-to-string-sort-in-gvk-comparison-if-indices-equal
add fallback for GVK comparison
2018-11-02 13:07:56 -07:00
Andrew Lavery
9d82d54c5b add fallback for GVK comparison
only return comparison of 'Kind' indices if they do not match
otherwise fall back to GVK string comparison
this reduces output instability
2018-11-01 12:22:21 -07:00
Jingfang Liu
4827d9984f Add example for generatorOptions 2018-10-30 13:53:26 -07:00
Jeff Regan
d718fe3ee1 Merge pull request #525 from monopole/renameDisableHash
Rename disableHash to disableNameSuffixHash
2018-10-30 11:42:57 -07:00
Jeffrey Regan
a8fbe35ecf Rename disableHash to disableNameSuffixHash 2018-10-30 11:36:00 -07:00
Jingfang Liu
5947f696ff make sure the objects loaded have name and kind 2018-10-29 14:59:56 -07:00
k8s-ci-robot
40e0bbeec2 Merge pull request #502 from Liujingfang1/yml
add support .yml extension for kusotmization file
2018-10-29 12:33:16 -07:00
Jingfang Liu
ecbf3c5f51 add support .yml extension for kusotmization file 2018-10-29 12:21:00 -07:00
k8s-ci-robot
dfa952f0d5 Merge pull request #520 from monopole/loadingWithHistory
Consult history in fileloader.
2018-10-29 11:27:11 -07:00
jregan
793577d044 Consult history in fileloader.
Fixes #366

To reproduce #366, add

```
bases:
- .
```

to `examples/helloWorld/kustomization.yaml`, attempt to build it, and enjoy the stack overflow.

This PR fixes this by adding history to file loaders,
allowing one to avoid cycles in overlay->base
relationships.  To make entry points clearer, this PR
exposes only two public ways to make a fresh
(no-history) loader

 * rooted at `/`
 * rooted at the process's current working directory.

When making a new loader from an existing loader,
retaining history along an overlay trace, the only
allowed use is to go deeper into a file hierarchy, or
go up and over to a never before visited sibling. This
fix can probably be defeated by devious symbolic links.
2018-10-29 11:10:21 -07:00
Jeff Regan
1224dc0c87 Merge pull request #517 from monopole/testCleanup
Improve test coverage.
2018-10-28 14:17:44 -07:00
jregan
885c1952a4 Improve test coverage. 2018-10-28 13:52:25 -07:00
k8s-ci-robot
383b3e798b Merge pull request #516 from kubernetes-sigs/revert-488-prefix
Revert "Skip adding nameprefix to namespace"
2018-10-26 16:07:54 -07:00
Jingfang Liu
1020167e22 Revert "Skip adding nameprefix to namespace" 2018-10-26 14:42:27 -07:00
k8s-ci-robot
3c242f58da Merge pull request #515 from kubernetes-sigs/revert-500-namespace
Revert "create namespace resource if not found"
2018-10-26 14:25:03 -07:00
Jingfang Liu
f8a18ce662 Revert "create namespace resource if not found" 2018-10-26 14:01:53 -07:00
k8s-ci-robot
6a917c5f36 Merge pull request #508 from ryane/fix-507
kustomize build loads transformer configs when path argument omitted
2018-10-26 11:10:14 -07:00
k8s-ci-robot
7af1f206aa Merge pull request #513 from sethpollack/patch-1
fix spelling
2018-10-26 10:48:29 -07:00
k8s-ci-robot
0714abfe79 Merge pull request #511 from BenTheElder/export-factory
make k8sdeps.NewFactory() importable
2018-10-26 10:43:55 -07:00
Seth Pollack
6037734641 fix spelling 2018-10-25 22:28:22 -04:00
Benjamin Elder
76ba38cec5 make k8sdeps.NewFactory() importable 2018-10-25 17:21:58 -07:00
k8s-ci-robot
5c918dc56a Merge pull request #510 from ryane/fix-509
fix goreleaser version injection
2018-10-25 16:52:10 -07:00
k8s-ci-robot
292ed0e605 Merge pull request #503 from BenTheElder/prune-vendor
Prune vendor
2018-10-25 16:27:29 -07:00
ryane
e97960c2f0 fix goreleaser version injection
version command and vars moved into misc package
2018-10-25 10:47:10 -04:00
ryane
9f73341271 kustomize build loads transformer configs when path argument omitted 2018-10-25 09:56:46 -04:00
Benjamin Elder
163515c5a0 dep ensure 2018-10-24 17:24:58 -07:00
Benjamin Elder
41845522f6 enable dep pruning and gitignore macOS DS_Store 2018-10-24 17:15:07 -07:00
k8s-ci-robot
ec86b30d2b Merge pull request #498 from Liujingfang1/doc
Add example for transformer configurations: crd
2018-10-24 12:13:53 -07:00
Jingfang Liu
a90c957463 Add example for transformer configurations: crd 2018-10-24 12:08:48 -07:00
k8s-ci-robot
18a2321ddd Merge pull request #500 from Liujingfang1/namespace
create namespace resource if not found
2018-10-23 15:33:16 -07:00
Jingfang Liu
a5f0d457ec create namespace resource if not found 2018-10-23 13:46:03 -07:00
k8s-ci-robot
368b7f3939 Merge pull request #497 from Liujingfang1/generatoroptions
Allow setting shell and timeout in generatorOptions
2018-10-22 16:15:06 -07:00
k8s-ci-robot
e4dfbe79e1 Merge pull request #496 from Liujingfang1/master
enable preserving order with generatorOptions
2018-10-22 16:13:01 -07:00
Jingfang Liu
fdf5fa58d3 Allow setting shell and timeout in generatorOptions 2018-10-22 16:10:56 -07:00
Jingfang Liu
9ef96e9bb2 enable preserving order with generatorOptions 2018-10-22 16:01:46 -07:00
k8s-ci-robot
a8e393496f Merge pull request #495 from monopole/testFieldOrdering
Test field output ordering.
2018-10-19 17:32:54 -07:00
Jeffrey Regan
6b302443e6 Test field output ordering. 2018-10-19 16:20:23 -07:00
Jeff Regan
3fdf7a0b88 Merge pull request #494 from Liujingfang1/generatoroptions
allow add labels/annotations to generated resources
2018-10-19 16:01:53 -07:00
Jingfang Liu
0cb02f1448 allow add labels/annotations to generated resources 2018-10-19 15:40:06 -07:00
k8s-ci-robot
8b09afdf3e Merge pull request #493 from Liujingfang1/options
skip hash transformer when DisableHash is set to true
2018-10-19 15:25:14 -07:00
Jingfang Liu
23963e854a skip hash transformer when DisableHash is set to true 2018-10-19 14:44:23 -07:00
k8s-ci-robot
04167cf77e Merge pull request #487 from monopole/deletePenultimateUseOfDeprecatedField
Delete penultimate use of Patches field.
2018-10-19 14:28:05 -07:00
k8s-ci-robot
6f0a01fcf4 Merge pull request #490 from Liujingfang1/options
Add generatorOptions in Kustomization type
2018-10-19 14:18:42 -07:00
Jingfang Liu
0824433260 Add generatorOptions in Kustomization type 2018-10-19 14:12:33 -07:00
Jeffrey Regan
3e0f5ea327 Delete penultimate use of Patches field. 2018-10-19 11:26:05 -07:00
k8s-ci-robot
a4be48eb32 Merge pull request #488 from Liujingfang1/prefix
Skip adding nameprefix to namespace
2018-10-19 10:02:43 -07:00
Jingfang Liu
90d03b0afe Skip adding nameprefix to namespace 2018-10-18 13:52:11 -07:00
k8s-ci-robot
37802e1026 Merge pull request #485 from monopole/deleteSomeUnnecessaryParmPassing
Delete some unnecessary parameter passing.
2018-10-18 11:57:28 -07:00
k8s-ci-robot
16add04ccf Merge pull request #477 from Liujingfang1/sa
skip filtering resmap when the resource is a cluster level resource
2018-10-18 11:21:10 -07:00
Jingfang Liu
90c88d7f96 skip filtering resmap when the resource is a cluster level resource 2018-10-18 11:09:24 -07:00
Jeffrey Regan
2b0e2725f9 Delete some unnecessary parameter passing. 2018-10-18 10:59:59 -07:00
k8s-ci-robot
66bbae586f Merge pull request #483 from Liujingfang1/fieldspec
add commonLabel fieldpath for volumeClaimTemplates
2018-10-18 10:46:27 -07:00
k8s-ci-robot
d2ac2df372 Merge pull request #482 from Liujingfang1/validators
fix kustomize edit add label bug
2018-10-18 10:45:06 -07:00
Jingfang Liu
d5aed20f0a add commonLabel fieldpath for volumeClaimTemplates 2018-10-18 10:25:19 -07:00
k8s-ci-robot
42fcdef9f0 Merge pull request #481 from monopole/deleteExec
Delete unused exec package.
2018-10-18 10:12:37 -07:00
Jingfang Liu
482811460d fix kustomize edit add label bug 2018-10-18 10:01:18 -07:00
Jeffrey Regan
8fd93030b4 Delete unused exec package. 2018-10-18 09:54:45 -07:00
k8s-ci-robot
5db1ef23fe Merge pull request #475 from Liujingfang1/namespace
add namespace to id when create resmap from files
2018-10-17 16:45:00 -07:00
Jingfang Liu
14fc54e323 add namespace to id when create resmap from files 2018-10-17 16:22:19 -07:00
Jeff Regan
3d1d1f0bb8 Merge pull request #478 from monopole/messWithTypesDoc
Improve kustomization.go comments.
2018-10-17 14:24:39 -07:00
jregan
a5f56027b5 Improve kustomization.go comments. 2018-10-17 14:24:20 -07:00
k8s-ci-robot
bad3ccddc3 Merge pull request #473 from Liujingfang1/script
add script build/vendor_kustomize.sh
2018-10-16 17:26:43 -07:00
Jingfang Liu
da35a219d1 add script build/vendor_kustomize.sh 2018-10-16 15:53:04 -07:00
Jingfang Liu
8209aeea6d fix copyright misalignment (#472) 2018-10-16 11:02:47 -07:00
Jeff Regan
2d2315c4c4 Merge pull request #471 from Liujingfang1/dep
downgrade the transitive dependency to be consistent with kubernetes
2018-10-16 10:01:16 -07:00
Jingfang Liu
c6a78cee92 change github.com/aws/aws-sdk-go to be the same revision in kubernetes 2018-10-16 09:35:05 -07:00
Jingfang Liu
e0958159f3 change golang.org/x/net to be the same revision as used in kubernetes 2018-10-16 09:35:04 -07:00
Jingfang Liu
9d804ba3a8 fix lint errors in internal (#469) 2018-10-15 13:38:32 -07:00
Jingfang Liu
808df20cdb add missing lines after copyright (#468) 2018-10-15 12:02:41 -07:00
k8s-ci-robot
c46d2ce791 Merge pull request #467 from monopole/deleteSomeKunstructCode
Delete some kunstruct code in favor of apimachinery code.
2018-10-15 10:57:38 -07:00
jregan
f20528be35 Delete some kunstruct code in favor of apimachinery code. 2018-10-15 10:23:03 -07:00
k8s-ci-robot
5253747c00 Merge pull request #466 from monopole/improveGetFieldValueCoverage
Improve unstruct test coverage and error messages.
2018-10-15 09:58:19 -07:00
jregan
aaee97c0fa Improve unstruct test coverage and error messages. 2018-10-15 09:44:00 -07:00
Jeff Regan
d82c40c9fe Merge pull request #465 from monopole/moveYamlCheck
Move yaml check to file in which it is called.
2018-10-15 09:40:31 -07:00
jregan
dcc9c4d31a Move yaml check to file in which it is called. 2018-10-15 09:20:01 -07:00
k8s-ci-robot
3b119fb707 Merge pull request #463 from monopole/moarTesting
Objectify nbrSlice code.
2018-10-12 17:22:55 -07:00
Jeffrey Regan
b198b65d52 Objectify nbrSlice code. 2018-10-12 16:27:50 -07:00
k8s-ci-robot
f94974cc2c Merge pull request #462 from monopole/fixTransformConfigNames
Fix names/doc in transformation config code.
2018-10-12 13:41:49 -07:00
Jeffrey Regan
d9f9a51e55 Fix names/doc in transformation config code. 2018-10-12 13:36:22 -07:00
Jeff Regan
111f41785f Merge pull request #458 from camilosampedro/master
Notes on mySql example
2018-10-12 09:52:48 -07:00
Camilo Sampedro
e65995cd32 Notes on mySql example
mySql example was not running without the persistent disk nor the secret
called as it should.
2018-10-12 14:35:21 +09:00
k8s-ci-robot
ea9d5e3670 Merge pull request #455 from Liujingfang1/factory
Add KustFactory as a wrapper of all factories
2018-10-11 16:06:45 -07:00
Jingfang Liu
40b2bf76ae Add KustFactory as a wrapper of all factories 2018-10-11 13:51:27 -07:00
k8s-ci-robot
6fa110d4fd Merge pull request #457 from Liujingfang1/split
split k8sdeps package into sub packages
2018-10-11 11:36:00 -07:00
Jingfang Liu
d33d154e14 split k8sdeps package into sub packages 2018-10-11 11:30:46 -07:00
Jeff Regan
483d329556 Merge pull request #456 from Liujingfang1/configmap
use fake filesystem in configmapandsecret tests
2018-10-11 11:24:43 -07:00
Jingfang Liu
f3e4615a33 use FakeFileSystem in configmapandsecret tests 2018-10-11 11:04:26 -07:00
Jeff Regan
9106cee216 Merge pull request #454 from yanc0/literals-documentation
Literals documentation configMap Generation
2018-10-11 09:18:20 -07:00
Yann
2d26d95a98 fix indent 2018-10-11 09:16:14 +02:00
Yann
5745d030fb Add literals in configMapGenerator example 2018-10-11 09:14:06 +02:00
Jeff Regan
9f7eccc68f Merge pull request #453 from monopole/docFix
Update ptrs to DAM doc.
2018-10-10 16:20:58 -07:00
Jeffrey Regan
3fe047f79c Update ptrs to DAM doc. 2018-10-10 16:16:15 -07:00
k8s-ci-robot
9897ce8bf2 Merge pull request #452 from Liujingfang1/config
move transformerconfig package to transformers/config
2018-10-10 15:17:06 -07:00
Jingfang Liu
c33a97fcf2 move transformerconfig package to transformers/config 2018-10-10 15:12:32 -07:00
k8s-ci-robot
ca4a5d33f0 Merge pull request #451 from Liujingfang1/hash
add MakeHashTransformer in TransformerFactory; remove hash interface
2018-10-10 14:10:48 -07:00
Jingfang Liu
2953dad221 add MakeHashTransformer in TransformerFactory; remove hash interface 2018-10-10 14:05:13 -07:00
Jeff Regan
f35a11ff37 Merge pull request #450 from monopole/crdToFactory
Move crd package to transformerconfig.factory.
2018-10-10 13:29:25 -07:00
Jeffrey Regan
8534107fc8 Move crd package to transformerconfig.factory. 2018-10-10 13:14:43 -07:00
k8s-ci-robot
681e2bf213 Merge pull request #449 from monopole/tcFactory
Consolidate TransformerConfig creation to factory.
2018-10-10 13:04:07 -07:00
Jeffrey Regan
2283c06971 Consolidate transformer config creation to factory. 2018-10-10 12:33:19 -07:00
Jeff Regan
bb9435a604 Merge pull request #448 from Liujingfang1/decoder
remove decoder interface since it is only used inside k8sdeps
2018-10-10 12:01:15 -07:00
Jingfang Liu
96091dfcf5 remove decoder interface since it is only used inside k8sdeps 2018-10-10 11:08:23 -07:00
k8s-ci-robot
cf4a1ba083 Merge pull request #446 from Liujingfang1/gvk
remove dependency on apimachinery from gvk package
2018-10-09 17:26:42 -07:00
Jingfang Liu
4c7b63a215 remove dependency on apimachinery from gvk package 2018-10-09 16:25:25 -07:00
k8s-ci-robot
1e04a0e943 Merge pull request #445 from Liujingfang1/typemeta
copy TypeMeta from apimachinery
2018-10-09 16:18:09 -07:00
Jingfang Liu
f7353b1295 copy TypeMeta from apimachinery 2018-10-09 16:10:17 -07:00
k8s-ci-robot
dbf04985c4 Merge pull request #444 from Liujingfang1/configmap
hide core/v1 behind interface
2018-10-09 16:00:09 -07:00
Jingfang Liu
f783486057 hide core/v1 behind interface 2018-10-09 15:50:52 -07:00
Jeff Regan
0faef46773 Merge pull request #443 from ryancox/use-go-1.11
Use Go 1.11 for CI Builds
2018-10-09 15:02:54 -07:00
Ryan Cox
cbd7a1bb58 Use Go 1.11 2018-10-09 14:44:05 -07:00
k8s-ci-robot
19ac0e9327 Merge pull request #426 from schweikert/add_jsonpatch_yaml_test
Add jsonpatch yaml test
2018-10-09 13:26:51 -07:00
David Schweikert
b5cf3a2146 add yaml-version of jsonpatch tests 2018-10-09 21:04:34 +02:00
Jeff Regan
5cf0cbe041 Merge pull request #440 from monopole/fix428
Maintain fields of TransformerConfig in sorted order.
2018-10-09 10:47:55 -07:00
jregan
df5c3ab91e Maintain fields of TransformerConfig in sorted order.
Not needed for execution, just makes logging and tests deterministic.
Related to #428
2018-10-09 10:14:57 -07:00
Jeff Regan
5b95db2208 Merge pull request #441 from monopole/replantTree
Replant tree (needed for example tests).
2018-10-09 10:09:36 -07:00
Jeffrey Regan
22d955b3a9 Replant tree (needed for example tests). 2018-10-09 10:05:50 -07:00
Jeff Regan
b7fa38e2e7 Merge pull request #437 from ryancox/golangci-lint
port to golangci and make travisci improvements
2018-10-09 09:36:05 -07:00
Jeff Regan
b16c85888e Merge pull request #435 from Liujingfang1/flakytest
fix the flaky test in crd package
2018-10-09 09:33:20 -07:00
Ryan Cox
261d64ec1d port to golangci and make travisci improvements 2018-10-09 00:58:34 -07:00
Jingfang Liu
62f7cdbb43 fix the flaky test in crd package 2018-10-08 16:06:35 -07:00
Jeff Regan
30814302af Fix some minor naming mistakes. (#434)
* Fix some minor naming mistakes.

* Fix some minor naming mistakes.
2018-10-08 15:58:44 -07:00
Jeff Regan
fd3cd64e11 Merge pull request #433 from Liujingfang1/patchtransformer
hide patch transformer behind interface
2018-10-08 15:32:49 -07:00
k8s-ci-robot
536cd8d45e Merge pull request #432 from monopole/mergeResmapFactoryCode
Gather resmap factory code into one file.
2018-10-08 15:17:46 -07:00
Jingfang Liu
78de5374ed hide patch transformer behind interface 2018-10-08 15:15:03 -07:00
Jeffrey Regan
aff76e0d0e Gather resmap factory code into one file. 2018-10-08 15:09:22 -07:00
k8s-ci-robot
0f4ab07324 Merge pull request #431 from Liujingfang1/error
remove apimachinery dependency from internal/error package
2018-10-08 14:54:40 -07:00
Jingfang Liu
08da2455dd remove apimachinery dependency from internal/error package 2018-10-08 14:32:24 -07:00
Jingfang Liu
8e0c55f9fa remove apimachinery dependency from crd package (#430) 2018-10-08 14:27:18 -07:00
Jeff Regan
00b4beda91 Merge pull request #429 from monopole/kunstructedFactory
Further isolate unstructured with factories.
2018-10-08 14:26:32 -07:00
Jeffrey Regan
1af119db80 Further isolate unstructured with factories. 2018-10-08 14:21:48 -07:00
jregan
4eb2757847 Further isolate unstructured with factories. 2018-10-08 11:52:38 -07:00
k8s-ci-robot
3cdfbd843b Merge pull request #423 from monopole/hideUnstruct
Hide unstructured.Unstructured behind interface.
2018-10-08 11:21:45 -07:00
jregan
0f5a39f328 Hide unstructured.Unstructured behind interface. 2018-10-08 11:12:06 -07:00
k8s-ci-robot
9c8302b2d2 Merge pull request #427 from ryancox/resmap-tests
add tests for resmap
2018-10-08 10:57:22 -07:00
Ryan Cox
e5ea1b0a19 typo 2018-10-08 10:16:10 -07:00
Ryan Cox
e6558fb9fc PR comments 2018-10-08 10:13:05 -07:00
k8s-ci-robot
b67f8d2b7b Merge pull request #425 from schweikert/mac_sed
use 'sed -i.bak' instead of 'sed -i' to make it compatible with macos…
2018-10-08 08:53:24 -07:00
k8s-ci-robot
5c92f09dd0 Merge pull request #422 from schweikert/issue_368
unify processing of JSON6902 patches for both json and yaml format
2018-10-08 08:35:15 -07:00
Ryan Cox
f2f1125e44 add tests for resmap 2018-10-07 21:57:20 -07:00
David Schweikert
6d4ad82262 use 'sed -i.bak' instead of 'sed -i' to make it compatible with macos sed 2018-10-07 22:26:15 +02:00
Jeff Regan
7cf5f8caae Merge pull request #421 from Liujingfang1/hash
Add hash interface
2018-10-05 14:33:17 -07:00
David Schweikert
3d4bf3abbf for yaml-formatted JSON6902 patches, convert first to json, then use the same code as for json-formatted JSON6902 patches 2018-10-05 22:53:26 +02:00
Jingfang Liu
5036a12a65 Add hash interface 2018-10-05 13:29:06 -07:00
k8s-ci-robot
489f6e2e67 Merge pull request #416 from monopole/residPackage
Move ResId to its own package.
2018-10-05 13:13:52 -07:00
Jeffrey Regan
c9887e8c15 WIP residPackage 2018-10-05 12:58:48 -07:00
Jeff Regan
239db504ff Merge pull request #418 from Liujingfang1/hash
combine HashComfigMap and HashSecret to Hash
2018-10-05 12:58:31 -07:00
Jeff Regan
9b7ce3b6ba Merge pull request #419 from monopole/deleteMakeUnstruct
Delete unused unstruct code.
2018-10-05 12:46:13 -07:00
Jeffrey Regan
3b86e64faf Delete unused unstruct code. 2018-10-05 12:39:45 -07:00
Jingfang Liu
c3ae23d3a5 combine HashComfigMap and HashSecret to Hash 2018-10-05 12:02:58 -07:00
k8s-ci-robot
73e28ca556 Merge pull request #411 from Liujingfang1/hash
decouple configmapandsecret and hash packages
2018-10-05 09:39:18 -07:00
Jeff Regan
a634da4d19 Merge pull request #415 from monopole/nits
Fix some go nits.
2018-10-05 07:38:37 -07:00
Jeffrey Regan
a3dce9409b Fix some go nits. 2018-10-05 07:33:54 -07:00
Jingfang Liu
a9cf1975ca decouple configmapandsecret and hash packages 2018-10-04 16:17:23 -07:00
k8s-ci-robot
51ece9412e Merge pull request #407 from monopole/cmdSplit
Improve command package isolation.
2018-10-03 20:09:45 -07:00
Jeff Regan
b37258edf0 Merge pull request #406 from schweikert/fix_issue_335
error out if patchesJson6902 target can't be found, fixes #335
2018-10-03 16:32:48 -07:00
Jeffrey Regan
bb9fafa6cc Improve command package isolation. 2018-10-03 16:29:04 -07:00
Jeff Regan
f5fee4decf Merge pull request #405 from monopole/generaterIsolation
Isolate generator calls.
2018-10-03 16:28:36 -07:00
David Schweikert
279826f6d6 error out if patchesJson6902 target can't be found, fixes #335 2018-10-03 21:53:45 +02:00
Jeffrey Regan
56e11b57e3 Isolate generator calls. 2018-10-03 12:09:53 -07:00
k8s-ci-robot
6d65049221 Merge pull request #404 from monopole/deprecationFix
Deal with field deprecation immediately after load.
2018-10-03 11:24:13 -07:00
Jeffrey Regan
65ee4e4f2a Deal with field deprecation immediately after load. 2018-10-03 10:55:35 -07:00
k8s-ci-robot
a1538c5610 Merge pull request #403 from monopole/isolateK8sdeps
Isolate k8sdeps to top level internal.
2018-10-03 10:54:40 -07:00
Jeffrey Regan
e32e5c21d7 Isolate k8sdeps to top level internal. 2018-10-03 10:21:43 -07:00
k8s-ci-robot
132cdad7c4 Merge pull request #400 from Liujingfang1/decoder
Add validator interface
2018-10-02 17:14:37 -07:00
Jingfang Liu
fa89a0ab4d Add validator interface 2018-10-02 15:09:19 -07:00
k8s-ci-robot
ad093555a6 Merge pull request #398 from monopole/injectDecoder
Introduce k8sdeps package to isolate k8s deps.
2018-10-02 13:41:55 -07:00
k8s-ci-robot
2fbccdd05b Merge pull request #394 from Liujingfang1/var
use local types in var reference
2018-10-02 11:52:43 -07:00
k8s-ci-robot
eb985a8af0 Merge pull request #397 from Liujingfang1/issue395
fix kustomize edit add label bug
2018-10-02 11:48:49 -07:00
jregan
8f150d84ae Introduce k8sdeps package to isolate k8s deps. 2018-10-02 11:36:53 -07:00
Jingfang Liu
74d8575097 fix kustomize edit add label bug 2018-10-02 10:44:35 -07:00
Jingfang Liu
71c3cf163e use local types in var reference 2018-10-02 10:25:28 -07:00
k8s-ci-robot
b95423285f Merge pull request #393 from monopole/resourceTests
Add tests for patch/resource reading.
2018-10-01 14:47:51 -07:00
jregan
24733315d7 Add tests for patch/resource reading. 2018-10-01 14:25:15 -07:00
Jeff Regan
fbc38d0c60 Merge pull request #390 from monopole/fixPatchNaming
Spelling nits.
2018-10-01 11:24:25 -07:00
k8s-ci-robot
8b5c4aa591 Merge pull request #391 from Liujingfang1/string
change sets.NewString() to []string
2018-10-01 11:13:52 -07:00
jregan
c9aff4c47a Spelling nits. 2018-10-01 10:56:35 -07:00
Jingfang Liu
8a8f35863c change sets.NewString() to []string 2018-10-01 10:53:39 -07:00
k8s-ci-robot
9a5d759230 Merge pull request #389 from Liujingfang1/pathconfig
add command to save the default transformer configurations to local files
2018-10-01 10:24:45 -07:00
Jingfang Liu
94c3b1212e add command to save the default transformer configurations to local files 2018-10-01 09:48:38 -07:00
k8s-ci-robot
c129a3d3b8 Merge pull request #385 from monopole/fixNits
Fix some Go nits.
2018-09-30 18:40:07 -07:00
jregan
6d935b6a4a Fix some Go nits. 2018-09-28 18:08:36 -07:00
k8s-ci-robot
8f903b6e3f Merge pull request #384 from monopole/renameApp
Rename Application to KustTarget
2018-09-28 14:34:38 -07:00
jregan
78139957d2 Rename Application to KustTarget 2018-09-28 14:07:01 -07:00
Jeff Regan
ffffbedf41 Merge pull request #383 from Liujingfang1/buildflag
Add flag to load transfomer configurations from files
2018-09-28 14:02:52 -07:00
Jingfang Liu
fb6130e1e0 Add flag to load transfomer configurations from files 2018-09-28 13:57:29 -07:00
k8s-ci-robot
4c94f3ec38 Merge pull request #382 from Liujingfang1/pathconfig
enable crd testcase
2018-09-28 11:33:47 -07:00
Jingfang Liu
d67425daf1 enable crd testcase 2018-09-28 10:48:16 -07:00
k8s-ci-robot
48065cc694 Merge pull request #381 from monopole/simplify
Simplify default config construction.
2018-09-28 10:31:23 -07:00
jregan
f35e16bd8d Simplify default config code. 2018-09-28 10:20:20 -07:00
k8s-ci-robot
986c7cc31b Merge pull request #380 from Liujingfang1/pathconfig
remove hard coded pathconfig
2018-09-28 10:01:41 -07:00
Jingfang Liu
078c90cabe remove hard coded pathconfig 2018-09-28 09:28:39 -07:00
k8s-ci-robot
30597252c7 Merge pull request #379 from Liujingfang1/pathconfig
Modify PathConfig.PathSlice method and add tests
2018-09-27 16:30:47 -07:00
Jingfang Liu
d8b27ef8fe Modify PathConfig.PathSlice method and add tests 2018-09-27 15:36:37 -07:00
k8s-ci-robot
19197a490e Merge pull request #378 from monopole/stringStuff
Increase sort determinism.
2018-09-27 13:46:23 -07:00
Jeffrey Regan
317833aeff Increase sort determinism. 2018-09-27 13:29:00 -07:00
k8s-ci-robot
acf989f1be Merge pull request #377 from Liujingfang1/pathconfig
Refactor crd package to depend on transformerconfig
2018-09-27 13:07:14 -07:00
Jingfang Liu
7ab710889c Refactor crd package to depend on transformerconfig 2018-09-27 10:39:29 -07:00
Jeff Regan
8ef87309a2 Merge pull request #315 from nikhita/fix-template-files
Move template files from docs/ to root
2018-09-27 09:30:33 -07:00
k8s-ci-robot
20fa90a137 Merge pull request #376 from monopole/gvk
Introduce gvk package to isolate apimachinery schema.
2018-09-26 16:45:15 -07:00
Jeffrey Regan
fb355eb320 Introduce gvk package to isolate apimachinery schema. 2018-09-26 15:02:38 -07:00
k8s-ci-robot
8aa0cc145c Merge pull request #375 from monopole/resIdTest
Add resid tests.
2018-09-26 13:49:36 -07:00
k8s-ci-robot
e276fc71c7 Merge pull request #373 from Liujingfang1/pathconfigmore
add default configurations for different transformers
2018-09-26 13:41:44 -07:00
Jeff Regan
119c3e3b24 Merge pull request #367 from OpenSourceZombie/patch-2
missing : after patchesJson6902 in the example file kustomization.yaml
2018-09-26 13:40:31 -07:00
Jeffrey Regan
67adc56c73 Add resid tests. 2018-09-26 13:31:25 -07:00
k8s-ci-robot
97a771d1e2 Merge pull request #374 from Liujingfang1/integrationtest
fix integration test script
2018-09-26 11:38:53 -07:00
Jingfang Liu
c27279ce7a fix integration test script 2018-09-26 11:20:10 -07:00
Jingfang Liu
13c368a2db add default configurations for different transformers 2018-09-26 11:11:29 -07:00
Jeff Regan
2f47e298d2 Merge pull request #371 from monopole/oddHgStuff
Goland wants these vendored hg files.
2018-09-25 11:56:41 -07:00
Jeffrey Regan
188ede2cd4 Goland wants these vendored hg files. 2018-09-25 11:55:55 -07:00
Jeff Regan
f23419fde6 Merge pull request #361 from Liujingfang1/pathconfig
Add transformer config package
2018-09-25 11:50:42 -07:00
theShirbiny
c614f4b5de missing : after patchesJson6902 2018-09-24 17:55:32 +02:00
k8s-ci-robot
3266716584 Merge pull request #356 from liuhuiping2013/master
remove metadata.creationTimestamp field from configMapGenerator
2018-09-21 09:46:02 -07:00
Jingfang Liu
8cc6df51f3 Add transformerconfig package and default configs 2018-09-19 11:14:14 -07:00
Jeff Regan
6b1ffe13a0 Merge pull request #357 from greghaynes/fix/install-sigs.k8s.io
Update install doc to use sigs.k8s.io
2018-09-18 13:50:29 -07:00
Gregory Haynes
ce3daf254f Update install doc to use sigs.k8s.io
When using go get github.com/kubernetes-sigs/kustomize running kustomize
panics with 'log_dir redefined'.
2018-09-18 19:03:06 +00:00
liuhuiping
6c5a75bf73 remove metadata.creationTimestamp field from configMapGenerator 2018-09-18 18:35:40 +08:00
Nikhita Raghunath
cdb78cbdd3 Move template files from docs/ to root 2018-09-01 20:22:22 +05:30
8020 changed files with 27042 additions and 3891188 deletions

7
.gitignore vendored
View File

@@ -4,9 +4,16 @@
*.dll
*.so
*.dylib
kustomize
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# We use sed -i.bak when doing in-line replace, because it works better cross-platform
.bak
# macOS
*.DS_store

30
.golangci.yml Normal file
View File

@@ -0,0 +1,30 @@
run:
deadline: 5m
linters:
disable-all: true
enable:
- dupl
- goconst
- gocyclo
- gofmt
- golint
- govet
- ineffassign
- interfacer
- lll
- misspell
- nakedret
- structcheck
- unparam
- varcheck
linters-settings:
dupl:
threshold: 400
lll:
line-length: 170
gocyclo:
min-complexity: 15
golint:
min-confidence: 0.85

View File

@@ -1,25 +1,42 @@
os:
- linux
- osx
# TODO: Uncomment when tests running on Windows.
# - windows
addons:
apt:
packages:
- tree
homebrew:
packages:
- tree
# Only clone the most recent commit.
git:
depth: 1
language: go
go:
- 1.10.x
- 1.12
go_import_path: sigs.k8s.io/kustomize
env:
- GOLANGCI_RELEASE="v1.12"
before_install:
- source ./bin/consider-early-travis-exit.sh
- sudo apt-get install tree
- go get -u github.com/golang/lint/golint
- go get -u golang.org/x/tools/cmd/goimports
- go get -u github.com/onsi/ginkgo/ginkgo
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $GOPATH/bin ${GOLANGCI_RELEASE}
- go get -u github.com/monopole/mdrip
- go get -u github.com/fzipp/gocyclo
- go get -u gopkg.in/alecthomas/gometalinter.v2 && gometalinter.v2 --install
# The following would install Helm if needed for some reason.
# - wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz
# - tar -xvzf helm-v2.13.1-linux-amd64.tar.gz
# - sudo mv linux-amd64/helm /usr/local/bin/helm
# Install must be set to prevent default `go get` to run.
# The dependencies have already been vendored by `dep` so
# we don't need to fetch them.
install:
-
# Skip the install process; let pre-commit.sh do it.
install: true
script:
- ./bin/pre-commit.sh

22
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,22 @@
# Contributing Guidelines
Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt:
_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._
## Getting Started
We have full documentation on how to get started contributing here:
- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests
- [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing)
- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet.md) - Common resources for existing developers
## Mentorship
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
## Contact Information
- [Slack channel](https://kubernetes.slack.com/messages/sig-cli)
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-cli)

527
Gopkg.lock generated
View File

@@ -1,527 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:8e47871087b94913898333f37af26732faaab30cdb41571136cf7aec9921dae7"
name = "github.com/PuerkitoBio/purell"
packages = ["."]
pruneopts = ""
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
version = "v1.1.0"
[[projects]]
branch = "master"
digest = "1:331a419049c2be691e5ba1d24342fc77c7e767a80c666a18fd8a9f7b82419c1c"
name = "github.com/PuerkitoBio/urlesc"
packages = ["."]
pruneopts = ""
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
[[projects]]
digest = "1:9299ad32dcec0f92ad06773f73426bd46a21efa96f6a8138c287bb185933e77e"
name = "github.com/aws/aws-sdk-go"
packages = [
"aws",
"aws/awserr",
"aws/awsutil",
"aws/client",
"aws/client/metadata",
"aws/corehandlers",
"aws/credentials",
"aws/credentials/ec2rolecreds",
"aws/credentials/endpointcreds",
"aws/credentials/stscreds",
"aws/csm",
"aws/defaults",
"aws/ec2metadata",
"aws/endpoints",
"aws/request",
"aws/session",
"aws/signer/v4",
"internal/sdkio",
"internal/sdkrand",
"internal/sdkuri",
"internal/shareddefaults",
"private/protocol",
"private/protocol/eventstream",
"private/protocol/eventstream/eventstreamapi",
"private/protocol/query",
"private/protocol/query/queryutil",
"private/protocol/rest",
"private/protocol/restxml",
"private/protocol/xml/xmlutil",
"service/s3",
"service/sts",
]
pruneopts = ""
revision = "daed0c76021ea9c4e659e3ec80bcd2d657297100"
version = "v1.15.12"
[[projects]]
branch = "master"
digest = "1:98e84060475ed245c3b355042afd43a74aa7d32efe50658f4f995977916f9fc3"
name = "github.com/bgentry/go-netrc"
packages = ["netrc"]
pruneopts = ""
revision = "9fd32a8b3d3d3f9d43c341bfe098430e07609480"
[[projects]]
digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = ""
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:971e9ba63a417c5f1f83ab358677bc59e96ff04285f26c6646ff089fb60b15e8"
name = "github.com/emicklei/go-restful"
packages = [
".",
"log",
]
pruneopts = ""
revision = "3658237ded108b4134956c1b3050349d93e7b895"
version = "v2.7.1"
[[projects]]
digest = "1:dcefbadf4534c5ecac8573698fba6e6e601157bfa8f96aafe29df31ae582ef2a"
name = "github.com/evanphx/json-patch"
packages = ["."]
pruneopts = ""
revision = "afac545df32f2287a079e2dfb7ba2745a643747e"
version = "v3.0.0"
[[projects]]
digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22"
name = "github.com/ghodss/yaml"
packages = ["."]
pruneopts = ""
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
version = "v1.0.0"
[[projects]]
digest = "1:858b7fe7b0f4bc7ef9953926828f2816ea52d01a88d72d1c45bc8c108f23c356"
name = "github.com/go-ini/ini"
packages = ["."]
pruneopts = ""
revision = "358ee7663966325963d4e8b2e1fbd570c5195153"
version = "v1.38.1"
[[projects]]
branch = "master"
digest = "1:e116a4866bffeec941056a1fcfd37e520fad1ee60e4e3579719f19a43c392e10"
name = "github.com/go-openapi/jsonpointer"
packages = ["."]
pruneopts = ""
revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2"
[[projects]]
branch = "master"
digest = "1:3830527ef0f4f9b268d9286661c0f52f9115f8aefd9f45ee7352516f93489ac9"
name = "github.com/go-openapi/jsonreference"
packages = ["."]
pruneopts = ""
revision = "3fb327e6747da3043567ee86abd02bb6376b6be2"
[[projects]]
branch = "master"
digest = "1:238a056875c4b053b4b29984765ee335bf8c539fdf17e527fd9b7aa72521c8dd"
name = "github.com/go-openapi/spec"
packages = ["."]
pruneopts = ""
revision = "bcff419492eeeb01f76e77d2ebc714dc97b607f5"
[[projects]]
branch = "master"
digest = "1:7b067ca8b94982960860d18c42e29f15bbd0e8d9ae8145a83a218296e75393cf"
name = "github.com/go-openapi/swag"
packages = ["."]
pruneopts = ""
revision = "811b1089cde9dad18d4d0c2d09fbdbf28dbd27a5"
[[projects]]
digest = "1:0a3f6a0c68ab8f3d455f8892295503b179e571b7fefe47cc6c556405d1f83411"
name = "github.com/gogo/protobuf"
packages = [
"proto",
"sortkeys",
]
pruneopts = ""
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:107b233e45174dbab5b1324201d092ea9448e58243ab9f039e4c0f332e121e3a"
name = "github.com/golang/glog"
packages = ["."]
pruneopts = ""
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
[[projects]]
digest = "1:f958a1c137db276e52f0b50efee41a1a389dcdded59a69711f3e872757dab34b"
name = "github.com/golang/protobuf"
packages = [
"proto",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/timestamp",
]
pruneopts = ""
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
version = "v1.1.0"
[[projects]]
branch = "master"
digest = "1:754f77e9c839b24778a4b64422236d38515301d2baeb63113aa3edc42e6af692"
name = "github.com/google/gofuzz"
packages = ["."]
pruneopts = ""
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
[[projects]]
digest = "1:2a131706ff80636629ab6373f2944569b8252ecc018cda8040931b05d32e3c16"
name = "github.com/googleapis/gnostic"
packages = [
"OpenAPIv2",
"compiler",
"extensions",
]
pruneopts = ""
revision = "ee43cbb60db7bd22502942cccbc39059117352ab"
version = "v0.1.0"
[[projects]]
branch = "master"
digest = "1:f5d25fd7bdda08e39e01193ef94a1ebf7547b1b931bcdec785d08050598f306c"
name = "github.com/hashicorp/go-cleanhttp"
packages = ["."]
pruneopts = ""
revision = "d5fe4b57a186c716b0e00b8c301cbd9b4182694d"
[[projects]]
branch = "master"
digest = "1:fd15b3f6aac9d0fe68c6e38922282e0d2e88cd77b927ac3dd842e363645522c0"
name = "github.com/hashicorp/go-getter"
packages = [
".",
"helper/url",
]
pruneopts = ""
revision = "4bda8fa99001c61db3cad96b421d4c12a81f256d"
[[projects]]
branch = "master"
digest = "1:2cf6c60c74eacadd31652674364af55c8d54a86b8ea193548f1c37f8c9af8f9c"
name = "github.com/hashicorp/go-safetemp"
packages = ["."]
pruneopts = ""
revision = "b1a1dbde6fdc11e3ae79efd9039009e22d4ae240"
[[projects]]
branch = "master"
digest = "1:139bdc2c89779b8ff8b1150be28f889b0ed964e6da96f32cbc9035bd4642881c"
name = "github.com/hashicorp/go-version"
packages = ["."]
pruneopts = ""
revision = "270f2f71b1ee587f3b609f00f422b76a6b28f348"
[[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
pruneopts = ""
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
digest = "1:6f49eae0c1e5dab1dafafee34b207aeb7a42303105960944828c2079b92fc88e"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = ""
revision = "0b12d6b5"
[[projects]]
digest = "1:9eab2325abbed0ebcee9d44bb3660a69d5d10e42d5ac4a0e77f7a6ea22bfce88"
name = "github.com/json-iterator/go"
packages = ["."]
pruneopts = ""
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
version = "1.1.3"
[[projects]]
digest = "1:10e1dfc240bcd0fce14366215fd2b070e79d9b9460b27382db4423ad74204f2b"
name = "github.com/krishicks/yaml-patch"
packages = ["."]
pruneopts = ""
revision = "83cc9ac50becbbfafb86a89167f3bc5372e8e530"
version = "v0.0.10"
[[projects]]
branch = "master"
digest = "1:d9e483f4b9e306facf126bd90b02d512bd22ea4471e1568867e32221a8abbb16"
name = "github.com/mailru/easyjson"
packages = [
"buffer",
"jlexer",
"jwriter",
]
pruneopts = ""
revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485"
[[projects]]
branch = "master"
digest = "1:83854f6b1d2ce047b69657e3a87ba7602f4c5505e8bdfd02ab857db8e983bde1"
name = "github.com/mitchellh/go-homedir"
packages = ["."]
pruneopts = ""
revision = "58046073cbffe2f25d425fe1331102f55cf719de"
[[projects]]
branch = "master"
digest = "1:51c98e2c9a8d0a724a69f46421876af14e12132cb02f1d0e144785d752247162"
name = "github.com/mitchellh/go-testing-interface"
packages = ["."]
pruneopts = ""
revision = "a61a99592b77c9ba629d254a693acffaeb4b7e28"
[[projects]]
digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd"
name = "github.com/modern-go/concurrent"
packages = ["."]
pruneopts = ""
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
version = "1.0.3"
[[projects]]
digest = "1:420f9231f816eeca3ff5aab070caac3ed7f27e4d37ded96ce9de3d7a7a2e31ad"
name = "github.com/modern-go/reflect2"
packages = ["."]
pruneopts = ""
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
version = "1.0.0"
[[projects]]
digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = ""
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
digest = "1:74c32990510c9f188556aa17600313e867d1d06f5a9db244056a95d144ec34ce"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = ""
revision = "a1f051bc3eba734da4772d60e2d677f47cf93ef4"
version = "v0.0.2"
[[projects]]
digest = "1:8e243c568f36b09031ec18dff5f7d2769dcf5ca4d624ea511c8e3197dc3d352d"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = ""
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1"
[[projects]]
digest = "1:ee723e6a1962a196eeba1b24f82af61a4f60f8821d7aa96d48e787f8337bcffc"
name = "github.com/ulikunitz/xz"
packages = [
".",
"internal/hash",
"internal/xlog",
"lzma",
]
pruneopts = ""
revision = "0c6b41e72360850ca4f98dc341fd999726ea007f"
version = "v0.5.4"
[[projects]]
branch = "master"
digest = "1:9e548233d0dc00e74be262e54a9d1bbe7e4c19e5951083520261740e37daeb02"
name = "golang.org/x/net"
packages = [
"http/httpguts",
"http2",
"http2/hpack",
"idna",
]
pruneopts = ""
revision = "2491c5de3490fced2f6cff376127c667efeed857"
[[projects]]
digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4"
name = "golang.org/x/text"
packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
"width",
]
pruneopts = ""
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
digest = "1:75fb3fcfc73a8c723efde7777b40e8e8ff9babf30d8c56160d01beffea8a95a6"
name = "gopkg.in/inf.v0"
packages = ["."]
pruneopts = ""
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
version = "v0.9.1"
[[projects]]
digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = ""
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[[projects]]
branch = "master"
digest = "1:663df6da5560210fc39194a0a2c4fceba09ead717c330f1174bb15597cf18ce8"
name = "k8s.io/api"
packages = [
"admissionregistration/v1alpha1",
"admissionregistration/v1beta1",
"apps/v1",
"apps/v1beta1",
"apps/v1beta2",
"authentication/v1",
"authentication/v1beta1",
"authorization/v1",
"authorization/v1beta1",
"autoscaling/v1",
"autoscaling/v2beta1",
"batch/v1",
"batch/v1beta1",
"batch/v2alpha1",
"certificates/v1beta1",
"core/v1",
"events/v1beta1",
"extensions/v1beta1",
"networking/v1",
"policy/v1beta1",
"rbac/v1",
"rbac/v1alpha1",
"rbac/v1beta1",
"scheduling/v1alpha1",
"settings/v1alpha1",
"storage/v1",
"storage/v1alpha1",
"storage/v1beta1",
]
pruneopts = ""
revision = "53d615ae3f440f957cb9989d989d597f047262d9"
[[projects]]
branch = "master"
digest = "1:bcb2285bb525712de7903a5d254c2789df65c8b58d2cfac5a26d950ad94c2079"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/equality",
"pkg/api/meta",
"pkg/api/resource",
"pkg/api/validation",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
"pkg/apis/meta/v1/validation",
"pkg/apis/meta/v1beta1",
"pkg/conversion",
"pkg/conversion/queryparams",
"pkg/fields",
"pkg/labels",
"pkg/runtime",
"pkg/runtime/schema",
"pkg/runtime/serializer",
"pkg/runtime/serializer/json",
"pkg/runtime/serializer/protobuf",
"pkg/runtime/serializer/recognizer",
"pkg/runtime/serializer/versioning",
"pkg/selection",
"pkg/types",
"pkg/util/errors",
"pkg/util/framer",
"pkg/util/intstr",
"pkg/util/json",
"pkg/util/mergepatch",
"pkg/util/net",
"pkg/util/runtime",
"pkg/util/sets",
"pkg/util/strategicpatch",
"pkg/util/validation",
"pkg/util/validation/field",
"pkg/util/wait",
"pkg/util/yaml",
"pkg/watch",
"third_party/forked/golang/json",
"third_party/forked/golang/reflect",
]
pruneopts = ""
revision = "13b73596e4b63e03203e86f6d9c7bcc1b937c62f"
[[projects]]
digest = "1:071cc2f032b701b9dba26568e040940f26931a49e3a3985f3375f17f7f6d9c5f"
name = "k8s.io/client-go"
packages = ["kubernetes/scheme"]
pruneopts = ""
revision = "23781f4d6632d88e869066eaebb743857aa1ef9b"
version = "v7.0.0"
[[projects]]
branch = "master"
digest = "1:386c5d69077ce740614e8309ddf107dde91a5db25d3d779143f452fb4fbdfd1e"
name = "k8s.io/kube-openapi"
packages = [
"pkg/common",
"pkg/util/proto",
]
pruneopts = ""
revision = "b3f03f55328800731ce03a164b80973014ecd455"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/evanphx/json-patch",
"github.com/ghodss/yaml",
"github.com/golang/glog",
"github.com/hashicorp/go-getter",
"github.com/krishicks/yaml-patch",
"github.com/pkg/errors",
"github.com/spf13/cobra",
"gopkg.in/yaml.v2",
"k8s.io/api/core/v1",
"k8s.io/apimachinery/pkg/api/validation",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"k8s.io/apimachinery/pkg/apis/meta/v1/validation",
"k8s.io/apimachinery/pkg/runtime",
"k8s.io/apimachinery/pkg/runtime/schema",
"k8s.io/apimachinery/pkg/util/mergepatch",
"k8s.io/apimachinery/pkg/util/sets",
"k8s.io/apimachinery/pkg/util/strategicpatch",
"k8s.io/apimachinery/pkg/util/validation",
"k8s.io/apimachinery/pkg/util/validation/field",
"k8s.io/apimachinery/pkg/util/yaml",
"k8s.io/client-go/kubernetes/scheme",
"k8s.io/kube-openapi/pkg/common",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,66 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/evanphx/json-patch"
version = "3.0.0"
[[constraint]]
name = "github.com/ghodss/yaml"
version = "1.0.0"
[[constraint]]
branch = "master"
name = "github.com/golang/glog"
[[constraint]]
name = "github.com/spf13/cobra"
version = "0.0.2"
[[constraint]]
branch = "master"
name = "k8s.io/api"
[[constraint]]
branch = "master"
name = "k8s.io/apimachinery"
[[constraint]]
name = "k8s.io/client-go"
version = "7.0.0"
[[override]]
branch = "master"
name = "k8s.io/utils"
[[override]]
branch = "master"
name = "github.com/go-openapi/spec"
[[constraint]]
branch = "master"
name = "github.com/hashicorp/go-getter"
[[constraint]]
name = "github.com/krishicks/yaml-patch"
version = "0.0.10"

View File

@@ -1,6 +1,5 @@
aliases:
kustomize-admins:
- grodrigues3
- monopole
- pwittrock
kustomize-maintainers:

View File

@@ -9,6 +9,10 @@ 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.
This tool is sponsored by [sig-cli] ([KEP]), and
inspired by [DAM].
[![Build Status](https://travis-ci.org/kubernetes-sigs/kustomize.svg?branch=master)](https://travis-ci.org/kubernetes-sigs/kustomize)
[![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes-sigs/kustomize)](https://goreportcard.com/report/github.com/kubernetes-sigs/kustomize)
@@ -16,6 +20,11 @@ and it's like [`sed`], in that it emits editted text.
page], or see these [install] notes. Then try one of
the tested [examples].
**Note** Kustomize is now available on kubectl v1.14 and can be used by specifying a directory containing a `kustomization.yaml`:
```shell
kubectl apply -k dir/
```
## Usage
@@ -113,21 +122,87 @@ The YAML can be directly [applied] to a cluster:
> kustomize build ~/someApp/overlays/production | kubectl apply -f -
> ```
## About
## Community
This tool is sponsored by [sig-cli] ([KEP]).
### Filing bug reports
[KEP]: https://github.com/kubernetes/community/blob/master/keps/sig-cli/0008-kustomize.md
##### A good report specifies
* the output of `kustomize version`,
* the input (the content of `kustomization.yaml`
and any files it refers to),
* the expected YAML output.
##### A _great_ report is a bug reproduction test
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].
The pattern is
* call `NewKustTestHarness`
* specify kustomization input data (resources,
patches, etc.) as inline strings,
* call `makeKustTarget().MakeCustomizedResMap()`
* compare the actual output to expected output
In a bug reproduction test, the expected output string
initially contains the _wrong_ (unexpected) output,
thus unambiguously reproducing the bug.
Nearby comments should explain what the output
_should_ be, and have a TODO pointing to the related
issue.
The person who fixes the bug then has a clear
bug reproduction and a test to modify when
the bug is fixed.
The bug reporter can then see the bug was fixed,
and has permanent regression coverage to prevent
its reintroduction.
### Feature requests
Feature requests are welcome.
Before working on an implementation, please
* Read the [eschewed feature list].
* File an issue describing
how the new feature would behave
and label it [kind/feature].
### Other communication channels
- [Slack]
- [Mailing List]
- General kubernetes [community page]
### Code of conduct
Participation in the Kubernetes community
is governed by the [Kubernetes Code of Conduct].
[`make`]: https://www.gnu.org/software/make
[`sed`]: https://www.gnu.org/software/sed
[DAM]: docs/glossary.md#declarative-application-management
[KEP]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/0008-kustomize.md
[Kubernetes Code of Conduct]: code-of-conduct.md
[Mailing List]: https://groups.google.com/forum/#!forum/kubernetes-sig-cli
[Slack]: https://kubernetes.slack.com/messages/sig-cli
[applied]: docs/glossary.md#apply
[base]: docs/glossary.md#base
[community page]: http://kubernetes.io/community/
[declarative configuration]: docs/glossary.md#declarative-application-management
[eschewed feature list]: docs/eschewedFeatures.md
[example of a target test]: https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/target/baseandoverlaysmall_test.go
[examples]: examples/README.md
[imageBase]: docs/base.jpg
[imageOverlay]: docs/overlay.jpg
[install]: docs/INSTALL.md
[kind/feature]: https://github.com/kubernetes-sigs/kustomize/labels/kind%2Ffeature
[kubernetes style]: docs/glossary.md#kubernetes-style-object
[kustomization]: docs/glossary.md#kustomization
[overlay]: docs/glossary.md#overlay
@@ -136,6 +211,7 @@ This tool is sponsored by [sig-cli] ([KEP]).
[resource]: docs/glossary.md#resource
[resources]: docs/glossary.md#resource
[sig-cli]: https://github.com/kubernetes/community/blob/master/sig-cli/README.md
[target package]: https://github.com/kubernetes-sigs/kustomize/tree/master/pkg/target
[variant]: docs/glossary.md#variant
[variants]: docs/glossary.md#variant
[workflows]: docs/workflows.md

View File

@@ -11,10 +11,6 @@ cd "$base_dir" || {
rc=0
function go_dirs {
go list -f '{{.Dir}}' ./... | tail -n +2 | tr '\n' '\0'
}
function runTest {
local name=$1
local result="SUCCESS"
@@ -28,56 +24,76 @@ function runTest {
printf "============== end %s : %s code=%d\n\n\n" "$name" "$result" $code
}
function testGoFmt {
diff <(echo -n) <(go_dirs | xargs -0 gofmt -s -d -l)
}
function testGoCyclo {
diff <(echo -n) <(go_dirs | xargs -0 gocyclo -over 15)
}
function testGoLint {
diff -u <(echo -n) <(go_dirs | xargs -0 golint --min_confidence 0.85 )
}
# Not using the 'goimports' check because it reports hyphens in imported
# package names as errors, and we vendor in packages that have
# hyphens in their names.
function testGoMetalinter {
diff -u <(echo -n) <(go_dirs | xargs -0 gometalinter.v2 --disable-all --deadline 5m \
--enable=misspell \
--enable=structcheck \
--enable=deadcode \
--enable=varcheck \
--enable=goconst \
--enable=unparam \
--enable=ineffassign \
--enable=nakedret \
--enable=interfacer \
--enable=misspell \
--line-length=170 --enable=lll \
--dupl-threshold=400 --enable=dupl)
}
function testGoVet {
go vet -all ./...
function testGoLangCILint {
golangci-lint run ./...
}
function testGoTest {
go test -v ./...
}
function testNoTravisGoTest {
go test -v sigs.k8s.io/kustomize/pkg/target \
-run TestChartInflatorExecPlugin -tags=notravis
}
function testExamples {
mdrip --mode test --label test README.md ./examples
}
runTest testGoFmt
runTest testGoMetalinter
runTest testGoLint
runTest testGoVet
runTest testGoCyclo
# Use of GOPATH is optional if go modules are
# used. This script tries to work for people who
# don't have GOPATH set, and work for travis.
#
# Upon entry, travis has GOPATH set, and used it
# to install mdrip and the like.
#
# Use GOPATH to define XDG_CONFIG_HOME, then unset
# GOPATH so that go.mod is unambiguously honored.
echo "GOPATH=$GOPATH"
if [ -z ${GOPATH+x} ]; then
echo GOPATH is unset
tmp=$HOME/gopath
if [ -d "$tmp" ]; then
oldGoPath=$tmp
else
tmp=$HOME/go
if [ -d "$tmp" ]; then
oldGoPath=$tmp
fi
fi
else
oldGoPath=$GOPATH
unset GOPATH
fi
echo "oldGoPath=$oldGoPath"
export XDG_CONFIG_HOME=$oldGoPath/src/sigs.k8s.io
echo "XDG_CONFIG_HOME=$XDG_CONFIG_HOME"
if [ ! -d "$XDG_CONFIG_HOME" ]; then
echo "$XDG_CONFIG_HOME is not a directory."
exit 1
fi
# Until go v1.13, set this explicitly.
export GO111MODULE=on
echo "HOME=$HOME"
echo "GOPATH=$GOPATH"
echo "GO111MODULE=$GO111MODULE"
echo pwd=`pwd`
echo " "
echo "Beginning tests..."
runTest testGoLangCILint
runTest testGoTest
if [ -z ${TRAVIS+x} ]; then
echo Not on travis, so running the notravis tests
runTest testNoTravisGoTest
fi
PATH=$HOME/go/bin:$PATH
runTest testExamples
if [ $rc -eq 0 ]; then

View File

@@ -4,7 +4,7 @@ project_name: kustomize
builds:
- main: ./kustomize.go
binary: kustomize
ldflags: -s -X sigs.k8s.io/kustomize/pkg/commands.kustomizeVersion={{.Version}} -X sigs.k8s.io/kustomize/pkg/commands.gitCommit={{.Commit}} -X sigs.k8s.io/kustomize/pkg/commands.buildDate={{.Date}}
ldflags: -s -X sigs.k8s.io/kustomize/pkg/commands/misc.kustomizeVersion={{.Version}} -X sigs.k8s.io/kustomize/pkg/commands/misc.gitCommit={{.Commit}} -X sigs.k8s.io/kustomize/pkg/commands/misc.buildDate={{.Date}}
goos:
- darwin
- linux

281
build/vendor_kustomize.diff Executable file
View File

@@ -0,0 +1,281 @@
commit 1b893558aa83ac6491e5ba416b493170a9045fec
Author: Jingfang Liu <jingfangliu@google.com>
Date: Mon Nov 12 10:26:12 2018 -0800
last change
diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/configMap.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/configMap.yaml
new file mode 100644
index 0000000000..0008853094
--- /dev/null
+++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/configMap.yaml
@@ -0,0 +1,8 @@
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: the-map
+data:
+ altGreeting: "Good Morning!"
+ enableRisky: "false"
diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/deployment.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/deployment.yaml
new file mode 100644
index 0000000000..6e79409080
--- /dev/null
+++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/deployment.yaml
@@ -0,0 +1,30 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: the-deployment
+spec:
+ replicas: 3
+ template:
+ metadata:
+ labels:
+ deployment: hello
+ spec:
+ containers:
+ - name: the-container
+ image: monopole/hello:1
+ command: ["/hello",
+ "--port=8080",
+ "--enableRiskyFeature=$(ENABLE_RISKY)"]
+ ports:
+ - containerPort: 8080
+ env:
+ - name: ALT_GREETING
+ valueFrom:
+ configMapKeyRef:
+ name: the-map
+ key: altGreeting
+ - name: ENABLE_RISKY
+ valueFrom:
+ configMapKeyRef:
+ name: the-map
+ key: enableRisky
diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/kustomization.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/kustomization.yaml
new file mode 100644
index 0000000000..6e1e3202d5
--- /dev/null
+++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/kustomization.yaml
@@ -0,0 +1,5 @@
+nameprefix: test-
+ resources:
+- deployment.yaml
+- service.yaml
+- configMap.yaml
diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/service.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/service.yaml
new file mode 100644
index 0000000000..2942cdb7df
--- /dev/null
+++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/service.yaml
@@ -0,0 +1,13 @@
+kind: Service
+apiVersion: v1
+metadata:
+ name: the-service
+spec:
+ selector:
+ deployment: hello
+ type: LoadBalancer
+ ports:
+ - protocol: TCP
+ port: 8666
+ targetPort: 8080
+
\ No newline at end of file
diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD
index 22b34de008..b91d1c0130 100644
--- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD
+++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD
@@ -35,12 +35,15 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
+ "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps:go_default_library",
"//staging/src/k8s.io/client-go/discovery:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/restmapper:go_default_library",
"//vendor/golang.org/x/text/encoding/unicode:go_default_library",
"//vendor/golang.org/x/text/transform:go_default_library",
+ "//vendor/sigs.k8s.io/kustomize/pkg/commands/build:go_default_library",
+ "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
],
)
diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go
index 7fd526b33c..801f13f772 100644
--- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go
+++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go
@@ -465,27 +465,48 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
}
func TestDirectoryBuilder(t *testing.T) {
- b := newDefaultBuilder().
- FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../artifacts/guestbook"}}).
- NamespaceParam("test").DefaultNamespace()
+ tests := []struct {
+ directories []string
+ singleItem bool
+ number int
+ expectedNames []string
+ }{
+ {[]string{"../../../artifacts/guestbook"}, false, 3, []string{"redis-master"}},
+ {[]string{"../../../artifacts/kustomization"}, true, 3, []string{"test-the-deployment"}},
+ {[]string{"../../../artifacts/guestbook", "../../../artifacts/kustomization"}, false, 6, []string{"redis-master", "test-the-deployment"}},
+ }
- test := &testVisitor{}
- singleItemImplied := false
+ for _, tt := range tests {
+ b := newDefaultBuilder().
+ FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: tt.directories}).
+ NamespaceParam("test").DefaultNamespace()
- err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
- if err != nil || singleItemImplied || len(test.Infos) < 3 {
- t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
- }
+ test := &testVisitor{}
+ singleItemImplied := false
- found := false
- for _, info := range test.Infos {
- if info.Name == "redis-master" && info.Namespace == "test" && info.Object != nil {
- found = true
- break
+ err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
+ if err != nil || singleItemImplied != tt.singleItem || len(test.Infos) < tt.number {
+ t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
+ }
+
+ contained := func(name string) bool {
+ for _, info := range test.Infos {
+ if info.Name == name && info.Namespace == "test" && info.Object != nil {
+ return true
+ }
+ }
+ return false
+ }
+
+ allFound := true
+ for _, name := range tt.expectedNames {
+ if !contained(name) {
+ allFound = false
+ }
+ }
+ if !allFound {
+ t.Errorf("unexpected responses: %#v", test.Infos)
}
- }
- if !found {
- t.Errorf("unexpected responses: %#v", test.Infos)
}
}
diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go
index 32c1a691a5..d7a37e1cde 100644
--- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go
+++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go
@@ -20,10 +20,12 @@ import (
"bytes"
"fmt"
"io"
+ "io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
+ "strings"
"time"
"golang.org/x/text/encoding/unicode"
@@ -38,6 +40,9 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/apimachinery/pkg/watch"
+ "k8s.io/cli-runtime/pkg/kustomize/k8sdeps"
+ "sigs.k8s.io/kustomize/pkg/commands/build"
+ "sigs.k8s.io/kustomize/pkg/fs"
)
const (
@@ -452,7 +457,10 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext
if err != nil {
return err
}
-
+ if isKustomizationDir(path) {
+ visitors = append(visitors, NewKustomizationVisitor(mapper, path, schema))
+ return filepath.SkipDir
+ }
if fi.IsDir() {
if path != paths && !recursive {
return filepath.SkipDir
@@ -463,7 +471,10 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext
if path != paths && ignoreFile(path, extensions) {
return nil
}
-
+ if strings.HasSuffix(path, "kustomization.yaml") {
+ visitors = append(visitors, NewKustomizationVisitor(mapper, filepath.Dir(path), schema))
+ return nil
+ }
visitor := &FileVisitor{
Path: path,
StreamVisitor: NewStreamVisitor(nil, mapper, path, schema),
@@ -479,6 +490,14 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext
return visitors, nil
}
+func isKustomizationDir(path string) bool {
+ if _, err := os.Stat(filepath.Join(path, "kustomization.yaml")); err == nil {
+ return true
+ }
+ return false
+}
+
+
// FileVisitor is wrapping around a StreamVisitor, to handle open/close files
type FileVisitor struct {
Path string
@@ -507,6 +526,37 @@ func (v *FileVisitor) Visit(fn VisitorFunc) error {
return v.StreamVisitor.Visit(fn)
}
+// KustomizationVisitor prorvides the output of kustomization build
+type KustomizationVisitor struct {
+ Path string
+ *StreamVisitor
+}
+
+// Visit in a KustomizationVisitor build the kustomization output
+func (v *KustomizationVisitor) Visit(fn VisitorFunc) error {
+ fSys := fs.MakeRealFS()
+ f := k8sdeps.NewFactory()
+ var out bytes.Buffer
+ cmd := build.NewCmdBuild(&out, fSys, f.ResmapF, f.TransformerF)
+ cmd.SetArgs([]string{v.Path})
+ // we want to silence usage, error output, and any future output from cobra
+ // we will get error output as a golang error from execute
+ cmd.SetOutput(ioutil.Discard)
+ _, err := cmd.ExecuteC()
+ if err != nil {
+ return err
+ }
+ v.StreamVisitor.Reader = bytes.NewReader(out.Bytes())
+ return v.StreamVisitor.Visit(fn)
+}
+
+func NewKustomizationVisitor(mapper *mapper, path string, schema ContentValidator) *KustomizationVisitor {
+ return &KustomizationVisitor{
+ Path: path,
+ StreamVisitor: NewStreamVisitor(nil, mapper, path, schema),
+ }
+}
+
// StreamVisitor reads objects from an io.Reader and walks them. A stream visitor can only be
// visited once.
// TODO: depends on objects being in JSON format before being passed to decode - need to implement

118
build/vendor_kustomize.sh Executable file
View File

@@ -0,0 +1,118 @@
#!/bin/bash
#
# 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.
set -e
set -x
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
# vendor_kustomize.sh creates the change in kubernetes repo for vendoring kustomize
function setUpWorkspace {
KPATH=~/kustomize_vendor
mkdir $KPATH
GOPATH=$KPATH
}
function cloneK8s {
mkdir -p $KPATH/src/k8s.io
cd $KPATH/src/k8s.io
git clone git@github.com:kubernetes/kubernetes.git
}
function godepRestore {
cd $KPATH/src/k8s.io/kubernetes
# restore dependencies
hack/run-in-gopath.sh hack/godep-restore.sh
}
function getKustomizeDeps {
# get Kustomize and Kustomize dependencies
hack/run-in-gopath.sh godep get sigs.k8s.io/kustomize/pkg/commands
hack/run-in-gopath.sh godep get github.com/bgentry/go-netrc/netrc
hack/run-in-gopath.sh godep get github.com/hashicorp/go-cleanhttp
hack/run-in-gopath.sh godep get github.com/hashicorp/go-getter
hack/run-in-gopath.sh godep get github.com/hashicorp/go-safetemp
hack/run-in-gopath.sh godep get github.com/hashicorp/go-version
# The hashes below passed bin/pre-commit.sh with kustomize HEAD at time of merger.
DEPS=(
"hashicorp/go-getter 4bda8fa99001c61db3cad96b421d4c12a81f256d"
"hashicorp/go-cleanhttp d5fe4b57a186c716b0e00b8c301cbd9b4182694d"
"hashicorp/go-safetemp b1a1dbde6fdc11e3ae79efd9039009e22d4ae240"
"hashicorp/go-version 270f2f71b1ee587f3b609f00f422b76a6b28f348"
"bgentry/go-netrc 9fd32a8b3d3d3f9d43c341bfe098430e07609480"
"mitchellh/go-homedir 58046073cbffe2f25d425fe1331102f55cf719de"
"mitchellh/go-testing-interface a61a99592b77c9ba629d254a693acffaeb4b7e28"
"ulikunitz/xz v0.5.4"
)
function foo {
cd $KPATH/src/k8s.io/kubernetes/_output/local/go/src/github.com/$1
git checkout $2
}
for i in "${DEPS[@]}"; do
foo $i
done
}
function updateK8s {
# Copy k8sdeps from Kustomize to cli-runtime in staging
mkdir -p $KPATH/src/k8s.io/kubernetes/staging/src/k8s.io/cli-runtime/pkg/kustomize
cp -r $KPATH/src/k8s.io/kubernetes/_output/local/go/src/sigs.k8s.io/kustomize/k8sdeps \
$KPATH/src/k8s.io/kubernetes/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps
# Change import path of k8sdeps
find $KPATH/src/k8s.io/kubernetes/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps \
-type f -name "*.go" | \
xargs sed -i \
's!sigs.k8s.io/kustomize/k8sdeps!k8s.io/cli-runtime/pkg/kustomize/k8sdeps!'
# Add kustomize command to kubectl
cp $DIR/vendor_kustomize.diff $KPATH/vendor_kustomize.diff
cd $GOPATH/src/k8s.io/kubernetes
git apply --ignore-space-change --ignore-whitespace $KPATH/vendor_kustomize.diff
}
function godepSave {
# Save all dependencies into k8s.io/kubernetes/vendor by running
# hack/godep-save.sh
hack/run-in-gopath.sh hack/godep-save.sh
}
function verify {
# make sure in k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize
# there is no internal package
test 0 == $(ls $KPATH/src/k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize | grep “internal” | wc -l)
# Make sure it compiles.
test 0 == $(bazel build cmd/kubectl:kubectl)
# next step, open a PR
echo "The change for vendoring kustomize is ready in $GOPATH/src/k8s.io/kubernetes.\n Next step, open a PR for it.\n"
}
setUpWorkspace
cloneK8s
godepRestore
getKustomizeDeps
updateK8s
godepSave
verify

View File

@@ -1,4 +0,0 @@
# Kustomize Community Code of Conduct
Kustomize contributers expected to adhere to
the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

View File

@@ -1,36 +0,0 @@
# Contributing guidelines
[Contributor License Agreement]: https://git.k8s.io/community/CLA.md
[github workflow guide]: https://github.com/kubernetes/community/blob/master/contributors/guide/github-workflow.md
[CNCF code of conduct]: https://github.com/cncf/foundation/blob/master/code-of-conduct.md
## Contributing a Patch
1. Kubernetes projects require contributors to sign the
[Contributor License Agreement] before pull requests
can be considered.
1. Submit an issue describing your proposed change to
the repo in question.
1. The [repo owners](../OWNERS) will respond to your issue
promptly.
1. Fork the repo, develop and test your code.
See the [github workflow guide].
1. For _new features_, provide a markdown-based demo following
the pattern established in the [examples](../examples) directory.
Run `bin/pre-commit.sh` to test your demo.
1. Submit a pull request.
## Community, discussion, contribution, and support
Learn how to engage with the Kubernetes community on
the [community page](http://kubernetes.io/community/).
You can reach the maintainers of this project at:
- [Slack](http://slack.k8s.io/)
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-kustomize)
## Code of conduct
Participation in the Kubernetes community is governed
by the [CNCF code of conduct].

39
docs/FAQ.md Normal file
View File

@@ -0,0 +1,39 @@
# FAQ
## security: file 'foo' is not in or below 'bar'
v2.0 added a security check that prevents
kustomizations from reading files outside their own
directory root.
This was meant to help protect the person inclined to
download kustomization directories from the web and use
them without inspection to control their production
cluster
(see [#693](https://github.com/kubernetes-sigs/kustomize/issues/693),
[#700](https://github.com/kubernetes-sigs/kustomize/pull/700),
[#995](https://github.com/kubernetes-sigs/kustomize/pull/995) and
[#998](https://github.com/kubernetes-sigs/kustomize/pull/998))
Resources (including configmap and secret generators)
can _still be shared_ via the recommended best practice
of placing them in a directory with their own
kustomization file, and refering to this directory as a
[`base`](glossary.md#base) from any kustomization that
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:
```
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

@@ -8,9 +8,20 @@ manager:
brew install kustomize
On windows, you can install kustomize with Chocolatey package
manager.
choco install kustomize
For support on the chocolatey package and prior releases, please reference the following links:
- [Choco Package](https://chocolatey.org/packages/kustomize)
- [Package Source](https://github.com/kenmaglio/choco-kustomize)
For all operating systems, download a binary from the
[release page].
Or try this to grab the latest official release
using the command line:
@@ -29,5 +40,5 @@ To install from head with [Go] v1.10.1 or higher:
<!-- @installkustomize @test -->
```
go get github.com/kubernetes-sigs/kustomize
go get sigs.k8s.io/kustomize
```

View File

@@ -1,23 +1,26 @@
# Kustomize docs
* [installation instructions](INSTALL.md)
* [FAQ](FAQ.md)
* [kustomization.yaml](kustomization.yaml) - Example of a
[kustomization](glossary.md#kustomization)
with explanations of each field.
* [versioning policy](versioningPolicy.md) - How the code and the kustomization
file evolve in time.
* [version 2.0.0](version2.0.0.md) - Release notes for Kustomize 2.0.0.
* [workflow](workflows.md) - Some steps one might take in using
bespoke and off-the-shelf configurations.
* [glossary](glossary.md) - An attempt to disambiguiate terminology.
* [eschewed features](eschewedFeatures.md) - Why certain features are (currently)
not supported in Kustomize.
* [contributing guidelines](CONTRIBUTING.md) - Please read before sending a PR.
* [code of conduct](CODE_OF_CONDUCT.md)
* [contributing guidelines](../CONTRIBUTING.md) - Please read before sending a PR.
* [code of conduct](../code-of-conduct.md)

View File

@@ -1,13 +1,22 @@
# Eschewed Features
The maintainers established this list to
place bounds on the kustomize feature
set. The bounds can be changed with
a consensus on the risks.
For a bigger picture about why kustomize
does some things and not others, see the
glossary entry for [DAM].
## Removal directives
`kustomize` supports configurations that can be reasoned about as
_compositions_ or _mixins_ - concepts that are widely accepted as
a best practice in various programming languages.
To this end, `kustomize` offers various _addition_ directives. One
can add labels, annotations, patches, resources and bases.
To this end, `kustomize` offers various _addition_ directives.
One may add labels, annotations, patches, resources, bases, etc.
Corresponding _removal_ directives are not offered.
Removal semantics would introduce many possibilities for
@@ -27,6 +36,48 @@ what you don't want and commit it to your private fork, then use
kustomize on your fork. As often as desired, use _git rebase_ to
capture improvements from the upstream base.
## Unstructured edits
_Structured edits_ are changes controlled by
knowledge of the k8s API, and YAML or JSON syntax.
Most edits performed by kustomize can be expressed as
[JSON patches] or [SMP patches]. Common edits, like
adding labels or adding a name prefix, get dedicated
shorthand commands. Another class of edits take
data from one specific object's field and use it in
another (e.g. a service object's name found and
copied into a container's command line).
These edits are designed to create valid output
given valid input, and can provide syntactically
and semantically informed error messages if inputs
are invalid.
_Unstructured edits_, e.g. a templating approach,
or a command to replace any target string in the
character stream with some other string, aren't
limited by any syntax or object structure.
Such powerful techniques are eschewed because
- There would be no way to say that a kustomization
was correct without running it and checking
the output.
- Errors in the output would be
disconnected from the edit that caused it.
- They are toil to maintain by a rotating
staff of operators.
Kustomizations are meant to be sharable and stackable.
Imagine tracing down a problem rooted in a
clever set of stacked regexp replacements
performed by various overlays on some remote base.
Other tools (sed, jinja, erb, envsubst, helm, ksonnet,
etc.) provide varying degrees of unstructured editting
and/or embedded languages, and can be used instead
of, or in a pipe with, kustomize.
## Build-time side effects from CLI args or env variables
`kustomize` supports the best practice of storing one's
@@ -35,7 +86,7 @@ entire configuration in a version control system.
Changing `kustomize build` configuration output as a result
of additional arguments or flags to `build`, or by
consulting shell environment variable values in `build`
code, would violate that goal.
code, would frustrate that goal.
`kustomize` insteads offers [kustomization] file `edit`
commands. Like any shell command, they can accept
@@ -45,7 +96,7 @@ For example, to set the tag used on an image to match an
environment variable, run
```
kustomize edit set imagetag nginx:$MY_NGINX_VERSION
kustomize edit set image nginx:$MY_NGINX_VERSION
```
as part of some encapsulating work flow executed before
@@ -70,11 +121,10 @@ commands that accept globbed arguments, expand them at _edit
time_ relative to the local file system, and store the resulting
explicit names into the kustomization file.
In this way the resources, patches and bases used at _build time_
remain explicitly declared in version control.
[base]: glossary.md#base
[DAM]: glossary.md#declarative-application-management
[java import]: https://www.codebyamir.com/blog/pitfalls-java-import-wildcards
[JSON patches]: glossary.md#patchjson6902
[kustomization]: glossary.md#kustomization
[OTS workflow]: workflows.md#off-the-shelf-configuration
[java import]: https://www.codebyamir.com/blog/pitfalls-java-import-wildcards
[SMP patches]: glossary.md#patchstrategicmerge

View File

@@ -1,8 +1,11 @@
# Glossary
[CRD spec]: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/
[CRD]: #custom-resource-definition
[DAM]: #declarative-application-management
[Declarative Application Management]: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/declarative-application-management.md
[JSON]: https://www.json.org/
[JSONPatch]: https://tools.ietf.org/html/rfc6902
[JSONMergePatch]: https://tools.ietf.org/html/rfc7386
[Resource]: #resource
[YAML]: http://www.yaml.org/start.html
[application]: #application
@@ -21,14 +24,15 @@
[overlays]: #overlay
[patch]: #patch
[patches]: #patch
[patchJson6902]: #patchJson6902
[patchJson6902]: #patchjson6902
[patchExampleJson6902]: https://github.com/kubernetes-sigs/kustomize/blob/master/examples/jsonpatch.md
[patchesJson6902]: #patchjson6902
[proposal]: https://github.com/kubernetes/community/pull/1629
[rebase]: https://git-scm.com/docs/git-rebase
[resource]: #resource
[resources]: #resource
[rpm]: https://en.wikipedia.org/wiki/Rpm_(software)
[strategic merge]: https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md
[strategic-merge]: https://git.k8s.io/community/contributors/devel/sig-api-machinery/strategic-merge-patch.md
[target]: #target
[variant]: #variant
[variants]: #variant
@@ -96,22 +100,37 @@ simpler than the workflow associated with an
periodically capturing someone else's upgrades to the
[off-the-shelf] config.
## custom resource definition
One can extend the k8s API by making a
Custom Resource Definition ([CRD spec]).
This defines a custom [resource] (CD), an entirely
new resource that can be used alongside _native_
resources like ConfigMaps, Deployments, etc.
Kustomize can customize a CD, but to do so
kustomize must also be given the corresponding CRD
so that it can interpret the structure correctly.
## declarative application management
_Declarative Application Management_ (DAM) is a [set of
ideas](https://goo.gl/T66ZcD) aiming to ease management
of k8s clusters.
Kustomize aspires to support [Declarative Application Management],
a set of best practices around managing k8s clusters.
* Works with any configuration, be it bespoke,
In brief, kustomize should
* Work with any configuration, be it bespoke,
off-the-shelf, stateless, stateful, etc.
* Supports common customizations, and creation of
[variants] (dev vs. staging vs. production).
* Exposes and teaches native k8s APIs, rather than
hiding them.
* No friction integration with version control to
* Support common customizations, and creation of
[variants] (e.g. _development_ vs.
_staging_ vs. _production_).
* Expose and teach native k8s APIs, rather than
hide them.
* Add no friction to version control integration to
support reviews and audit trails.
* Composable with other tools in a unix sense.
* Eschews crossing the line into templating, domain
* Compose with other tools in a unix sense.
* Eschew crossing the line into templating, domain
specific languages, etc., frustrating the other
goals.
@@ -131,18 +150,23 @@ Here's an [example](kustomization.yaml).
A kustomization contains fields falling into these categories:
* Immediate customization declarations, e.g.
_namePrefix_, _commonLabels_, etc.
* Resource _generators_ for configmaps and secrets.
* References to _external files_ in these categories:
* _Customization operators_ for modifying operands, e.g.
_namePrefix_, _nameSuffix_, _commonLabels_, _patches_, etc.
* _Customization operands_:
* [resources] - completely specified k8s API objects,
e.g. `deployment.yaml`, `configmap.yaml`, etc.
* [patches] - _partial_ resources that modify full
resources defined in a [base]
(only meaningful in an [overlay]).
* [bases] - path to a directory containing
a [kustomization] (only meaningful in an [overlay]).
* (_TBD_) Standard k8s API kind-version fields.
* [bases] - paths or github URLs specifying directories
containing a [kustomization]. These bases may
be subjected to more customization, or merely
included in the output.
* [CRD]s - custom resource definition files, to allow use
of _custom_ resources in the _resources_ list.
Not an actual operand - but allows the use of new operands.
* Generators, for creating more resources
(configmaps and secrets) which can then be
customized.
## kubernetes
@@ -246,45 +270,71 @@ management tool in the tradition of, say, [apt] or
## patch
A _patch_ is a partially defined k8s resource with a
name that must match a resource already known per
traversal rules built into [kustomize].
General instructions to modify a resource.
_Patch_ is a field in the kustomization, distinct from
resources, because a patch file looks like a resource
file, but has different semantics. A patch depends on
(modifies) a resource, whereas a resource has no
dependencies. Since any resource file can be used as a
patch, one cannot reliably distinguish a resource from
a patch just by looking at the file's [YAML].
There are two alternative techniques with similar
power but different notation - the
[strategic merge patch](#patchstrategicmerge)
and the [JSON patch](#patchjson6902).
## patchStrategicMerge
A _patchStrategicMerge_ is [strategic-merge]-style patch (SMP).
An SMP looks like an incomplete YAML specification of
a k8s resource. The SMP includes `TypeMeta`
fields to establish the group/version/kind/name of the
[resource] to patch, then just enough remaining fields
to step into a nested structure to specify a new field
value, e.g. an image tag.
By default, an SMP _replaces_ values. This
usually desired when the target value is a simple
string, but may not be desired when the target
value is a list.
To change this
default behavior, add a _directive_. Recognized
directives include _replace_ (the default), _merge_
(avoid replacing a list), _delete_ and a few more
(see [these notes][strategic-merge]).
Note that for custom resources, SMPs are treated as
[json merge patches][JSONMergePatch].
Fun fact - any resource file can be used as
an SMP, overwriting matching fields in another
resource with the same group/version/kind/name,
but leaving all other fields as they were.
TODO(monopole): add ptr to example.
## patchJson6902
A _patchJson6902_ refers to a kubernetes object and a [JSONPatch]
that can patch the object. A [JSONPatch] contains a list of operations to change the object's field directly.
This is different from [patch], which is
applied to a target kubernetes object by [strategic merge].
_patchesJson6902_ is a field in kustomization. It contains a list of
_patchJson6902_.
A _patchJson6902_ refers to a kubernetes [resource] and
a [JSONPatch] specifying how to change the resource.
A _patchJson6902_ can do almost everything a
_patchStrategicMerge_ can do, but with a briefer
syntax. See this [example][patchExampleJson6902].
## resource
A _resource_, in the context of kustomize, is a path to
a [YAML] or [JSON] file that completely defines a
functional k8s API object, like a deployment or a
configmap.
A _resource_ in the context of a REST-ful API is the
target object of an HTTP operation like _GET_, _PUT_ or
_POST_. k8s offers a REST-ful API surface to interact
with clients.
A _resource_, in the context of kustomization file,
is a path to a [YAML] or [JSON] file describing
a k8s API object, like a Deployment or a
ConfigmMap.
More generally, a resource can be any correct YAML file
that [defines an object](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields)
with a _kind_ and a _metadata/name_ field.
A _resource_ in the content of a REST-ful API is the
target of an HTTP operation like _GET_, _PUT_ or
_POST_. k8s offers a RESTful API surface to interact
with clients.
## sub-target / sub-application / sub-package
A _sub-whatever_ is not a thing. There are only

View File

@@ -28,9 +28,12 @@
# don't exist.
#
# In practice, fields with no value should simply be
# omitted from kustomize.yaml to reduce the content
# omitted from kustomization.yaml to reduce the content
# visible in configuration reviews.
# ----------------------------------------------------
# apiVersion and kind of Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Adds namespace to all resources.
namespace: my-namespace
@@ -40,6 +43,13 @@ namespace: my-namespace
# "wordpress" becomes "alices-wordpress".
namePrefix: alices-
# Value of this field is appended to the
# names of all resources, e.g. a deployment named
# "wordpress" becomes "wordpress-v2".
# The suffix is appended before content hash
# if resource type is ConfigMap or Secret.
nameSuffix: -v2
# Labels to add to all resources and selectors.
commonLabels:
someName: someValue
@@ -59,44 +69,60 @@ commonAnnotations:
# markers ("---").
resources:
- some-service.yaml
- ../some-dir/some-deployment.yaml
- sub-dir/some-deployment.yaml
# Each entry in this list results in the creation of
# one ConfigMap resource (it's a generator of n maps).
# The example below creates a ConfigMap with the
# names and contents of the given files.
# The example below creates two ConfigMaps. One with the
# names and contents of the given files, the other with
# key/value as data.
# Each configMapGenerator item accepts a parameter of
# behavior: [create|replace|merge]. This allows an overlay to modify or
# replace an existing configMap from the parent.
configMapGenerator:
- name: myJavaServerProps
files:
- application.properties
- more.properties
- name: myJavaServerEnvVars
literals:
- JAVA_HOME=/opt/java/jdk
- JAVA_TOOL_OPTIONS=-agentlib:hprof
# Each entry in this list results in the creation of
# one Secret resource (it's a generator of n secrets).
# A command can do anything to get a secret,
# e.g. prompt the user directly, start a webserver to
# initate an oauth dance, etc.
secretGenerator:
- name: app-tls
commands:
tls.crt: "cat secret/tls.cert"
tls.key: "cat secret/tls.key"
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: downloaded_secret
# timeoutSeconds specifies the number of seconds to
# wait for the commands below. It defaults to 5 seconds.
timeoutSeconds: 30
commands:
username: "curl -s https://path/to/secrets/username.yaml"
password: "curl -s https://path/to/secrets/password.yaml"
type: Opaque
- name: env_file_secret
# envCommand is similar to command but outputs lines of key=val pairs
# i.e. a Docker .env file or a .ini file.
# you can only specify one envCommand per secret.
envCommand: printf \"DB_USERNAME=admin\nDB_PASSWORD=somepw\"
# env is a path to a file to read lines of key=val
# you can only specify one env file per secret.
env: env.txt
type: Opaque
# generatorOptions modify behavior of all ConfigMap and Secret generators
generatorOptions:
# labels to add to all generated resources
labels:
kustomize.generated.resources: somevalue
# annotations to add to all generated resources
annotations:
kustomize.generated.resource: somevalue
# disableNameSuffixHash is true disables the default behavior of adding a
# suffix to the names of generated resources that is a hash of
# the resource contents.
disableNameSuffixHash: true
# Each entry in this list should resolve to a directory
# containing a kustomization file, else the
# customization fails.
@@ -116,9 +142,9 @@ secretGenerator:
# etc. that differ from the common base).
bases:
- ../../base
- github.com/kubernetes-sigs/kustomize//examples/multibases?ref=v1.0.6
- github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6
- github.com/Liujingfang1/mysql
- github.com/Liujingfang1/kustomize//examples/helloWorld?ref=test-branch
- github.com/Liujingfang1/kustomize/examples/helloWorld?ref=test-branch
# Each entry in this list should resolve to
# a partial or complete resource definition file.
@@ -133,7 +159,7 @@ bases:
# a memory request/limit, change an env var in a
# ConfigMap, etc. Small patches are easy to review and
# easy to mix together in overlays.
patches:
patchesStrategicMerge:
- service_port_8888.yaml
- deployment_increase_replicas.yaml
- deployment_increase_memory.yaml
@@ -162,7 +188,7 @@ patches:
# path: /some/existing/path
# value: new value
#
patchesJson6902
patchesJson6902:
- target:
version: v1
kind: Deployment
@@ -175,25 +201,35 @@ patchesJson6902
path: add_service_annotation.yaml
# Each entry in this list should be a relative path to
# a file for custom resource definition(CRD).
# a file for custom resource definition(CRD) in openAPI definition.
#
# The presence of this field is to allow kustomize be
# aware of CRDs and apply proper
# transformation for any objects in those types.
#
# Typical use case: A CRD object refers to a ConfigMap object.
# In kustomization, the ConfigMap object name may change by adding namePrefix or hashing
# In kustomization, the ConfigMap object name may change by adding namePrefix, nameSuffix, or hashing
# The name reference for this ConfigMap object in CRD object need to be
# updated with namePrefix or hashing in the same way.
# updated with namePrefix, nameSuffix, or hashing in the same way.
#
# The annotations can be put into openAPI definitions are:
# "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
- crds/typeA.json
- crds/typeB.json
# Vars are used to insert values from resources that cannot be referenced
# otherwise. For example if you need to pass a Service's name to the arguments
# or environment variables of a program but without hard coding the actual name
# of the Service you'd insert `$(MY_SERVICE_NAME)` into the value field of the
# env var or into the command or args of the container as shown here:
# Vars are used to capture text from one resource's field
# and insert that text elsewhere.
#
# For example, suppose someone specifies the name of a k8s Service
# object in a container's command line, and the name of a
# k8s Secret object in a container's environment variable,
# so that the following would work:
# ```
# containers:
# - image: myimage
@@ -203,19 +239,8 @@ crds:
# value: $(SOME_SECRET_NAME)
# ```
#
# Then you'll add an entry to `vars:` like shown below with the same name
# and a reference to the resource from which to pull the field's value.
# The actual field's path is optional and by default it will use
# `metadata.name`. Currently only string type fields are supported, no integers
# or booleans, etc. Also array access is currently not possible. For example getting
# the image field of container number 2 inside of a pod can currently not be done.
# To do so, add an entry to `vars:` as follows:
#
# Not every location of a variable is supported. To see a complete list of locations
# see the file [refvars.go](https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/transformers/refvars.go#L20).
#
# An example of a situation where you'd not use vars is when you'd like to set a
# pod's `serviceAccountName`. In that case you would just reference the ServiceAccount
# by name and Kustomize will resolve it to the eventual name while building the manifests.
vars:
- name: SOME_SECRET_NAME
objref:
@@ -236,23 +261,64 @@ vars:
apiVersion: apps/v1
fieldref:
fieldpath: spec.template.spec.restartPolicy
#
# A var is a tuple of variable name, object reference and field
# reference within that object. That's where the text is found.
#
# The field reference is optional; it defaults to `metadata.name`,
# a normal default, since kustomize is used to generate or
# modify the names of resources.
#
# At time of writing, only string type fields are supported.
# No ints, bools, arrays etc. It's not possible to, say,
# extract the name of the image in container number 2 of
# some pod template.
#
# A variable reference, i.e. the string '$(FOO)', can only
# be placed in particular fields of particular objects as
# specified by kustomize's configuration data.
#
# The default config data for vars is at
# https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/transformers/config/defaultconfig/varreference.go
# Long story short, the default targets are all
# container command args and env value fields.
#
# Vars should _not_ be used for inserting names in places
# where kustomize is already handling that job. E.g.,
# a Deployment may reference a ConfigMap by name, and
# if kustomize changes the name of a ConfigMap, it knows
# to change the name reference in the Deployment.
# ImageTags modify the tags for images without creating patches.
# E.g. Given this fragment of a Deployment:
# Images modify the name, tags and/or digest for images without creating patches.
# E.g. Given this kubernetes Deployment fragment:
# ```
# containers:
# - name: myapp
# image: mycontainerregistry/myimage:v0
# - 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
#```
# one can change the tag of myimage to v1 and the tag of nginx to 1.8.0 with the following:
# one can change the `image` in the following ways:
#
# - `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
#
# It also supports digests. If digest is present newTag is ignored.
imageTags:
- name: mycontainerregistry/myimage
# all with the following *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

70
docs/version2.0.0.md Normal file
View File

@@ -0,0 +1,70 @@
# Kustomize 2.0.0
After security review, a field used in secret generation (see below) was removed from the definition of a kustomization file with no mechanism to convert it to a new form. Also, the set of files accessible from a kustomization file has been further constrained.
Per the [versioning policy](versioningPolicy.md), backward incompatible changes trigger an increment of the major version number, hence we go from 1.0.11 to 2.0.0. We're taking this major version increment opportunity to remove some already deprecated fields, and the code paths associated with them.
## Backward Incompatible Changes
### Kustomization Path Constraints
A kustomization file can specify paths to other files, including resources, patches, configmap generation data, secret generation data and bases. In the case of a base, the path can be a git URL instead.
In 1.x, these paths had to be relative to the current kustomization directory (the location of the kustomization file used in the `build` command).
In 2.0, bases can continue to specify, via relative paths, kustomizations outside the current kustomization directory.
But non-base paths are constrained to terminate in or below the current kustomization directory. Further, bases specified via a git URL may not reference files outside of the directory used to clone the repository.
### Kustomization Field Removals
#### patches
`patches` was deprecated and replaced by `patchesStrategicMerge` when `patchesJson6902` was introduced.
In Kustomize 2.0.0, `patches` is removed. Please use `patchesStrategicMerge` instead.
#### imageTags
`imageTags` is replaced by `images` since `images` can provide more features to change image names, registries, tags and digests.
#### secretGenerator/commands
`commands` is removed from SecretGenerator due to [security concern](https://docs.google.com/document/d/1FYgLVdq-siB_Cef9yuQBmit0PbrE8lsyTBdGI2eA2y8/edit). One can use `files` or `literals`, similar to ConfigMapGenerator, to generate a secret.
```
secretGenerator:
- name: app-tls
files:
- secret/tls.cert
- secret/tls.key
type: "kubernetes.io/tls"
```
## Compatible Changes (New Features)
As this release is triggered by a security change,
there are no major new features to announce. A few things that are worth mentioning in this release are:
* More than _40_ issues closed since 1.0.11 release (including many extensions to transformation rules).
* Users can run `kustomize edit fix` to migrate a kustomization file working with previous versions to one working with 2.0.0. For example, a kustomization.yaml with following content
```
patches:
- deployment-patch.yaml
imageTags:
- name: postgres
newTag: v1
```
will be converted to
```
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patchesStrategicMerge:
- deployment-patch.yaml
images:
- name: postgres
newTag: v1
```
* Kustomization filename
In previous versions, the canonical name of a kustomization file is `kustomization.yaml`. Kustomize 2.0.0 is extended to recognize more file names: `kustomization.yaml`, `kustomization.yml` and `Kustomization`. In a directory, only one of those filenames is allowed. If there are more than one found, Kustomize will exit with an error. Please select the best filename for your use cases.
* No longer planning to deprecate namespace prefix/suffix. The deprecation warning
```
Adding nameprefix and namesuffix to Namespace resource will be deprecated in next release.
```
is removed. Since changing this behavior will break many users' workflow. Kustomize will continue with adding nameprefix and namesuffix to Namespace resources.

219
docs/versioningPolicy.md Normal file
View File

@@ -0,0 +1,219 @@
# Versioning
Running `kustomize` means one is running a
particular version of a program, 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
[semantic versioning].
When enough changes have accumulated to
warrant a new release, a [release process]
is followed, and the fields in the version
number are bumped per semver.
## Kustomization File Versioning
At the time of writing (circa release of v2.0.0):
- A [kustomization] file is just a YAML file that
can be successfully parsed into a particular Go
struct defined in the `kustomize` binary.
- This struct does not have a version number,
which is the same as saying that its version
number matches the program's version number,
since it's compiled in.
### Field Change Policy
- A field's meaning cannot be changed.
- A field may be deprecated, then removed.
- Deprecation means triggering a _minor_ (semver)
version bump in the program, and
defining a migration path in a non-fatal
error message.
- Removal means triggering a _major_ (semver)
version bump, and fatal error if field encountered
(as with any unknown field).
### The `edit fix` Command
This `kustomize` command reads a Kustomization
file, converts deprecated fields to new
fields, and writes it out again in the latest
format.
This is a type version upgrade mechanism that
works within _major_ program revisions. There is
no downgrade capability, as there's no use case
for it (see discussion below).
### Examples
At the time of writing, in v1.0.x, there were 12
minor releases, with backward compatible
deprecations fixable via `edit fix`.
With the 2.0.0 release, there were three field
removals:
- `imageTag` was deprecated when `images` was
introduced, because the latter offers more
general features for image data manipulation.
`imageTag` was removed in v2.0.0.
- `patches` was deprecated and replaced by
`patchesStrategicMerge` when `patchesJson6902`
was introduced, to make a clearer
distinction between patch specification formats.
`patches` was removed in v2.0.0.
- `secretGenerator/commands` was removed
due to security concerns in v2.0.0
with no deprecation period.
The `edit fix` command in a v2.0.x binary
will no longer recognize these fields.
## Relationship to the k8s API
### Review of k8s API versioning
The k8s API has specific [conventions] and a
process for making [changes].
The presence of an `apiVersion` field in a k8s
native type signals:
- its reliability level (alpha vs beta vs
generally available),
- the existence of code to provide default values
to fields not present in a serialization,
- the existence of code to provide both forward
and backward conversion between different
versions of types.
The k8s API promises a lossless _conversion_
between versions over a specific range. This
means that a recent client can write an object
bearing the newest possible value for its version,
the server will accept it and store it in
"versionless" JSON form in storage, and can
convert it to a range of older versions should
an older client request data.
For native k8s types, this all requires writing Go
code in the kubernetes core repo, to provide
defaulting and conversions.
For CRDs, there's a [proposal] on how to manage
versioning (e.g. a remote service can offer type
defaulting and conversions).
### Kustomization file versioning
The critical difference between k8s API versioning
and kustomization file versioning is
- A k8s API server is able to go _forward_ and
_backward_ in versioning, to work with older
clients, over [some range].
- The `kustomize edit fix` command only moves
_forward_ within a _major_ program
version.
At the time of writing, the YAML in a
kustomization file does not represent a [k8s API]
object, and the kustomize command and associated
library is neither a server of, nor a client to,
the k8s API.
### Additional Kustomization file rules
In addition to the [field change policy] described
above, kustomization files conform to
the following rules.
#### Eschew classic k8s fields
Field names with dedicated meaning in k8s
(`metadata`, `spec`, `status`, etc.) aren't used.
This is enforced via code review.
#### Optional use of k8s `kind` and `apiVersion`
At the time of writing two [special] k8s
resource fields are allowed, but not required, in
a kustomization file: [`kind`] and [`apiVersion`].
If either field is present, they both must be, and
they must have the following values:
``` yaml
kind: Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
```
They are allowed to exist and have specific values
in a kustomization file only as a sort of
domain-squatting behavior for some future API. A
kustomize user gains nothing from adding these
fields to a kustomization file.
### Why not require `kind` and `apiVersion`
#### Ease of use and setting proper expectations
Use cases for a kustomization file don't include a
server storing muliple k8s kinds and offering
version downgrades.
The kustomization file is more akin to a
`Makefile`. A kustomize command can either read a
kustomization file, or it cannot, and in the later
case will complain as specifically as possible
about why (e.g. `unknown field Foo`).
So requiring a `kind` and `apiVersion` would just
be boilerplate in a user's files, and in all the
examples and tests.
Nevertheless, _a user still benefits from a
versioning policy_ and has a `fix` command to
upgrade files as needed.
#### We can change our minds
When/if the kustomization struct graduates to some
kind of API status, with an expectation of
"versionless" storage and downgrade capability,
whatever it looks like at that moment can be
locked into `/v1beta1` or `/v1` and the `kind`
and `apiVersion` fields can be required from that
moment forward.
[field change policy]: #field-change-policy
[some range]: https://kubernetes.io/docs/reference/using-api/deprecation-policy
[proposal]: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/customresources-versioning.md
[beta-level rules]: https://github.com/kubernetes/community/blob/master/contributors/devel/api_changes.md#alpha-beta-and-stable-versions
[changes]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
[adapt]: https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/types/kustomization.go#L166
[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
[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
[semantic versioning]: https://semver.org

View File

@@ -13,6 +13,7 @@
[resources]: glossary.md#resource
[workflowBespoke]: workflowBespoke.jpg
[workflowOts]: workflowOts.jpg
[kubectl-v1.14.0]:https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement/
# workflows
@@ -71,6 +72,11 @@ Run kustomize, and pipe the output to [apply].
> kustomize build ~/ldap/overlays/production | kubectl apply -f -
> ```
You can also use [kubectl-v1.14.0] to apply your [variants].
> ```
> kubectl apply -k ~/ldap/overlays/staging
> kubectl apply -k ~/ldap/overlays/production
> ```
## Off-the-shelf configuration
@@ -120,6 +126,12 @@ distinct repository.
> kustomize build ~/ldap/overlays/production | kubectl apply -f -
> ```
You can also use [kubectl-v1.14.0] to apply your [variants].
> ```
> kubectl apply -k ~/ldap/overlays/staging
> kubectl apply -k ~/ldap/overlays/production
> ```
#### 5) (optionally) capture changes from upstream
The user can periodically [rebase] their [base] to

View File

@@ -28,17 +28,26 @@ go get sigs.k8s.io/kustomize
(e.g. devops/SRE and developers).
* [configGenerations](configGeneration.md) -
Rolling update when ConfigMapGenerator changes
Rolling update when ConfigMapGenerator changes.
* [secret generation](kvSourceGoPlugin.md) - Generating secrets.
* [generatorOptions](generatorOptions.md) -
Modifying behavior of all ConfigMap and Secret generators.
* [breakfast](breakfast.md) - Customize breakfast for
Alice and Bob.
* [container args](wordpress/README.md) - Injecting k8s runtime data into container arguments (e.g. to point wordpress to a SQL service).
* [vars](wordpress/README.md) - Injecting k8s runtime data into
container arguments (e.g. to point wordpress to a SQL service) by vars.
* [image tags](imageTags.md) - Updating image tags without applying a patch.
* [image names and tags](image.md) - Updating image names and tags without applying a patch.
* [multibases](multibases/README.md) - Composing three variants (dev, staging, production) with a common base.
* [remote target](remoteBuild.md) - Building a kustomization from a github URL
* [json patch](jsonpatch.md) - Apply a json patch in a kustomization
* [transformer configs](transformerconfigs/README.md) - Customize transformer configurations

View File

@@ -92,9 +92,9 @@ secret holding them (not covering that here).
<!--
secretGenerator:
- name: app-tls
commands:
tls.crt: "cat tls.cert"
tls.key: "cat tls.key"
files:
tls.crt=tls.cert
tls.key=tls.key
type: "kubernetes.io/tls"
EOF
-->
@@ -194,6 +194,7 @@ cat <<EOF >$OVERLAYS/development/kustomization.yaml
bases:
- ../../base
namePrefix: dev-
nameSuffix: -v1
configMapGenerator:
- name: my-configmap
behavior: merge
@@ -215,11 +216,12 @@ kustomize build $OVERLAYS/development
The name of the generated `ConfigMap` is visible in this
output.
The name should be something like `dev-my-configmap-b5m75ck895`:
The name should be something like `dev-my-configmap-v1-2gccmccgd5`:
* `"dev-"` comes from the `namePrefix` field,
* `"my-configmap"` comes from the `configMapGenerator/name` field,
* `"-b5m75ck895"` comes from a deterministic hash that `kustomize`
* `"-v1"` comes from the `nameSuffix` field,
* `"-2gccmccgd5"` comes from a deterministic hash that `kustomize`
computes from the contents of the configMap.
The hash suffix is critical. If the configMap content
@@ -291,7 +293,7 @@ kustomize build $OVERLAYS/production
```
A CICD process could apply this directly to
the cluser using:
the cluster using:
> ```
> kustomize build $OVERLAYS/production | kubectl apply -f -

View File

@@ -60,6 +60,7 @@ mkdir -p $OVERLAYS/staging
cat <<'EOF' >$OVERLAYS/staging/kustomization.yaml
namePrefix: staging-
nameSuffix: -v1
commonLabels:
variant: staging
org: acmeCorporation
@@ -150,13 +151,17 @@ The configMap name is prefixed by _staging-_, per the
`namePrefix` field in
`$OVERLAYS/staging/kustomization.yaml`.
The configMap name is suffixed by _-v1_, per the
`nameSuffix` field in
`$OVERLAYS/staging/kustomization.yaml`.
The suffix to the configMap name is generated from a
hash of the maps content - in this case the name suffix
is _hhhhkfmgmk_:
is _k25m8k5k5m_:
<!-- @grepStagingHash @test -->
```
kustomize build $OVERLAYS/staging | grep hhhhkfmgmk
kustomize build $OVERLAYS/staging | grep k25m8k5k5m
```
Now modify the map patch, to change the greeting
@@ -164,7 +169,7 @@ the server will use:
<!-- @changeMap @test -->
```
sed -i 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
sed -i.bak 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
```
See the new greeting:
@@ -183,20 +188,20 @@ kustomize build $OVERLAYS/staging |\
```
Confirm that the change in configMap content resulted
in three new names ending in _khk45ktkd9_ - one in the
in three new names ending in _cd7kdh48fd_ - one in the
configMap name itself, and two in the deployment that
uses the map:
<!-- @countHashes @test -->
```
test 3 == \
$(kustomize build $OVERLAYS/staging | grep khk45ktkd9 | wc -l); \
$(kustomize build $OVERLAYS/staging | grep cd7kdh48fd | wc -l); \
echo $?
```
Applying these resources to the cluster will result in
a rolling update of the deployments pods, retargetting
them from the _hhhhkfmgmk_ maps to the _khk45ktkd9_
them from the _k25m8k5k5m_ maps to the _cd7kdh48fd_
maps. The system will later garbage collect the
unused maps.

View File

@@ -0,0 +1,60 @@
# Generator Options
Kustomize provides options to modify the behavior of ConfigMap and Secret generators. These options include
- disable appending a content hash suffix to the names of generated resources
- adding labels to generated resources
- adding annotations to generated resources
This demo shows how to use these options. First create a workspace.
```
DEMO_HOME=$(mktemp -d)
```
Create a kustomization and add a ConfigMap generator to it.
<!-- @createCMGenerator @test -->
```
cat > $DEMO_HOME/kustomization.yaml << EOF
configMapGenerator:
- name: my-configmap
literals:
- foo=bar
- baz=qux
EOF
```
Add following generatorOptions
<!-- @addGeneratorOptions @test -->
```
cat >> $DEMO_HOME/kustomization.yaml << EOF
generatorOptions:
disableNameSuffixHash: true
labels:
kustomize.generated.resource: somevalue
annotations:
annotations.only.for.generated: othervalue
EOF
```
Run `kustomize build` and make sure that the generated ConfigMap
- doesn't have name suffix
<!-- @verify @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep "name: my-configmap$" | wc -l); \
echo $?
```
- has label `kustomize.generated.resource: somevalue`
```
test 1 == \
$(kustomize build $DEMO_HOME | grep -A 1 "labels" | grep "kustomize.generated.resource" | wc -l); \
echo $?
```
- has annotation `annotations.only.for.generated: othervalue`
```
test 1 == \
$(kustomize build $DEMO_HOME | grep -A 1 "annotations" | grep "annotations.only.for.generated" | wc -l); \
echo $?
```

View File

@@ -108,16 +108,10 @@ label_ applied to all resources:
<!-- @addLabel @test -->
```
sed -i 's/app: hello/app: my-hello/' \
sed -i.bak 's/app: hello/app: my-hello/' \
$BASE/kustomization.yaml
```
On a Mac, use:
```
sed -i '' $pattern $file
```
to get in-place editing.
See the effect:
<!-- @checkLabel @test -->
```

76
examples/image.md Normal file
View File

@@ -0,0 +1,76 @@
# Demo: change image names and tags
Define a place to work:
<!-- @makeWorkplace @test -->
```
DEMO_HOME=$(mktemp -d)
```
Make a `kustomization` containing a pod resource
<!-- @createKustomization @test -->
```
cat <<EOF >$DEMO_HOME/kustomization.yaml
resources:
- pod.yaml
EOF
```
Declare the pod resource
<!-- @createDeployment @test -->
```
cat <<EOF >$DEMO_HOME/pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.29.0
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-mydb
image: busybox:1.29.0
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
EOF
```
The `myapp-pod` resource declares an initContainer and a container, both use the image `busybox:1.29.0`.
The image `busybox` and tag `1.29.0` can be changed by adding `images` in `kustomization.yaml`.
Add `images`:
<!-- @addImages @test -->
```
cd $DEMO_HOME
kustomize edit set image busybox=alpine:3.6
```
The following `images` will be added to `kustomization.yaml`:
> ```
> images:
> - name: busybox
> newName: alpine
> newTag: 3.6
> ```
Now build this `kustomization`
<!-- @kustomizeBuild @test -->
```
kustomize build $DEMO_HOME
```
Confirm that this replaces _both_ busybox images and tags for `alpine:3.6`:
<!-- @confirmImages @test -->
```
test 2 = \
$(kustomize build $DEMO_HOME | grep alpine:3.6 | wc -l); \
echo $?
```

View File

@@ -1,75 +0,0 @@
# Demo: change image tags
Define a place to work:
<!-- @makeWorkplace @test -->
```
DEMO_HOME=$(mktemp -d)
```
Make a `kustomization` containing a pod resource
<!-- @createKustomization @test -->
```
cat <<EOF >$DEMO_HOME/kustomization.yaml
resources:
- pod.yaml
EOF
```
Declare the pod resource
<!-- @createDeployment @test -->
```
cat <<EOF >$DEMO_HOME/pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.29.0
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-mydb
image: busybox:1.29.0
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
EOF
```
The `myapp-pod` resource declares an initContainer and a container, both use the image `busybox:1.29.0`.
The tag `1.29.0` can be changed by adding `imageTags` in `kustomization.yaml`.
Add `imageTags`:
<!-- @addImageTags @test -->
```
cd $DEMO_HOME
kustomize edit set imagetag busybox:1.29.1
```
The `kustomization.yaml` will be added following `imageTags`.
> ```
> imageTags:
> - name: busybox
> newTag: 1.29.1
> ```
Now build this `kustomization`
<!-- @kustomizeBuild @test -->
```
kustomize build $DEMO_HOME
```
Confirm that this replaces _both_ busybox tags:
<!-- @confirmTags @test -->
```
test 2 == \
$(kustomize build $DEMO_HOME | grep busybox:1.29.1 | wc -l); \
echo $?
```

View File

@@ -48,7 +48,7 @@ function setUpEnv {
[[ $? -eq 0 ]] || "Failed to cd to $repo"
echo "pwd is " `pwd`
local expectedRepo=kubernetes-sigs/kustomize
local expectedRepo=sigs.k8s.io/kustomize
if [[ `pwd` != */$expectedRepo ]]; then
exitWith "Script must be run from $expectedRepo"
fi

View File

@@ -46,6 +46,25 @@ cat <<EOF >$DEMO_HOME/ingress_patch.json
EOF
```
You can also write the patch in YAML format. This example also shows the "add" operation:
<!-- @addYamlPatch @test -->
```
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
```
Apply the patch by adding _patchesJson6902_ field in kustomization.yaml
<!-- @applyJsonPatch @test -->
@@ -61,17 +80,39 @@ patchesJson6902:
EOF
```
Running `kustomize build $DEMO_HOME`, in the ourput confirm that host has been updated correctly.
Running `kustomize build $DEMO_HOME`, in the output confirm that host has been updated correctly.
<!-- @confirmHost @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep "host: foo.bar.io" | wc -l); \
echo $?
```
Running `kustomize build $DEMO_HOME`, in the ourput confirm that the servicePort has been updated correctly.
Running `kustomize build $DEMO_HOME`, in the output confirm that the servicePort has been updated correctly.
<!-- @confirmServicePort @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep "servicePort: 8080" | wc -l); \
echo $?
```
If the patch is YAML-formatted, it will be parsed correctly:
<!-- @applyYamlPatch @test -->
```
cat <<EOF >>$DEMO_HOME/kustomization.yaml
patchesJson6902:
- target:
group: extensions
version: v1beta1
kind: Ingress
name: my-ingress
path: ingress_patch.yaml
EOF
```
<!-- @confirmYamlPatch @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep "path: /test" | wc -l); \
echo $?
```

View File

@@ -0,0 +1,378 @@
[ConfigMaps]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/#configmap-v1-core
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
[Go plugin]: https://golang.org/pkg/plugin
[Secrets]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/#secret-v1-core
[base64]: https://tools.ietf.org/html/rfc4648#section-4
[configuration directory]: https://wiki.archlinux.org/index.php/XDG_Base_Directory#Specification
[grpc]: https://grpc.io
[tag]: https://github.com/kubernetes-sigs/kustomize/releases
[v2.0.3]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.0.3
[`exec.Command`]: https://golang.org/pkg/os/exec/#Command
# Generating Secrets
## What's a Secret?
Kubernetes [ConfigMaps] and [Secrets] are both
key:value (KV) maps, but the latter is intended to
signal that its values have a sensitive nature -
e.g. ssh keys or passwords.
Kubernetes assumes that the values in a Secret are
[base64] encoded, and decodes them before actual
use (as, say, the argument to a container
command). The user that creates the Secret must
base64 encode the data, or use a tool that does it
for them. This encoding doesn't protect the
secret from anything other than an
over-the-shoulder glance.
Protecting the actual secrecy of a Secret value is
up to the cluster operator. They must lock down
the cluster (and its `etcd` data store) as tightly
as desired, and likewise protect the bytes that
feed into the cluster to ultimately become the
content of a Secret value.
## Make a place to work
<!-- @establishBase @test -->
```
DEMO_HOME=$(mktemp -d)
```
## Secret values from local files
kustomize has three different ways to generate a secret
from local files:
* get them from so-called _env_ files (`NAME=VALUE`, one per line),
* consume the entire contents of a file to make one secret value,
* get literal values from the kustomization file itself.
Here's an example combining all three methods:
Make an env file with some short secrets:
<!-- @makeEnvFile @test -->
```
cat <<'EOF' >$DEMO_HOME/foo.env
ROUTER_PASSWORD=admin
DB_PASSWORD=iloveyou
EOF
```
Make a text file with a long secret:
<!-- @makeLongSecretFile @test -->
```
cat <<'EOF' >$DEMO_HOME/longsecret.txt
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
EOF
```
And make a kustomization file referring to the
above and additionally defining some literal KV
pairs:
<!-- @makeKustomization1 @test -->
```
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
secretGenerator:
- name: mysecrets
kvSources:
- name: envfiles
pluginType: builtin
args:
- foo.env
- name: files
pluginType: builtin
args:
- longsecret.txt
- name: literals
pluginType: builtin
args:
- FRUIT=apple
- VEGETABLE=carrot
EOF
```
> The above syntax is _alpha_ behavior at HEAD, for v2.1+.
>
> The default value of `pluginType` is `builtin`, so the
> `pluginType` fields could be omitted.
>
> The equivalent [v2.0.3] syntax (still supported) is
> ```
> secretGenerator:
> - name: mysecrets
> env: foo.env
> files:
> - longsecret.txt
> literals:
> - FRUIT=apple
> - VEGETABLE=carrot
> ```
Now generate the Secret:
<!-- @build1 @test -->
```
result=$(kustomize build $DEMO_HOME)
echo "$result"
# Spot check the result:
test 1 == $(echo "$result" | grep -c "FRUIT: YXBwbGU=")
```
This emits something like
> ```
> apiVersion: v1
> kind: Secret
> metadata:
> name: mysecrets-hfb5df789h
> type: Opaque
> data:
> FRUIT: YXBwbGU=
> VEGETABLE: Y2Fycm90
> ROUTER_PASSWORD: YWRtaW4=
> DB_PASSWORD: aWxvdmV5b3U=
> longsecret.txt: TG9yZW0gaXBzdW0gZG9sb3Igc2l0I... (elided)
> ```
The name of the resource is a prefix, `mysecrets`
(as specfied in the kustomization file), followed
by a hash of its contents.
Use your favorite base64 decoder to confirm the raw
versions of any of these values.
The problem that these three approaches share is
that the purported secrets must live on disk.
This adds additional security questions - who can
see the files, who installs them, who deletes
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 [Go plugin].
The values can then come in via, say, an
authenticated and authorized RPC to a password
vault service.
Here's a trivial plugin that provides
hardcoded values:
<!-- @makePlugin @test -->
```
cat <<'EOF' >$DEMO_HOME/kvMaker.go
package main
var database = map[string]string{
"TREE": "oak",
"ROCKET": "Saturn V",
"FRUIT": "apple",
"VEGETABLE": "carrot",
"SIMPSON": "homer",
}
type plugin struct{}
var KVSource plugin
func (p plugin) Get(
root string, args []string) (map[string]string, error) {
r := make(map[string]string)
for _, k := range args {
v, ok := database[k]
if ok {
r[k] = v
}
}
return r, nil
}
EOF
```
The two crucial items needed to
load and query the plugin are
1) the public symbol `KVSource`,
1) its public `Get` method and signature.
Plugins that generate KV pairs for kustomize
must be installed at
> ```
> $XDG_CONFIG_HOME/kustomize/plugin/kvSource
> ```
`XDG_CONFIG_HOME` is an environment variable
honored by many programs as the root of a
[configuration directory]. If the variable is
undefined, the convention is to fall back to
`$HOME/.config`.
The rest of the required directory path
establishes that the files found there are
kustomize plugins for generating KV pairs.
Compile and install the plugin:
<!-- @compilePlugin @test -->
```
kvSources=$DEMO_HOME/kustomize/plugin/kvSources
mkdir -p $kvSources
go build -buildmode plugin \
-o $kvSources/kvMaker.so \
$DEMO_HOME/kvMaker.go
```
Create a new kustomization file
referencing this plugin:
<!-- @makeKustomization2 @test -->
```
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
secretGenerator:
- name: mysecrets
kvSources:
- name: kvMaker
pluginType: go
args:
- FRUIT
- VEGETABLE
EOF
```
Finally, generate the secret, setting
`XDG_CONFIG_HOME` so that the plugin
can be found under `$DEMO_HOME`:
<!-- @build2 @test -->
```
result=$( \
XDG_CONFIG_HOME=$DEMO_HOME \
kustomize \
--enable_alpha_goplugins_accept_panic_risk \
build $DEMO_HOME )
echo "$result"
# Spot check the result:
test 1 == $(echo "$result" | grep -c "FRUIT: YXBwbGU=")
```
This should emit something like:
> ```
> apiVersion: v1
> kind: Secret
> metadata:
> name: mysecrets-bdt27dbkd6
> type: Opaque
> data:
> FRUIT: YXBwbGU=
> VEGETABLE: Y2Fycm90
> ```
i.e. a subset of the same values as above.
### Go Plugin Caveats
Kustomize supports Go plugins to allow someone to
extend kustomize in type-safe fashion against a
documented Go interface type, without having to
get their code merged into the kustomize
repository, and without having to maintain a
permanent fork.
Go plugins work well, but fall short of what many
people think of when they hear the word _plugin_.
Go plugin compilation creates an [ELF] formatted
`.so` file, which by definition has no information
about the _provenance_ of the file. One cannot
know which version of Go was used, which packages
were imported (and their version), what value of
`GOOS` and `GOARCH` were used, etc. If the skew
between the compilation conditions of the main
program ELF and the plugin ELF are too great, the
program will crash. Also, there's no certificate
to check in a `.so` file, so no way to know who
wrote it or what it does. A bare `.so` file, not
packaged with provenance information, is not a
suitable distrubution format. It's not what
people expect from decades of adding features
IDEs, browsers, CAD tools, graphics tools, etc.
via things called _plugins_.
There's no reason why someone couldn't build a
`.so` packaging mechanism into `go` to emit an ELF
packaged with provenance allowing ELF
compatibility checks, but this isn't supported in
kustomize (or Go) at the time of writing.
To avoid provenance issues simply compile your Go
plugins and the main program at the same time.
Bundle them into a container image for use by
downstream users and/or your continuous delivery
bot. This is the intended usage idiom for Go
plugins.
A `kustomize build` attempt with Go plugins that omits
the flag
> `--enable_alpha_goplugins_accept_panic_risk`
will fail with an error message about skew risks.
Flag use is an opt-in acknowledging the absence of
`.so` provenance, an absence that doesn't matter
to someone building the code from source.
### Leveraging Go plugins to run non-Go code
#### external services
For particular (user-created) transformations or
generations, kustomize could prepare a request,
send it to some service, and process a response.
How to do this is a [solved problem][grpc]. The
communication is struct-to-struct type safe - no
need to write parsing code.
If the service is written in Go, and one can
vendor its code, it's simplest to write a small Go
plugin that calls it like a library rather than
running the service as an independent process.
If the service is not written in Go, or if the
source code is unavailable, one can use a small Go
plugin to make the RPC.
#### subprocesses (also known as `exec` plugins)
In this approach one arranges for executable files
to be identified by name or location, and runs
them as a kustomize subprocess, sending a
'request' to the subprocess its `stdin`, and
obtaining a 'response' via its `stdout`.
An immediate way to use an arbitrary executable
with arbitrary i/o requirements is through a Go
plugin that runs the executable via
[`exec.Command`]. Each special purpose
tranformation or generation - needed by `kustomize
build` - will require it's own `stdin`/`stdout`
processing to convert from/to the Go types that
kustomize uses.
The Go plugin provides this translation layer, and
handles process exit codes.

View File

@@ -136,7 +136,7 @@ a label, but one can always edit `kustomization.yaml` directly:
<!-- @customizeLabels @test -->
```
sed -i 's/app: helloworld/app: prod/' \
sed -i.bak 's/app: helloworld/app: prod/' \
$DEMO_HOME/kustomization.yaml
```
@@ -181,6 +181,8 @@ patchesStrategicMerge:
EOF
```
A `mysql-persistent-storage` persistent disk needs to exist for it to run successfully.
Lets break this down:
- In the first step, we created a YAML file named

View File

@@ -2,7 +2,7 @@ apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
name: mysql-pass-d2gtcm2t2k
name: mysql-pass
type: Opaque
data:
# Default password is "admin".

View File

@@ -1,33 +1,38 @@
# remote targets
`kustomize build` can be run against a url. The effect is the same as cloing the repo, checking out the specified ref,
then running `kustomize build` against the desired directory in the local copy.
`kustomize build` can be run on a URL.
Take `github.com/kubernetes-sigs/kustomize//examples/multibases?ref=v1.0.6` as an example.
According to [multibases](multibases/README.md) demo, this kustomization contains three Pod objects with names as
`cluster-a-dev-myapp-pod`, `cluster-a-stag-myapp-pod`, `cluster-a-prod-myapp-pod`.
Running `kustomize build` against the url gives the same output.
The effect is the same as cloning the repo, checking out a particular
_ref_ (commit hash, branch name, release tag, etc.),
then running `kustomize build` against the desired
directory in the local copy.
To try this immediately, run a build against the kustomization
in the [multibases](multibases/README.md) example. There's
one pod in the output:
<!-- @remoteOverlayBuild @test -->
```
target="github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?ref=v1.0.6"
test 1 == \
$(kustomize build $target | grep dev-myapp-pod | wc -l); \
echo $?
```
Run against the overlay in that example to get three pods
(the overlay combines the dev, staging and prod bases for
someone who wants to send them all at the same time):
<!-- @remoteBuild @test -->
```
target=github.com/kubernetes-sigs/kustomize//examples/multibases?ref=v1.0.6
target="https://github.com/kubernetes-sigs/kustomize//examples/multibases?ref=v1.0.6"
test 3 == \
$(kustomize build $target | grep cluster-a-.*-myapp-pod | wc -l); \
echo $?
```
Overlays can be remote as well:
<!-- @remoteOverlayBuild @test -->
```
target=github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?ref=v1.0.6
test 1 == \
$(kustomize build $target | grep cluster-a-dev-myapp-pod | wc -l); \
echo $?
```
A base can also be specified as a URL:
A base can be a URL:
<!-- @createOverlay @test -->
```
@@ -39,7 +44,10 @@ bases:
namePrefix: remote-
EOF
```
Running `kustomize build $DEMO_HOME` and confirm the output contains three Pods and all have `remote-` prefix.
Build this to confirm that all three pods from the base
have the `remote-` prefix.
<!-- @remoteBases @test -->
```
test 3 == \
@@ -48,6 +56,7 @@ test 3 == \
```
## URL format
The url should follow
[hashicorp/go-getter URL format](https://github.com/hashicorp/go-getter#url-format).
Here are some example urls pointing to Github repos following this convention.

View File

@@ -0,0 +1,168 @@
# Transformer Configurations
Kustomize creates new resources by applying a series of transformations to an original
set of resources. Kustomize provides the following default transformers:
- annotations
- images
- labels
- name reference
- namespace
- prefix/suffix
- variable reference
A `fieldSpec` list, in a transformer's configuration, determines which resource types and which fields
within those types the transformer can modify.
## FieldSpec
FieldSpec is a type that represents a path to a field in one kind of resource.
```yaml
group: some-group
version: some-version
kind: some-kind
path: path/to/the/field
create: false
```
If `create` is set to `true`, the transformer creates the path to the field in the resource if the path is not already found. This is most useful for label and annotation transformers, where the path for labels or annotations may not be set before the transformation.
## Images transformer
The default images transformer updates the specified image key values found in paths that include
`containers` and `initcontainers` sub-paths.
If found, the `image` key value is customized by the values set in the `newName`, `newTag`, and `digest` fields.
The `name` field should match the `image` key value in a resource.
Example kustomization.yaml:
```yaml
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:25a0d4
```
Image transformer configurations can be customized by creating a list of `images` containing the `path` and `kind` fields.
The images transformation tutorial shows how to specify the default images transformer and customize the [images transformer configuration](images/README.md).
## Prefix/suffix transformer
The prefix/suffix transformer adds a prefix/suffix to the `metadata/name` field for all resources. Here is the default prefix transformer configuration:
```yaml
namePrefix:
- path: metadata/name
```
Example kustomization.yaml:
```yaml
namePrefix:
alices-
nameSuffix:
-v2
```
## Labels transformer
The labels transformer adds labels to the `metadata/labels` field for all resources. It also adds labels to the `spec/selector` field in all Service resources as well as the `spec/selector/matchLabels` field in all Deployment resources.
Example:
```yaml
commonLabels:
- path: metadata/labels
create: true
- path: spec/selector
create: true
version: v1
kind: Service
- path: spec/selector/matchLabels
create: true
kind: Deployment
```
Example kustomization.yaml:
```yaml
commonLabels:
someName: someValue
owner: alice
app: bingo
```
## Annotations transformer
The annotations transformer adds annotations to the `metadata/annotations` field for all resources.
Annotations are also added to `spec/template/metadata/annotations` for Deployment,
ReplicaSet, DaemonSet, StatefulSet, Job, and CronJob resources, and `spec/jobTemplate/spec/template/metadata/annotations`
for CronJob resources.
Example kustomization.yaml
```yaml
commonAnnotations:
oncallPager: 800-555-1212
```
## Name reference transformer
Name reference transformer's configuration is different from all other transformers. It contains a list of `nameReferences`, which represent all of the possible fields that a type could be used as a reference in other types of resources. A `nameReference` contains a type such as ConfigMap as well as a list of `fieldSpecs` where ConfigMap is referenced in other resources. Here is an example:
```yaml
kind: ConfigMap
version: v1
fieldSpecs:
- kind: Pod
version: v1
path: spec/volumes/configMap/name
- kind: Deployment
path: spec/template/spec/volumes/configMap/name
- kind: Job
path: spec/template/spec/volumes/configMap/name
```
Name reference transformer's configuration contains a list of `nameReferences` for resources such as ConfigMap, Secret, Service, Role, and ServiceAccount. Here is an example configuration:
```yaml
nameReference:
- kind: ConfigMap
version: v1
fieldSpecs:
- path: spec/volumes/configMap/name
version: v1
kind: Pod
- path: spec/containers/env/valueFrom/configMapKeyRef/name
version: v1
kind: Pod
# ...
- kind: Secret
version: v1
fieldSpecs:
- path: spec/volumes/secret/secretName
version: v1
kind: Pod
- path: spec/containers/env/valueFrom/secretKeyRef/name
version: v1
kind: Pod
```
## Customizing transformer configurations
In addition to the default transformers, you can create custom transformer configurations. Save the default transformer configurations to a local directory by calling `kustomize config save -d`, and modify and use these configurations. This tutorial shows how to create custom transformer configurations:
- [support a CRD type](crd/README.md)
- add extra fields for variable substitution
- add extra fields for name reference

View File

@@ -0,0 +1,139 @@
## Supporting Custom Resources (defined by a CRD)
This tutorial shows how to add transformer configurations to support a custom resource.
Create a workspace by
<!-- @createws @test -->
```
DEMO_HOME=$(mktemp -d)
```
### Adding a custom resource
Consider a CRD of kind `MyKind` with fields
- `.spec.secretRef.name` reference a Secret
- `.spec.beeRef.name` reference an instance of CRD `Bee`
- `.spec.containers.command` as the list of container commands
- `.spec.selectors` as the label selectors
Add the following file to configure the transformers for the above fields
<!-- @addConfig @test -->
```
mkdir $DEMO_HOME/kustomizeconfig
cat > $DEMO_HOME/kustomizeconfig/mykind.yaml << EOF
commonLabels:
- path: spec/selectors
create: true
kind: MyKind
nameReference:
- kind: Bee
fieldSpecs:
- path: spec/beeRef/name
kind: MyKind
- kind: Secret
fieldSpecs:
- path: spec/secretRef/name
kind: MyKind
varReference:
- path: spec/containers/command
kind: MyKind
- path: spec/beeRef/action
kind: MyKind
EOF
```
### Apply config
Create a file with some resources that
includes an instance of `MyKind`:
<!-- @createResource @test -->
```
cat > $DEMO_HOME/resources.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: crdsecret
data:
PATH: YmJiYmJiYmIK
---
apiVersion: v1beta1
kind: Bee
metadata:
name: bee
spec:
action: fly
---
apiVersion: jingfang.example.com/v1beta1
kind: MyKind
metadata:
name: mykind
spec:
secretRef:
name: crdsecret
beeRef:
name: bee
action: \$(BEE_ACTION)
containers:
- command:
- "echo"
- "\$(BEE_ACTION)"
image: myapp
EOF
```
Create a kustomization referring to it:
<!-- @createKustomization @test -->
```
cat > $DEMO_HOME/kustomization.yaml << EOF
resources:
- resources.yaml
namePrefix: test-
commonLabels:
foo: bar
vars:
- name: BEE_ACTION
objref:
kind: Bee
name: bee
apiVersion: v1beta1
fieldref:
fieldpath: spec.action
EOF
```
Use the customized transformer configurations by specifying them
in the kustomization file:
<!-- @addTransformerConfigs @test -->
```
cat >> $DEMO_HOME/kustomization.yaml << EOF
configurations:
- kustomizeconfig/mykind.yaml
EOF
```
Run `kustomize build` and verify that the namereference is correctly resolved.
<!-- @build @test -->
```
test 2 == \
$(kustomize build $DEMO_HOME | grep -A 2 ".*Ref" | grep "test-" | wc -l); \
echo $?
```
Run `kustomize build` and verify that the vars correctly resolved.
<!-- @verify @test -->
```
test 0 == \
$(kustomize build $DEMO_HOME | grep "BEE_ACTION" | wc -l); \
echo $?
```

View File

@@ -0,0 +1,16 @@
resources:
- resources.yaml
namePrefix: test-
commonLabels:
foo: bar
vars:
- name: BEE_ACTION
objref:
kind: Bee
name: bee
apiVersion: v1beta1
fieldref:
fieldpath: spec.action

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: Secret
metadata:
name: crdsecret
data:
PATH: YmJiYmJiYmIK
---
apiVersion: v1beta1
kind: Bee
metadata:
name: bee
spec:
action: fly
---
apiVersion: jingfang.example.com/v1beta1
kind: MyKind
metadata:
name: mykind
spec:
secretRef:
name: crdsecret
beeRef:
name: bee
action: $(BEE_ACTION)
containers:
- command:
- "echo"
- "$(BEE_ACTION)"
image: myapp

View File

@@ -0,0 +1,128 @@
## Images transformations
This tutorial shows how to modify images in resources, and create a custom images transformer configuration.
Create a workspace by
<!-- @createws @test -->
```
DEMO_HOME=$(mktemp -d)
```
### Adding a custom resource
Consider a Custom Resource Definition(CRD) of kind `MyKind` with field
- `.spec.runLatest.container.image` referencing an image
Add the following file to configure the images transformer for the CRD:
<!-- @addConfig @test -->
```
mkdir $DEMO_HOME/kustomizeconfig
cat > $DEMO_HOME/kustomizeconfig/mykind.yaml << EOF
images:
- path: spec/runLatest/container/image
kind: MyKind
EOF
```
### Apply config
Create a file with some resources that includes an instance of `MyKind`:
<!-- @createResource @test -->
```
cat > $DEMO_HOME/resources.yaml << EOF
apiVersion: config/v1
kind: MyKind
metadata:
name: testSvc
spec:
runLatest:
container:
image: crd-image
containers:
- image: docker
name: ecosystem
- image: my-mysql
name: testing-1
---
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
initContainers:
- name: nginx2
image: my-app
- name: init-alpine
image: alpine:1.8.0
EOF
```
Create a kustomization.yaml referring to it:
<!-- @createKustomization @test -->
```
cat > $DEMO_HOME/kustomization.yaml << EOF
resources:
- resources.yaml
images:
- name: crd-image
newName: new-crd-image
newTag: new-v1-tag
- name: my-app
newName: new-app-1
newTag: MYNEWTAG-1
- name: my-mysql
newName: prod-mysql
newTag: v3
- name: docker
newName: my-docker2
digest: sha256:25a0d4
EOF
```
Use the customized transformer configurations by specifying them
in the kustomization file:
<!-- @addTransformerConfigs @test -->
```
cat >> $DEMO_HOME/kustomization.yaml << EOF
configurations:
- kustomizeconfig/mykind.yaml
EOF
```
Run `kustomize build` and verify that the images have been updated.
<!-- @build @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "new-crd-image:new-v1-tag" | wc -l); \
echo $?
```
<!-- @build @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "new-app-1:MYNEWTAG-1" | wc -l); \
echo $?
```
<!-- @build @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "my-docker2@sha" | wc -l); \
echo $?
```
<!-- @build @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "prod-mysql:v3" | wc -l); \
echo $?
```

View File

@@ -0,0 +1,19 @@
resources:
- resources.yaml
configurations:
- kustomizeconfig/mykind.yaml
images:
- name: crd-image
newName: new-crd-image
newTag: new-v1-tag
- name: my-app
newName: new-app-1
newTag: MYNEWTAG-1
- name: my-mysql
newName: prod-mysql
newTag: v3
- name: docker
newName: my-docker2
digest: sha256:25a0d4

View File

@@ -0,0 +1,3 @@
images:
- path: spec/runLatest/container/image
kind: MyKind

View File

@@ -0,0 +1,27 @@
apiVersion: config/v1
kind: MyKind
metadata:
name: testSvc
spec:
runLatest:
container:
image: crd-image
containers:
- image: docker
name: ecosystem
- image: my-mysql
name: testing-1
---
group: apps
apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
initContainers:
- name: nginx2
image: my-app
- name: init-alpine
image: alpine:1.8.0

View File

@@ -1,6 +1,6 @@
# Demo: Injecting k8s runtime data into containers
In this tutorial, you will learn how to use `kustomize` to declare a variable reference and substitute it in container's command.
In this tutorial, you will learn how to use `kustomize` to declare a variable reference and substitute it in container's command. Note that, the substitution is not for arbitrary fields, it is only applicable to container env, args and command.
To run WordPress, it's necessary to

39
go.mod Normal file
View File

@@ -0,0 +1,39 @@
module sigs.k8s.io/kustomize
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/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/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/net v0.0.0-20190225153610-fe579d43d832 // indirect
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // 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
sigs.k8s.io/yaml v1.1.0
)

90
go.sum Normal file
View File

@@ -0,0 +1,90 @@
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/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/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/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
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/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/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 v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
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 v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/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/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/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/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/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=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -15,7 +15,7 @@ limitations under the License.
*/
// Package error has contextual error types.
package error
package kusterr
import "fmt"

View File

@@ -14,17 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestConfigmapError_Error(t *testing.T) {
filepath := "/path/to/" + constants.KustomizationFileName
errorMsg := "configmap name is missing"
me := ConfigmapError{Path: filepath, ErrorMsg: errorMsg}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import (
"fmt"

View File

@@ -14,17 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestPatchError_Error(t *testing.T) {
filepath := "/path/to/" + constants.KustomizationFileName
patchfilepath := "/path/to/patch/patch.yaml"
errorMsg := "file not found"
me := PatchError{KustomizationPath: filepath, PatchFilepath: patchfilepath, ErrorMsg: errorMsg}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import "fmt"

View File

@@ -14,17 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import (
"strings"
"testing"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestResourceError_Error(t *testing.T) {
filepath := "/path/to/" + constants.KustomizationFileName
resourcefilepath := "/path/to/resource/deployment.yaml"
errorMsg := "file not found"
me := ResourceError{KustomizationPath: filepath, ResourceFilepath: resourcefilepath, ErrorMsg: errorMsg}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import "fmt"

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import (
"strings"
@@ -22,7 +22,6 @@ import (
)
func TestSecretError_Error(t *testing.T) {
filepath := "/path/to/secret.yaml"
errorMsg := "missing a command"
me := SecretError{KustomizationPath: filepath, ErrorMsg: errorMsg}
if !strings.Contains(me.Error(), filepath) {

View File

@@ -15,12 +15,11 @@ limitations under the License.
*/
// Package error has contextual error types.
package error
package kusterr
import (
"fmt"
"k8s.io/apimachinery/pkg/util/yaml"
"strings"
)
// YamlFormatError represents error with yaml file name where json/yaml format error happens.
@@ -35,11 +34,15 @@ func (e YamlFormatError) Error() string {
// Handler handles YamlFormatError
func Handler(e error, path string) error {
if err, ok := e.(yaml.YAMLSyntaxError); ok {
if isYAMLSyntaxError(e) {
return YamlFormatError{
Path: path,
ErrorMsg: err.Error(),
ErrorMsg: e.Error(),
}
}
return e
}
func isYAMLSyntaxError(e error) bool {
return strings.Contains(e.Error(), "error converting YAML to JSON") || strings.Contains(e.Error(), "error unmarshaling JSON")
}

View File

@@ -14,26 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package error
package kusterr
import (
"bytes"
"fmt"
"testing"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/pkg/constants"
)
var (
filepath = "/path/to/" + constants.KustomizationFileName
expected = "YAML file [/path/to/kustomization.yaml] encounters a format error.\n" +
const (
filepath = "/path/to/whatever"
expected = "YAML file [/path/to/whatever] encounters a format error.\n" +
"error converting YAML to JSON: yaml: line 2: found character that cannot start any token\n"
doc = `
foo:
- fiz
- fu
`
)
func TestYamlFormatError_Error(t *testing.T) {
@@ -47,8 +38,7 @@ func TestYamlFormatError_Error(t *testing.T) {
}
func TestErrorHandler(t *testing.T) {
f := foo{}
err := yaml.NewYAMLToJSONDecoder(bytes.NewReader([]byte(doc))).Decode(&f)
err := fmt.Errorf("error converting YAML to JSON: yaml: line 2: found character that cannot start any token")
testErr := Handler(err, filepath)
expectedErr := fmt.Errorf("format error message")
fmtErr := Handler(expectedErr, filepath)
@@ -62,6 +52,3 @@ func TestErrorHandler(t *testing.T) {
t.Errorf("Expected : %s\n, but found : %s\n", expected, testErr.Error())
}
}
//type foo struct
type foo struct{}

View File

@@ -0,0 +1,88 @@
/*
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 loadertest holds a fake for the Loader interface.
package loadertest
import (
"log"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/loader"
)
// FakeLoader encapsulates the delegate Loader and the fake file system.
type FakeLoader struct {
fs fs.FileSystem
delegate ifc.Loader
}
// NewFakeLoader returns a Loader that uses a fake filesystem.
// The loader will be restricted to root only.
// The initialDir argument should be an absolute file path.
func NewFakeLoader(initialDir string) FakeLoader {
return NewFakeLoaderWithRestrictor(
loader.RestrictionRootOnly, initialDir)
}
// NewFakeLoaderWithRestrictor returns a Loader that
// uses a fake filesystem.
// The initialDir argument should be an absolute file path.
func NewFakeLoaderWithRestrictor(
lr loader.LoadRestrictorFunc, initialDir string) FakeLoader {
// Create fake filesystem and inject it into initial Loader.
fSys := fs.MakeFakeFS()
fSys.Mkdir(initialDir)
ldr, err := loader.NewLoader(lr, initialDir, fSys)
if err != nil {
log.Fatalf("Unable to make loader: %v", err)
}
return FakeLoader{fs: fSys, delegate: ldr}
}
// AddFile adds a fake file to the file system.
func (f FakeLoader) AddFile(fullFilePath string, content []byte) error {
return f.fs.WriteFile(fullFilePath, content)
}
// AddDirectory adds a fake directory to the file system.
func (f FakeLoader) AddDirectory(fullDirPath string) error {
return f.fs.Mkdir(fullDirPath)
}
// Root returns root.
func (f FakeLoader) Root() string {
return f.delegate.Root()
}
// New creates a new loader from a new root.
func (f FakeLoader) New(newRoot string) (ifc.Loader, error) {
l, err := f.delegate.New(newRoot)
if err != nil {
return nil, err
}
return FakeLoader{fs: f.fs, delegate: l}, nil
}
// Load performs load from a given location.
func (f FakeLoader) Load(location string) ([]byte, error) {
return f.delegate.Load(location)
}
// Cleanup does nothing
func (f FakeLoader) Cleanup() error {
return nil
}

View File

@@ -0,0 +1,129 @@
/*
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 plugintest_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/plugins"
)
// PluginTestEnv manages the plugin test environment.
// It sets/resets XDG_CONFIG_HOME, makes/removes a temp objRoot.
type PluginTestEnv struct {
t *testing.T
compiler *plugins.Compiler
workDir string
oldXdg string
wasSet bool
}
func NewPluginTestEnv(t *testing.T) *PluginTestEnv {
return &PluginTestEnv{t: t}
}
func (x *PluginTestEnv) Set() *PluginTestEnv {
x.createWorkDir()
x.compiler = x.makeCompiler()
x.setEnv()
return x
}
func (x *PluginTestEnv) Reset() {
x.resetEnv()
x.removeWorkDir()
}
func (x *PluginTestEnv) BuildGoPlugin(g, v, k string) {
err := x.compiler.Compile(g, v, k)
if err != nil {
x.t.Errorf("compile failed: %v", err)
}
}
func (x *PluginTestEnv) BuildExecPlugin(name ...string) {
obj := filepath.Join(
append([]string{x.workDir, pgmconfig.ProgramName, plugin.PluginRoot}, name...)...)
srcRoot, err := plugins.DefaultSrcRoot()
if err != nil {
x.t.Error(err)
}
src := filepath.Join(
append([]string{srcRoot}, name...)...)
if err := os.MkdirAll(filepath.Dir(obj), 0755); err != nil {
x.t.Errorf("error making directory: %s", filepath.Dir(obj))
}
cmd := exec.Command("cp", src, obj)
cmd.Env = os.Environ()
if err := cmd.Run(); err != nil {
x.t.Errorf("error copying %s: %v", src, err)
}
}
func (x *PluginTestEnv) makeCompiler() *plugins.Compiler {
// The plugin loader wants to find object code under
// $XDG_CONFIG_HOME/kustomize/plugins
// and the compiler writes object code to
// $objRoot
// so set things up accordingly.
objRoot := filepath.Join(
x.workDir, pgmconfig.ProgramName, plugin.PluginRoot)
err := os.MkdirAll(objRoot, os.ModePerm)
if err != nil {
x.t.Error(err)
}
srcRoot, err := plugins.DefaultSrcRoot()
if err != nil {
x.t.Error(err)
}
return plugins.NewCompiler(srcRoot, objRoot)
}
func (x *PluginTestEnv) createWorkDir() {
var err error
x.workDir, err = ioutil.TempDir("", "kustomize-plugin-tests")
if err != nil {
x.t.Errorf("failed to make work dir: %v", err)
}
}
func (x *PluginTestEnv) removeWorkDir() {
err := os.RemoveAll(x.workDir)
if err != nil {
x.t.Errorf(
"removing work dir: %s %v", x.workDir, err)
}
}
func (x *PluginTestEnv) setEnv() {
x.oldXdg, x.wasSet = os.LookupEnv(pgmconfig.XDG_CONFIG_HOME)
os.Setenv(pgmconfig.XDG_CONFIG_HOME, x.workDir)
}
func (x *PluginTestEnv) resetEnv() {
if x.wasSet {
os.Setenv(pgmconfig.XDG_CONFIG_HOME, x.oldXdg)
} else {
os.Unsetenv(pgmconfig.XDG_CONFIG_HOME)
}
}

View File

@@ -0,0 +1,148 @@
/*
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 configmapandsecret
import (
"fmt"
"sort"
"strings"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/kustomize/k8sdeps/kv"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
)
// baseFactory holds code shared by Factory and SecretFactory.
type baseFactory struct {
ldr ifc.Loader
options *types.GeneratorOptions
reg plugin.Registry
}
func (bf baseFactory) loadKvPairs(
args types.GeneratorArgs) (all []kv.Pair, err error) {
pairs, err := bf.keyValuesFromPlugins(args.KVSources)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"plugins: %s",
args.EnvSource))
}
all = append(all, pairs...)
pairs, err = bf.keyValuesFromEnvFile(args.EnvSource)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"env source file: %s",
args.EnvSource))
}
all = append(all, pairs...)
pairs, err = keyValuesFromLiteralSources(args.LiteralSources)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"literal sources %v", args.LiteralSources))
}
all = append(all, pairs...)
pairs, err = bf.keyValuesFromFileSources(args.FileSources)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"file sources: %v", args.FileSources))
}
return append(all, pairs...), nil
}
const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v"
func errIfInvalidKey(keyName string) error {
if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 {
return fmt.Errorf("%q is not a valid key name: %s",
keyName, strings.Join(errs, ";"))
}
return nil
}
func keyValuesFromLiteralSources(sources []string) ([]kv.Pair, error) {
var kvs []kv.Pair
for _, s := range sources {
k, v, err := kv.ParseLiteralSource(s)
if err != nil {
return nil, err
}
kvs = append(kvs, kv.Pair{Key: k, Value: v})
}
return kvs, nil
}
func (bf baseFactory) keyValuesFromPlugins(sources []types.KVSource) ([]kv.Pair, error) {
var result []kv.Pair
for _, s := range sources {
plug, err := bf.reg.Load(s.PluginType, s.Name)
if err != nil {
return nil, err
}
kvs, err := plug.Get(bf.reg.Root(), s.Args)
if err != nil {
return nil, err
}
for _, k := range sortedKeys(kvs) {
result = append(result, kv.Pair{Key: k, Value: kvs[k]})
}
}
return result, nil
}
func sortedKeys(m map[string]string) []string {
keys := make([]string, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}
func (bf baseFactory) keyValuesFromFileSources(sources []string) ([]kv.Pair, error) {
var kvs []kv.Pair
for _, s := range sources {
k, fPath, err := kv.ParseFileSource(s)
if err != nil {
return nil, err
}
content, err := bf.ldr.Load(fPath)
if err != nil {
return nil, err
}
kvs = append(kvs, kv.Pair{Key: k, Value: string(content)})
}
return kvs, nil
}
func (bf baseFactory) keyValuesFromEnvFile(path string) ([]kv.Pair, error) {
if path == "" {
return nil, nil
}
content, err := bf.ldr.Load(path)
if err != nil {
return nil, err
}
return kv.KeyValuesFromLines(content)
}

View File

@@ -0,0 +1,139 @@
/*
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 configmapandsecret
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kv"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
func TestKeyValuesFromFileSources(t *testing.T) {
tests := []struct {
description string
sources []string
expected []kv.Pair
}{
{
description: "create kvs from file sources",
sources: []string{"files/app-init.ini"},
expected: []kv.Pair{
{
Key: "app-init.ini",
Value: "FOO=bar",
},
},
},
}
fSys := fs.MakeFakeFS()
fSys.WriteFile("/files/app-init.ini", []byte("FOO=bar"))
ldr := loader.NewFileLoaderAtRoot(fSys)
reg := plugin.NewRegistry(ldr)
bf := baseFactory{loader.NewFileLoaderAtRoot(fSys), nil, reg}
for _, tc := range tests {
kvs, err := bf.keyValuesFromFileSources(tc.sources)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(kvs, tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, kvs, tc.expected)
}
}
}
func TestKeyValuesFromPlugins(t *testing.T) {
tests := []struct {
description string
sources []types.KVSource
expected []kv.Pair
}{
{
description: "Create kv.Pairs from builtin literals plugin",
sources: []types.KVSource{
{
PluginType: "builtin",
Name: "literals",
Args: []string{"FOO=bar", "BAR=baz"},
},
},
expected: []kv.Pair{
{
Key: "BAR",
Value: "baz",
},
{
Key: "FOO",
Value: "bar",
},
},
},
{
description: "Create kv.Pairs from builtin files plugin",
sources: []types.KVSource{
{
PluginType: "builtin",
Name: "files",
Args: []string{"files/app-init.ini"},
},
},
expected: []kv.Pair{
{
Key: "app-init.ini",
Value: "FOO=bar",
},
},
},
{
description: "Create kv.Pairs from builtin envfiles plugin",
sources: []types.KVSource{
{
PluginType: "builtin",
Name: "envfiles",
Args: []string{"files/app-init.ini"},
},
},
expected: []kv.Pair{
{
Key: "FOO",
Value: "bar",
},
},
},
}
fSys := fs.MakeFakeFS()
fSys.WriteFile("/files/app-init.ini", []byte("FOO=bar"))
ldr := loader.NewFileLoaderAtRoot(fSys)
reg := plugin.NewRegistry(ldr)
bf := baseFactory{ldr, nil, reg}
for _, tc := range tests {
kvs, err := bf.keyValuesFromPlugins(tc.sources)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(kvs, tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, kvs, tc.expected)
}
}
}

View File

@@ -0,0 +1,97 @@
/*
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 configmapandsecret generates configmaps and secrets per generator rules.
package configmapandsecret
import (
"fmt"
"unicode/utf8"
"k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
)
// Factory makes ConfigMaps and Secrets.
type Factory struct {
baseFactory
}
// NewFactory returns a new Factory.
func NewFactory(
l ifc.Loader, o *types.GeneratorOptions, reg plugin.Registry) *Factory {
return &Factory{baseFactory{ldr: l, options: o, reg: reg}}
}
func makeFreshConfigMap(
args *types.ConfigMapArgs) *v1.ConfigMap {
cm := &v1.ConfigMap{}
cm.APIVersion = "v1"
cm.Kind = "ConfigMap"
cm.Name = args.Name
cm.Namespace = args.Namespace
cm.Data = map[string]string{}
return cm
}
// MakeConfigMap returns a new ConfigMap, or nil and an error.
func (f *Factory) MakeConfigMap(
args *types.ConfigMapArgs) (*v1.ConfigMap, error) {
all, err := f.loadKvPairs(args.GeneratorArgs)
if err != nil {
return nil, err
}
cm := makeFreshConfigMap(args)
for _, p := range all {
err = addKvToConfigMap(cm, p.Key, p.Value)
if err != nil {
return nil, err
}
}
if f.options != nil {
cm.SetLabels(f.options.Labels)
cm.SetAnnotations(f.options.Annotations)
}
return cm, nil
}
// addKvToConfigMap adds the given key and data to the given config map.
// Error if key invalid, or already exists.
func addKvToConfigMap(configMap *v1.ConfigMap, keyName, data string) error {
if err := errIfInvalidKey(keyName); err != nil {
return err
}
// If the configmap data contains byte sequences that are all in the UTF-8
// range, we will write it to .Data
if utf8.Valid([]byte(data)) {
if _, entryExists := configMap.Data[keyName]; entryExists {
return fmt.Errorf(keyExistsErrorMsg, keyName, configMap.Data)
}
configMap.Data[keyName] = data
return nil
}
// otherwise, it's BinaryData
if configMap.BinaryData == nil {
configMap.BinaryData = map[string][]byte{}
}
if _, entryExists := configMap.BinaryData[keyName]; entryExists {
return fmt.Errorf(keyExistsErrorMsg, keyName, configMap.BinaryData)
}
configMap.BinaryData[keyName] = []byte(data)
return nil
}

View File

@@ -0,0 +1,157 @@
/*
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 configmapandsecret
import (
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
func makeEnvConfigMap(name string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}
}
func makeFileConfigMap(name string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"app-init.ini": `FOO=bar
BAR=baz
`,
},
BinaryData: map[string][]byte{
"app.bin": {0xff, 0xfd},
},
}
}
func makeLiteralConfigMap(name string) *corev1.ConfigMap {
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"a": "x",
"b": "y",
"c": "Hello World",
"d": "true",
},
}
cm.SetLabels(map[string]string{"foo": "bar"})
return cm
}
func TestConstructConfigMap(t *testing.T) {
type testCase struct {
description string
input types.ConfigMapArgs
options *types.GeneratorOptions
expected *corev1.ConfigMap
}
testCases := []testCase{
{
description: "construct config map from env",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "envConfigMap",
DataSources: types.DataSources{
EnvSource: "configmap/app.env",
},
},
},
options: nil,
expected: makeEnvConfigMap("envConfigMap"),
},
{
description: "construct config map from file",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileConfigMap",
DataSources: types.DataSources{
FileSources: []string{"configmap/app-init.ini", "configmap/app.bin"},
},
},
},
options: nil,
expected: makeFileConfigMap("fileConfigMap"),
},
{
description: "construct config map from literal",
input: types.ConfigMapArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalConfigMap",
DataSources: types.DataSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
expected: makeLiteralConfigMap("literalConfigMap"),
},
}
fSys := fs.MakeFakeFS()
fSys.WriteFile("/configmap/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile("/configmap/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
fSys.WriteFile("/configmap/app.bin", []byte{0xff, 0xfd})
ldr := loader.NewFileLoaderAtRoot(fSys)
reg := plugin.NewRegistry(ldr)
for _, tc := range testCases {
f := NewFactory(ldr, tc.options, reg)
cm, err := f.MakeConfigMap(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(*cm, *tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, *cm, tc.expected)
}
}
}

View File

@@ -0,0 +1,71 @@
/*
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 configmapandsecret
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/types"
)
func makeFreshSecret(
args *types.SecretArgs) *corev1.Secret {
s := &corev1.Secret{}
s.APIVersion = "v1"
s.Kind = "Secret"
s.Name = args.Name
s.Namespace = args.Namespace
s.Type = corev1.SecretType(args.Type)
if s.Type == "" {
s.Type = corev1.SecretTypeOpaque
}
s.Data = map[string][]byte{}
return s
}
// MakeSecret returns a new secret.
func (f *Factory) MakeSecret(
args *types.SecretArgs) (*corev1.Secret, error) {
all, err := f.loadKvPairs(args.GeneratorArgs)
if err != nil {
return nil, err
}
s := makeFreshSecret(args)
for _, p := range all {
err = addKvToSecret(s, p.Key, p.Value)
if err != nil {
return nil, err
}
}
if f.options != nil {
s.SetLabels(f.options.Labels)
s.SetAnnotations(f.options.Annotations)
}
return s, nil
}
func addKvToSecret(secret *corev1.Secret, keyName, data string) error {
if err := errIfInvalidKey(keyName); err != nil {
return err
}
if _, entryExists := secret.Data[keyName]; entryExists {
return fmt.Errorf(keyExistsErrorMsg, keyName, secret.Data)
}
secret.Data[keyName] = []byte(data)
return nil
}

View File

@@ -0,0 +1,154 @@
/*
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 configmapandsecret
import (
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
func makeEnvSecret(name string) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string][]byte{
"DB_PASSWORD": []byte("somepw"),
"DB_USERNAME": []byte("admin"),
},
Type: "Opaque",
}
}
func makeFileSecret(name string) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string][]byte{
"app-init.ini": []byte(`FOO=bar
BAR=baz
`),
},
Type: "Opaque",
}
}
func makeLiteralSecret(name string) *corev1.Secret {
s := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string][]byte{
"a": []byte("x"),
"b": []byte("y"),
},
Type: "Opaque",
}
s.SetLabels(map[string]string{"foo": "bar"})
return s
}
func TestConstructSecret(t *testing.T) {
type testCase struct {
description string
input types.SecretArgs
options *types.GeneratorOptions
expected *corev1.Secret
}
testCases := []testCase{
{
description: "construct secret from env",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "envSecret",
DataSources: types.DataSources{
EnvSource: "secret/app.env",
},
},
},
options: nil,
expected: makeEnvSecret("envSecret"),
},
{
description: "construct secret from file",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "fileSecret",
DataSources: types.DataSources{
FileSources: []string{"secret/app-init.ini"},
},
},
},
options: nil,
expected: makeFileSecret("fileSecret"),
},
{
description: "construct secret from literal",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalSecret",
DataSources: types.DataSources{
LiteralSources: []string{"a=x", "b=y"},
},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
expected: makeLiteralSecret("literalSecret"),
},
}
fSys := fs.MakeFakeFS()
fSys.WriteFile("/secret/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
ldr := loader.NewFileLoaderAtRoot(fSys)
reg := plugin.NewRegistry(ldr)
for _, tc := range testCases {
f := NewFactory(ldr, tc.options, reg)
cm, err := f.MakeSecret(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(*cm, *tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, *cm, tc.expected)
}
}
}

76
k8sdeps/doc.go Normal file
View File

@@ -0,0 +1,76 @@
/*
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.
*/
// It's possible that kustomize's features will be vendored into
// the kubernetes/kubernetes repo and made available to kubectl
// commands, while at the same time the kustomize program will
// continue to exist as an independent CLI. Vendoring snapshots
// would be taken just before a kubectl release.
//
// This creates a problem in that freestanding-kustomize depends on
// (for example):
//
// https://github.com/kubernetes/apimachinery/
// tree/master/pkg/util/yaml
//
// It vendors that package into
// sigs.k8s.io/kustomize/vendor/k8s.io/apimachinery/
//
// Whereas kubectl-kustomize would have to depend on the "staging"
// version of this code, located at
//
// https://github.com/kubernetes/kubernetes/
// blob/master/staging/src/k8s.io/apimachinery/pkg/util/yaml
//
// which is "vendored" via symlinks:
// k8s.io/kubernetes/vendor/k8s.io/apimachinery
// is a symlink to
// ../../staging/src/k8s.io/apimachinery
//
// The staging version is the canonical, under-development
// version of the code that kubectl depends on, whereas the packages
// at kubernetes/apimachinery are periodic snapshots of staging made
// for outside tools to depend on.
//
// apimachinery isn't the only package that poses this problem, just
// using it as a specific example.
//
// The kubectl binary cannot vendor in kustomize code that in
// turn vendors in the non-staging packages.
//
// One way to fix some of this would be to copy code - a hard fork.
// This has all the problems associated with a hard forking.
//
// Another way would be to break the kustomize repo into three:
//
// (1) kustomize - repo with the main() function,
// vendoring (2) and (3).
//
// (2) kustomize-libs - packages used by (1) with no
// apimachinery dependence.
//
// (3) kustomize-k8sdeps - A thin code layer that depends
// on (vendors) apimachinery to provide thin implementations
// to interfaces used in (2).
//
// The kubectl repo would then vendor from (2) only, and have
// a local implementation of (3). With that in mind, it's clear
// that (3) doesn't have to be a repo; the kustomize version of
// the thin layer can live directly in (1).
//
// This package is the code in (3), meant for kustomize.
package k8sdeps

View File

@@ -0,0 +1,131 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kunstruct
import (
"bytes"
"fmt"
"io"
"strings"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/k8sdeps/configmapandsecret"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
)
// KunstructuredFactoryImpl hides construction using apimachinery types.
type KunstructuredFactoryImpl struct {
generatorMetaArgs *types.GeneratorMetaArgs
}
var _ ifc.KunstructuredFactory = &KunstructuredFactoryImpl{}
// NewKunstructuredFactoryImpl returns a factory.
func NewKunstructuredFactoryImpl() ifc.KunstructuredFactory {
return NewKunstructuredFactoryWithGeneratorArgs(
&types.GeneratorMetaArgs{})
}
// NewKunstructuredFactoryWithGeneratorArgs returns a factory.
func NewKunstructuredFactoryWithGeneratorArgs(
gma *types.GeneratorMetaArgs) ifc.KunstructuredFactory {
return &KunstructuredFactoryImpl{gma}
}
// SliceFromBytes returns a slice of Kunstructured.
func (kf *KunstructuredFactoryImpl) SliceFromBytes(
in []byte) ([]ifc.Kunstructured, error) {
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
var result []ifc.Kunstructured
var err error
for err == nil || isEmptyYamlError(err) {
var out unstructured.Unstructured
err = decoder.Decode(&out)
if err == nil {
if len(out.Object) == 0 {
continue
}
err = kf.validate(out)
if err != nil {
return nil, err
}
result = append(result, &UnstructAdapter{Unstructured: out})
}
}
if err != io.EOF {
return nil, err
}
return result, nil
}
func isEmptyYamlError(err error) bool {
return strings.Contains(err.Error(), "is missing in 'null'")
}
// FromMap returns an instance of Kunstructured.
func (kf *KunstructuredFactoryImpl) FromMap(
m map[string]interface{}) ifc.Kunstructured {
return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}}
}
// MakeConfigMap returns an instance of Kunstructured for ConfigMap
func (kf *KunstructuredFactoryImpl) MakeConfigMap(
ldr ifc.Loader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(
ldr, options,
plugin.NewConfiguredRegistry(
ldr, kf.generatorMetaArgs.PluginConfig)).MakeConfigMap(args)
if err != nil {
return nil, err
}
return NewKunstructuredFromObject(o)
}
// MakeSecret returns an instance of Kunstructured for Secret
func (kf *KunstructuredFactoryImpl) MakeSecret(
ldr ifc.Loader,
options *types.GeneratorOptions,
args *types.SecretArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(
ldr, options,
plugin.NewConfiguredRegistry(
ldr, kf.generatorMetaArgs.PluginConfig)).MakeSecret(args)
if err != nil {
return nil, err
}
return NewKunstructuredFromObject(o)
}
// validate validates that u has kind and name
// except for kind `List`, which doesn't require a name
func (kf *KunstructuredFactoryImpl) validate(u unstructured.Unstructured) error {
kind := u.GetKind()
if kind == "" {
return fmt.Errorf("missing kind in object %v", u)
} else if strings.HasSuffix(kind, "List") {
return nil
}
if u.GetName() == "" {
return fmt.Errorf("missing metadata.name in object %v", u)
}
return nil
}

View File

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

View File

@@ -0,0 +1,71 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
import (
"fmt"
"strings"
)
func parseFields(path string) ([]string, error) {
if !strings.Contains(path, "[") {
return strings.Split(path, "."), nil
}
var fields []string
start := 0
insideParentheses := false
for i := range path {
switch path[i] {
case '.':
if !insideParentheses {
fields = append(fields, path[start:i])
start = i + 1
}
case '[':
if !insideParentheses {
if i == start {
start = i + 1
} else {
fields = append(fields, path[start:i])
start = i + 1
}
insideParentheses = true
} else {
return nil, fmt.Errorf("nested parentheses are not allowed: %s", path)
}
case ']':
if insideParentheses {
fields = append(fields, path[start:i])
start = i + 1
insideParentheses = false
} else {
return nil, fmt.Errorf("invalid field path %s", path)
}
}
}
if start < len(path)-1 {
fields = append(fields, path[start:])
}
for i, f := range fields {
if strings.HasPrefix(f, "\"") || strings.HasPrefix(f, "'") {
fields[i] = strings.Trim(f, "\"'")
}
}
return fields, nil
}

View File

@@ -0,0 +1,106 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
import (
"encoding/json"
"sigs.k8s.io/kustomize/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"
)
var _ ifc.Kunstructured = &UnstructAdapter{}
// UnstructAdapter wraps unstructured.Unstructured from
// https://github.com/kubernetes/apimachinery/blob/master/
// pkg/apis/meta/v1/unstructured/unstructured.go
// to isolate dependence on apimachinery.
type UnstructAdapter struct {
unstructured.Unstructured
}
// NewKunstructuredFromObject returns a new instance of Kunstructured.
func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
// Convert obj to a byte stream, then convert that to JSON (Unstructured).
marshaled, err := json.Marshal(obj)
if err != nil {
return &UnstructAdapter{}, err
}
var u unstructured.Unstructured
err = u.UnmarshalJSON(marshaled)
// creationTimestamp always 'null', remove it
u.SetCreationTimestamp(metav1.Time{})
return &UnstructAdapter{Unstructured: u}, err
}
// GetGvk returns the Gvk name of the object.
func (fs *UnstructAdapter) GetGvk() gvk.Gvk {
x := fs.GroupVersionKind()
return gvk.Gvk{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}
// Copy provides a copy behind an interface.
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
return &UnstructAdapter{*fs.DeepCopy()}
}
// Map returns the unstructured content map.
func (fs *UnstructAdapter) Map() map[string]interface{} {
return fs.Object
}
// SetMap overrides the unstructured content map.
func (fs *UnstructAdapter) SetMap(m map[string]interface{}) {
fs.Object = m
}
// GetFieldValue returns value at the given fieldpath.
func (fs *UnstructAdapter) GetFieldValue(path string) (string, error) {
fields, err := parseFields(path)
if err != nil {
return "", err
}
s, found, err := unstructured.NestedString(
fs.UnstructuredContent(), fields...)
if found || err != nil {
return s, err
}
return "", types.NoFieldError{Field: path}
}
// GetStringSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringSlice(path string) ([]string, error) {
fields, err := parseFields(path)
if err != nil {
return []string{}, err
}
s, found, err := unstructured.NestedStringSlice(
fs.UnstructuredContent(), fields...)
if found || err != nil {
return s, err
}
return []string{}, types.NoFieldError{Field: path}
}

View File

@@ -0,0 +1,148 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kunstruct
import (
"testing"
)
func TestGetFieldValue(t *testing.T) {
factory := NewKunstructuredFactoryImpl()
kunstructured := factory.FromMap(map[string]interface{}{
"Kind": "Service",
"metadata": map[string]interface{}{
"labels": map[string]string{
"app": "application-name",
},
"name": "service-name",
},
"spec": map[string]interface{}{
"ports": map[string]interface{}{
"port": "80",
},
},
"this": map[string]interface{}{
"is": map[string]interface{}{
"aNumber": 1000,
"aNilValue": nil,
"anEmptyMap": map[string]interface{}{},
"unrecognizable": testing.InternalExample{
Name: "fooBar",
},
},
},
})
tests := []struct {
name string
pathToField string
expectedValue string
errorExpected bool
errorMsg string
}{
{
name: "oneField",
pathToField: "Kind",
expectedValue: "Service",
errorExpected: false,
},
{
name: "twoFields",
pathToField: "metadata.name",
expectedValue: "service-name",
errorExpected: false,
},
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: "80",
errorExpected: false,
},
{
name: "empty",
pathToField: "",
errorExpected: true,
errorMsg: "no field named ''",
},
{
name: "emptyDotEmpty",
pathToField: ".",
errorExpected: true,
errorMsg: "no field named '.'",
},
{
name: "twoFieldsOneMissing",
pathToField: "metadata.banana",
errorExpected: true,
errorMsg: "no field named 'metadata.banana'",
},
{
name: "deeperMissingField",
pathToField: "this.is.aDeep.field.that.does.not.exist",
errorExpected: true,
errorMsg: "no field named 'this.is.aDeep.field.that.does.not.exist'",
},
{
name: "emptyMap",
pathToField: "this.is.anEmptyMap",
errorExpected: true,
errorMsg: ".this.is.anEmptyMap accessor error: map[] is of the type map[string]interface {}, expected string",
},
{
name: "numberAsValue",
pathToField: "this.is.aNumber",
errorExpected: true,
errorMsg: ".this.is.aNumber accessor error: 1000 is of the type int, expected string",
},
{
name: "nilAsValue",
pathToField: "this.is.aNilValue",
errorExpected: true,
errorMsg: ".this.is.aNilValue accessor error: <nil> is of the type <nil>, expected string",
},
{
name: "unrecognizable",
pathToField: "this.is.unrecognizable.Name",
errorExpected: true,
errorMsg: ".this.is.unrecognizable.Name accessor error: {fooBar <nil> false} is of the type testing.InternalExample, expected map[string]interface{}",
},
}
for _, test := range tests {
s, err := kunstructured.GetFieldValue(test.pathToField)
if test.errorExpected {
if err == nil {
t.Fatalf("%q; path %q - should return error, but no error returned",
test.name, test.pathToField)
}
if test.errorMsg != err.Error() {
t.Fatalf("%q; path %q - expected error: \"%s\", got error: \"%v\"",
test.name, test.pathToField, test.errorMsg, err.Error())
}
continue
}
if err != nil {
t.Fatalf("%q; path %q - unexpected error %v",
test.name, test.pathToField, err)
}
if test.expectedValue != s {
t.Fatalf("%q; Got: %s expected: %s",
test.name, s, test.expectedValue)
}
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
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.
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package configmapandsecret
package kv
import (
"bufio"
@@ -28,17 +28,16 @@ import (
"k8s.io/apimachinery/pkg/util/validation"
)
// kvPair represents a key value pair.
type kvPair struct {
key string
value string
type Pair struct {
Key string
Value string
}
var utf8bom = []byte{0xEF, 0xBB, 0xBF}
// keyValuesFromLines parses given content in to a list of key-value pairs.
func keyValuesFromLines(content []byte) ([]kvPair, error) {
var kvs []kvPair
// KeyValuesFromLines parses given content in to a list of key-value pairs.
func KeyValuesFromLines(content []byte) ([]Pair, error) {
var kvs []Pair
scanner := bufio.NewScanner(bytes.NewReader(content))
currentLine := 0
@@ -46,13 +45,13 @@ func keyValuesFromLines(content []byte) ([]kvPair, error) {
// Process the current line, retrieving a key/value pair if
// possible.
scannedBytes := scanner.Bytes()
kv, err := kvFromLine(scannedBytes, currentLine)
kv, err := KeyValuesFromLine(scannedBytes, currentLine)
if err != nil {
return nil, err
}
currentLine++
if len(kv.key) == 0 {
if len(kv.Key) == 0 {
// no key means line was empty or a comment
continue
}
@@ -62,10 +61,10 @@ func keyValuesFromLines(content []byte) ([]kvPair, error) {
return kvs, nil
}
// kvFromLine returns a kv with blank key if the line is empty or a comment.
// KeyValuesFromLine returns a kv with blank key if the line is empty or a comment.
// The value will be retrieved from the environment if necessary.
func kvFromLine(line []byte, currentLine int) (kvPair, error) {
kv := kvPair{}
func KeyValuesFromLine(line []byte, currentLine int) (Pair, error) {
kv := Pair{}
if !utf8.Valid(line) {
return kv, fmt.Errorf("line %d has invalid utf8 bytes : %v", line, string(line))
@@ -91,12 +90,12 @@ func kvFromLine(line []byte, currentLine int) (kvPair, error) {
}
if len(data) == 2 {
kv.value = data[1]
kv.Value = data[1]
} else {
// No value (no `=` in the line) is a signal to obtain the value
// from the environment.
kv.value = os.Getenv(key)
kv.Value = os.Getenv(key)
}
kv.key = key
kv.Key = key
return kv, nil
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
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.
@@ -13,7 +13,8 @@ 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 configmapandsecret
package kv
import (
"reflect"
@@ -24,7 +25,7 @@ func TestKeyValuesFromLines(t *testing.T) {
tests := []struct {
desc string
content string
expectedPairs []kvPair
expectedPairs []Pair
expectedErr bool
}{
{
@@ -33,9 +34,9 @@ func TestKeyValuesFromLines(t *testing.T) {
k1=v1
k2=v2
`,
expectedPairs: []kvPair{
{key: "k1", value: "v1"},
{key: "k2", value: "v2"},
expectedPairs: []Pair{
{Key: "k1", Value: "v1"},
{Key: "k2", Value: "v2"},
},
expectedErr: false,
},
@@ -45,8 +46,8 @@ func TestKeyValuesFromLines(t *testing.T) {
k1=v1
#k2=v2
`,
expectedPairs: []kvPair{
{key: "k1", value: "v1"},
expectedPairs: []Pair{
{Key: "k1", Value: "v1"},
},
expectedErr: false,
},
@@ -54,7 +55,7 @@ func TestKeyValuesFromLines(t *testing.T) {
}
for _, test := range tests {
pairs, err := keyValuesFromLines([]byte(test.content))
pairs, err := KeyValuesFromLines([]byte(test.content))
if test.expectedErr && err == nil {
t.Fatalf("%s should not return error", test.desc)
}

View File

@@ -0,0 +1,51 @@
/*
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 builtin
import (
"sigs.k8s.io/kustomize/k8sdeps/kv"
"sigs.k8s.io/kustomize/pkg/ifc"
)
// EnvFiles format should be a path to a file to read lines of key=val
// pairs to create a configmap.
// i.e. a Docker .env file or a .ini file.
type EnvFiles struct {
Ldr ifc.Loader
}
// Get implements the interface for kv plugins.
func (p EnvFiles) Get(root string, args []string) (map[string]string, error) {
all := make(map[string]string)
for _, path := range args {
if path == "" {
return nil, nil
}
content, err := p.Ldr.Load(path)
if err != nil {
return nil, err
}
kvs, err := kv.KeyValuesFromLines(content)
if err != nil {
return nil, err
}
for _, pair := range kvs {
all[pair.Key] = pair.Value
}
}
return all, nil
}

View File

@@ -0,0 +1,49 @@
/*
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 builtin
import (
"sigs.k8s.io/kustomize/k8sdeps/kv"
"sigs.k8s.io/kustomize/pkg/ifc"
)
// Files is a list of file sources.
// Each file source can be specified using its file path, in which case file
// basename will be used as configmap key, or optionally with a key and file
// path, in which case the given key will be used.
// Specifying a directory will iterate each named file in the directory
// whose basename is a valid configmap key.
type Files struct {
Ldr ifc.Loader
}
// Get implements the interface for kv plugins.
func (p Files) Get(root string, args []string) (map[string]string, error) {
kvs := make(map[string]string)
for _, s := range args {
k, fPath, err := kv.ParseFileSource(s)
if err != nil {
return nil, err
}
content, err := p.Ldr.Load(fPath)
if err != nil {
return nil, err
}
kvs[k] = string(content)
}
return kvs, nil
}

View File

@@ -0,0 +1,39 @@
/*
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 builtin
import (
"sigs.k8s.io/kustomize/k8sdeps/kv"
)
// Literals takes a list of literals.
// Each literal source should be a key and literal value,
// e.g. `somekey=somevalue`
type Literals struct{}
// Get implements the interface for kv plugins.
func (p Literals) Get(root string, args []string) (map[string]string, error) {
kvs := make(map[string]string)
for _, s := range args {
k, v, err := kv.ParseLiteralSource(s)
if err != nil {
return nil, err
}
kvs[k] = v
}
return kvs, nil
}

View File

@@ -0,0 +1,47 @@
/*
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 plugin
import (
"fmt"
"sigs.k8s.io/kustomize/k8sdeps/kv/plugin/builtin"
"sigs.k8s.io/kustomize/pkg/ifc"
)
var _ Factory = &builtinFactory{}
type builtinFactory struct {
plugins map[string]KVSource
}
func newBuiltinFactory(ldr ifc.Loader) *builtinFactory {
return &builtinFactory{
plugins: map[string]KVSource{
"literals": builtin.Literals{},
"files": builtin.Files{Ldr: ldr},
"envfiles": builtin.EnvFiles{Ldr: ldr},
},
}
}
func (p *builtinFactory) load(name string) (KVSource, error) {
if plug, ok := p.plugins[name]; ok {
return plug, nil
}
return nil, fmt.Errorf("plugin %s not found", name)
}

View File

@@ -0,0 +1,94 @@
/*
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 plugin
import (
"fmt"
"path/filepath"
"plugin"
"sigs.k8s.io/kustomize/pkg/types"
)
var _ Factory = &goFactory{}
const (
kvSourcesDir = "kvSources"
EnableGoPluginsFlagName = "enable_alpha_goplugins_accept_panic_risk"
EnableGoPluginsFlagHelp = `The main program may panic and exit on an attempt
to use a goplugin that was compiled under conditions
differing from the those in effect when main was
compiled. It's safest to use this flag in the
context of a container image holding both the main
and the goplugins it needs, all built on the same
machine, with the same transitive libs and the same
compiler version.`
errorFmt = `
enable go plugins by specifying flag
--%s
Place .so files in
%s
%s`
)
func newGoFactory(c *types.PluginConfig) *goFactory {
return &goFactory{
config: c,
plugins: make(map[string]KVSource),
}
}
type goFactory struct {
config *types.PluginConfig
plugins map[string]KVSource
}
func (p *goFactory) load(name string) (KVSource, error) {
if plug, ok := p.plugins[name]; ok {
return plug, nil
}
dir := filepath.Join(
p.config.DirectoryPath,
kvSourcesDir)
if !p.config.GoEnabled {
return nil, fmt.Errorf(
errorFmt,
EnableGoPluginsFlagName,
dir,
EnableGoPluginsFlagHelp)
}
goPlugin, err := plugin.Open(
filepath.Join(dir, name+".so"))
if err != nil {
return nil, err
}
symbol, err := goPlugin.Lookup("KVSource")
if err != nil {
return nil, err
}
plug, ok := symbol.(KVSource)
if !ok {
return nil, fmt.Errorf("plugin %s not found", name)
}
p.plugins[name] = plug
return plug, nil
}

View File

@@ -0,0 +1,28 @@
/*
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 plugin provides a plugin abstraction layer.
package plugin
// KVSource is the interface for kv source plugins.
type KVSource interface {
Get(root string, args []string) (map[string]string, error)
}
// Factory is the interface for new kv source plugin implementations.
type Factory interface {
load(string) (KVSource, error)
}

View File

@@ -0,0 +1,89 @@
/*
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 plugin
import (
"fmt"
"path/filepath"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/pgmconfig"
"sigs.k8s.io/kustomize/pkg/types"
)
// Registry holds all the plugin factories.
type Registry struct {
factories map[types.PluginType]Factory
ldr ifc.Loader
}
const (
PluginSymbol = "KustomizePlugin"
PluginRoot = "plugin"
pluginTypeGo = types.PluginType("go")
pluginTypeBuiltIn = types.PluginType("builtin")
)
func ActivePluginConfig() *types.PluginConfig {
pc := DefaultPluginConfig()
pc.GoEnabled = true
return pc
}
func DefaultPluginConfig() *types.PluginConfig {
return &types.PluginConfig{
GoEnabled: false,
DirectoryPath: filepath.Join(
pgmconfig.ConfigRoot(), PluginRoot),
}
}
// NewConfiguredRegistry returns a new Registry loaded
// with all the factories and a custom PluginConfig.
func NewConfiguredRegistry(
ldr ifc.Loader, pc *types.PluginConfig) Registry {
return Registry{
ldr: ldr,
factories: map[types.PluginType]Factory{
pluginTypeGo: newGoFactory(pc),
pluginTypeBuiltIn: newBuiltinFactory(ldr),
},
}
}
// NewRegistry returns a new Registry with default config.
func NewRegistry(ldr ifc.Loader) Registry {
return NewConfiguredRegistry(ldr, &types.PluginConfig{})
}
// Load returns a plugin by type and name.
func (r *Registry) Load(
pt types.PluginType, name string) (KVSource, error) {
if pt.IsUndefined() {
pt = pluginTypeBuiltIn
}
factory, exists := r.factories[pt]
if !exists {
return nil, fmt.Errorf("%s is not a valid plugin type", pt)
}
return factory.load(name)
}
// Root returns the root of the plugins kustomization file.
func (r *Registry) Root() string {
return r.ldr.Root()
}

65
k8sdeps/kv/util.go Normal file
View File

@@ -0,0 +1,65 @@
/*
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 kv
import (
"errors"
"fmt"
"path"
"strings"
)
// ParseFileSource parses the source given.
//
// Acceptable formats include:
// 1. source-path: the basename will become the key name
// 2. source-name=source-path: the source-name will become the key name and
// source-path is the path to the key file.
//
// Key names cannot include '='.
func ParseFileSource(source string) (keyName, filePath string, err error) {
numSeparators := strings.Count(source, "=")
switch {
case numSeparators == 0:
return path.Base(source), source, nil
case numSeparators == 1 && strings.HasPrefix(source, "="):
return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "="))
case numSeparators == 1 && strings.HasSuffix(source, "="):
return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "="))
case numSeparators > 1:
return "", "", errors.New("key names or file paths cannot contain '='")
default:
components := strings.Split(source, "=")
return components[0], components[1], nil
}
}
// ParseLiteralSource parses the source key=val pair into its component pieces.
// This functionality is distinguished from strings.SplitN(source, "=", 2) since
// it returns an error in the case of empty keys, values, or a missing equals sign.
func ParseLiteralSource(source string) (keyName, value string, err error) {
// leading equal is invalid
if strings.Index(source, "=") == 0 {
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
}
// split after the first equal (so values can have the = character)
items := strings.SplitN(source, "=", 2)
if len(items) != 2 {
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
}
return items[0], strings.Trim(items[1], "\"'"), nil
}

View File

@@ -0,0 +1,49 @@
/*
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 transformer provides transformer factory
package transformer
import (
"sigs.k8s.io/kustomize/k8sdeps/transformer/hash"
"sigs.k8s.io/kustomize/k8sdeps/transformer/inventory"
"sigs.k8s.io/kustomize/k8sdeps/transformer/patch"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/types"
)
// FactoryImpl makes patch transformer and name hash transformer
type FactoryImpl struct{}
// NewFactoryImpl makes a new factoryImpl instance
func NewFactoryImpl() *FactoryImpl {
return &FactoryImpl{}
}
// MakePatchTransformer makes a new patch transformer
func (p *FactoryImpl) MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) {
return patch.NewPatchTransformer(slice, rf)
}
// MakeHashTransformer makes a new name hash transformer
func (p *FactoryImpl) MakeHashTransformer() transformers.Transformer {
return hash.NewNameHashTransformer()
}
func (p *FactoryImpl) MakeInventoryTransformer(arg *types.Inventory, namespace string, append bool) transformers.Transformer {
return inventory.NewInventoryTransformer(arg, namespace, append)
}

View File

@@ -0,0 +1,184 @@
/*
Copyright 2017 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 hash
import (
"crypto/sha256"
"encoding/json"
"fmt"
"sort"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// KustHash compute hash for unstructured objects
type KustHash struct{}
// NewKustHash returns a KustHash object
func NewKustHash() *KustHash {
return &KustHash{}
}
// Hash returns a hash of either a ConfigMap or a Secret
func (h *KustHash) Hash(m map[string]interface{}) (string, error) {
u := unstructured.Unstructured{
Object: m,
}
kind := u.GetKind()
switch kind {
case "ConfigMap":
cm, err := unstructuredToConfigmap(u)
if err != nil {
return "", err
}
return ConfigMapHash(cm)
case "Secret":
sec, err := unstructuredToSecret(u)
if err != nil {
return "", err
}
return SecretHash(sec)
default:
return "", fmt.Errorf("type %s is supported for hashing in %v", kind, m)
}
}
// ConfigMapHash returns a hash of the ConfigMap.
// The Data, Kind, and Name are taken into account.
func ConfigMapHash(cm *v1.ConfigMap) (string, error) {
encoded, err := encodeConfigMap(cm)
if err != nil {
return "", err
}
h, err := encodeHash(hash(encoded))
if err != nil {
return "", err
}
return h, nil
}
// SecretHash returns a hash of the Secret.
// The Data, Kind, Name, and Type are taken into account.
func SecretHash(sec *v1.Secret) (string, error) {
encoded, err := encodeSecret(sec)
if err != nil {
return "", err
}
h, err := encodeHash(hash(encoded))
if err != nil {
return "", err
}
return h, nil
}
// SortArrayAndComputeHash sorts a string array and
// returns a hash for it
func SortArrayAndComputeHash(s []string) (string, error) {
sort.Strings(s)
data, err := json.Marshal(s)
if err != nil {
return "", err
}
h, err := encodeHash(hash(string(data)))
if err != nil {
return "", err
}
return h, nil
}
// encodeConfigMap encodes a ConfigMap.
// Data, Kind, and Name are taken into account.
func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
// json.Marshal sorts the keys in a stable order in the encoding
m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data}
if len(cm.BinaryData) > 0 {
m["binaryData"] = cm.BinaryData
}
data, err := json.Marshal(m)
if err != nil {
return "", err
}
return string(data), nil
}
// encodeSecret encodes a Secret.
// Data, Kind, Name, and Type are taken into account.
func encodeSecret(sec *v1.Secret) (string, error) {
// json.Marshal sorts the keys in a stable order in the encoding
data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data})
if err != nil {
return "", err
}
return string(data), nil
}
// encodeHash extracts the first 40 bits of the hash from the hex string
// (1 hex char represents 4 bits), and then maps vowels and vowel-like hex
// characters to consonants to prevent bad words from being formed (the theory
// is that no vowels makes it really hard to make bad words). Since the string
// is hex, the only vowels it can contain are 'a' and 'e'.
// We picked some arbitrary consonants to map to from the same character set as GenerateName.
// See: https://github.com/kubernetes/apimachinery/blob/dc1f89aff9a7509782bde3b68824c8043a3e58cc/pkg/util/rand/rand.go#L75
// If the hex string contains fewer than ten characters, returns an error.
func encodeHash(hex string) (string, error) {
if len(hex) < 10 {
return "", fmt.Errorf("the hex string must contain at least 10 characters")
}
enc := []rune(hex[:10])
for i := range enc {
switch enc[i] {
case '0':
enc[i] = 'g'
case '1':
enc[i] = 'h'
case '3':
enc[i] = 'k'
case 'a':
enc[i] = 'm'
case 'e':
enc[i] = 't'
}
}
return string(enc), nil
}
// hash hashes `data` with sha256 and returns the hex string
func hash(data string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(data)))
}
func unstructuredToConfigmap(u unstructured.Unstructured) (*v1.ConfigMap, error) {
marshaled, err := json.Marshal(u.Object)
if err != nil {
return nil, err
}
var out v1.ConfigMap
err = json.Unmarshal(marshaled, &out)
return &out, err
}
func unstructuredToSecret(u unstructured.Unstructured) (*v1.Secret, error) {
marshaled, err := json.Marshal(u.Object)
if err != nil {
return nil, err
}
var out v1.Secret
err = json.Unmarshal(marshaled, &out)
return &out, err
}

View File

@@ -22,8 +22,14 @@ import (
"testing"
"k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/gvk"
)
var service = gvk.Gvk{Version: "v1", Kind: "Service"}
var secret = gvk.Gvk{Version: "v1", Kind: "Secret"}
var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"}
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
func TestConfigMapHash(t *testing.T) {
cases := []struct {
desc string
@@ -84,6 +90,28 @@ func TestSecretHash(t *testing.T) {
}
}
func TestArrayHash(t *testing.T) {
array1 := []string{"a", "b", "c"}
array2 := []string{"c", "b", "a"}
h1, err := SortArrayAndComputeHash(array1)
if err != nil {
t.Errorf("unexpected error %v", err)
}
if h1 == "" {
t.Errorf("failed to hash %v", array1)
}
h2, err := SortArrayAndComputeHash(array2)
if err != nil {
t.Errorf("unexpected error %v", err)
}
if h2 == "" {
t.Errorf("failed to hash %v", array2)
}
if h1 != h2 {
t.Errorf("hash is not consistent with reordered list: %s %s", h1, h2)
}
}
func TestEncodeConfigMap(t *testing.T) {
cases := []struct {
desc string

View File

@@ -0,0 +1,47 @@
/*
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 hash
import (
"fmt"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
)
type nameHashTransformer struct{}
var _ transformers.Transformer = &nameHashTransformer{}
// NewNameHashTransformer construct a nameHashTransformer.
func NewNameHashTransformer() transformers.Transformer {
return &nameHashTransformer{}
}
// Transform appends hash to generated resources.
func (o *nameHashTransformer) Transform(m resmap.ResMap) error {
for _, res := range m {
if res.NeedHashSuffix() {
h, err := NewKustHash().Hash(res.Map())
if err != nil {
return err
}
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
}
}
return nil
}

View File

@@ -14,19 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package transformers
package hash
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
func TestNameHashTransformer(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
objs := resmap.ResMap{
resource.NewResId(cmap, "cm1"): resource.NewResourceFromMap(
resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -34,7 +39,7 @@ func TestNameHashTransformer(t *testing.T) {
"name": "cm1",
},
}),
resource.NewResId(deploy, "deploy1"): resource.NewResourceFromMap(
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
@@ -60,7 +65,7 @@ func TestNameHashTransformer(t *testing.T) {
},
},
}),
resource.NewResId(service, "svc1"): resource.NewResourceFromMap(
resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
@@ -76,18 +81,18 @@ func TestNameHashTransformer(t *testing.T) {
},
},
}),
resource.NewResId(secret, "secret1"): resource.NewResourceFromMap(
resid.NewResId(secret, "secret1"): rf.FromMapAndOption(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "secret1",
},
}).SetBehavior(resource.BehaviorCreate),
}, &types.GeneratorArgs{Behavior: "create"}, &types.GeneratorOptions{DisableNameSuffixHash: false}),
}
expected := resmap.ResMap{
resource.NewResId(cmap, "cm1"): resource.NewResourceFromMap(
resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -95,7 +100,7 @@ func TestNameHashTransformer(t *testing.T) {
"name": "cm1",
},
}),
resource.NewResId(deploy, "deploy1"): resource.NewResourceFromMap(
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
@@ -121,7 +126,7 @@ func TestNameHashTransformer(t *testing.T) {
},
},
}),
resource.NewResId(service, "svc1"): resource.NewResourceFromMap(
resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
@@ -137,14 +142,14 @@ func TestNameHashTransformer(t *testing.T) {
},
},
}),
resource.NewResId(secret, "secret1"): resource.NewResourceFromMap(
resid.NewResId(secret, "secret1"): rf.FromMapAndOption(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "secret1-7kc45hd5f7",
},
}).SetBehavior(resource.BehaviorCreate),
}, &types.GeneratorArgs{Behavior: "create"}, &types.GeneratorOptions{DisableNameSuffixHash: false}),
}
tran := NewNameHashTransformer()

View File

@@ -0,0 +1,111 @@
/*
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 inventory
import (
"fmt"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/k8sdeps/transformer/hash"
"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/pkg/types"
)
//const PruneAnnotation = "kustomize.k8s.io/PruneRevision"
const PruneAnnotation = "current"
// inventoryTransformer compute the ConfigMap used in prune
type inventoryTransformer struct {
append bool
cmName string
cmNamespace string
}
var _ transformers.Transformer = &inventoryTransformer{}
// NewInventoryTransformer makes a inventoryTransformer.
func NewInventoryTransformer(p *types.Inventory, namespace string, append bool) transformers.Transformer {
if p == nil || p.Type != "ConfigMap" || p.ConfigMap.Namespace != namespace {
return transformers.NewNoOpTransformer()
}
return &inventoryTransformer{
append: append,
cmName: p.ConfigMap.Name,
cmNamespace: p.ConfigMap.Namespace,
}
}
// Transform generates an inventory ConfigMap based on the input ResMap.
// this tranformer doesn't change existing resources -
// it just visits resources and accumulates information to make a new ConfigMap.
// The prune ConfigMap is used to support the pruning command in the client side tool,
// which is proposed in https://github.com/kubernetes/enhancements/pull/810
func (o *inventoryTransformer) Transform(m resmap.ResMap) error {
var keys []string
for _, r := range m {
s := r.PruneString()
keys = append(keys, s)
for _, refid := range r.GetRefBy() {
ref := m[refid]
keys = append(keys, s+"---"+ref.PruneString())
}
}
h, err := hash.SortArrayAndComputeHash(keys)
if err != nil {
return err
}
args := &types.ConfigMapArgs{}
args.Name = o.cmName
args.Namespace = o.cmNamespace
for _, key := range keys {
args.LiteralSources = append(args.LiteralSources,
key+"="+h)
}
opts := &types.GeneratorOptions{
Annotations: make(map[string]string),
}
opts.Annotations[PruneAnnotation] = h
kf := kunstruct.NewKunstructuredFactoryImpl()
k, err := kf.MakeConfigMap(nil, opts, args)
if err != nil {
return err
}
if !o.append {
for k := range m {
delete(m, k)
}
}
id := resid.NewResIdWithPrefixNamespace(
gvk.Gvk{
Version: "v1",
Kind: "ConfigMap",
},
o.cmName,
"", o.cmNamespace)
if _, ok := m[id]; ok {
return fmt.Errorf("id %v is already used, please use a different name in the prune field", id)
}
m[id] = resource.NewFactory(kf).FromKunstructured(k)
return nil
}

View File

@@ -0,0 +1,170 @@
/*
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 inventory
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
"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/types"
)
var secret = gvk.Gvk{Version: "v1", Kind: "Secret"}
var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"}
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
func makeResMap() resmap.ResMap {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
objs := resmap.ResMap{
resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
},
}),
resid.NewResId(secret, "secret1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "secret1",
},
}),
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
"env": []interface{}{
map[string]interface{}{
"name": "CM_FOO",
"valueFrom": map[string]interface{}{
"configMapKeyRef": map[string]interface{}{
"name": "cm1",
"key": "somekey",
},
},
},
},
"envFrom": []interface{}{
map[string]interface{}{
"configMapRef": map[string]interface{}{
"name": "cm1",
"key": "somekey",
},
},
map[string]interface{}{
"secretRef": map[string]interface{}{
"name": "secret1",
"key": "somekey",
},
},
},
},
},
},
},
},
}),
}
objs[resid.NewResId(cmap, "cm1")].AppendRefBy(resid.NewResId(deploy, "deploy1"))
objs[resid.NewResId(secret, "secret1")].AppendRefBy(resid.NewResId(deploy, "deploy1"))
return objs
}
func TestInventoryTransformer(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
// hash is derived based on all keys in the ConfigMap data field.
// It is added to annotations as
// current: hash
// When seeing the same annotation, prune binary assumes no
// clean up is needed
hash := "k777d7h45b"
// This is the root or inventory object which tracks all
// the applied resources - this is the thing we expect the transformer to create.
pruneMap := rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "pruneCM",
"namespace": "default",
"annotations": map[string]interface{}{
"current": hash,
},
},
"data": map[string]interface{}{
"_ConfigMap__cm1": hash,
"_Secret__secret1": hash,
"apps_Deployment__deploy1": hash,
"_ConfigMap__cm1---apps_Deployment__deploy1": hash,
"_Secret__secret1---apps_Deployment__deploy1": hash,
},
})
expected := resmap.ResMap{
resid.NewResIdWithPrefixNamespace(cmap, "pruneCM", "", "default"): pruneMap,
}
p := &types.Inventory{
Type: "ConfigMap",
ConfigMap: types.NameArgs{
Name: "pruneCM",
Namespace: "default",
},
}
objs := makeResMap()
// include the original resmap; only return the ConfigMap for pruning
tran := NewInventoryTransformer(p, "default", false)
tran.Transform(objs)
if !reflect.DeepEqual(objs, expected) {
err := expected.ErrorIfNotEqual(objs)
t.Fatalf("actual doesn't match expected: %v", err)
}
objs = makeResMap()
expected = objs.DeepCopy(rf)
expected[resid.NewResIdWithPrefixNamespace(cmap, "pruneCM", "", "default")] = pruneMap
// append the ConfigMap for pruning to the original resmap
tran = NewInventoryTransformer(p, "default", true)
tran.Transform(objs)
if !reflect.DeepEqual(objs, expected) {
err := expected.ErrorIfNotEqual(objs)
t.Fatalf("actual doesn't match expected: %v", err)
}
}

View File

@@ -0,0 +1,174 @@
/*
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 patch
import (
"encoding/json"
"fmt"
"github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// patchTransformer applies patches.
type patchTransformer struct {
patches []*resource.Resource
rf *resource.Factory
}
var _ transformers.Transformer = &patchTransformer{}
// NewPatchTransformer constructs a patchTransformer.
func NewPatchTransformer(
slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) {
if len(slice) == 0 {
return transformers.NewNoOpTransformer(), nil
}
return &patchTransformer{patches: slice, rf: rf}, nil
}
// Transform apply the patches on top of the base resources.
func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error {
// Merge and then index the patches by Id.
patches, err := pt.mergePatches()
if err != nil {
return err
}
// Strategic merge the resources exist in both base and patches.
for _, patch := range patches {
// Merge patches with base resource.
id := patch.Id()
matchedIds := baseResourceMap.GetMatchingIds(id.GvknEquals)
if len(matchedIds) == 0 {
return fmt.Errorf("failed to find an object with %s to apply the patch", id.GvknString())
}
if len(matchedIds) > 1 {
return fmt.Errorf("found multiple objects %#v targeted by patch %#v (ambiguous)", matchedIds, id)
}
id = matchedIds[0]
base := baseResourceMap[id]
merged := map[string]interface{}{}
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk()))
baseName := base.GetName()
switch {
case runtime.IsNotRegisteredError(err):
// Use JSON merge patch to handle types w/o schema
baseBytes, err := json.Marshal(base.Map())
if err != nil {
return err
}
patchBytes, err := json.Marshal(patch.Map())
if err != nil {
return err
}
mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
if err != nil {
return err
}
err = json.Unmarshal(mergedBytes, &merged)
if err != nil {
return err
}
case err != nil:
return err
default:
// Use Strategic-Merge-Patch to handle types w/ schema
// TODO: Change this to use the new Merge package.
// Store the name of the base object, because this name may have been munged.
// Apply this name to the patched object.
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
if err != nil {
return err
}
merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
base.Map(),
patch.Map(),
lookupPatchMeta)
if err != nil {
return err
}
}
base.SetName(baseName)
baseResourceMap[id].SetMap(merged)
}
return nil
}
// mergePatches merge and index patches by Id.
// It errors out if there is conflict between patches.
func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) {
rc := resmap.ResMap{}
for ix, patch := range pt.patches {
id := patch.Id()
existing, found := rc[id]
if !found {
rc[id] = patch
continue
}
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk()))
if err != nil && !runtime.IsNotRegisteredError(err) {
return nil, err
}
var cd conflictDetector
if err != nil {
cd = newJMPConflictDetector(pt.rf)
} else {
cd, err = newSMPConflictDetector(versionedObj, pt.rf)
if err != nil {
return nil, err
}
}
conflict, err := cd.hasConflict(existing, patch)
if err != nil {
return nil, err
}
if conflict {
conflictingPatch, err := cd.findConflict(ix, pt.patches)
if err != nil {
return nil, err
}
return nil, fmt.Errorf(
"conflict between %#v and %#v",
conflictingPatch.Map(), patch.Map())
}
merged, err := cd.mergePatches(existing, patch)
if err != nil {
return nil, err
}
rc[id] = merged
}
return rc, nil
}
// toSchemaGvk converts to a schema.GroupVersionKind.
func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind {
return schema.GroupVersionKind{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}

View File

@@ -0,0 +1,563 @@
/*
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 patch
import (
"reflect"
"strings"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
var rf = resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
var foo = gvk.Gvk{Group: "example.com", Version: "v1", Kind: "Foo"}
func TestOverlayRun(t *testing.T) {
base := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx",
},
},
},
},
},
}),
}
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"another-label": "foo",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:latest",
"env": []interface{}{
map[string]interface{}{
"name": "SOMEENV",
"value": "BAR",
},
},
},
},
},
},
},
},
),
}
expected := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
"another-label": "foo",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:latest",
"env": []interface{}{
map[string]interface{}{
"name": "SOMEENV",
"value": "BAR",
},
},
},
},
},
},
},
}),
}
lt, err := NewPatchTransformer(patch, rf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = lt.Transform(base)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(base, expected) {
err = expected.ErrorIfNotEqual(base)
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestMultiplePatches(t *testing.T) {
base := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx",
},
},
},
},
},
}),
}
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:latest",
"env": []interface{}{
map[string]interface{}{
"name": "SOMEENV",
"value": "BAR",
},
},
},
},
},
},
},
},
),
rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"env": []interface{}{
map[string]interface{}{
"name": "ANOTHERENV",
"value": "HELLO",
},
},
},
map[string]interface{}{
"name": "busybox",
"image": "busybox",
},
},
},
},
},
},
),
}
expected := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:latest",
"env": []interface{}{
map[string]interface{}{
"name": "ANOTHERENV",
"value": "HELLO",
},
map[string]interface{}{
"name": "SOMEENV",
"value": "BAR",
},
},
},
map[string]interface{}{
"name": "busybox",
"image": "busybox",
},
},
},
},
},
}),
}
lt, err := NewPatchTransformer(patch, rf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = lt.Transform(base)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(base, expected) {
err = expected.ErrorIfNotEqual(base)
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestMultiplePatchesWithConflict(t *testing.T) {
base := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx",
},
},
},
},
},
}),
}
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:latest",
"env": []interface{}{
map[string]interface{}{
"name": "SOMEENV",
"value": "BAR",
},
},
},
},
},
},
},
},
),
rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"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 := NewPatchTransformer(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(), "conflict") {
t.Fatalf("expected error to contain %q but get %v", "conflict", err)
}
}
func TestNoSchemaOverlayRun(t *testing.T) {
base := resmap.ResMap{
resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"A": "X",
"B": "Y",
},
},
}),
}
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"B": nil,
"C": "Z",
},
},
},
),
}
expected := resmap.ResMap{
resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"A": "X",
"C": "Z",
},
},
}),
}
lt, err := NewPatchTransformer(patch, rf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = lt.Transform(base)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqual(base); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestNoSchemaMultiplePatches(t *testing.T) {
base := resmap.ResMap{
resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"A": "X",
"B": "Y",
},
},
}),
}
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"B": nil,
"C": "Z",
},
},
},
),
rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"C": "Z",
"D": "W",
},
"baz": map[string]interface{}{
"hello": "world",
},
},
},
),
}
expected := resmap.ResMap{
resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"A": "X",
"C": "Z",
"D": "W",
},
"baz": map[string]interface{}{
"hello": "world",
},
},
}),
}
lt, err := NewPatchTransformer(patch, rf)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = lt.Transform(base)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqual(base); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) {
base := resmap.ResMap{
resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"A": "X",
"B": "Y",
},
},
}),
}
patch := []*resource.Resource{
rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"B": nil,
"C": "Z",
},
},
}),
rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "my-foo",
},
"spec": map[string]interface{}{
"bar": map[string]interface{}{
"C": "NOT_Z",
},
},
}),
}
lt, err := NewPatchTransformer(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(), "conflict") {
t.Fatalf("expected error to contain %q but get %v", "conflict", err)
}
}

View File

@@ -0,0 +1,137 @@
/*
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 patch
import (
"encoding/json"
"github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/mergepatch"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"sigs.k8s.io/kustomize/pkg/resource"
)
type conflictDetector interface {
hasConflict(patch1, patch2 *resource.Resource) (bool, error)
findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error)
mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error)
}
type jsonMergePatch struct {
rf *resource.Factory
}
var _ conflictDetector = &jsonMergePatch{}
func newJMPConflictDetector(rf *resource.Factory) conflictDetector {
return &jsonMergePatch{rf: rf}
}
func (jmp *jsonMergePatch) hasConflict(
patch1, patch2 *resource.Resource) (bool, error) {
return mergepatch.HasConflicts(patch1.Map(), patch2.Map())
}
func (jmp *jsonMergePatch) findConflict(
conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) {
for i, patch := range patches {
if i == conflictingPatchIdx {
continue
}
if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) {
continue
}
conflict, err := mergepatch.HasConflicts(
patch.Map(),
patches[conflictingPatchIdx].Map())
if err != nil {
return nil, err
}
if conflict {
return patch, nil
}
}
return nil, nil
}
func (jmp *jsonMergePatch) mergePatches(
patch1, patch2 *resource.Resource) (*resource.Resource, error) {
baseBytes, err := json.Marshal(patch1.Map())
if err != nil {
return nil, err
}
patchBytes, err := json.Marshal(patch2.Map())
if err != nil {
return nil, err
}
mergedBytes, err := jsonpatch.MergeMergePatches(baseBytes, patchBytes)
if err != nil {
return nil, err
}
mergedMap := make(map[string]interface{})
err = json.Unmarshal(mergedBytes, &mergedMap)
return jmp.rf.FromMap(mergedMap), err
}
type strategicMergePatch struct {
lookupPatchMeta strategicpatch.LookupPatchMeta
rf *resource.Factory
}
var _ conflictDetector = &strategicMergePatch{}
func newSMPConflictDetector(
versionedObj runtime.Object,
rf *resource.Factory) (conflictDetector, error) {
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err
}
func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) {
return strategicpatch.MergingMapsHaveConflicts(
p1.Map(), p2.Map(), smp.lookupPatchMeta)
}
func (smp *strategicMergePatch) findConflict(
conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) {
for i, patch := range patches {
if i == conflictingPatchIdx {
continue
}
if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) {
continue
}
conflict, err := strategicpatch.MergingMapsHaveConflicts(
patch.Map(),
patches[conflictingPatchIdx].Map(),
smp.lookupPatchMeta)
if err != nil {
return nil, err
}
if conflict {
return patch, nil
}
}
return nil, nil
}
func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) {
mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
return smp.rf.FromMap(mergeJSONMap), err
}

View File

@@ -0,0 +1,61 @@
/*
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 validator provides functions to validate labels, annotations, namespace using apimachinery
package validator
import (
"errors"
apivalidation "k8s.io/apimachinery/pkg/api/validation"
v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
)
// KustValidator validates Labels and annotations by apimachinery
type KustValidator struct{}
// NewKustValidator returns a KustValidator object
func NewKustValidator() *KustValidator {
return &KustValidator{}
}
// MakeAnnotationValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeAnnotationValidator() func(map[string]string) error {
return func(x map[string]string) error {
errs := apivalidation.ValidateAnnotations(x, field.NewPath("field"))
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// MakeLabelValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeLabelValidator() func(map[string]string) error {
return func(x map[string]string) error {
errs := v1validation.ValidateLabels(x, field.NewPath("field"))
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// ValidateNamespace validates a string is a valid namespace using apimachinery.
func (v *KustValidator) ValidateNamespace(s string) []string {
return validation.IsDNS1123Label(s)
}

View File

@@ -19,14 +19,10 @@ package main
import (
"os"
"github.com/golang/glog"
"sigs.k8s.io/kustomize/pkg/commands"
)
func main() {
defer glog.Flush()
if err := commands.NewDefaultCommand().Execute(); err != nil {
os.Exit(1)
}

View File

@@ -0,0 +1,161 @@
/*
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 accumulator
import (
"fmt"
"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"
)
// ResAccumulator accumulates resources and the rules
// used to customize those resources.
type ResAccumulator struct {
resMap resmap.ResMap
tConfig *config.TransformerConfig
varSet types.VarSet
}
func MakeEmptyAccumulator() *ResAccumulator {
ra := &ResAccumulator{}
ra.resMap = make(resmap.ResMap)
ra.tConfig = &config.TransformerConfig{}
ra.varSet = types.VarSet{}
return ra
}
// ResMap returns a copy of the internal resMap.
func (ra *ResAccumulator) ResMap() resmap.ResMap {
result := make(resmap.ResMap)
for k, v := range ra.resMap {
result[k] = v
}
return result
}
// Vars returns a copy of underlying vars.
func (ra *ResAccumulator) Vars() []types.Var {
return ra.varSet.Set()
}
func (ra *ResAccumulator) MergeResourcesWithErrorOnIdCollision(
resources resmap.ResMap) (err error) {
ra.resMap, err = resmap.MergeWithErrorOnIdCollision(
resources, ra.resMap)
return err
}
func (ra *ResAccumulator) MergeResourcesWithOverride(
resources resmap.ResMap) (err error) {
ra.resMap, err = resmap.MergeWithOverride(
ra.resMap, resources)
return err
}
func (ra *ResAccumulator) MergeConfig(
tConfig *config.TransformerConfig) (err error) {
ra.tConfig, err = ra.tConfig.Merge(tConfig)
return err
}
func (ra *ResAccumulator) GetTransformerConfig() *config.TransformerConfig {
return ra.tConfig
}
func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
return ra.varSet.MergeSlice(incoming)
}
func (ra *ResAccumulator) MergeAccumulator(other *ResAccumulator) (err error) {
err = ra.MergeResourcesWithErrorOnIdCollision(other.resMap)
if err != nil {
return err
}
err = ra.MergeConfig(other.tConfig)
if err != nil {
return err
}
return ra.varSet.MergeSet(&other.varSet)
}
// makeVarReplacementMap returns a map of Var names to
// their final values. The values are strings intended
// for substitution wherever the $(var.Name) occurs.
func (ra *ResAccumulator) makeVarReplacementMap() (map[string]string, error) {
result := map[string]string{}
for _, v := range ra.Vars() {
matched := ra.resMap.GetMatchingIds(
resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name).GvknEquals)
if len(matched) > 1 {
return nil, fmt.Errorf(
"found %d resId matches for var %s "+
"(unable to disambiguate)",
len(matched), v)
}
if len(matched) == 1 {
s, err := ra.resMap[matched[0]].GetFieldValue(v.FieldRef.FieldPath)
if err != nil {
return nil, fmt.Errorf(
"field specified in var '%v' "+
"not found in corresponding resource", v)
}
result[v.Name] = s
} else {
return nil, fmt.Errorf(
"var '%v' cannot be mapped to a field "+
"in the set of known resources", v)
}
}
return result, nil
}
func (ra *ResAccumulator) Transform(t transformers.Transformer) error {
return t.Transform(ra.resMap)
}
func (ra *ResAccumulator) ResolveVars() error {
replacementMap, err := ra.makeVarReplacementMap()
if err != nil {
return err
}
if len(replacementMap) == 0 {
return nil
}
t := transformers.NewRefVarTransformer(
replacementMap, ra.tConfig.VarReference)
err = ra.Transform(t)
if len(t.UnusedVars()) > 0 {
log.Printf(
"well-defined vars that were never replaced: %s\n",
strings.Join(t.UnusedVars(), ","))
}
return err
}
func (ra *ResAccumulator) FixBackReferences() (err error) {
if ra.tConfig.NameReference == nil {
return nil
}
return ra.Transform(transformers.NewNameReferenceTransformer(
ra.tConfig.NameReference))
}

View File

@@ -0,0 +1,284 @@
/*
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 accumulator_test
import (
"bytes"
"log"
"os"
"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/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/kustomize/pkg/types"
)
func makeResAccumulator() (*ResAccumulator, *resource.Factory, error) {
ra := MakeEmptyAccumulator()
err := ra.MergeConfig(config.MakeDefaultConfig())
if err != nil {
return nil, nil, err
}
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
ra.MergeResourcesWithErrorOnIdCollision(resmap.ResMap{
resid.NewResId(
gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"},
"deploy1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"command": []interface{}{
"myserver",
"--somebackendService $(SERVICE_ONE)",
"--yetAnother $(SERVICE_TWO)",
},
},
},
},
},
},
}),
resid.NewResId(
gvk.Gvk{Version: "v1", Kind: "Service"},
"backendOne"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "backendOne",
},
}),
resid.NewResId(
gvk.Gvk{Version: "v1", Kind: "Service"},
"backendTwo"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "backendTwo",
},
}),
})
return ra, rf, nil
}
func TestResolveVarsHappy(t *testing.T) {
ra, _, err := makeResAccumulator()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "backendOne"},
},
{
Name: "SERVICE_TWO",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "backendTwo"},
},
})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.ResolveVars()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
c := getCommand(find("deploy1", ra.ResMap()))
if c != "myserver --somebackendService backendOne --yetAnother backendTwo" {
t.Fatalf("unexpected command: %s", c)
}
}
func TestResolveVarsOneUnused(t *testing.T) {
ra, _, err := makeResAccumulator()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "backendOne"},
},
{
Name: "SERVICE_UNUSED",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "backendTwo"},
},
})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
var buf bytes.Buffer
log.SetOutput(&buf)
defer func() {
log.SetOutput(os.Stderr)
}()
err = ra.ResolveVars()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
expectLog(t, buf, "well-defined vars that were never replaced: SERVICE_UNUSED")
c := getCommand(find("deploy1", ra.ResMap()))
if c != "myserver --somebackendService backendOne --yetAnother $(SERVICE_TWO)" {
t.Fatalf("unexpected command: %s", c)
}
}
func expectLog(t *testing.T, log bytes.Buffer, expect string) {
if !strings.Contains(log.String(), expect) {
t.Fatalf("expected log containing '%s', got '%s'", expect, log.String())
}
}
func TestResolveVarsVarNeedsDisambiguation(t *testing.T) {
ra, rf, err := makeResAccumulator()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
ra.MergeResourcesWithErrorOnIdCollision(resmap.ResMap{
resid.NewResIdWithPrefixNamespace(
gvk.Gvk{Version: "v1", Kind: "Service"},
"backendOne", "", "fooNamespace"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "backendOne",
},
}),
})
err = ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "backendOne",
},
},
})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.ResolveVars()
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(
err.Error(), "unable to disambiguate") {
t.Fatalf("unexpected err: %v", err)
}
}
func TestResolveVarsGoodResIdBadField(t *testing.T) {
ra, _, err := makeResAccumulator()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.MergeVars([]types.Var{
{
Name: "SERVICE_ONE",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "backendOne"},
FieldRef: types.FieldSelector{FieldPath: "nope_nope_nope"},
},
})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.ResolveVars()
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(
err.Error(),
"not found in corresponding resource") {
t.Fatalf("unexpected err: %v", err)
}
}
func TestResolveVarsUnmappableVar(t *testing.T) {
ra, _, err := makeResAccumulator()
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.MergeVars([]types.Var{
{
Name: "SERVICE_THREE",
ObjRef: types.Target{
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
Name: "doesNotExist"},
},
})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = ra.ResolveVars()
if err == nil {
t.Fatalf("expected error")
}
if !strings.Contains(
err.Error(),
"cannot be mapped to a field in the set of known resources") {
t.Fatalf("unexpected err: %v", err)
}
}
func find(name string, resMap resmap.ResMap) *resource.Resource {
for k, v := range resMap {
if k.Name() == name {
return v
}
}
return nil
}
// Assumes arg is a deployment, returns the command of first container.
func getCommand(r *resource.Resource) string {
var m map[string]interface{}
var c []interface{}
m, _ = r.Map()["spec"].(map[string]interface{})
m, _ = m["template"].(map[string]interface{})
m, _ = m["spec"].(map[string]interface{})
c, _ = m["containers"].([]interface{})
m, _ = c[0].(map[string]interface{})
return strings.Join(m["command"].([]string), " ")
}

View File

@@ -1,330 +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 app implements state for the set of all resources being customized.
// Should rename this - there's nothing "app"y about it.
package app
import (
"bytes"
"encoding/json"
"fmt"
"github.com/ghodss/yaml"
"github.com/golang/glog"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/crds"
"sigs.k8s.io/kustomize/pkg/fs"
interror "sigs.k8s.io/kustomize/pkg/internal/error"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/patch"
patchtransformer "sigs.k8s.io/kustomize/pkg/patch/transformer"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/types"
)
// Application implements the guts of the kustomize 'build' command.
// TODO: Change name, as "application" is overloaded and somewhat
// misleading (one can customize an RBAC policy). Perhaps "Target"
// https://github.com/kubernetes-sigs/kustomize/blob/master/docs/glossary.md#target
type Application struct {
kustomization *types.Kustomization
ldr loader.Loader
fSys fs.FileSystem
}
// NewApplication returns a new instance of Application primed with a Loader.
func NewApplication(ldr loader.Loader, fSys fs.FileSystem) (*Application, error) {
content, err := ldr.Load(constants.KustomizationFileName)
if err != nil {
return nil, err
}
var m types.Kustomization
err = unmarshal(content, &m)
if err != nil {
return nil, err
}
return &Application{kustomization: &m, ldr: ldr, fSys: fSys}, nil
}
func unmarshal(y []byte, o interface{}) error {
j, err := yaml.YAMLToJSON(y)
if err != nil {
return err
}
dec := json.NewDecoder(bytes.NewReader(j))
dec.DisallowUnknownFields()
return dec.Decode(o)
}
// MakeCustomizedResMap creates a ResMap per kustomization instructions.
// The Resources in the returned ResMap are fully customized.
func (a *Application) MakeCustomizedResMap() (resmap.ResMap, error) {
m, err := a.loadCustomizedResMap()
if err != nil {
return nil, err
}
return a.resolveRefsToGeneratedResources(m)
}
// resolveRefsToGeneratedResources fixes all name references.
func (a *Application) resolveRefsToGeneratedResources(m resmap.ResMap) (resmap.ResMap, error) {
err := transformers.NewNameHashTransformer().Transform(m)
if err != nil {
return nil, err
}
var r []transformers.Transformer
t, err := transformers.NewDefaultingNameReferenceTransformer()
if err != nil {
return nil, err
}
r = append(r, t)
refVars, err := a.resolveRefVars(m)
if err != nil {
return nil, err
}
t, err = transformers.NewRefVarTransformer(refVars)
if err != nil {
return nil, err
}
r = append(r, t)
err = transformers.NewMultiTransformer(r).Transform(m)
if err != nil {
return nil, err
}
return m, nil
}
// loadCustomizedResMap loads and customizes resources to build a ResMap.
func (a *Application) loadCustomizedResMap() (resmap.ResMap, error) {
errs := &interror.KustomizationErrors{}
result, err := a.loadResMapFromBasesAndResources()
if err != nil {
errs.Append(errors.Wrap(err, "loadResMapFromBasesAndResources"))
}
err = crds.RegisterCRDs(a.ldr, a.kustomization.Crds)
if err != nil {
errs.Append(errors.Wrap(err, "RegisterCRDs"))
}
cms, err := resmap.NewResMapFromConfigMapArgs(
configmapandsecret.NewConfigMapFactory(a.fSys, a.ldr),
a.kustomization.ConfigMapGenerator)
if err != nil {
errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs"))
}
secrets, err := resmap.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(a.fSys, a.ldr.Root()),
a.kustomization.SecretGenerator)
if err != nil {
errs.Append(errors.Wrap(err, "NewResMapFromSecretArgs"))
}
res, err := resmap.MergeWithoutOverride(cms, secrets)
if err != nil {
return nil, errors.Wrap(err, "Merge")
}
result, err = resmap.MergeWithOverride(result, res)
if err != nil {
return nil, err
}
a.kustomization.PatchesStrategicMerge = patch.Append(a.kustomization.PatchesStrategicMerge, a.kustomization.Patches...)
patches, err := resmap.NewResourceSliceFromPatches(a.ldr, a.kustomization.PatchesStrategicMerge)
if err != nil {
errs.Append(errors.Wrap(err, "NewResourceSliceFromPatches"))
}
if len(errs.Get()) > 0 {
return nil, errs
}
var r []transformers.Transformer
t, err := a.newTransformer(patches)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = patchtransformer.NewPatchJson6902Factory(a.ldr).MakePatchJson6902Transformer(a.kustomization.PatchesJson6902)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewImageTagTransformer(a.kustomization.ImageTags)
if err != nil {
return nil, err
}
r = append(r, t)
err = transformers.NewMultiTransformer(r).Transform(result)
if err != nil {
return nil, err
}
return result, nil
}
// Gets Bases and Resources as advertised.
func (a *Application) loadResMapFromBasesAndResources() (resmap.ResMap, error) {
bases, errs := a.loadCustomizedBases()
resources, err := resmap.NewResMapFromFiles(a.ldr, a.kustomization.Resources)
if err != nil {
errs.Append(errors.Wrap(err, "rawResources failed to read Resources"))
}
if len(errs.Get()) > 0 {
return nil, errs
}
return resmap.MergeWithoutOverride(resources, bases)
}
// Loop through the Bases of this kustomization recursively loading resources.
// Combine into one ResMap, demanding unique Ids for each resource.
func (a *Application) loadCustomizedBases() (resmap.ResMap, *interror.KustomizationErrors) {
var list []resmap.ResMap
errs := &interror.KustomizationErrors{}
for _, path := range a.kustomization.Bases {
ldr, err := a.ldr.New(path)
if err != nil {
errs.Append(errors.Wrap(err, "couldn't make ldr for "+path))
continue
}
app, err := NewApplication(ldr, a.fSys)
if err != nil {
errs.Append(errors.Wrap(err, "couldn't make app for "+path))
continue
}
resMap, err := app.loadCustomizedResMap()
if err != nil {
errs.Append(errors.Wrap(err, "SemiResources"))
continue
}
ldr.Cleanup()
list = append(list, resMap)
}
result, err := resmap.MergeWithoutOverride(list...)
if err != nil {
errs.Append(errors.Wrap(err, "Merge failed"))
}
return result, errs
}
func (a *Application) loadBasesAsFlatList() ([]*Application, error) {
var result []*Application
errs := &interror.KustomizationErrors{}
for _, path := range a.kustomization.Bases {
ldr, err := a.ldr.New(path)
if err != nil {
errs.Append(err)
continue
}
a, err := NewApplication(ldr, a.fSys)
if err != nil {
errs.Append(err)
continue
}
result = append(result, a)
}
if len(errs.Get()) > 0 {
return nil, errs
}
return result, nil
}
// newTransformer makes a Transformer that does everything except resolve generated names.
func (a *Application) newTransformer(patches []*resource.Resource) (transformers.Transformer, error) {
var r []transformers.Transformer
t, err := transformers.NewPatchTransformer(patches)
if err != nil {
return nil, err
}
r = append(r, t)
r = append(r, transformers.NewNamespaceTransformer(string(a.kustomization.Namespace)))
t, err = transformers.NewDefaultingNamePrefixTransformer(string(a.kustomization.NamePrefix))
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewDefaultingLabelsMapTransformer(a.kustomization.CommonLabels)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewDefaultingAnnotationsMapTransformer(a.kustomization.CommonAnnotations)
if err != nil {
return nil, err
}
r = append(r, t)
return transformers.NewMultiTransformer(r), nil
}
func (a *Application) resolveRefVars(m resmap.ResMap) (map[string]string, error) {
result := map[string]string{}
vars, err := a.getAllVars()
if err != nil {
return result, err
}
for _, v := range vars {
id := resource.NewResId(v.ObjRef.GroupVersionKind(), v.ObjRef.Name)
if r, found := m.DemandOneMatchForId(id); found {
s, err := r.GetFieldValue(v.FieldRef.FieldPath)
if err != nil {
return nil, fmt.Errorf("failed to resolve referred var: %+v", v)
}
result[v.Name] = s
} else {
glog.Infof("couldn't resolve v: %v", v)
}
}
return result, nil
}
// getAllVars returns all the "environment" style Var instances defined in the app.
func (a *Application) getAllVars() ([]types.Var, error) {
var result []types.Var
errs := &interror.KustomizationErrors{}
bases, err := a.loadBasesAsFlatList()
if err != nil {
return nil, err
}
// TODO: computing vars and resources for bases can be combined
for _, b := range bases {
vars, err := b.getAllVars()
if err != nil {
errs.Append(err)
continue
}
b.ldr.Cleanup()
result = append(result, vars...)
}
for _, v := range a.kustomization.Vars {
v.Defaulting()
result = append(result, v)
}
if len(errs.Get()) > 0 {
return nil, errs
}
return result, nil
}

View File

@@ -1,263 +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 app
import (
"encoding/base64"
"reflect"
"strings"
"testing"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
const (
kustomizationContent1 = `
namePrefix: foo-
namespace: ns1
commonLabels:
app: nginx
commonAnnotations:
note: This is a test annotation
resources:
- deployment.yaml
- namespace.yaml
configMapGenerator:
- name: literalConfigMap
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
secretGenerator:
- name: secret
commands:
DB_USERNAME: "printf admin"
DB_PASSWORD: "printf somepw"
type: Opaque
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: dply1
path: jsonpatch.json
`
kustomizationContent2 = `
secretGenerator:
- name: secret
timeoutSeconds: 1
commands:
USER: "sleep 2"
type: Opaque
`
deploymentContent = `apiVersion: apps/v1
metadata:
name: dply1
kind: Deployment
`
namespaceContent = `apiVersion: v1
kind: Namespace
metadata:
name: ns1
`
jsonpatchContent = `[
{"op": "add", "path": "/spec/replica", "value": "3"}
]`
)
func makeLoader1(t *testing.T) loader.Loader {
ldr := loadertest.NewFakeLoader("/testpath")
err := ldr.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
err = ldr.AddFile("/testpath/deployment.yaml", []byte(deploymentContent))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
err = ldr.AddFile("/testpath/namespace.yaml", []byte(namespaceContent))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
err = ldr.AddFile("/testpath/jsonpatch.json", []byte(jsonpatchContent))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
return ldr
}
var deploy = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}
var cmap = schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"}
var secret = schema.GroupVersionKind{Version: "v1", Kind: "Secret"}
var ns = schema.GroupVersionKind{Version: "v1", Kind: "Namespace"}
func TestResources1(t *testing.T) {
expected := resmap.ResMap{
resource.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-dply1",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"spec": map[string]interface{}{
"replica": "3",
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"labels": map[string]interface{}{
"app": "nginx",
},
},
},
},
}),
resource.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "foo-literalConfigMap-mc92bgcbh5",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"creationTimestamp": nil,
},
"data": map[string]interface{}{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}).SetBehavior(resource.BehaviorCreate),
resource.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "foo-secret-877fcfhgt5",
"namespace": "ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"creationTimestamp": nil,
},
"type": string(corev1.SecretTypeOpaque),
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).SetBehavior(resource.BehaviorCreate),
resource.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "foo-ns1",
"labels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
}),
}
l := makeLoader1(t)
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/")
app, err := NewApplication(l, fakeFs)
if err != nil {
t.Fatalf("Unexpected construction error %v", err)
}
actual, err := app.MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected Resources error %v", err)
}
if !reflect.DeepEqual(actual, expected) {
err = expected.ErrorIfNotEqual(actual)
t.Fatalf("unexpected inequality: %v", err)
}
}
func TestResourceNotFound(t *testing.T) {
l := loadertest.NewFakeLoader("/testpath")
err := l.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/")
app, err := NewApplication(l, fakeFs)
if err != nil {
t.Fatalf("Unexpected construction error %v", err)
}
_, err = app.MakeCustomizedResMap()
if err == nil {
t.Fatalf("Didn't get the expected error for an unknown resource")
}
if !strings.Contains(err.Error(), `cannot read file "/testpath/deployment.yaml"`) {
t.Fatalf("Unpexpected error message %q", err)
}
}
func TestSecretTimeout(t *testing.T) {
l := loadertest.NewFakeLoader("/testpath")
err := l.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent2))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/")
app, err := NewApplication(l, fakeFs)
if err != nil {
t.Fatalf("Unexpected construction error %v", err)
}
_, err = app.MakeCustomizedResMap()
if err == nil {
t.Fatalf("Didn't get the expected error for an unknown resource")
}
if !strings.Contains(err.Error(), "killed") {
t.Fatalf("Unpexpected error message %q", err)
}
}

View File

@@ -1,175 +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 commands
import (
"fmt"
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
)
// 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 addMetadataOptions struct {
metadata map[string]string
mapValidator validators.MapValidatorFunc
kind kindOfAdd
}
// newCmdAddAnnotation adds one or more commonAnnotations to the kustomization file.
func newCmdAddAnnotation(fSys fs.FileSystem, v validators.MapValidatorFunc) *cobra.Command {
var o addMetadataOptions
o.kind = annotation
o.mapValidator = v
cmd := &cobra.Command{
Use: "annotation",
Short: "Adds one or more commonAnnotations to " + constants.KustomizationFileName,
Example: `
add annotation {annotationKey1:annotationValue1},{annotationKey2:annotationValue2}`,
RunE: func(cmd *cobra.Command, args []string) error {
return o.runE(args, fSys, o.addAnnotations)
},
}
return cmd
}
// newCmdAddLabel adds one or more commonLabels to the kustomization file.
func newCmdAddLabel(fSys fs.FileSystem, v validators.MapValidatorFunc) *cobra.Command {
var o addMetadataOptions
o.kind = label
o.mapValidator = v
cmd := &cobra.Command{
Use: "label",
Short: "Adds one or more commonLabels to " + constants.KustomizationFileName,
Example: `
add label {labelKey1:labelValue1},{labelKey2:labelValue2}`,
RunE: func(cmd *cobra.Command, args []string) error {
return o.runE(args, fSys, o.addLabels)
},
}
return cmd
}
func (o *addMetadataOptions) runE(
args []string, fSys fs.FileSystem, adder func(*types.Kustomization) error) error {
err := o.validateAndParse(args)
if err != nil {
return err
}
kf, err := newKustomizationFile(constants.KustomizationFileName, fSys)
if err != nil {
return err
}
m, err := kf.read()
if err != nil {
return err
}
err = adder(m)
if err != nil {
return err
}
return kf.write(m)
}
// validateAndParse validates `add` commands and parses them into o.metadata
func (o *addMetadataOptions) 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.convertToMap(args[0])
if err != nil {
return err
}
if err = o.mapValidator(m); err != nil {
return err
}
o.metadata = m
return nil
}
func (o *addMetadataOptions) convertToMap(arg string) (map[string]string, error) {
result := make(map[string]string)
inputs := strings.Split(arg, ",")
for _, input := range inputs {
kv := strings.Split(input, ":")
if len(kv[0]) < 1 {
return nil, o.makeError(input, "empty key")
}
if len(kv) > 2 {
return nil, o.makeError(input, "too many colons")
}
if len(kv) > 1 {
result[kv[0]] = kv[1]
} else {
result[kv[0]] = ""
}
}
return result, nil
}
func (o *addMetadataOptions) addAnnotations(m *types.Kustomization) error {
if m.CommonAnnotations == nil {
m.CommonAnnotations = make(map[string]string)
}
return o.writeToMap(m.CommonAnnotations, annotation)
}
func (o *addMetadataOptions) addLabels(m *types.Kustomization) error {
if m.CommonLabels == nil {
m.CommonLabels = make(map[string]string)
}
return o.writeToMap(m.CommonLabels, label)
}
func (o *addMetadataOptions) writeToMap(m map[string]string, kind kindOfAdd) error {
for k, v := range o.metadata {
if _, ok := m[k]; ok {
return fmt.Errorf("%s %s already in kustomization file", kind, k)
}
m[k] = v
}
return nil
}
func (o *addMetadataOptions) makeError(input string, message string) error {
return fmt.Errorf("invalid %s: %s (%s)", o.kind, input, message)
}

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