Compare commits

...

153 Commits

Author SHA1 Message Date
Jingfang Liu
6f82073d4b Merge pull request #133 from Liujingfang1/loader
Add glob support
2018-06-27 15:20:01 -07:00
Jingfang Liu
2a3f09a2f0 Add integration test for glob support 2018-06-27 14:48:50 -07:00
Jingfang Liu
6392e6629f Add glob support 2018-06-27 10:54:12 -07:00
Jingfang Liu
c25ed7f7bc Merge pull request #137 from babiel/add-cronjob-to-refvars
Add CronJob to refvars transformer
2018-06-26 10:02:38 -07:00
Jingfang Liu
918247d2cc Merge pull request #138 from guineveresaenger/secret-docs
Adds example for secret download using curl
2018-06-26 10:02:01 -07:00
Maximilian Gaß
2a06a174e8 Add CronJob to refvars transformer 2018-06-26 12:20:52 +02:00
guineveresaenger
54e8a014bc Adds example for secret download using curl
It is possible to download secrets from web locations, as the command subfield can execute any terminal command specified.
This is a useful feature that should be highlighted.
2018-06-25 16:39:29 -07:00
Jingfang Liu
5b67b580f2 Merge pull request #129 from fanzhangio/issue114
Enhancement for format error message
2018-06-25 10:33:36 -07:00
fanzhangio
6a67183ed7 Enhancement for format error message
- add yaml format error handler
- silent usage when build command fails
2018-06-25 07:35:43 -07:00
Jingfang Liu
a38befdaa1 Merge pull request #132 from Liujingfang1/order
correct ordering of the k8s objects
2018-06-22 10:33:31 -07:00
Jingfang Liu
0312cdf677 Merge pull request #130 from sethpollack/image-pull-secret
add imagePullSecrets namerefs
2018-06-22 10:22:33 -07:00
Jingfang Liu
991ffbbdfc populate the map from a slice 2018-06-22 10:19:41 -07:00
Seth Pollack
bbd29d9dc1 add test 2018-06-21 23:17:03 -04:00
Jingfang Liu
28953e03a0 Merge pull request #120 from guineveresaenger/edit-add-base
New command: kustomize edit add base
2018-06-21 16:54:15 -07:00
guineveresaenger
37489ec2e9 Adds ability to add multiple base directories to kustomization 2018-06-21 16:39:46 -07:00
Jingfang Liu
636ab874eb update failed test 2018-06-21 16:36:27 -07:00
Jingfang Liu
90d16c2377 correct ordering of the k8s objects:
NameSpace, CRD, ServiceAccount, Role, ClusterRole, RoleBinding,
ClusterRoleBinding
2018-06-21 16:21:31 -07:00
Seth Pollack
5d24dda28a add imagePullSecrets namerefs 2018-06-20 23:23:31 -04:00
Jingfang Liu
dec5109e31 Merge pull request #127 from Liujingfang1/master
remove extra package comment on crds
2018-06-20 13:23:41 -07:00
Jingfang Liu
cc8690381c remove extra package comment on crds 2018-06-20 13:22:17 -07:00
Jingfang Liu
f5f95e3692 Merge pull request #125 from Liujingfang1/order
put namespace objects first in the output
2018-06-19 16:10:48 -07:00
Jingfang Liu
809d5b1fe2 put namespace objects first in the output 2018-06-19 15:44:33 -07:00
Jingfang Liu
38b4365ab3 Merge pull request #121 from traherom/master
Jobs do not create a selector if not already present
2018-06-19 14:22:15 -07:00
Jingfang Liu
d865300fdb Merge pull request #105 from Liujingfang1/crdsupport
Add support for CRDs
2018-06-19 12:04:35 -07:00
Jingfang Liu
e2677cdc8a Merge pull request #123 from Liujingfang1/master
Add variable reference to pod command,args,env
2018-06-19 12:04:06 -07:00
Jingfang Liu
ea00134776 Update pathconfigs library
implement CRD support and add unit tests

Add integration test for crd support

address comments
2018-06-19 11:45:53 -07:00
Jingfang Liu
ad3cd47c25 Add variable reference to pod command,args,env 2018-06-19 11:25:58 -07:00
guineveresaenger
a1dcf3386b Adds kustomize edit add base command
This pull request adds support for editing the kustomization.yaml in the current directory with a base.
2018-06-19 10:09:13 -07:00
Jingfang Liu
e7ecceb0c2 Update vendor 2018-06-19 09:36:30 -07:00
Ryan Morehart
50c40eb80c CronJob transformation fixed
- no longer add labels in an invalid location (#116)
- only have selector added it already present
2018-06-19 06:14:05 -06:00
Ryan Morehart
398ceb0a92 Jobs do not create a selector if not already present 2018-06-18 17:09:23 -06:00
Jingfang Liu
b7be630924 Merge pull request #113 from uthark/unparam
Enable unparam linter and fix found issues
2018-06-18 11:55:57 -07:00
Oleg Atamanenko
f557841e54 Enable unparam linter and fix issues 2018-06-18 14:49:57 -04:00
Jingfang Liu
9fc24634a2 Merge pull request #115 from woop/patch-1
Update example to show correct environment
2018-06-15 12:35:12 -07:00
Jingfang Liu
0617a283a0 Merge pull request #111 from Liujingfang1/master
Add variable reference to container env
2018-06-15 11:20:25 -07:00
Willem Pienaar
f616e30a38 Update example to show correct environment 2018-06-15 23:27:16 +08:00
Jingfang Liu
50b197f329 Merge pull request #110 from uthark/gometalinter
Add gometalinter to pre-commit hook
2018-06-14 18:52:59 -07:00
Oleg Atamanenko
6fd0330b80 Add gometalinter to pre-commit hook
Enable varcheck and fix found issues

Add ineffassign to list of checks and fix found issues

Added nakedret and fixed found issues

Add interfacer check and fix found issue

Add lll and fix found issues

Add deadcode linter, remove unused code
2018-06-14 20:55:20 -04:00
Jingfang Liu
8127b09d12 Merge pull request #73 from guineveresaenger/example-docfix
Clarifies hello-world example documentation
2018-06-14 15:24:25 -07:00
Jingfang Liu
09ab2bb5c0 Add variable reference to container env 2018-06-14 13:38:58 -07:00
Sunil Arora
54ac4e73e7 Merge pull request #108 from Liujingfang1/args
Add variable reference support for args
2018-06-13 14:51:46 -07:00
Jeff Regan
d4ad7f80e0 Merge pull request #104 from monopole/renameExamplesToTestData
Rename examples dir to examplelayout.
2018-06-12 15:07:14 -07:00
Jeffrey Regan
623e21d1c0 Rename examples dir to examplelayout. 2018-06-12 15:03:45 -07:00
Jeff Regan
0c88c43c67 Merge pull request #102 from monopole/upgradeCrypto
Replace deprecated crypto/md5 with crypto/sha256
2018-06-12 13:51:10 -07:00
Jeffrey Regan
c6d8bcb01b Replace deprecated crypto/md5 with crypto/sha256 2018-06-12 13:47:22 -07:00
Jeff Regan
5285e6101f Merge pull request #101 from monopole/moveVersion
Move version.go to commands dir.
2018-06-12 13:10:00 -07:00
Jeffrey Regan
2fb69db685 Move version.go to commands dir. 2018-06-12 13:08:23 -07:00
guineveresaenger
730597b77e grepping for kiwi 2018-06-12 10:33:37 -07:00
guineveresaenger
d488d9804d grepping for configMap name 2018-06-12 10:29:25 -07:00
Jeff Regan
f98bc42cbb Merge pull request #99 from monopole/tempCaptureExec
Absorb exec package from k8s.io/utils.
2018-06-12 09:46:14 -07:00
Jeffrey Regan
d7b9f64c5a Absorb exec package from utils. 2018-06-12 09:22:07 -07:00
Jeff Regan
785291af62 Merge pull request #95 from Liujingfang1/crdsupport
Add skeleton for CRD support
2018-06-12 09:21:10 -07:00
Jingfang Liu
4f05482e00 Add support for CRDs 2018-06-11 21:52:13 -07:00
Jeff Regan
3c3f85e623 Merge pull request #96 from monopole/secContacts
Fixes #33; add SECURITY_CONTACTS
2018-06-11 19:32:10 -07:00
jregan
40bb81142b Fixes #33; add SECURITY_CONTACTS 2018-06-11 19:30:13 -07:00
Jeff Regan
5563f1529b Update README.md 2018-06-11 15:20:20 -07:00
Jeff Regan
a95b26182a Merge pull request #93 from Liujingfang1/configmaps
make generated configmaps composable
2018-06-11 15:04:43 -07:00
Jingfang Liu
934e37d781 add unit test and address comments 2018-06-11 14:52:31 -07:00
Jeff Regan
40bad7783f Merge pull request #94 from monopole/addTODO
Add TODO referencing bug
2018-06-11 14:44:32 -07:00
Jeffrey Regan
44696d5fb9 Add TODO referencing bug 2018-06-11 14:43:22 -07:00
Jeff Regan
9d268de5a0 Merge pull request #90 from Liujingfang1/master
Add README.md for wordpress to show variable reference usage
2018-06-11 14:13:23 -07:00
Jingfang Liu
46e8fd7065 Add variable reference support for args 2018-06-11 13:57:34 -07:00
Jingfang Liu
ab0c9b4118 address comments 2018-06-11 13:52:18 -07:00
guineveresaenger
4e7610a44d Addresses review comments 2018-06-11 12:35:33 -07:00
Jingfang Liu
37720765fc Add a test case 2018-06-11 12:18:26 -07:00
Jingfang Liu
09e64e5991 Merge pull request #81 from sethpollack/skip
refactor namespaces to use PathConfig
2018-06-11 12:08:35 -07:00
Jingfang Liu
e017d04a16 make generated configmaps composable 2018-06-11 12:07:16 -07:00
Jingfang Liu
b6efde13eb Add README.md for wordpress to show variable reference usage 2018-06-11 11:41:09 -07:00
Seth Pollack
f774172927 refactor namespaces to use PathConfig 2018-06-11 14:16:04 -04:00
Jeff Regan
9459665c96 Merge pull request #70 from Liujingfang1/crds
Skip adding nameprefix for CRD
2018-06-11 11:05:05 -07:00
Jeff Regan
7fb4eaec60 Merge pull request #89 from monopole/maybeReduceNameConfusion
Some cleanup refactoring in app package.
2018-06-11 10:34:32 -07:00
jregan
211cda054e Some cleanup refactoring in app package. 2018-06-11 09:51:03 -07:00
Jingfang Liu
5f75564ff5 Skip adding nameprefix for CRD 2018-06-11 09:22:18 -07:00
Jeff Regan
6b5569d5ed Merge pull request #82 from vreon/ingress-tls-secretname
Add Ingress spec.tls.secretName to Secret namerefs
2018-06-10 20:15:52 -07:00
Jeff Regan
e20edaf41e Merge pull request #83 from uthark/returnerror
Return error along with a resource
2018-06-10 20:14:48 -07:00
Jeff Regan
d934a28caf Merge pull request #84 from monopole/troubleWithRawResources
Add more test coverage for RawResources.
2018-06-10 20:14:22 -07:00
jregan
e002b69ffa Add more test coverage for RawResources. 2018-06-10 20:09:31 -07:00
Oleg Atamanenko
bdad67c3ef Return error along with a resource 2018-06-10 21:57:30 -04:00
Jesse Dubay
92864ba0f7 Add Ingress spec.tls.secretName to Secret namerefs 2018-06-10 16:26:50 -07:00
Jeff Regan
ba45b1366a Merge pull request #80 from monopole/fixNameOfPatchTransformer
Rename OverlayTranformer to PatchTransformer.
2018-06-10 11:29:37 -07:00
jregan
d06620c74d Rename OverlayTranformer to PatchTransformer. 2018-06-10 11:23:47 -07:00
Jeff Regan
4f3f76addd Merge pull request #78 from uthark/gocyclo
Fixed gocyclo warnings and added pre-commit hook
2018-06-10 11:11:48 -07:00
Jeff Regan
71b7e07b02 Merge pull request #77 from uthark/golint
Fix go lint error and add golint checks to a pre-commit hook
2018-06-10 10:35:56 -07:00
Jeff Regan
27f652ae8e Merge pull request #76 from monopole/reduceUnstructNoise
Reduce unstruct notation noise in Resource construction.
2018-06-10 09:46:53 -07:00
Oleg Atamanenko
5c8d82aed0 Fixed gocyclo warnings and added pre-commit hook 2018-06-09 23:43:42 -04:00
Oleg Atamanenko
c994130005 Fix go lint error and add golint checks to a pre-commit hook 2018-06-09 23:05:26 -04:00
jregan
ccd255f323 Reduce unstruct notation noise in Resource construction. 2018-06-09 08:10:57 -07:00
Jeff Regan
2b05d39067 Merge pull request #75 from monopole/yada
Handle arb length paths in GetFieldName
2018-06-08 16:24:59 -07:00
Jeffrey Regan
de65503177 Handle arb length paths in GetFieldName 2018-06-08 15:07:57 -07:00
guineveresaenger
5a3c6553fc Clarifies hello-world example documentation
The example documentation had a few minor discrepancies between commands suggested and expected outcomes. This pull request addresses those, making it easier for folks to use the hello-world demo.
2018-06-08 13:27:20 -07:00
Jeff Regan
7c4ca21578 Merge pull request #71 from sethpollack/namespaces
add namespace to the doc
2018-06-08 12:58:31 -07:00
Jeff Regan
efcc167c35 Merge pull request #72 from Liujingfang1/master
Add wordpress example for demonstrating variable reference
2018-06-08 12:58:01 -07:00
Jingfang Liu
1f8e56a210 Add wordpress example for demonstrating variable reference 2018-06-08 11:49:42 -07:00
Seth Pollack
fa8d6f08e2 add namespace to the doc 2018-06-08 12:47:52 -04:00
Jeff Regan
900ac005dd Merge pull request #66 from monopole/reduceIndirection
Reduce indirection in code w/r to the unstruct types.
2018-06-08 08:59:47 -07:00
jregan
a42c72b2e0 Reduce indirection. 2018-06-07 21:53:55 -07:00
Jeff Regan
a82bd23f8f Merge pull request #52 from Liujingfang1/master
variable reference support
2018-06-06 16:43:48 -07:00
Jeff Regan
ea24b3795c Merge pull request #64 from monopole/docErrorPackage
Doc the error package.
2018-06-06 14:43:56 -07:00
Jingfang Liu
95f568b857 add comments in refvar transformer
Refactor change
2018-06-06 14:42:18 -07:00
Jeffrey Regan
708cd7ef17 Doc the error package. 2018-06-06 14:41:43 -07:00
Jeff Regan
ed7261ca01 Merge pull request #63 from monopole/packageDoc
Improve package structure and documentation.
2018-06-06 14:18:31 -07:00
Jeff Regan
8a27162d98 Merge pull request #62 from sethpollack/ingress
add namerefs for ingress
2018-06-06 14:17:29 -07:00
Jeffrey Regan
2e0e43cd76 Improve package doc. 2018-06-06 14:15:50 -07:00
Jeff Regan
ba2866645e Merge pull request #60 from sethpollack/initContainers
add namerefs for initContainers
2018-06-06 14:04:42 -07:00
Jeff Regan
fd2ee6034b Merge pull request #59 from sethpollack/hpa
add namerefs for hpa
2018-06-06 14:03:15 -07:00
Jeff Regan
86241dfd98 Merge pull request #58 from sethpollack/labels
add PodDisruptionBudget labels
2018-06-06 14:01:11 -07:00
Jingfang Liu
1a28f3a391 Address comments: add unit tests, defaulting and update comment 2018-06-06 10:21:15 -07:00
Jingfang Liu
35344c163a Add test case for variable reference 2018-06-06 09:30:12 -07:00
Jingfang Liu
526ba2df0c add varialber reference support 2018-06-06 09:30:12 -07:00
Seth Pollack
db15bc6372 add namerefs for ingress 2018-06-06 12:17:54 -04:00
Seth Pollack
c83b7019f5 add namerefs for initContainers 2018-06-06 12:04:49 -04:00
Seth Pollack
08e2a1047b add namerefs for hpa 2018-06-06 11:24:12 -04:00
Seth Pollack
69d816d5ab add PodDisruptionBudget labels 2018-06-05 22:02:35 -04:00
Jeff Regan
ea2d2c9db1 Merge pull request #56 from Liujingfang1/expansion
Add expansion package
2018-06-05 17:31:40 -07:00
Jingfang Liu
c7ef8a7e4d Add expansion package 2018-06-05 17:04:53 -07:00
Jeff Regan
9bda5cf092 Merge pull request #54 from sethpollack/namespace
kustomize namespace
2018-06-05 16:22:48 -07:00
Seth Pollack
815db033cb add namespace.yaml 2018-06-05 18:41:48 -04:00
Seth Pollack
501e1a406d add regression coverage 2018-06-05 15:32:22 -04:00
Seth Pollack
6e54814b6d kustomize namespace 2018-06-04 22:35:03 -04:00
Jeff Regan
df2407ad3f Merge pull request #49 from monopole/removeAnotherUtil
Remove util and privatize selectByGvk
2018-06-01 14:20:29 -07:00
Jeffrey Regan
d0c6a824c8 Remove util and privatize selectByGvk 2018-06-01 14:17:56 -07:00
Jeff Regan
57f3743be8 Merge pull request #47 from monopole/introduceResourceMap
Introduce ResId and ResMap in resmap package.
2018-06-01 14:02:46 -07:00
jregan
ef71cb478f Introduce ResId and ResMap. 2018-06-01 13:56:43 -07:00
Jeff Regan
9a5c0f5a25 Merge pull request #46 from monopole/dropUtilPackage
Drop the util package.
2018-05-31 17:24:36 -07:00
Jeffrey Regan
0e2c71cd6f Drop the util package. 2018-05-31 17:17:41 -07:00
Jeff Regan
0b3ab31248 Merge pull request #45 from monopole/createDiffPackage
Create and document diff package.
2018-05-31 16:57:11 -07:00
Jeffrey Regan
49f586af39 Create and document diff package. 2018-05-31 16:50:34 -07:00
Jeff Regan
487a6ebee4 Merge pull request #43 from monopole/fixLinkInHelp
Fix URL in help message
2018-05-31 14:18:11 -07:00
Jeff Regan
bee9490129 Merge pull request #44 from monopole/constantsCleanup
Document constants package.
2018-05-31 14:17:54 -07:00
Jeffrey Regan
8afba0b56c Document constants package. 2018-05-31 13:42:03 -07:00
jregan
16fa3403a4 Fix kubernetes-sigs/kustomize#40 2018-05-30 20:28:46 -07:00
Jeff Regan
bcb89ee908 Merge pull request #39 from guineveresaenger/no-secret
Removes help text for `kustomize edit add secret`
2018-05-30 10:11:01 -07:00
Jeff Regan
37f03b4d01 Merge pull request #37 from ahmetb/mv-examples
demos --> examples
2018-05-30 10:08:44 -07:00
guineveresaenger
bc144275b4 Removes help text for kustomize edit add secret
There is currently no support for adding a secret with kustomize. The help text should not show such an option.
Fixes #14.
2018-05-29 10:27:18 -07:00
Ahmet Alp Balkan
7086e4f974 demos --> examples
examples/ is pretty standard whereas demos/ isn't. So I just refactored that.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-05-25 10:07:46 -07:00
Jeff Regan
4d111436aa Merge pull request #35 from monopole/baseOverlayNotes
Base overlay notes
2018-05-24 17:08:24 -07:00
Jeffrey Regan
1583486546 base overlay notes 2018-05-24 17:07:19 -07:00
Jeff Regan
10b4c5db43 Merge pull request #34 from monopole/updateReadme
update readmes
2018-05-24 14:16:13 -07:00
Jeffrey Regan
5a54c96203 update readmes 2018-05-24 14:13:10 -07:00
Jeff Regan
4a5b82333b Merge pull request #31 from droot/release-instructions
add instructions for publishing a release
2018-05-24 10:51:08 -07:00
Sunil Arora
e3934ee69c add instructions for publishing a release 2018-05-23 14:20:09 -07:00
Jeff Regan
24daa9e3dc Merge pull request #29 from monopole/updateReadme
Update README with file layout
2018-05-23 10:06:04 -07:00
Jeffrey Regan
d9b422cc54 Update README with file layout 2018-05-23 10:05:11 -07:00
Jeff Regan
d62fb53472 Merge pull request #28 from monopole/updateworkflow
Update workflow doc
2018-05-22 16:53:47 -07:00
Jeffrey Regan
00e52095d6 Update workflow doc 2018-05-22 16:53:07 -07:00
Jeff Regan
9c6d31d70e Merge pull request #2 from rajatjindal/patch-1
Update README.md
2018-05-22 14:40:14 -07:00
Jeff Regan
a734b96560 Merge pull request #26 from monopole/newFigs
betterFigs
2018-05-22 12:21:25 -07:00
Jeffrey Regan
8f3fe7d4bd betterFigs 2018-05-22 12:21:02 -07:00
Jeff Regan
5f950813c4 Merge pull request #25 from monopole/removeLastInstanceUsage
use variant in figure
2018-05-22 12:15:12 -07:00
Jeffrey Regan
920f53853b use variant in figure 2018-05-22 12:14:33 -07:00
Sunil Arora
2f6e7ecfbe Merge pull request #24 from droot/add-goreleaser-config
add goreleaser config file
2018-05-21 15:01:57 -07:00
Sunil Arora
c8ac9c763f add goreleaser config file 2018-05-21 14:58:13 -07:00
Rajat Jindal
aa88a0563b Update README.md 2018-05-14 13:53:13 -07:00
528 changed files with 68262 additions and 4766 deletions

View File

@@ -12,6 +12,8 @@ before_install:
- go get -u golang.org/x/tools/cmd/goimports
- go get -u github.com/onsi/ginkgo/ginkgo
- 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
# Install must be set to prevent default `go get` to run.
# The dependencies have already been vendored by `dep` so

View File

@@ -16,7 +16,7 @@
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 [demos](demos) directory.
the pattern established in the [examples](examples) directory.
Run `bin/pre-commit.sh` to test your demo.
1. Submit a pull request.

184
Gopkg.lock generated
View File

@@ -1,12 +1,33 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/PuerkitoBio/purell"
packages = ["."]
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/PuerkitoBio/urlesc"
packages = ["."]
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
[[projects]]
name = "github.com/davecgh/go-spew"
packages = ["spew"]
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
name = "github.com/emicklei/go-restful"
packages = [
".",
"log"
]
revision = "3658237ded108b4134956c1b3050349d93e7b895"
version = "v2.7.1"
[[projects]]
name = "github.com/evanphx/json-patch"
packages = ["."]
@@ -19,9 +40,36 @@
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
version = "v1.0.0"
[[projects]]
branch = "master"
name = "github.com/go-openapi/jsonpointer"
packages = ["."]
revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2"
[[projects]]
branch = "master"
name = "github.com/go-openapi/jsonreference"
packages = ["."]
revision = "3fb327e6747da3043567ee86abd02bb6376b6be2"
[[projects]]
branch = "master"
name = "github.com/go-openapi/spec"
packages = ["."]
revision = "bcff419492eeeb01f76e77d2ebc714dc97b607f5"
[[projects]]
branch = "master"
name = "github.com/go-openapi/swag"
packages = ["."]
revision = "811b1089cde9dad18d4d0c2d09fbdbf28dbd27a5"
[[projects]]
name = "github.com/gogo/protobuf"
packages = ["proto","sortkeys"]
packages = [
"proto",
"sortkeys"
]
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
version = "v1.0.0"
@@ -33,7 +81,13 @@
[[projects]]
name = "github.com/golang/protobuf"
packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"]
packages = [
"proto",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/timestamp"
]
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
version = "v1.1.0"
@@ -45,7 +99,11 @@
[[projects]]
name = "github.com/googleapis/gnostic"
packages = ["OpenAPIv2","compiler","extensions"]
packages = [
"OpenAPIv2",
"compiler",
"extensions"
]
revision = "ee43cbb60db7bd22502942cccbc39059117352ab"
version = "v0.1.0"
@@ -61,6 +119,16 @@
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
version = "1.1.3"
[[projects]]
branch = "master"
name = "github.com/mailru/easyjson"
packages = [
"buffer",
"jlexer",
"jwriter"
]
revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485"
[[projects]]
name = "github.com/modern-go/concurrent"
packages = ["."]
@@ -73,6 +141,12 @@
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
version = "1.0.0"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
name = "github.com/spf13/cobra"
packages = ["."]
@@ -88,12 +162,33 @@
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["http/httpguts","http2","http2/hpack","idna"]
packages = [
"http/httpguts",
"http2",
"http2/hpack",
"idna"
]
revision = "2491c5de3490fced2f6cff376127c667efeed857"
[[projects]]
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"]
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"
]
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
@@ -112,13 +207,75 @@
[[projects]]
branch = "master"
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"]
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"
]
revision = "53d615ae3f440f957cb9989d989d597f047262d9"
[[projects]]
branch = "master"
name = "k8s.io/apimachinery"
packages = ["pkg/api/resource","pkg/apis/meta/v1","pkg/apis/meta/v1/unstructured","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"]
packages = [
"pkg/api/resource",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
"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"
]
revision = "13b73596e4b63e03203e86f6d9c7bcc1b937c62f"
[[projects]]
@@ -130,18 +287,15 @@
[[projects]]
branch = "master"
name = "k8s.io/kube-openapi"
packages = ["pkg/util/proto"]
packages = [
"pkg/common",
"pkg/util/proto"
]
revision = "b3f03f55328800731ce03a164b80973014ecd455"
[[projects]]
branch = "master"
name = "k8s.io/utils"
packages = ["exec"]
revision = "258e2a2fa64568210fbd6267cf1d8fd87c3cb86e"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "6e36daa1798b0dae7f45160f9275ca6bbe6c5667de7cd808d0057cbaf19fc55e"
inputs-digest = "586d4cb9094e9b5c0731f16e931b953e9c0f709b7125a7537ae3625ada179eee"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -52,3 +52,7 @@
[[constraint]]
branch = "master"
name = "k8s.io/utils"
[[constraint]]
branch = "master"
name = "github.com/go-openapi/spec"

27
INSTALL.md Normal file
View File

@@ -0,0 +1,27 @@
[release page]: https://github.com/kubernetes-sigs/kustomize/releases
[Go]: https://golang.org
## Installation
Download a binary from the [release page].
Or try this to grab the latest official release
using the command line:
```
opsys=linux # or darwin, or windows
curl -s https://api.github.com/repos/kubernetes-sigs/kustomize/releases/latest |\
grep browser_download |\
grep $opsys |\
cut -d '"' -f 4 |\
xargs curl -O -L
mv kustomize_*_${opsys}_amd64 kustomize
chmod u+x kustomize
```
To install from head with [Go] v1.10.1 or higher:
<!-- @installkustomize @test -->
```
go get github.com/kubernetes-sigs/kustomize
```

166
README.md
View File

@@ -1,71 +1,141 @@
# kustomize
[applied]: docs/glossary.md#apply
[base]: docs/glossary.md#base
[declarative configuration]: docs/glossary.md#declarative-application-management
[demo]: demos/README.md
[demos]: demos/README.md
[imageBase]: docs/base.jpg
[imageOverlay]: docs/overlay.jpg
[kubernetes style]: docs/glossary.md#kubernetes-style-object
[KEP]: https://github.com/kubernetes/community/blob/master/keps/sig-cli/0008-kustomize.md
[kustomization]: docs/glossary.md#kustomization
[overlay]: docs/glossary.md#overlay
[resources]: docs/glossary.md#resource
[sig-cli]: https://github.com/kubernetes/community/blob/master/sig-cli/README.md
[workflows]: docs/workflows.md
`kustomize` lets you customize raw, template-free YAML
files for multiple purposes, leaving the original YAML
untouched and usable as is.
`kustomize` is a command line tool supporting
template-free customization of YAML (or JSON) objects
that conform to the [kubernetes style]. If your
objects have a `kind` and a `metadata` field,
`kustomize` can patch them to support configuration
sharing and re-use.
For more details, try a [demo].
`kustomize` targets kubernetes; it understands and can
patch [kubernetes style] API objects. It's like
[`make`], in that what it does is declared in a file,
and it's like [`sed`], in that it emits editted text.
[![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)
## Installation
This assumes [Go](https://golang.org/) (v1.10.1 or higher)
is installed and your `PATH` contains `$GOPATH/bin`:
<!-- @installkustomize @test -->
```
go get github.com/kubernetes-sigs/kustomize
```
**Installation**: Download a binary from the [release
page], or see these [install] notes. Then try one of
the tested [examples].
## Usage
#### 1) Make a base
A [base] configuration is a [kustomization] file listing a set of
k8s [resources] - deployments, services, configmaps,
secrets that serve some common purpose.
### 1) Make a [kustomization] file
In some directory containing your YAML [resource]
files (deployments, services, configmaps, etc.), create a
[kustomization] file.
This file should declare those resources, and any
customization to apply to them, e.g. _add a common
label_.
![base image][imageBase]
#### 2) Customize it with overlays
File structure:
An [overlay] customizes your base along different dimensions
for different purposes or different teams, e.g. for
_development, staging and production_.
> ```
> ~/someApp
> ├── deployment.yaml
> ├── kustomization.yaml
> └── service.yaml
> ```
The resources in this directory could be a fork of
someone else's configuration. If so, you can easily
rebase from the source material to capture
improvements, because you don't modify the resources
directly.
Generate customized YAML with:
```
kustomize build ~/someApp
```
The YAML can be directly [applied] to a cluster:
> ```
> kustomize build ~/someApp | kubectl apply -f -
> ```
### 2) Create [variants] using [overlays]
Manage traditional [variants] of a configuration - like
_development_, _staging_ and _production_ - using
[overlays] that modify a common [base].
![overlay image][imageOverlay]
#### 3) Run kustomize
File structure:
> ```
> ~/someApp
> ├── base
> │   ├── deployment.yaml
> │   ├── kustomization.yaml
> │   └── service.yaml
> └── overlays
> ├── development
> │   ├── cpu_count.yaml
> │   ├── kustomization.yaml
> │   └── replica_count.yaml
> └── production
> ├── cpu_count.yaml
> ├── kustomization.yaml
> └── replica_count.yaml
> ```
Run `kustomize` on your overlay. The result
is printed to `stdout` as a set of complete
resources, ready to be [applied] to a cluster.
See the [demos].
Take the work from step (1) above, move it into a
`someApp` subdirectory called `base`, then
place overlays in a sibling directory.
An overlay is just another kustomization, refering to
the base, and referring to patches to apply to that
base.
This arrangement makes it easy to manage your
configuration with `git`. The base could have files
from an upstream repository managed by someone else.
The overlays could be in a repository you own.
Arranging the repo clones as siblings on disk avoids
the need for git submodules (though that works fine, if
you are a submodule fan).
Generate YAML with
```sh
kustomize build ~/someApp/overlays/production
```
The YAML can be directly [applied] to a cluster:
> ```sh
> kustomize build ~/someApp/overlays/production | kubectl apply -f -
> ```
## About
This project sponsored by [sig-cli] ([KEP]).
This tool is sponsored by [sig-cli] ([KEP]).
[KEP]: https://github.com/kubernetes/community/blob/master/keps/sig-cli/0008-kustomize.md
[`make`]: https://www.gnu.org/software/make
[`sed`]: https://www.gnu.org/software/sed
[applied]: docs/glossary.md#apply
[base]: docs/glossary.md#base
[declarative configuration]: docs/glossary.md#declarative-application-management
[examples]: examples/README.md
[imageBase]: docs/base.jpg
[imageOverlay]: docs/overlay.jpg
[install]: INSTALL.md
[kubernetes style]: docs/glossary.md#kubernetes-style-object
[kustomization]: docs/glossary.md#kustomization
[overlay]: docs/glossary.md#overlay
[overlays]: docs/glossary.md#overlay
[release page]: https://github.com/kubernetes-sigs/kustomize/releases
[resource]: docs/glossary.md#resource
[resources]: docs/glossary.md#resource
[sig-cli]: https://github.com/kubernetes/community/blob/master/sig-cli/README.md
[variant]: docs/glossary.md#variant
[variants]: docs/glossary.md#variant
[workflows]: docs/workflows.md

15
SECURITY_CONTACTS Normal file
View File

@@ -0,0 +1,15 @@
# Defined below are the security contacts for this repo.
#
# They are the contact point for the Product Security Team to reach out
# to for triaging and handling of incoming issues.
#
# The below names agree to abide by the
# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy)
# and will be removed and replaced if they violate that agreement.
#
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
# INSTRUCTIONS AT https://kubernetes.io/security/
monopole
Liujingfang1
pwittrock

View File

@@ -1,4 +1,5 @@
#!/bin/bash
set -e
# Make sure, we run in the root of the repo and
# therefore run the tests on all packages
@@ -31,10 +32,33 @@ function testGoFmt {
diff <(echo -n) <(go_dirs | xargs -0 gofmt -s -d -l)
}
function testGoImports {
diff -u <(echo -n) <(go_dirs | xargs -0 goimports -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 )
}
function testGoMetalinter {
diff -u <(echo -n) <(go_dirs | xargs -0 gometalinter.v2 --disable-all --deadline 5m \
--enable=misspell \
--enable=structcheck \
--enable=deadcode \
--enable=goimports \
--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 ./...
}
@@ -43,14 +67,22 @@ function testGoTest {
go test -v ./...
}
function testDemos {
mdrip --mode test --label test README.md ./demos
function testExamples {
mdrip --mode test --label test README.md ./examples
}
runTest testGoFmt
runTest testGoImports
runTest testGoMetalinter
runTest testGoLint
runTest testGoVet
runTest testGoCyclo
runTest testGoTest
runTest testDemos
runTest testExamples
if [ $rc -eq 0 ]; then
echo "SUCCESS!"
else
echo "FAILURE; exit code $rc"
fi
exit $rc

View File

@@ -1,13 +1,45 @@
## Overview
[releases page]: https://github.com/kubernetes-sigs/kustomize/releases
[`container-builder-local`]: https://github.com/GoogleCloudPlatform/container-builder-local
[Google Container Builder]: https://cloud.google.com/container-builder
This directory contains scripts and configruation files for publishing a
`kustomize` release on [release page](https://github.com/kubernetes-sigs/kustomize/releases)
Scripts and configuration files for publishing a
`kustomize` release on the [releases page].
## Steps to run build a release locally
Install container-builder-local from [github](https://github.com/GoogleCloudPlatform/container-builder-local).
### Build a release locally
```sh
container-builder-local --config=build/cloudbuild_local.yaml --dryrun=false --write-workspace=/tmp/w .
Install [`container-builder-local`], then run
```
container-builder-local \
--config=build/cloudbuild_local.yaml \
--dryrun=false --write-workspace=/tmp/w .
```
You will find the build artifacts under `/tmp/w/dist` directory
to build artifacts under `/tmp/w/dist`.
### Publish a Release
Get on an up-to-date master branch:
```
git checkout master
git fetch upstream
git rebase upstream/master
```
Define the version (see [semver principles](https://semver.org)), e.g.:
```
version=v1.0.3
```
Tag the repo:
```
git tag -a $version -m "$version release"
```
Push the tag upstream:
```
git push upstream $version
```
The new tag will trigger a job in [Google Container
Builder] to put a new release on the [releases page].

33
build/goreleaser.yml Normal file
View File

@@ -0,0 +1,33 @@
# This is an example goreleaser.yaml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
project_name: kustomize
builds:
- main: ./kustomize.go
binary: kustomize
ldflags: -s -X github.com/kubernetes-sigs/kustomize/version.kustomizeVersion={{.Version}} -X github.com/kubernetes-sigs/kustomize/version.gitCommit={{.Commit}} -X github.com/kubernetes-sigs/kustomize/version.buildDate={{.Date}}
goos:
- darwin
- linux
- windows
goarch:
- amd64
env:
- CGO_ENABLED=0
checksum:
name_template: 'checksums.txt'
archive:
format: binary
snapshot:
name_template: "master"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- Merge pull request
- Merge branch
release:
github:
owner: kubernetes-sigs
name: kustomize

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -68,25 +68,17 @@ management in k8s.
A _base_ is a [target] that some [overlay] modifies.
Any target, including an overlay, can be a base to
Any target, including an [overlay], can be a base to
another target.
A base has no knowledge of the overlays that refer to it.
A base is usable in isolation, i.e. one should
be able to [apply] a base to a cluster directly.
For simple [gitops] management, a base configuration
could be the _sole content of a git repository
dedicated to that purpose_. Same with [overlays].
Changes in a repo could generate a build, test and
deploy cycle.
Some of the demos for [kustomize] will break from this
idiom and store all demo config files in directories
_next_ to the `kustomize` code so that the code and
demos can be more easily maintained by the same group
of people.
## bespoke configuration
@@ -162,10 +154,10 @@ It's often abbreviated as _k8s_.
An object, expressed in a YAML or JSON file, with the
[fields required] by kubernetes. Basically just a
`kind` field to identify the type, a `metadata/name`
field to identify the variant, and an `apiVersion`
field to identify the version (if there's more than one
version).
_kind_ field to identify the type, a _metadata/name_
field to identify the particular instance, and an
_apiVersion_ field to identify the version (if there's
more than one version).
## kustomize
@@ -210,19 +202,24 @@ An _overlay_ is a [target] that modifies (and thus
depends on) another target.
The [kustomization] in an overlay refers to (via file
path, URI or other method) _some other kustomization_,
path, URI or other method) some other kustomization,
known as its [base].
An overlay is unusable without its base.
An overlay supports the typical notion of a
_development_, _QA_, _staging_ and _production_
environment variants.
An overlay may act as a base to another overlay.
The configuration of these environments is specified in
individual overlays (one per environment) that all
refer to a common base that holds common configuration.
One configures the cluster like this:
Overlays make the most sense when there is _more than
one_, because they create different [variants] of a
common base - e.g. _development_, _QA_, _staging_ and
_production_ environment variants.
These variants use the same overall resources, and vary
in relatively simple ways, e.g. the number of replicas
in a deployment, the CPU to a particular pod, the data
source used in a configmap, etc.
One configures a cluster like this:
> ```
> kustomize build someapp/overlays/staging |\
@@ -232,10 +229,9 @@ One configures the cluster like this:
> kubectl apply -f -
> ```
Usage of the base is implicit (the overlay's kustomization
points to the base).
Usage of the base is implicit - the overlay's
kustomization points to the base.
An overlay may act as a base to another overlay.
## package
@@ -267,7 +263,7 @@ configmap.
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.
with a _kind_ and a _metadata/name_ field.
A _resource_ in the content of a REST-ful API is the
@@ -290,8 +286,7 @@ The _target_ is the argument to `kustomize build`, e.g.:
> ```
`$target` must be a path to a directory that
immediately contains a file called
`kustomization.yaml` (i.e. a [kustomization]).
immediately contains a [kustomization].
The target contains, or refers to, all the information
needed to create customized resources to send to the
@@ -304,15 +299,15 @@ A target is a [base] or an [overlay].
A _variant_ is the outcome, in a cluster, of applying
an [overlay] to a [base].
> E.g., a _staging_ and _production_ overlay both modify some
> common base to create distinct variants.
>
> The _staging_ variant is the set of resources
> exposed to quality assurance testing, or to some
> external users who'd like to see what the next
> version of production will look like.
>
> The _production_ variant is the set of resources
> exposed to production traffic, and thus may employ
> deployments with a large number of replicas and higher
> cpu and memory requests.
E.g., a _staging_ and _production_ overlay both modify
some common base to create distinct variants.
The _staging_ variant is the set of resources exposed
to quality assurance testing, or to some external users
who'd like to see what the next version of production
will look like.
The _production_ variant is the set of resources
exposed to production traffic, and thus may employ
deployments with a large number of replicas and higher
cpu and memory requests.

View File

@@ -32,6 +32,8 @@
# visible in configuration reviews.
# ----------------------------------------------------
# Adds namespace to all resources.
namespace: my-namespace
# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
@@ -80,6 +82,11 @@ secretGenerator:
tls.crt: "cat secret/tls.cert"
tls.key: "cat secret/tls.key"
type: "kubernetes.io/tls"
- name: downloaded_secret
commands:
username: "curl -s https://path/to/secrets/username.yaml"
password: "curl -s https://path/to/secrets/password.yaml"
type: Opaque
# Each entry in this list should resolve to a directory
# containing a kustomization file, else the
@@ -113,3 +120,19 @@ patches:
- service_port_8888.yaml
- deployment_increase_replicas.yaml
- deployment_increase_memory.yaml
# Each entry in this list should be a relative path to
# a file for custom resource definition(CRD).
#
# 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
# The name reference for this ConfigMap object in CRD object need to be
# updated with namePrefix or hashing in the same way.
crds:
- crds/typeA.yaml
- crds/typeB.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -10,7 +10,7 @@
[patch]: glossary.md#patch
[patches]: glossary.md#patch
[rebase]: https://git-scm.com/docs/git-rebase
[resources]: glossary.md#resources
[resources]: glossary.md#resource
[workflowBespoke]: workflowBespoke.jpg
[workflowOts]: workflowOts.jpg
@@ -64,8 +64,8 @@ specified in the base.
Run kustomize, and pipe the output to [apply].
> ```
> kustomize ~/ldap/overlays/staging | kubectl apply -f -
> kustomize ~/ldap/overlays/production | kubectl apply -f -
> kustomize build ~/ldap/overlays/staging | kubectl apply -f -
> kustomize build ~/ldap/overlays/production | kubectl apply -f -
> ```
@@ -85,13 +85,13 @@ is periodically consulted for updates.
The [base] directory is maintained in a repo whose
upstream is an [OTS] configuration, in this case
https://github.com/kinflate/ldap.
some user's `ldap` repo:
> ```
> mkdir ~/ldap
> git clone https://github.com/$USER/ldap ~/ldap/base
> cd ~/ldap/base
> git remote add upstream git@github.com:kustomize/ldap
> git remote add upstream git@github.com:$USER/ldap
> ```
#### 3) create [overlays]
@@ -107,17 +107,19 @@ The [overlays] are siblings to each other and to the
> mkdir -p ~/ldap/overlays/production
> ```
The user can maintain the `overlays` directory in a
distinct repository.
#### 4) bring up [variants]
> ```
> kustomize ~/ldap/overlays/staging | kubectl apply -f -
> kustomize ~/ldap/overlays/production | kubectl apply -f -
> kustomize build ~/ldap/overlays/staging | kubectl apply -f -
> kustomize build ~/ldap/overlays/production | kubectl apply -f -
> ```
#### 5) (optionally) capture changes from upstream
The user can optionally [rebase] their [base] to
The user can periodically [rebase] their [base] to
capture changes made in the upstream repository.
> ```

View File

@@ -1,7 +1,14 @@
# Demos
# Examples
These demos assume that `kustomize` is on your `$PATH`.
They are covered by pre-submit tests.
These examples assume that `kustomize` is on your `$PATH`.
They are covered by [pre-commit](../bin/pre-commit.sh)
tests, and should work with HEAD
<!-- @installkustomize @test -->
```
go get github.com/kubernetes-sigs/kustomize
```
* [hello world](helloWorld/README.md) - Deploy multiple
(differently configured) variants of a simple Hello
@@ -22,3 +29,5 @@ They are covered by pre-submit tests.
* [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).

View File

@@ -51,7 +51,7 @@ mkdir -p $BASE
curl -s -o "$BASE/#1.yaml" "https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/demos/helloWorld\
/master/examples/helloWorld\
/{configMap,deployment,kustomization,service}.yaml"
```
@@ -112,6 +112,12 @@ sed -i '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 -->
```
@@ -397,7 +403,14 @@ the server will use:
sed -i 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
```
Run kustomize again to see the new names:
See the new greeting:
```
kustomize build $OVERLAYS/staging |\
grep -B 2 -A 3 kiwi
```
Run kustomize again to see the new configMap names:
<!-- @grepStagingName @test -->
```
@@ -413,7 +426,8 @@ uses the map:
<!-- @countHashes @test -->
```
test 3 == \
$(kustomize build $OVERLAYS/staging | grep khk45ktkd9 | wc -l)
$(kustomize build $OVERLAYS/staging | grep khk45ktkd9 | wc -l); \
echo $?
```
Applying these resources to the cluster will result in

View File

@@ -24,7 +24,7 @@
#
# This script assumes that the process running it has
# checked out the kubernetes-sigs/kustomize repo, and
# has cd'ed into it (i.e. the directory above "demos")
# has cd'ed into it (i.e. the directory above "examples")
# before running it.
#
# At time of writing, its 'call point' was in
@@ -79,6 +79,6 @@ function runTest {
setUpEnv
pushd demos
pushd examples
runTest ldap/integration_test.sh ldap/base
popd

View File

@@ -45,7 +45,7 @@ mkdir -p $BASE
CONTENT="https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/demos/ldap"
/master/examples/ldap"
curl -s -o "$BASE/#1" "$CONTENT/base\
/{deployment.yaml,kustomization.yaml,service.yaml,env.startup.txt}"

View File

@@ -29,7 +29,7 @@ Download them:
```
curl -s -o "$DEMO_HOME/#1.yaml" "https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/demos/mySql\
/master/examples/mySql\
/{deployment,secret,service}.yaml"
```

View File

@@ -31,7 +31,7 @@ Download them:
```
CONTENT="https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/demos/springboot"
/master/examples/springboot"
curl -s -o "$DEMO_HOME/#1.yaml" \
"$CONTENT/base/{deployment,service}.yaml"

View File

@@ -4,7 +4,7 @@ metadata:
name: demo-configmap
data:
application.properties: |
app.name=Staging Kinflate Demo
app.name=Production Kinflate Demo
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://<production_db_ip>:3306/db_example
spring.datasource.username=root

View File

@@ -0,0 +1,144 @@
# 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.
To run WordPress, it's necessary to
- connect WordPress with a MySQL database
- access the service name of MySQL database from WordPress container
First make a place to work:
<!-- @makeDemoHome @test -->
```
DEMO_HOME=$(mktemp -d)
MYSQL_HOME=$DEMO_HOME/mysql
mkdir -p $MYSQL_HOME
WORDPRESS_HOME=$DEMO_HOME/wordpress
mkdir -p $WORDPRESS_HOME
```
### Download resources
Download the resources and `kustomization.yaml` for WordPress.
<!-- @downloadResources @test -->
```
CONTENT="https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/wordpress/wordpress"
curl -s -o "$WORDPRESS_HOME/#1.yaml" \
"$CONTENT/{deployment,service,kustomization}.yaml"
```
Download the resources and `kustomization.yaml` for MySQL.
<!-- @downloadResources @test -->
```
CONTENT="https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/wordpress/mysql"
curl -s -o "$MYSQL_HOME/#1.yaml" \
"$CONTENT/{deployment,service,secret,kustomization}.yaml"
```
### Create kustomization.yaml
Create a new kustomization with two bases:
<!-- @createKustomization @test -->
```
cat <<EOF >$DEMO_HOME/kustomization.yaml
bases:
- wordpress
- mysql
namePrefix: demo-
EOF
```
### Download patch for WordPress
In the new kustomization, apply a patch for wordpress deployment. The patch does two things
- Add an initial container to show the mysql service name
- Add environment variable that allow wordpress to find the mysql database
<!-- @downloadPatch @test -->
```
CONTENT="https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/patch.yaml"
curl -s -o "$DEMO_HOME/#1.yaml" \
"$CONTENT/{patch}.yaml"
```
The patch has following content
> ```
> apiVersion: apps/v1beta2
> kind: Deployment
> metadata:
> name: wordpress
> spec:
> template:
> spec:
> initContainers:
> - name: init-command
> image: debian
> command:
> - "echo $(WORDPRESS_SERVICE)"
> - "echo $(MYSQL_SERVICE)"
> containers:
> - name: wordpress
> env:
> - name: WORDPRESS_DB_HOST
> value: $(MYSQL_SERVICE)
> - name: WORDPRESS_DB_PASSWORD
> valueFrom:
> secretKeyRef:
> name: mysql-pass
> key: password
> ```
The init container's command requires information that depends on k8s resource object fields, represented by the placeholder variables
$(WORDPRESS_SERVICE) and $(MYSQL_SERVICE).
### Bind the Variables to k8s Object Fields
<!-- @addVarRef @test -->
```
cat <<EOF >>$DEMO_HOME/kustomization.yaml
vars:
- name: WORDPRESS_SERVICE
objref:
kind: Service
name: wordpress
apiVersion: v1
fieldref:
fieldpath: metadata.name
- name: MYSQL_SERVICE
objref:
kind: Service
name: mysql
apiVersion: v1
EOF
```
`WORDPRESS_SERVICE` is from the field `metadata.name` of Service `wordpress`. If we don't specify `fieldref`, the default is `metadata.name`. So `MYSQL_SERVICE` is from the field `metadata.name` of Service `mysql`.
### Substitution
Confirm the variable substitution:
<!-- @kustomizeBuild @test -->
```
kustomize build $DEMO_HOME
```
Expect this in the output:
> ```
> (truncated)
> ...
> initContainers:
> - command:
> - echo demo-wordpress
> - echo demo-mysql
> image: debian
> name: init-command
>
> ```

View File

@@ -0,0 +1,19 @@
bases:
- wordpress
- mysql
patches:
- patch.yaml
namePrefix: demo-
vars:
- name: WORDPRESS_SERVICE
objref:
kind: Service
name: wordpress
apiVersion: v1
- name: MYSQL_SERVICE
objref:
kind: Service
name: mysql
apiVersion: v1

View File

@@ -0,0 +1,35 @@
apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
emptyDir: {}

View File

@@ -0,0 +1,4 @@
resources:
- deployment.yaml
- service.yaml
- secret.yaml

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: mysql-pass
type: Opaque
data:
# Default password is "admin".
password: YWRtaW4=

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- port: 3306
selector:
app: mysql

View File

@@ -0,0 +1,23 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: wordpress
spec:
template:
spec:
initContainers:
- name: init-command
image: debian
command:
- "echo $(WORDPRESS_SERVICE)"
- "echo $(MYSQL_SERVICE)"
containers:
- name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: $(MYSQL_SERVICE)
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password

View File

@@ -0,0 +1,29 @@
apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
spec:
containers:
- image: wordpress:4.8-apache
name: wordpress
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
emptyDir: {}

View File

@@ -0,0 +1,3 @@
resources:
- deployment.yaml
- service.yaml

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
type: LoadBalancer

View File

@@ -14,44 +14,40 @@ 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/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/crds"
interror "github.com/kubernetes-sigs/kustomize/pkg/internal/error"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/resmap"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"github.com/kubernetes-sigs/kustomize/pkg/transformers"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/pkg/errors"
)
type Application interface {
// Resources computes and returns the resources for the app.
Resources() (resource.ResourceCollection, error)
// SemiResources computes and returns the resources without name hash and name reference for the app
SemiResources() (resource.ResourceCollection, error)
// RawResources computes and returns the raw resources from the kustomization file.
// It contains resources from
// 1) untransformed resources from current kustomization file
// 2) transformed resources from sub packages
RawResources() (resource.ResourceCollection, error)
}
var _ Application = &applicationImpl{}
// Private implementation of the Application interface
type applicationImpl struct {
// 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
loader loader.Loader
}
// NewApp parses the kustomization file at the path using the loader.
func New(loader loader.Loader) (Application, error) {
// NewApplication returns a new instance of Application primed with a Loader.
func NewApplication(loader loader.Loader) (*Application, error) {
content, err := loader.Load(constants.KustomizationFileName)
if err != nil {
return nil, err
@@ -62,186 +58,7 @@ func New(loader loader.Loader) (Application, error) {
if err != nil {
return nil, err
}
return &applicationImpl{kustomization: &m, loader: loader}, nil
}
// Resources computes and returns the resources from the kustomization file.
// The namehashing for configmap/secrets and resolving name reference is only done
// in the most top overlay once at the end of getting resources.
func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
res, err := a.SemiResources()
if err != nil {
return nil, err
}
t, err := a.getHashAndReferenceTransformer()
if err != nil {
return nil, err
}
err = t.Transform(res)
if err != nil {
return nil, err
}
return res, nil
}
// SemiResources computes and returns the resources without name hash and name reference for the app
func (a *applicationImpl) SemiResources() (resource.ResourceCollection, error) {
errs := &interror.KustomizationErrors{}
raw, err := a.rawResources()
if err != nil {
errs.Append(err)
}
cms, err := resource.NewFromConfigMaps(a.loader, a.kustomization.ConfigMapGenerator)
if err != nil {
errs.Append(err)
}
secrets, err := resource.NewFromSecretGenerators(a.loader.Root(), a.kustomization.SecretGenerator)
if err != nil {
errs.Append(err)
}
res, err := resource.Merge(cms, secrets)
if err != nil {
return nil, err
}
allRes, err := resource.MergeWithOverride(raw, res)
if err != nil {
return nil, err
}
patches, err := resource.NewFromPatches(a.loader, a.kustomization.Patches)
if err != nil {
errs.Append(err)
}
if len(errs.Get()) > 0 {
return nil, errs
}
t, err := a.getTransformer(patches)
if err != nil {
return nil, err
}
err = t.Transform(allRes)
if err != nil {
return nil, err
}
return allRes, nil
}
// RawResources computes and returns the raw resources from the kustomization file.
// The namehashing for configmap/secrets and resolving name reference is only done
// in the most top overlay once at the end of getting resources.
func (a *applicationImpl) RawResources() (resource.ResourceCollection, error) {
res, err := a.rawResources()
if err != nil {
return nil, err
}
t, err := a.getHashAndReferenceTransformer()
if err != nil {
return nil, err
}
err = t.Transform(res)
if err != nil {
return nil, err
}
return res, nil
}
func (a *applicationImpl) rawResources() (resource.ResourceCollection, error) {
subAppResources, errs := a.subAppResources()
resources, err := resource.NewFromResources(a.loader, a.kustomization.Resources)
if err != nil {
errs.Append(err)
}
if len(errs.Get()) > 0 {
return nil, errs
}
return resource.Merge(resources, subAppResources)
}
func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *interror.KustomizationErrors) {
sliceOfSubAppResources := []resource.ResourceCollection{}
errs := &interror.KustomizationErrors{}
for _, pkgPath := range a.kustomization.Bases {
subloader, err := a.loader.New(pkgPath)
if err != nil {
errs.Append(err)
continue
}
subapp, err := New(subloader)
if err != nil {
errs.Append(err)
continue
}
// Gather all transformed resources from subpackages.
subAppResources, err := subapp.SemiResources()
if err != nil {
errs.Append(err)
continue
}
sliceOfSubAppResources = append(sliceOfSubAppResources, subAppResources)
}
allResources, err := resource.Merge(sliceOfSubAppResources...)
if err != nil {
errs.Append(err)
}
return allResources, errs
}
// getTransformer generates the following transformers:
// 1) apply overlay
// 2) name prefix
// 3) apply labels
// 4) apply annotations
func (a *applicationImpl) getTransformer(patches []*resource.Resource) (transformers.Transformer, error) {
ts := []transformers.Transformer{}
ot, err := transformers.NewOverlayTransformer(patches)
if err != nil {
return nil, err
}
ts = append(ts, ot)
npt, err := transformers.NewDefaultingNamePrefixTransformer(string(a.kustomization.NamePrefix))
if err != nil {
return nil, err
}
ts = append(ts, npt)
lt, err := transformers.NewDefaultingLabelsMapTransformer(a.kustomization.CommonLabels)
if err != nil {
return nil, err
}
ts = append(ts, lt)
at, err := transformers.NewDefaultingAnnotationsMapTransformer(a.kustomization.CommonAnnotations)
if err != nil {
return nil, err
}
ts = append(ts, at)
return transformers.NewMultiTransformer(ts), nil
}
// getHashAndReferenceTransformer generates the following transformers:
// 1) name hash for configmap and secrests
// 2) apply name reference
func (a *applicationImpl) getHashAndReferenceTransformer() (transformers.Transformer, error) {
ts := []transformers.Transformer{}
nht := transformers.NewNameHashTransformer()
ts = append(ts, nht)
nrt, err := transformers.NewDefaultingNameReferenceTransformer()
if err != nil {
return nil, err
}
ts = append(ts, nrt)
return transformers.NewMultiTransformer(ts), nil
return &Application{kustomization: &m, loader: loader}, nil
}
func unmarshal(y []byte, o interface{}) error {
@@ -254,3 +71,245 @@ func unmarshal(y []byte, o interface{}) error {
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)
}
// MakeUncustomizedResMap purports to create a ResMap without customization.
// The Resources in the returned ResMap include all resources mentioned
// in the kustomization file and transitively reachable via its Bases,
// and all generated secrets and configMaps.
// Meant for use in generating a diff against customized resources.
// TODO: See https://github.com/kubernetes-sigs/kustomize/issues/85
func (a *Application) MakeUncustomizedResMap() (resmap.ResMap, error) {
m, err := a.loadResMapFromBasesAndResources()
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) {
r := []transformers.Transformer{transformers.NewNameHashTransformer()}
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.loader, a.kustomization.CRDs)
if err != nil {
errs.Append(errors.Wrap(err, "RegisterCRDs"))
}
cms, err := resmap.NewResMapFromConfigMapArgs(a.loader, a.kustomization.ConfigMapGenerator)
if err != nil {
errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs"))
}
secrets, err := resmap.NewResMapFromSecretArgs(a.loader.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
}
patches, err := resmap.NewResourceSliceFromPatches(a.loader, a.kustomization.Patches)
if err != nil {
errs.Append(errors.Wrap(err, "NewResourceSliceFromPatches"))
}
if len(errs.Get()) > 0 {
return nil, errs
}
t, err := a.newTransformer(patches)
if err != nil {
return nil, err
}
err = t.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.loader, 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) {
list := []resmap.ResMap{}
errs := &interror.KustomizationErrors{}
for _, path := range a.kustomization.Bases {
loader, err := a.loader.New(path)
if err != nil {
errs.Append(errors.Wrap(err, "couldn't make loader for "+path))
continue
}
app, err := NewApplication(loader)
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
}
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 {
loader, err := a.loader.New(path)
if err != nil {
errs.Append(err)
continue
}
a, err := NewApplication(loader)
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) {
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[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) {
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
}
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

@@ -18,29 +18,30 @@ package app
import (
"encoding/base64"
"fmt"
"os"
"reflect"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/internal/loadertest"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/loader/loadertest"
"github.com/kubernetes-sigs/kustomize/pkg/resmap"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"github.com/kubernetes-sigs/kustomize/pkg/types"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func setupTest(t *testing.T) loader.Loader {
kustomizationContent := []byte(`
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:
@@ -52,184 +53,288 @@ secretGenerator:
DB_USERNAME: "printf admin"
DB_PASSWORD: "printf somepw"
type: Opaque
`)
deploymentContent := []byte(`apiVersion: apps/v1
kind: Deployment
`
deploymentContent = `apiVersion: apps/v1
metadata:
name: dply1
`)
kind: Deployment
`
namespaceContent = `apiVersion: v1
kind: Namespace
metadata:
name: ns1
`
)
func makeLoader1(t *testing.T) loader.Loader {
loader := loadertest.NewFakeLoader("/testpath")
err := loader.AddFile("/testpath/"+constants.KustomizationFileName, kustomizationContent)
err := loader.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1))
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
err = loader.AddFile("/testpath/deployment.yaml", deploymentContent)
err = loader.AddFile("/testpath/deployment.yaml", []byte(deploymentContent))
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
err = loader.AddFile("/testpath/namespace.yaml", []byte(namespaceContent))
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
return loader
}
func TestResources(t *testing.T) {
expected := resource.ResourceCollection{
types.GroupVersionKindName{
GVK: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
Name: "dply1",
}: &resource.Resource{
Data: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-dply1",
"labels": map[string]interface{}{
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"}
var svc = schema.GroupVersionKind{Version: "v1", Kind: "Service"}
func TestResources1(t *testing.T) {
expected := resmap.ResMap{
resource.NewResId(deploy, "dply1"): 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{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
},
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"note": "This is a test annotation",
},
"labels": 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.NewResId(cmap, "literalConfigMap"): 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",
},
}),
resource.NewResId(secret, "secret"): 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")),
},
}),
resource.NewResId(ns, "ns1"): 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)
app, err := NewApplication(l)
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 TestRawResources1(t *testing.T) {
expected := resmap.ResMap{
resource.NewResId(deploy, "dply1"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "dply1",
},
}),
resource.NewResId(ns, "ns1"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "ns1",
},
}),
}
l := makeLoader1(t)
app, err := NewApplication(l)
if err != nil {
t.Fatalf("Unexpected construction error %v", err)
}
actual, err := app.MakeUncustomizedResMap()
if err != nil {
t.Fatalf("Unexpected RawResources error %v", err)
}
if err := expected.ErrorIfNotEqual(actual); err != nil {
t.Fatalf("unexpected inequality: %v", err)
}
}
const (
kustomizationContentBase = `
namePrefix: foo-
commonLabels:
app: banana
resources:
- deployment.yaml
`
kustomizationContentOverlay = `
commonLabels:
env: staging
resources:
- service.yaml
bases:
- base
`
serviceContent = `apiVersion: v1
kind: Service
metadata:
name: svc
spec:
type: LoadBalancer
`
)
func makeLoader2(t *testing.T) loader.Loader {
loader := loadertest.NewFakeLoader("/testpath")
err := loader.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContentOverlay))
if err != nil {
t.Fatal(err)
}
err = loader.AddFile("/testpath/service.yaml", []byte(serviceContent))
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
err = loader.AddDirectory("/testpath/base", os.ModeDir)
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
err = loader.AddFile("/testpath/base/"+constants.KustomizationFileName, []byte(kustomizationContentBase))
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
err = loader.AddFile("/testpath/base/deployment.yaml", []byte(deploymentContent))
if err != nil {
t.Fatalf("Failed to setup fake loader.")
}
return loader
}
// TODO: This test covers incorrect behavior; it should not pass.
// It asks for raw resources. The Service resource is returned in raw form,
// but the resources in the base are modified to have the banana label,
// the 'foo' name prefix, etc. This method exists only to support the
// diff command comparing customized to non-customized resources;
// perhaps it's not worth supporting the command.
func TestRawResources2(t *testing.T) {
expected := resmap.ResMap{
resource.NewResId(deploy, "dply1"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "foo-dply1",
"labels": map[string]interface{}{
"app": "banana",
},
},
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "banana",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "banana",
},
},
},
},
},
},
types.GroupVersionKindName{
GVK: schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"},
Name: "literalConfigMap",
}: &resource.Resource{
Data: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "foo-literalConfigMap-mc92bgcbh5",
"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",
},
}),
resource.NewResId(svc, "svc"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc",
},
},
},
types.GroupVersionKindName{
GVK: schema.GroupVersionKind{Version: "v1", Kind: "Secret"},
Name: "secret",
}: &resource.Resource{
Data: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "foo-secret-877fcfhgt5",
"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")),
},
"spec": map[string]interface{}{
"type": "LoadBalancer",
},
},
},
}),
}
l := setupTest(t)
app, err := New(l)
l := makeLoader2(t)
app, err := NewApplication(l)
if err != nil {
t.Fatalf("Unexpected error %v", err)
t.Fatalf("Unexpected construction error %v", err)
}
actual, err := app.Resources()
actual, err := app.MakeUncustomizedResMap()
if err != nil {
t.Fatalf("Unexpected error %v", err)
t.Fatalf("Unexpected RawResources error %v", err)
}
if !reflect.DeepEqual(actual, expected) {
err = compareMap(actual, expected)
t.Fatalf("unexpected error: %v", err)
if err := expected.ErrorIfNotEqual(actual); err != nil {
t.Fatalf("unexpected inequality: %v", err)
}
}
func TestRawResources(t *testing.T) {
expected := resource.ResourceCollection{
types.GroupVersionKindName{
GVK: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
Name: "dply1",
}: &resource.Resource{
Data: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "dply1",
},
},
},
},
}
l := setupTest(t)
app, err := New(l)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
actual, err := app.RawResources()
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if err := compareMap(actual, expected); err != nil {
t.Fatalf("unexpected error: %v", err)
}
}
func compareMap(m1, m2 resource.ResourceCollection) error {
if len(m1) != len(m2) {
keySet1 := []types.GroupVersionKindName{}
keySet2 := []types.GroupVersionKindName{}
for GVKn := range m1 {
keySet1 = append(keySet1, GVKn)
}
for GVKn := range m1 {
keySet2 = append(keySet2, GVKn)
}
return fmt.Errorf("maps has different number of entries: %#v doesn't equals %#v", keySet1, keySet2)
}
for GVKn, obj1 := range m1 {
obj2, found := m2[GVKn]
if !found {
return fmt.Errorf("%#v doesn't exist in %#v", GVKn, m2)
}
if !reflect.DeepEqual(obj1, obj2) {
return fmt.Errorf("%#v doesn't match %#v", obj1, obj2)
}
}
return nil
}

99
pkg/commands/addbase.go Normal file
View File

@@ -0,0 +1,99 @@
/*
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 (
"errors"
"fmt"
"strings"
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
type addBaseOptions struct {
baseDirectoryPaths string
}
// newCmdAddBase adds the file path of the kustomize base to the kustomization file.
func newCmdAddBase(fsys fs.FileSystem) *cobra.Command {
var o addBaseOptions
cmd := &cobra.Command{
Use: "base",
Short: "Adds one or more bases to the kustomization.yaml in current directory",
Example: `
add base {filepath1},{filepath2}`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
if err != nil {
return err
}
err = o.Complete(cmd, args)
if err != nil {
return err
}
return o.RunAddBase(fsys)
},
}
return cmd
}
// Validate validates addBase command.
func (o *addBaseOptions) Validate(args []string) error {
if len(args) != 1 {
return errors.New("must specify a base directory")
}
o.baseDirectoryPaths = args[0]
return nil
}
// Complete completes addBase command.
func (o *addBaseOptions) Complete(cmd *cobra.Command, args []string) error {
return nil
}
// RunAddBase runs addBase command (do real work).
func (o *addBaseOptions) RunAddBase(fsys fs.FileSystem) error {
mf, err := newKustomizationFile(constants.KustomizationFileName, fsys)
if err != nil {
return err
}
m, err := mf.read()
if err != nil {
return err
}
// split directory paths
paths := strings.Split(o.baseDirectoryPaths, ",")
for _, path := range paths {
_, err := fsys.Stat(path)
if err != nil {
return err
}
if stringInSlice(path, m.Bases) {
return fmt.Errorf("base %s already in kustomization file", path)
}
m.Bases = append(m.Bases, path)
}
return mf.write(m)
}

View File

@@ -0,0 +1,100 @@
/*
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 (
"testing"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
const (
baseDirectoryPaths = "my/path/to/wonderful/base,other/path/to/even/more/wonderful/base"
)
func TestAddBaseHappyPath(t *testing.T) {
fakeFS := fs.MakeFakeFS()
bases := strings.Split(baseDirectoryPaths, ",")
for _, base := range bases {
fakeFS.Mkdir(base, 0777)
}
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddBase(fakeFS)
args := []string{baseDirectoryPaths}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected cmd error: %v", err)
}
content, err := fakeFS.ReadFile(constants.KustomizationFileName)
if err != nil {
t.Errorf("unexpected read error: %v", err)
}
for _, base := range bases {
if !strings.Contains(string(content), base) {
t.Errorf("expected base name in kustomization")
}
}
}
func TestAddBaseAlreadyThere(t *testing.T) {
fakeFS := fs.MakeFakeFS()
// Create fake directories
bases := strings.Split(baseDirectoryPaths, ",")
for _, base := range bases {
fakeFS.Mkdir(base, 0777)
}
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddBase(fakeFS)
args := []string{baseDirectoryPaths}
err := cmd.RunE(cmd, args)
if err != nil {
t.Fatalf("unexpected cmd error: %v", err)
}
// adding an existing base should return an error
err = cmd.RunE(cmd, args)
if err == nil {
t.Errorf("expected already there problem")
}
var expectedErrors []string
for _, base := range bases {
error := "base " + base + " already in kustomization file"
expectedErrors = append(expectedErrors, error)
if !stringInSlice(error, expectedErrors) {
t.Errorf("unexpected error %v", err)
}
}
}
func TestAddBaseNoArgs(t *testing.T) {
fakeFS := fs.MakeFakeFS()
cmd := newCmdAddBase(fakeFS)
err := cmd.Execute()
if err == nil {
t.Errorf("expected error: %v", err)
}
if err.Error() != "must specify a base directory" {
t.Errorf("incorrect error: %v", err.Error())
}
}

View File

@@ -19,12 +19,11 @@ package commands
import (
"errors"
"fmt"
"io"
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
type addPatchOptions struct {
@@ -32,7 +31,7 @@ type addPatchOptions struct {
}
// newCmdAddPatch adds the name of a file containing a patch to the kustomization file.
func newCmdAddPatch(out, errOut io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdAddPatch(fsys fs.FileSystem) *cobra.Command {
var o addPatchOptions
cmd := &cobra.Command{
@@ -49,7 +48,7 @@ func newCmdAddPatch(out, errOut io.Writer, fsys fs.FileSystem) *cobra.Command {
if err != nil {
return err
}
return o.RunAddPatch(out, errOut, fsys)
return o.RunAddPatch(fsys)
},
}
return cmd
@@ -70,7 +69,7 @@ func (o *addPatchOptions) Complete(cmd *cobra.Command, args []string) error {
}
// RunAddPatch runs addPatch command (do real work).
func (o *addPatchOptions) RunAddPatch(out, errOut io.Writer, fsys fs.FileSystem) error {
func (o *addPatchOptions) RunAddPatch(fsys fs.FileSystem) error {
_, err := fsys.Stat(o.patchFilePath)
if err != nil {
return err

View File

@@ -17,14 +17,12 @@ limitations under the License.
package commands
import (
"bytes"
"os"
"testing"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
const (
@@ -36,12 +34,11 @@ sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
)
func TestAddPatchHappyPath(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(patchFileName, []byte(patchFileContent))
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddPatch(buf, os.Stderr, fakeFS)
cmd := newCmdAddPatch(fakeFS)
args := []string{patchFileName}
err := cmd.RunE(cmd, args)
if err != nil {
@@ -57,12 +54,11 @@ func TestAddPatchHappyPath(t *testing.T) {
}
func TestAddPatchAlreadyThere(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(patchFileName, []byte(patchFileContent))
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddPatch(buf, os.Stderr, fakeFS)
cmd := newCmdAddPatch(fakeFS)
args := []string{patchFileName}
err := cmd.RunE(cmd, args)
if err != nil {
@@ -80,10 +76,9 @@ func TestAddPatchAlreadyThere(t *testing.T) {
}
func TestAddPatchNoArgs(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
cmd := newCmdAddPatch(buf, os.Stderr, fakeFS)
cmd := newCmdAddPatch(fakeFS)
err := cmd.Execute()
if err == nil {
t.Errorf("expected error: %v", err)

View File

@@ -19,12 +19,11 @@ package commands
import (
"errors"
"fmt"
"io"
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
type addResourceOptions struct {
@@ -32,7 +31,7 @@ type addResourceOptions struct {
}
// newCmdAddResource adds the name of a file containing a resource to the kustomization file.
func newCmdAddResource(out, errOut io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdAddResource(fsys fs.FileSystem) *cobra.Command {
var o addResourceOptions
cmd := &cobra.Command{
@@ -49,7 +48,7 @@ func newCmdAddResource(out, errOut io.Writer, fsys fs.FileSystem) *cobra.Command
if err != nil {
return err
}
return o.RunAddResource(out, errOut, fsys)
return o.RunAddResource(fsys)
},
}
return cmd
@@ -70,7 +69,7 @@ func (o *addResourceOptions) Complete(cmd *cobra.Command, args []string) error {
}
// RunAddResource runs addResource command (do real work).
func (o *addResourceOptions) RunAddResource(out, errOut io.Writer, fsys fs.FileSystem) error {
func (o *addResourceOptions) RunAddResource(fsys fs.FileSystem) error {
_, err := fsys.Stat(o.resourceFilePath)
if err != nil {
return err

View File

@@ -17,14 +17,12 @@ limitations under the License.
package commands
import (
"bytes"
"os"
"testing"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
const (
@@ -52,12 +50,11 @@ secretGenerator: []
)
func TestAddResourceHappyPath(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(resourceFileName, []byte(resourceFileContent))
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddResource(buf, os.Stderr, fakeFS)
cmd := newCmdAddResource(fakeFS)
args := []string{resourceFileName}
err := cmd.RunE(cmd, args)
if err != nil {
@@ -73,12 +70,11 @@ func TestAddResourceHappyPath(t *testing.T) {
}
func TestAddResourceAlreadyThere(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(resourceFileName, []byte(resourceFileContent))
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddResource(buf, os.Stderr, fakeFS)
cmd := newCmdAddResource(fakeFS)
args := []string{resourceFileName}
err := cmd.RunE(cmd, args)
if err != nil {
@@ -96,10 +92,9 @@ func TestAddResourceAlreadyThere(t *testing.T) {
}
func TestAddResourceNoArgs(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
cmd := newCmdAddResource(buf, os.Stderr, fakeFS)
cmd := newCmdAddResource(fakeFS)
err := cmd.Execute()
if err == nil {
t.Errorf("expected error: %v", err)

View File

@@ -26,9 +26,8 @@ import (
"github.com/kubernetes-sigs/kustomize/pkg/app"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
kutil "github.com/kubernetes-sigs/kustomize/pkg/util"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
)
type buildOptions struct {
@@ -36,7 +35,7 @@ type buildOptions struct {
}
// newCmdBuild creates a new build command.
func newCmdBuild(out, errOut io.Writer, fs fs.FileSystem) *cobra.Command {
func newCmdBuild(out io.Writer, fs fs.FileSystem) *cobra.Command {
var o buildOptions
cmd := &cobra.Command{
@@ -44,12 +43,13 @@ func newCmdBuild(out, errOut io.Writer, fs fs.FileSystem) *cobra.Command {
Short: "Print current configuration per contents of " + constants.KustomizationFileName,
Example: "Use the file somedir/" + constants.KustomizationFileName +
" to generate a set of api resources:\nbuild somedir/",
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
if err != nil {
return err
}
return o.RunBuild(out, errOut, fs)
return o.RunBuild(out, fs)
},
}
return cmd
@@ -69,7 +69,7 @@ func (o *buildOptions) Validate(args []string) error {
}
// RunBuild runs build command.
func (o *buildOptions) RunBuild(out, errOut io.Writer, fs fs.FileSystem) error {
func (o *buildOptions) RunBuild(out io.Writer, fs fs.FileSystem) error {
l := loader.Init([]loader.SchemeLoader{loader.NewFileLoader(fs)})
absPath, err := filepath.Abs(o.kustomizationPath)
@@ -82,19 +82,19 @@ func (o *buildOptions) RunBuild(out, errOut io.Writer, fs fs.FileSystem) error {
return err
}
application, err := app.New(rootLoader)
application, err := app.NewApplication(rootLoader)
if err != nil {
return err
}
allResources, err := application.Resources()
allResources, err := application.MakeCustomizedResMap()
if err != nil {
return err
}
// Output the objects.
res, err := kutil.Encode(allResources)
res, err := allResources.EncodeAsYaml()
if err != nil {
return err
}

View File

@@ -28,7 +28,7 @@ import (
"github.com/ghodss/yaml"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"k8s.io/apimachinery/pkg/util/sets"
)
@@ -104,49 +104,51 @@ func TestBuild(t *testing.T) {
}
for _, testcaseName := range testcases.List() {
t.Run(testcaseName, func(t *testing.T) {
name := testcaseName
testcase := buildTestCase{}
testcaseDir := filepath.Join("testdata", "testcase-"+name)
testcaseData, err := ioutil.ReadFile(filepath.Join(testcaseDir, "test.yaml"))
if err != nil {
t.Fatalf("%s: %v", name, err)
}
if err := yaml.Unmarshal(testcaseData, &testcase); err != nil {
t.Fatalf("%s: %v", name, err)
}
ops := &buildOptions{
kustomizationPath: testcase.Filename,
}
buf := bytes.NewBuffer([]byte{})
err = ops.RunBuild(buf, os.Stderr, fs)
switch {
case err != nil && len(testcase.ExpectedError) == 0:
t.Errorf("unexpected error: %v", err)
case err != nil && len(testcase.ExpectedError) != 0:
if !strings.Contains(err.Error(), testcase.ExpectedError) {
t.Errorf("expected error to contain %q but got: %v", testcase.ExpectedError, err)
}
return
case err == nil && len(testcase.ExpectedError) != 0:
t.Errorf("unexpected no error")
}
actualBytes := buf.Bytes()
if !updateKustomizeExpected {
expectedBytes, err := ioutil.ReadFile(testcase.ExpectedStdout)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actualBytes, expectedBytes) {
t.Errorf("%s\ndoesn't equal expected:\n%s\n", actualBytes, expectedBytes)
}
} else {
ioutil.WriteFile(testcase.ExpectedStdout, actualBytes, 0644)
}
})
t.Run(testcaseName, func(t *testing.T) { runBuildTestCase(t, testcaseName, updateKustomizeExpected, fs) })
}
}
func runBuildTestCase(t *testing.T, testcaseName string, updateKustomizeExpected bool, fs fs.FileSystem) {
name := testcaseName
testcase := buildTestCase{}
testcaseDir := filepath.Join("testdata", "testcase-"+name)
testcaseData, err := ioutil.ReadFile(filepath.Join(testcaseDir, "test.yaml"))
if err != nil {
t.Fatalf("%s: %v", name, err)
}
if err := yaml.Unmarshal(testcaseData, &testcase); err != nil {
t.Fatalf("%s: %v", name, err)
}
ops := &buildOptions{
kustomizationPath: testcase.Filename,
}
buf := bytes.NewBuffer([]byte{})
err = ops.RunBuild(buf, fs)
switch {
case err != nil && len(testcase.ExpectedError) == 0:
t.Errorf("unexpected error: %v", err)
case err != nil && len(testcase.ExpectedError) != 0:
if !strings.Contains(err.Error(), testcase.ExpectedError) {
t.Errorf("expected error to contain %q but got: %v", testcase.ExpectedError, err)
}
return
case err == nil && len(testcase.ExpectedError) != 0:
t.Errorf("unexpected no error")
}
actualBytes := buf.Bytes()
if !updateKustomizeExpected {
expectedBytes, err := ioutil.ReadFile(testcase.ExpectedStdout)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actualBytes, expectedBytes) {
t.Errorf("%s\ndoesn't equal expected:\n%s\n", actualBytes, expectedBytes)
}
} else {
ioutil.WriteFile(testcase.ExpectedStdout, actualBytes, 0644)
}
}

View File

@@ -14,15 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package commands holds the CLI glue mapping textual commands/args to method calls.
package commands
import (
"flag"
"io"
"os"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/version"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/spf13/cobra"
)
@@ -37,15 +36,16 @@ func NewDefaultCommand() *cobra.Command {
Long: `
kustomize manages declarative configuration of Kubernetes.
More info at https://github.com/kubernetes/kubectl/tree/master/cmd/kustomize
See https://github.com/kubernetes-sigs/kustomize
`,
}
c.AddCommand(
newCmdBuild(stdOut, stdErr, fsys),
// TODO: Make consistent API for newCmd* functions.
newCmdBuild(stdOut, fsys),
newCmdDiff(stdOut, stdErr, fsys),
newCmdEdit(stdOut, stdErr, fsys),
version.NewCmdVersion(stdOut),
newCmdEdit(fsys),
newCmdVersion(stdOut),
)
c.PersistentFlags().AddGoFlagSet(flag.CommandLine)
@@ -56,7 +56,7 @@ More info at https://github.com/kubernetes/kubectl/tree/master/cmd/kustomize
}
// newCmdEdit returns an instance of 'edit' subcommand.
func newCmdEdit(stdOut, stdErr io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdEdit(fsys fs.FileSystem) *cobra.Command {
c := &cobra.Command{
Use: "edit",
Short: "Edits a kustomization file",
@@ -71,43 +71,45 @@ func newCmdEdit(stdOut, stdErr io.Writer, fsys fs.FileSystem) *cobra.Command {
Args: cobra.MinimumNArgs(1),
}
c.AddCommand(
newCmdAdd(stdOut, stdErr, fsys),
newCmdSet(stdOut, stdErr, fsys),
newCmdAdd(fsys),
newCmdSet(fsys),
)
return c
}
// newAddCommand returns an instance of 'add' subcommand.
func newCmdAdd(stdOut, stdErr io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdAdd(fsys fs.FileSystem) *cobra.Command {
c := &cobra.Command{
Use: "add",
Short: "Adds configmap/resource/secret to the kustomization file.",
Short: "Adds configmap/resource/patch/base to the kustomization file.",
Long: "",
Example: `
# Adds a configmap to the kustomization file
kustomize edit add configmap NAME --from-literal=k=v
# Adds a secret to the kustomization file
kustomize edit add secret NAME --from-literal=k=v
# Adds a resource to the kustomization
kustomize edit add resource <filepath>
# Adds a patch to the kustomization
kustomize edit add patch <filepath>
# Adds one or more base directories to the kustomization
kustomize edit add base <filepath>
kustomize edit add base <filepath1>,<filepath2>,<filepath3>
`,
Args: cobra.MinimumNArgs(1),
}
c.AddCommand(
newCmdAddResource(stdOut, stdErr, fsys),
newCmdAddPatch(stdOut, stdErr, fsys),
newCmdAddConfigMap(stdErr, fsys),
newCmdAddResource(fsys),
newCmdAddPatch(fsys),
newCmdAddConfigMap(fsys),
newCmdAddBase(fsys),
)
return c
}
// newSetCommand returns an instance of 'set' subcommand.
func newCmdSet(stdOut, stdErr io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdSet(fsys fs.FileSystem) *cobra.Command {
c := &cobra.Command{
Use: "set",
Short: "Sets the value of different fields in kustomization file.",
@@ -120,7 +122,7 @@ func newCmdSet(stdOut, stdErr io.Writer, fsys fs.FileSystem) *cobra.Command {
}
c.AddCommand(
newCmdSetNamePrefix(stdOut, stdErr, fsys),
newCmdSetNamePrefix(fsys),
)
return c
}

View File

@@ -18,17 +18,16 @@ package commands
import (
"fmt"
"io"
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/configmapandsecret"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
)
func newCmdAddConfigMap(errOut io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdAddConfigMap(fsys fs.FileSystem) *cobra.Command {
var config dataConfig
cmd := &cobra.Command{
Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1]",
@@ -76,7 +75,9 @@ func newCmdAddConfigMap(errOut io.Writer, fsys fs.FileSystem) *cobra.Command {
&config.FileSources,
"from-file",
[]string{},
"Key file 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.")
"Key file 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.")
cmd.Flags().StringArrayVar(
&config.LiteralSources,
"from-literal",

View File

@@ -19,12 +19,12 @@ package commands
import (
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
)
func TestNewAddConfigMapIsNotNil(t *testing.T) {
if newCmdAddConfigMap(nil, fs.MakeFakeFS()) == nil {
if newCmdAddConfigMap(fs.MakeFakeFS()) == nil {
t.Fatal("newCmdAddConfigMap shouldn't be nil")
}
}

View File

@@ -25,10 +25,9 @@ import (
"github.com/kubernetes-sigs/kustomize/pkg/app"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/diff"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/util"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"k8s.io/utils/exec"
)
type diffOptions struct {
@@ -43,7 +42,7 @@ func newCmdDiff(out, errOut io.Writer, fs fs.FileSystem) *cobra.Command {
Use: "diff [path]",
Short: "diff between customized resources and uncustomized resources",
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(cmd, args)
err := o.Validate(args)
if err != nil {
return err
}
@@ -54,7 +53,7 @@ func newCmdDiff(out, errOut io.Writer, fs fs.FileSystem) *cobra.Command {
}
// Validate validates diff command.
func (o *diffOptions) Validate(cmd *cobra.Command, args []string) error {
func (o *diffOptions) Validate(args []string) error {
if len(args) > 1 {
return errors.New("specify one path to " + constants.KustomizationFileName)
}
@@ -66,14 +65,8 @@ func (o *diffOptions) Validate(cmd *cobra.Command, args []string) error {
return nil
}
// RunDiff gets the differences between Application.Resources() and Application.RawResources().
// RunDiff gets the differences between Application.MakeCustomizedResMap() and Application.MakeUncustomizedResMap().
func (o *diffOptions) RunDiff(out, errOut io.Writer, fs fs.FileSystem) error {
printer := util.Printer{}
diff := util.DiffProgram{
Exec: exec.New(),
Stdout: out,
Stderr: errOut,
}
l := loader.Init([]loader.SchemeLoader{loader.NewFileLoader(fs)})
@@ -87,30 +80,18 @@ func (o *diffOptions) RunDiff(out, errOut io.Writer, fs fs.FileSystem) error {
return err
}
application, err := app.New(rootLoader)
application, err := app.NewApplication(rootLoader)
if err != nil {
return err
}
resources, err := application.Resources()
transformedResources, err := application.MakeCustomizedResMap()
if err != nil {
return err
}
rawResources, err := application.RawResources()
rawResources, err := application.MakeUncustomizedResMap()
if err != nil {
return err
}
transformedDir, err := util.WriteToDir(resources, "transformed", printer)
if err != nil {
return err
}
defer transformedDir.Delete()
noopDir, err := util.WriteToDir(rawResources, "noop", printer)
if err != nil {
return err
}
defer noopDir.Delete()
return diff.Run(noopDir.Name, transformedDir.Name)
return diff.RunDiff(rawResources, transformedResources, out, errOut)
}

View File

@@ -27,7 +27,7 @@ import (
"github.com/ghodss/yaml"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"k8s.io/apimachinery/pkg/util/sets"
)
@@ -74,51 +74,57 @@ func TestDiff(t *testing.T) {
for _, testcaseName := range testcases.List() {
t.Run(testcaseName, func(t *testing.T) {
name := testcaseName
testcase := DiffTestCase{}
testcaseDir := filepath.Join("testdata", "testcase-"+name)
testcaseData, err := ioutil.ReadFile(filepath.Join(testcaseDir, "test.yaml"))
if err != nil {
t.Fatalf("%s: %v", name, err)
}
if err := yaml.Unmarshal(testcaseData, &testcase); err != nil {
t.Fatalf("%s: %v", name, err)
}
diffOps := &diffOptions{
kustomizationPath: testcase.Filename,
}
buf := bytes.NewBuffer([]byte{})
err = diffOps.RunDiff(buf, os.Stderr, fs)
switch {
case err != nil && len(testcase.ExpectedError) == 0:
t.Errorf("unexpected error: %v", err)
case err != nil && len(testcase.ExpectedError) != 0:
if !strings.Contains(err.Error(), testcase.ExpectedError) {
t.Errorf("expected error to contain %q but got: %v", testcase.ExpectedError, err)
}
return
case err == nil && len(testcase.ExpectedError) != 0:
t.Errorf("unexpected no error")
}
actualString := string(buf.Bytes())
actualString = noopDir.ReplaceAllString(actualString, "/tmp/noop/")
actualString = transformedDir.ReplaceAllString(actualString, "/tmp/transformed/")
actualString = timestamp.ReplaceAllString(actualString, "YYYY-MM-DD HH:MM:SS")
actualBytes := []byte(actualString)
if !updateKustomizeExpected {
expectedBytes, err := ioutil.ReadFile(testcase.ExpectedDiff)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actualBytes, expectedBytes) {
t.Errorf("%s\ndoesn't equal expected:\n%s\n", actualBytes, expectedBytes)
}
} else {
ioutil.WriteFile(testcase.ExpectedDiff, actualBytes, 0644)
}
runDiffTestCase(t, testcaseName, updateKustomizeExpected, fs,
noopDir, transformedDir, timestamp)
})
}
}
func runDiffTestCase(t *testing.T, testcaseName string, updateKustomizeExpected bool, fs fs.FileSystem,
noopDir, transformedDir, timestamp *regexp.Regexp) {
name := testcaseName
testcase := DiffTestCase{}
testcaseDir := filepath.Join("testdata", "testcase-"+name)
testcaseData, err := ioutil.ReadFile(filepath.Join(testcaseDir, "test.yaml"))
if err != nil {
t.Fatalf("%s: %v", name, err)
}
if err := yaml.Unmarshal(testcaseData, &testcase); err != nil {
t.Fatalf("%s: %v", name, err)
}
diffOps := &diffOptions{
kustomizationPath: testcase.Filename,
}
buf := bytes.NewBuffer([]byte{})
err = diffOps.RunDiff(buf, os.Stderr, fs)
switch {
case err != nil && len(testcase.ExpectedError) == 0:
t.Errorf("unexpected error: %v", err)
case err != nil && len(testcase.ExpectedError) != 0:
if !strings.Contains(err.Error(), testcase.ExpectedError) {
t.Errorf("expected error to contain %q but got: %v", testcase.ExpectedError, err)
}
return
case err == nil && len(testcase.ExpectedError) != 0:
t.Errorf("unexpected no error")
}
actualString := string(buf.Bytes())
actualString = noopDir.ReplaceAllString(actualString, "/tmp/noop/")
actualString = transformedDir.ReplaceAllString(actualString, "/tmp/transformed/")
actualString = timestamp.ReplaceAllString(actualString, "YYYY-MM-DD HH:MM:SS")
actualBytes := []byte(actualString)
if !updateKustomizeExpected {
expectedBytes, err := ioutil.ReadFile(testcase.ExpectedDiff)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actualBytes, expectedBytes) {
t.Errorf("%s\ndoesn't equal expected:\n%s\n", actualBytes, expectedBytes)
}
} else {
ioutil.WriteFile(testcase.ExpectedDiff, actualBytes, 0644)
}
}

View File

@@ -1,96 +0,0 @@
/*
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 commands
import (
"fmt"
"io"
"errors"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/spf13/cobra"
)
const kustomizationTemplate = `
namePrefix: some-prefix
# Labels to add to all objects and selectors.
# These labels would also be used to form the selector for apply --prune
# Named differently than “labels” to avoid confusion with metadata for this object
commonLabels:
app: helloworld
commonAnnotations:
note: This is an example annotation
resources: []
#- service.yaml
#- ../some-dir/
# There could also be configmaps in Base, which would make these overlays
configMapGenerator: []
# There could be secrets in Base, if just using a fork/rebase workflow
secretGenerator: []
`
type initOptions struct {
}
// NewCmdInit makes the init command.
func newCmdInit(out, errOut io.Writer, fs fs.FileSystem) *cobra.Command {
var o initOptions
cmd := &cobra.Command{
Use: "init",
Short: "Creates a file called \"" + constants.KustomizationFileName + "\" in the current directory",
Long: "Creates a file called \"" +
constants.KustomizationFileName + "\" in the current directory with example values.",
Example: `init`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(cmd, args)
if err != nil {
return err
}
err = o.Complete(cmd, args)
if err != nil {
return err
}
return o.RunInit(out, errOut, fs)
},
}
return cmd
}
// Validate validates init command.
func (o *initOptions) Validate(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return errors.New("The init command takes no arguments.")
}
return nil
}
// Complete completes init command.
func (o *initOptions) Complete(cmd *cobra.Command, args []string) error {
return nil
}
// RunInit writes a kustomization file.
func (o *initOptions) RunInit(out, errOut io.Writer, fs fs.FileSystem) error {
if _, err := fs.Stat(constants.KustomizationFileName); err == nil {
return fmt.Errorf("%q already exists", constants.KustomizationFileName)
}
return fs.WriteFile(constants.KustomizationFileName, []byte(kustomizationTemplate))
}

View File

@@ -25,9 +25,9 @@ import (
"github.com/ghodss/yaml"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
interror "github.com/kubernetes-sigs/kustomize/pkg/internal/error"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
)
type kustomizationFile struct {
@@ -35,7 +35,7 @@ type kustomizationFile struct {
fsys fs.FileSystem
}
func newKustomizationFile(mPath string, fsys fs.FileSystem) (*kustomizationFile, error) {
func newKustomizationFile(mPath string, fsys fs.FileSystem) (*kustomizationFile, error) { // nolint
mf := &kustomizationFile{path: mPath, fsys: fsys}
err := mf.validate()
if err != nil {
@@ -61,7 +61,7 @@ func (mf *kustomizationFile) validate() error {
}
} else {
if !strings.HasSuffix(mf.path, constants.KustomizationFileName) {
errorMsg := fmt.Sprintf("Kustomization file path (%s) should have %s suffix\n", mf.path, constants.KustomizationSuffix)
errorMsg := fmt.Sprintf("Kustomization file path (%s) should have %s suffix\n", mf.path, constants.KustomizationFileSuffix)
merr := interror.KustomizationError{KustomizationPath: mf.path, ErrorMsg: errorMsg}
return merr
}

View File

@@ -22,8 +22,8 @@ import (
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
)
func TestWriteAndRead(t *testing.T) {

View File

@@ -18,12 +18,11 @@ package commands
import (
"errors"
"io"
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
type setNamePrefixOptions struct {
@@ -31,7 +30,7 @@ type setNamePrefixOptions struct {
}
// newCmdSetNamePrefix sets the value of the namePrefix field in the kustomization.
func newCmdSetNamePrefix(out, errOut io.Writer, fsys fs.FileSystem) *cobra.Command {
func newCmdSetNamePrefix(fsys fs.FileSystem) *cobra.Command {
var o setNamePrefixOptions
cmd := &cobra.Command{
@@ -52,7 +51,7 @@ and overwrite the value with "acme-" if the field does exist.
if err != nil {
return err
}
return o.RunSetNamePrefix(out, errOut, fsys)
return o.RunSetNamePrefix(fsys)
},
}
return cmd
@@ -74,7 +73,7 @@ func (o *setNamePrefixOptions) Complete(cmd *cobra.Command, args []string) error
}
// RunSetNamePrefix runs setNamePrefix command (does real work).
func (o *setNamePrefixOptions) RunSetNamePrefix(out, errOut io.Writer, fsys fs.FileSystem) error {
func (o *setNamePrefixOptions) RunSetNamePrefix(fsys fs.FileSystem) error {
mf, err := newKustomizationFile(constants.KustomizationFileName, fsys)
if err != nil {
return err

View File

@@ -17,14 +17,12 @@ limitations under the License.
package commands
import (
"bytes"
"os"
"testing"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/util/fs"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
)
const (
@@ -32,11 +30,10 @@ const (
)
func TestSetNamePrefixHappyPath(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdSetNamePrefix(buf, os.Stderr, fakeFS)
cmd := newCmdSetNamePrefix(fakeFS)
args := []string{goodPrefixValue}
err := cmd.RunE(cmd, args)
if err != nil {
@@ -52,10 +49,9 @@ func TestSetNamePrefixHappyPath(t *testing.T) {
}
func TestSetNamePrefixNoArgs(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
fakeFS := fs.MakeFakeFS()
cmd := newCmdSetNamePrefix(buf, os.Stderr, fakeFS)
cmd := newCmdSetNamePrefix(fakeFS)
err := cmd.Execute()
if err == nil {
t.Errorf("expected error: %v", err)

View File

@@ -6,5 +6,4 @@ commonLabels:
commonAnnotations:
note: This is a test annotation
resources:
- deployment.yaml
- service.yaml
- resources/*.yaml

View File

@@ -0,0 +1,6 @@
namePrefix: p1-
configMapGenerator:
- name: com1
behavior: create
literals:
- from=base

View File

@@ -0,0 +1,6 @@
namePrefix: p2-
configMapGenerator:
- name: com2
behavior: create
literals:
- from=base

View File

@@ -0,0 +1,16 @@
diff -u -N /tmp/noop/v1_ConfigMap_com1.yaml /tmp/transformed/v1_ConfigMap_com1.yaml
--- /tmp/noop/v1_ConfigMap_com1.yaml YYYY-MM-DD HH:MM:SS
+++ /tmp/transformed/v1_ConfigMap_com1.yaml YYYY-MM-DD HH:MM:SS
@@ -1,9 +1,11 @@
apiVersion: v1
data:
+ baz: qux
+ foo: bar
from: overlay
kind: ConfigMap
metadata:
annotations: {}
creationTimestamp: null
labels: {}
- name: p1-com1-cmdb776d5b
+ name: p1-com1-dhbbm922gd

View File

@@ -0,0 +1,21 @@
apiVersion: v1
data:
baz: qux
foo: bar
from: overlay
kind: ConfigMap
metadata:
annotations: {}
creationTimestamp: null
labels: {}
name: p1-com1-dhbbm922gd
---
apiVersion: v1
data:
from: overlay
kind: ConfigMap
metadata:
annotations: {}
creationTimestamp: null
labels: {}
name: p2-com2-c4b8md75k9

View File

@@ -0,0 +1,9 @@
bases:
- myapp/mycomponent
- myapp/mycomponent2
configMapGenerator:
- name: com1
behavior: merge
literals:
- foo=bar
- baz=qux

View File

@@ -0,0 +1,7 @@
bases:
- ../../../../base/myapp/mycomponent
configMapGenerator:
- name: com1
behavior: merge
literals:
- from=overlay

View File

@@ -0,0 +1,7 @@
bases:
- ../../../../base/myapp/mycomponent2
configMapGenerator:
- name: com2
behavior: merge
literals:
- from=overlay

View File

@@ -0,0 +1,5 @@
description: configmap generator overlay
args: []
filename: testdata/testcase-configmaps/overlay/dev
expectedStdout: testdata/testcase-configmaps/expected.yaml
expectedDiff: testdata/testcase-configmaps/expected.diff

View File

@@ -0,0 +1,6 @@
apiVersion: v1beta1
kind: Bee
metadata:
name: bee
spec:
action: fly

View File

@@ -0,0 +1,9 @@
crds:
- mycrd.json
resources:
- secret.yaml
- mykind.yaml
- bee.yaml
namePrefix: test-

View File

@@ -0,0 +1,170 @@
{
"github.com/example/pkg/apis/jingfang/v1beta1.Bee": {
"Schema": {
"description": "Bee",
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
},
"spec": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec"
},
"status": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec",
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus",
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.BeeList": {
"Schema": {
"required": [
"items"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"items": {
"type": "array",
"items": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.Bee"
}
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.Bee",
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference": {
"Schema": {
"properties": {
"name": {
"type": "string"
}
}
},
"Dependencies": []
},
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec": {
"Schema": {
"description": "BeeSpec defines the desired state of Bee"
},
"Dependencies": []
},
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus": {
"Schema": {
"description": "BeeStatus defines the observed state of Bee"
},
"Dependencies": []
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKind": {
"Schema": {
"description": "MyKind",
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
},
"spec": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec"
},
"status": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec",
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus",
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindList": {
"Schema": {
"required": [
"items"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"items": {
"type": "array",
"items": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKind"
}
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.MyKind",
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec": {
"Schema": {
"description": "MyKindSpec defines the desired state of MyKind",
"properties": {
"beeRef": {
"x-kubernetes-object-ref-api-version": "v1beta1",
"x-kubernetes-object-ref-kind": "Bee",
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference"
},
"secretRef": {
"description": "If defined, we use this secret for configuring the MYSQL_ROOT_PASSWORD If it is not set we generate a secret dynamically",
"x-kubernetes-object-ref-api-version": "v1",
"x-kubernetes-object-ref-kind": "Secret",
"$ref": "k8s.io/api/core/v1.LocalObjectReference"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference",
"k8s.io/api/core/v1.LocalObjectReference"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus": {
"Schema": {
"description": "MyKindStatus defines the observed state of MyKind"
},
"Dependencies": []
}
}

View File

@@ -0,0 +1,9 @@
apiVersion: jingfang.example.com/v1beta1
kind: MyKind
metadata:
name: mykind
spec:
secretRef:
name: crdsecret
beeRef:
name: bee

View File

@@ -0,0 +1,6 @@
apiVersion: v1
kind: Secret
metadata:
name: crdsecret
data:
PATH: YmJiYmJiYmIK

View File

@@ -0,0 +1,36 @@
diff -u -N /tmp/noop/jingfang.example.com_v1beta1_MyKind_mykind.yaml /tmp/transformed/jingfang.example.com_v1beta1_MyKind_mykind.yaml
--- /tmp/noop/jingfang.example.com_v1beta1_MyKind_mykind.yaml YYYY-MM-DD HH:MM:SS
+++ /tmp/transformed/jingfang.example.com_v1beta1_MyKind_mykind.yaml YYYY-MM-DD HH:MM:SS
@@ -1,9 +1,9 @@
apiVersion: jingfang.example.com/v1beta1
kind: MyKind
metadata:
- name: mykind
+ name: test-mykind
spec:
beeRef:
- name: bee
+ name: test-bee
secretRef:
- name: crdsecret-m5ht5thcb4
+ name: test-crdsecret-m48btmkck5
diff -u -N /tmp/noop/v1beta1_Bee_bee.yaml /tmp/transformed/v1beta1_Bee_bee.yaml
--- /tmp/noop/v1beta1_Bee_bee.yaml YYYY-MM-DD HH:MM:SS
+++ /tmp/transformed/v1beta1_Bee_bee.yaml YYYY-MM-DD HH:MM:SS
@@ -1,6 +1,6 @@
apiVersion: v1beta1
kind: Bee
metadata:
- name: bee
+ name: test-bee
spec:
action: fly
diff -u -N /tmp/noop/v1_Secret_crdsecret.yaml /tmp/transformed/v1_Secret_crdsecret.yaml
--- /tmp/noop/v1_Secret_crdsecret.yaml YYYY-MM-DD HH:MM:SS
+++ /tmp/transformed/v1_Secret_crdsecret.yaml YYYY-MM-DD HH:MM:SS
@@ -3,4 +3,4 @@
PATH: YmJiYmJiYmIK
kind: Secret
metadata:
- name: crdsecret-m5ht5thcb4
+ name: test-crdsecret-m48btmkck5

View File

@@ -0,0 +1,23 @@
apiVersion: v1
data:
PATH: YmJiYmJiYmIK
kind: Secret
metadata:
name: test-crdsecret-m48btmkck5
---
apiVersion: v1beta1
kind: Bee
metadata:
name: test-bee
spec:
action: fly
---
apiVersion: jingfang.example.com/v1beta1
kind: MyKind
metadata:
name: test-mykind
spec:
beeRef:
name: test-bee
secretRef:
name: test-crdsecret-m48btmkck5

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