mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 09:40:49 +00:00
Compare commits
462 Commits
v3.0.3
...
release-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74255f6bad | ||
|
|
3dfe62fe55 | ||
|
|
ad9b869ddb | ||
|
|
5c4c19bf19 | ||
|
|
1f86a0ca5d | ||
|
|
db630a9d07 | ||
|
|
388dd13a5f | ||
|
|
67c9d469c4 | ||
|
|
28a55bbd9c | ||
|
|
bdacb941ab | ||
|
|
d87ad523de | ||
|
|
ec36993d42 | ||
|
|
6b5aebac22 | ||
|
|
883714e2e5 | ||
|
|
8b0f4bf714 | ||
|
|
e83b97ea1f | ||
|
|
48dfcf5a3e | ||
|
|
cb4498594b | ||
|
|
b0bd4b5410 | ||
|
|
dbf8a0fde4 | ||
|
|
3db1111f8e | ||
|
|
e482ffa3f9 | ||
|
|
2b1749778f | ||
|
|
6af51a1bfe | ||
|
|
e0b46acf2f | ||
|
|
2e33a69388 | ||
|
|
018698ec85 | ||
|
|
0029a8ce32 | ||
|
|
04d5494246 | ||
|
|
41a8bd208d | ||
|
|
6bb470dbd0 | ||
|
|
9fa0391ce9 | ||
|
|
bda22d08cc | ||
|
|
09faaa1b2c | ||
|
|
9a65634df6 | ||
|
|
300383959d | ||
|
|
ab17d8dd74 | ||
|
|
c5ba2ced3b | ||
|
|
4103580834 | ||
|
|
d36e3f015d | ||
|
|
975e071394 | ||
|
|
6542af600d | ||
|
|
9e6e928725 | ||
|
|
ad24ba2234 | ||
|
|
c7fd1dee8b | ||
|
|
606eb8a74c | ||
|
|
2340c98f6a | ||
|
|
a7607c20e3 | ||
|
|
0b5cf74945 | ||
|
|
0687699d27 | ||
|
|
357126fc4e | ||
|
|
0aeb53a2b3 | ||
|
|
efd7c8e3f7 | ||
|
|
152ee44b92 | ||
|
|
588297f1f9 | ||
|
|
6b81ae9a93 | ||
|
|
077c7b2d20 | ||
|
|
1a4330a7cb | ||
|
|
d08690a6aa | ||
|
|
ba925e833d | ||
|
|
4c15c42447 | ||
|
|
690e01c2ba | ||
|
|
133d8bff5e | ||
|
|
079c3307c1 | ||
|
|
e0070f7ec5 | ||
|
|
a45eca7e22 | ||
|
|
79c5f8a977 | ||
|
|
69d1699963 | ||
|
|
b6b8f4396f | ||
|
|
9ca5284e4f | ||
|
|
335292fe8a | ||
|
|
cf9edbfb3c | ||
|
|
364a2342df | ||
|
|
3301913178 | ||
|
|
ac3c53557e | ||
|
|
8bf98dd255 | ||
|
|
f2368201d9 | ||
|
|
f44574cf43 | ||
|
|
3054d69dd9 | ||
|
|
739c2a5bac | ||
|
|
a780bd6465 | ||
|
|
4716cb026f | ||
|
|
a186144a78 | ||
|
|
2ea4762d0f | ||
|
|
eb268fa722 | ||
|
|
3b3a1309e4 | ||
|
|
72db6dde9e | ||
|
|
6d30bc5c35 | ||
|
|
773629e544 | ||
|
|
cd50bf4e1e | ||
|
|
ff59e9b52f | ||
|
|
9a954d4f0b | ||
|
|
5c63c20390 | ||
|
|
a84f8d65db | ||
|
|
6e2335ec3d | ||
|
|
4cf6630fc0 | ||
|
|
d239d52217 | ||
|
|
c260105212 | ||
|
|
44cdf98a47 | ||
|
|
92390eabe4 | ||
|
|
7b8fa51ec5 | ||
|
|
af8e17a1ed | ||
|
|
e2eeb90639 | ||
|
|
1704977a4b | ||
|
|
7050c6a7b6 | ||
|
|
02f9b98b5a | ||
|
|
ce7ebe3299 | ||
|
|
3928ada0e5 | ||
|
|
0a8faced8f | ||
|
|
3c06debf98 | ||
|
|
fcee91eafd | ||
|
|
b0b3a705f4 | ||
|
|
67c8fbcc3c | ||
|
|
9b50b78ec8 | ||
|
|
943a1b0195 | ||
|
|
f77143cd34 | ||
|
|
b7d2ba2376 | ||
|
|
c28a0eb83d | ||
|
|
f7e5b5138b | ||
|
|
61149cbf21 | ||
|
|
310d516030 | ||
|
|
a9e3fe155b | ||
|
|
24837bad40 | ||
|
|
9686cc9861 | ||
|
|
a4784ee5ec | ||
|
|
3063560e77 | ||
|
|
bff0604bee | ||
|
|
9f8faa7d7e | ||
|
|
335077eade | ||
|
|
491baa74cb | ||
|
|
2f2d078669 | ||
|
|
b7bcb90057 | ||
|
|
35dc15b16b | ||
|
|
83f70877c8 | ||
|
|
98cd31b820 | ||
|
|
5416ae7365 | ||
|
|
644f2ddcdc | ||
|
|
46524d3b6a | ||
|
|
4f014d0262 | ||
|
|
0cf2057fc5 | ||
|
|
3f08e1546c | ||
|
|
10619fb0f7 | ||
|
|
c88e8cc057 | ||
|
|
327a3f5300 | ||
|
|
fddde81f9c | ||
|
|
22d07ed37d | ||
|
|
dee1c425da | ||
|
|
951d15bf17 | ||
|
|
0f82d2932c | ||
|
|
e2d7a06e9f | ||
|
|
286b9c1aed | ||
|
|
f54d4a5837 | ||
|
|
d9031fb2c9 | ||
|
|
3af5a8afea | ||
|
|
e2fd33c54a | ||
|
|
c90e0a4080 | ||
|
|
5de000ee3d | ||
|
|
c28b82510c | ||
|
|
fda3ba8af9 | ||
|
|
fd1356e5d8 | ||
|
|
a62f1364fe | ||
|
|
d1240bcc63 | ||
|
|
1c24fe7d16 | ||
|
|
e5c8b5ec8f | ||
|
|
180429774a | ||
|
|
586bba0b31 | ||
|
|
2ce138ab3a | ||
|
|
5e99ad000e | ||
|
|
0f0e740c21 | ||
|
|
33600189bc | ||
|
|
07d2500ee3 | ||
|
|
de6eb14867 | ||
|
|
85b71a31e3 | ||
|
|
16e7638220 | ||
|
|
04c23b2085 | ||
|
|
24db94dd0d | ||
|
|
5f862ba17c | ||
|
|
18ba3ee91b | ||
|
|
4e9d42fae7 | ||
|
|
52e57dab7f | ||
|
|
ba464a5e11 | ||
|
|
2734085fb0 | ||
|
|
d21ff7cfe6 | ||
|
|
3a15f450a9 | ||
|
|
bb77e7491a | ||
|
|
aa82240b4c | ||
|
|
cac7b46ebd | ||
|
|
367d0e042c | ||
|
|
d851305c33 | ||
|
|
0c52bd71ba | ||
|
|
41a008e9a3 | ||
|
|
2fadb4dd59 | ||
|
|
a88ee3f93c | ||
|
|
237848a80b | ||
|
|
9e3b837093 | ||
|
|
c4eca908ac | ||
|
|
72d9b4cbca | ||
|
|
19d94110b1 | ||
|
|
1756765dbc | ||
|
|
b306f8511c | ||
|
|
9778f867b5 | ||
|
|
a69ebf2b11 | ||
|
|
cf9c81f908 | ||
|
|
b95164b9a8 | ||
|
|
0551338958 | ||
|
|
40b7ad23ea | ||
|
|
ce66ceeed6 | ||
|
|
4e45af6265 | ||
|
|
07a9454215 | ||
|
|
9f5a936236 | ||
|
|
e6770e5f1e | ||
|
|
705b4ab212 | ||
|
|
2cb964ab8e | ||
|
|
949b10bf93 | ||
|
|
cc4341c546 | ||
|
|
d0caea0ce1 | ||
|
|
f2ac5a2d0d | ||
|
|
78d14d0d75 | ||
|
|
d5034af5ca | ||
|
|
40ed9e6a44 | ||
|
|
c1d20546ec | ||
|
|
3cf6b8ec4d | ||
|
|
3aee7a9081 | ||
|
|
abefa2b155 | ||
|
|
5d800f0b0a | ||
|
|
4eb2d5bcc2 | ||
|
|
988af1ff61 | ||
|
|
1617183ea4 | ||
|
|
ee72746481 | ||
|
|
c9e7dc3bfa | ||
|
|
07e0e46ac7 | ||
|
|
404d2d631a | ||
|
|
baa0296a12 | ||
|
|
0f665ac153 | ||
|
|
14b0a65091 | ||
|
|
2d58f8b81c | ||
|
|
9a43ca53cc | ||
|
|
5372fc6f6c | ||
|
|
86bc344057 | ||
|
|
a014f7d414 | ||
|
|
9a94bcb854 | ||
|
|
07634ef098 | ||
|
|
995f88d60c | ||
|
|
5caba59073 | ||
|
|
334a64676f | ||
|
|
08963ba503 | ||
|
|
326fb689be | ||
|
|
970ce67c34 | ||
|
|
98d1893057 | ||
|
|
d89b448c74 | ||
|
|
17bf9d325b | ||
|
|
a99aff1d1c | ||
|
|
a694ac7b63 | ||
|
|
b5b11ef6e9 | ||
|
|
fa1af6f51e | ||
|
|
9288dec02a | ||
|
|
1a45dd0b4f | ||
|
|
592c5acf5a | ||
|
|
ac9424fa3e | ||
|
|
79fbe7c4cc | ||
|
|
f69d526fa3 | ||
|
|
07a95a60f6 | ||
|
|
032b385711 | ||
|
|
810629596a | ||
|
|
b82a8fd316 | ||
|
|
2d0c22d6a4 | ||
|
|
aa342deff7 | ||
|
|
10786ec0a7 | ||
|
|
7c7056877b | ||
|
|
e8933d9789 | ||
|
|
9d7b65446f | ||
|
|
7a0946a922 | ||
|
|
def4f04572 | ||
|
|
2f2408f1cd | ||
|
|
3b9bcc48a0 | ||
|
|
d0429ff43b | ||
|
|
33deefc307 | ||
|
|
9b3de82b45 | ||
|
|
d217074fbf | ||
|
|
1d90ba7c7b | ||
|
|
eeeb4c36a1 | ||
|
|
b1faa989f4 | ||
|
|
d8250c9ee2 | ||
|
|
c950046659 | ||
|
|
0c32691e9e | ||
|
|
88b1d62740 | ||
|
|
aec8206695 | ||
|
|
20c2b53a46 | ||
|
|
274b5c3b4e | ||
|
|
b1fdaa2311 | ||
|
|
a3103f1e62 | ||
|
|
74ed0b30e5 | ||
|
|
b5d5e70bdc | ||
|
|
2e82985380 | ||
|
|
55941f5769 | ||
|
|
32be1cf4c2 | ||
|
|
2050afdeb4 | ||
|
|
7e71009283 | ||
|
|
72d26c6ad5 | ||
|
|
e011f3be4f | ||
|
|
f725bfc165 | ||
|
|
94ac55f17b | ||
|
|
dd5b3c1e2e | ||
|
|
e898c5221b | ||
|
|
1237ae43b4 | ||
|
|
281f932814 | ||
|
|
cd0187e948 | ||
|
|
9516880042 | ||
|
|
4cb883863f | ||
|
|
9e226001e3 | ||
|
|
9ee35c9afb | ||
|
|
e455acc14b | ||
|
|
6a3c2b2893 | ||
|
|
f59d7998d2 | ||
|
|
77b63f96d1 | ||
|
|
6fcb78403f | ||
|
|
f87edc8c67 | ||
|
|
6a4150d199 | ||
|
|
143c5dd21d | ||
|
|
ed920afb2e | ||
|
|
2677f4c4e7 | ||
|
|
a081534938 | ||
|
|
4ebad27d7a | ||
|
|
716a7307b2 | ||
|
|
ed91bce275 | ||
|
|
c2d6f09ef3 | ||
|
|
119ff5af73 | ||
|
|
2e7ad48b44 | ||
|
|
6ead3b7b1f | ||
|
|
31262cccbe | ||
|
|
93cedbaa51 | ||
|
|
6e13acfac3 | ||
|
|
2e6dd481e0 | ||
|
|
a66808a10d | ||
|
|
a4e1ba0593 | ||
|
|
73660af10c | ||
|
|
84519c236b | ||
|
|
aedb362565 | ||
|
|
6918931728 | ||
|
|
3f1b2bb744 | ||
|
|
33ad02a6b4 | ||
|
|
bfd6e086de | ||
|
|
a9f58383d8 | ||
|
|
aabbbf05ef | ||
|
|
40c613d0cd | ||
|
|
eca5b8796f | ||
|
|
aa2bf7ed08 | ||
|
|
351df67e39 | ||
|
|
8a8698ccdd | ||
|
|
66fa2de073 | ||
|
|
3ace96d7a4 | ||
|
|
2b44ba200f | ||
|
|
4b67a6de12 | ||
|
|
33bd221a98 | ||
|
|
594a06d35b | ||
|
|
e541ff3999 | ||
|
|
9ea184c04a | ||
|
|
993993c6cd | ||
|
|
35b39763dd | ||
|
|
2c1dda5436 | ||
|
|
653123975c | ||
|
|
fb8b314a29 | ||
|
|
5cf3f4e275 | ||
|
|
766500508c | ||
|
|
423a8a6e0d | ||
|
|
7783a76b8f | ||
|
|
2b6a406dc7 | ||
|
|
bc303c4629 | ||
|
|
00360f381c | ||
|
|
fa834f9541 | ||
|
|
a2767cab2a | ||
|
|
24c173a49b | ||
|
|
d3d4908f95 | ||
|
|
be1d5478dc | ||
|
|
d3022ccd65 | ||
|
|
fe45157b26 | ||
|
|
df779fd720 | ||
|
|
e0d388c6f7 | ||
|
|
62edcae233 | ||
|
|
ac6918d70f | ||
|
|
ca41674df3 | ||
|
|
c02b4f3a11 | ||
|
|
64341a81fa | ||
|
|
fe8ba8e44b | ||
|
|
54f1952195 | ||
|
|
44b62a8ebc | ||
|
|
8e9c08ea61 | ||
|
|
c464fb0a81 | ||
|
|
9481e3fba6 | ||
|
|
0e5206a251 | ||
|
|
96c5b4aa3e | ||
|
|
6c44da52a2 | ||
|
|
694cf23df8 | ||
|
|
e66656aa7f | ||
|
|
eaae7af5fe | ||
|
|
2de052ecd8 | ||
|
|
6cf8b9e2b8 | ||
|
|
f9fe138114 | ||
|
|
78c9729252 | ||
|
|
2a2a889c37 | ||
|
|
34287e511f | ||
|
|
e6fffc8ba4 | ||
|
|
86f221611e | ||
|
|
b4d6e89fa2 | ||
|
|
adbb6228a5 | ||
|
|
5937bd0259 | ||
|
|
eeafd43513 | ||
|
|
a68f95b65f | ||
|
|
ed3c29be12 | ||
|
|
3d2e956b19 | ||
|
|
dd9d1f95e9 | ||
|
|
a279c08f7d | ||
|
|
a798109161 | ||
|
|
5dfa929906 | ||
|
|
e904f612f3 | ||
|
|
bafd6b5423 | ||
|
|
963913f9ef | ||
|
|
46905588ac | ||
|
|
5426888df4 | ||
|
|
35481ec6d9 | ||
|
|
6c92c30e94 | ||
|
|
02f6b3ec98 | ||
|
|
a9848f2738 | ||
|
|
b4038a6cd2 | ||
|
|
95f3303493 | ||
|
|
2faf4a491b | ||
|
|
e646bba1ff | ||
|
|
99a21b0a3c | ||
|
|
e7a22b6bc5 | ||
|
|
d783bbc0bc | ||
|
|
b7405f3872 | ||
|
|
abc419b5f9 | ||
|
|
336378b114 | ||
|
|
29959551da | ||
|
|
fc78917191 | ||
|
|
ffd95ef5a9 | ||
|
|
230090d790 | ||
|
|
8fa3861ba3 | ||
|
|
69c90e3427 | ||
|
|
5a73f345fd | ||
|
|
0e62d759f0 | ||
|
|
b2967d2f77 | ||
|
|
c23039c07a | ||
|
|
5747c417c4 | ||
|
|
8c53d77111 | ||
|
|
01667cabde | ||
|
|
f649b62629 | ||
|
|
3a4d025b5c | ||
|
|
c2cc93a009 | ||
|
|
af29855802 | ||
|
|
99eb08eb1e | ||
|
|
d3f8c0d87f | ||
|
|
0bec7b996b | ||
|
|
dd5674fe6b | ||
|
|
33159c26df | ||
|
|
afc7dbebe5 | ||
|
|
f363acf839 | ||
|
|
96d5a7401d | ||
|
|
403fa20546 | ||
|
|
ba4d7ddca8 | ||
|
|
5116e2f210 | ||
|
|
9e0f198227 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,6 +5,9 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|
||||||
# Test binary, build with `go test -c`
|
# Test binary, build with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
|
|||||||
15
.travis.yml
15
.travis.yml
@@ -1,7 +1,10 @@
|
|||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
# TODO: Uncomment when tests running on Windows.
|
# TODO: Speed up the slowness of the osx travis runs
|
||||||
|
# Maybe cache brew installs?
|
||||||
|
#
|
||||||
|
# TODO: Uncomment when some gets the tests running on Windows.
|
||||||
# - windows
|
# - windows
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
@@ -20,24 +23,20 @@ git:
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- "1.12"
|
- "1.13"
|
||||||
|
|
||||||
go_import_path: sigs.k8s.io/kustomize
|
go_import_path: sigs.k8s.io/kustomize
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- source ./travis/consider-early-travis-exit.sh
|
- source ./travis/consider-early-travis-exit.sh
|
||||||
- curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.17.1
|
|
||||||
- go get -u github.com/monopole/mdrip
|
|
||||||
# The following would install Helm if needed for some reason.
|
|
||||||
# - wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz
|
|
||||||
# - tar -xvzf helm-v2.13.1-linux-amd64.tar.gz
|
|
||||||
# - sudo mv linux-amd64/helm /usr/local/bin/helm
|
|
||||||
|
|
||||||
# Skip the install process; let pre-commit.sh do it.
|
# Skip the install process; let pre-commit.sh do it.
|
||||||
install: true
|
install: true
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- ./travis/verify-deps.sh
|
||||||
- ./travis/pre-commit.sh
|
- ./travis/pre-commit.sh
|
||||||
|
- ./travis/kyaml-pre-commit.sh
|
||||||
|
|
||||||
# TBD. Suppressing for now.
|
# TBD. Suppressing for now.
|
||||||
notifications:
|
notifications:
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ _As contributors and maintainers of this project, and in the interest of fosteri
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
Dev guides:
|
||||||
|
|
||||||
|
- [Mac](docs/macDevGuide.md)
|
||||||
|
|
||||||
We have full documentation on how to get started contributing here:
|
We have full documentation on how to get started contributing here:
|
||||||
|
|
||||||
- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests
|
- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests
|
||||||
|
|||||||
79
Makefile
Normal file
79
Makefile
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# This Makefile is (and must be) used by
|
||||||
|
# travis/pre-commit.sh to qualify pull requests.
|
||||||
|
#
|
||||||
|
# That script generates all the code that needs
|
||||||
|
# to be generated, and runs all the tests.
|
||||||
|
#
|
||||||
|
# Functionality in that script, expressed in bash, is
|
||||||
|
# gradually being moved here.
|
||||||
|
|
||||||
|
MYGOBIN := $(shell go env GOPATH)/bin
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all:
|
||||||
|
./travis/pre-commit.sh
|
||||||
|
|
||||||
|
$(MYGOBIN)/golangci-lint:
|
||||||
|
cd api; go install github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||||
|
|
||||||
|
$(MYGOBIN)/mdrip:
|
||||||
|
cd api; go install github.com/monopole/mdrip
|
||||||
|
|
||||||
|
# TODO: need a new release of the API, followed by a new pluginator.
|
||||||
|
# pluginator v1.1.0 is too old for the code currently needed in the API.
|
||||||
|
# Can release a new one at any time, just haven't done so.
|
||||||
|
# When one has been released,
|
||||||
|
# - uncomment the pluginator line in './api/internal/tools/tools.go'
|
||||||
|
# - pin the version tag in './api/go.mod' to match the new release
|
||||||
|
# - change the following to 'cd api; go install sigs.k8s.io/kustomize/pluginator'
|
||||||
|
$(MYGOBIN)/pluginator:
|
||||||
|
cd pluginator; go install .
|
||||||
|
|
||||||
|
$(MYGOBIN)/stringer:
|
||||||
|
cd api; go install golang.org/x/tools/cmd/stringer
|
||||||
|
|
||||||
|
# Specific version tags for these utilities are pinned in ./api/go.mod
|
||||||
|
# which seems to be as good a place as any to do so.
|
||||||
|
# That's the reason for all the occurances of 'cd api;' in the
|
||||||
|
# dependencies; 'go install' uses the local 'go.mod' to get the version.
|
||||||
|
install-tools: $(MYGOBIN)/golangci-lint \
|
||||||
|
$(MYGOBIN)/mdrip \
|
||||||
|
$(MYGOBIN)/pluginator \
|
||||||
|
$(MYGOBIN)/stringer
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: install-tools
|
||||||
|
cd api; $(MYGOBIN)/golangci-lint run ./...
|
||||||
|
cd kustomize; $(MYGOBIN)/golangci-lint run ./...
|
||||||
|
cd pluginator; $(MYGOBIN)/golangci-lint run ./...
|
||||||
|
|
||||||
|
.PHONY: unit-test-api
|
||||||
|
unit-test-api:
|
||||||
|
cd api; go test ./...
|
||||||
|
|
||||||
|
.PHONY: unit-test-plugins
|
||||||
|
unit-test-plugins:
|
||||||
|
./hack/runPluginUnitTests.sh
|
||||||
|
|
||||||
|
.PHONY: unit-test-kustomize
|
||||||
|
unit-test-kustomize:
|
||||||
|
cd kustomize; go test ./...
|
||||||
|
|
||||||
|
.PHONY: unit-test-all
|
||||||
|
unit-test-all: unit-test-api unit-test-kustomize unit-test-plugins
|
||||||
|
|
||||||
|
# linux only.
|
||||||
|
$(MYGOBIN)/kubeval:
|
||||||
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
|
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz; \
|
||||||
|
tar xf kubeval-linux-amd64.tar.gz; \
|
||||||
|
mv kubeval $(MYGOBIN); \
|
||||||
|
rm -rf $$d
|
||||||
|
|
||||||
|
# linux only.
|
||||||
|
$(MYGOBIN)/helm:
|
||||||
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
|
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz; \
|
||||||
|
tar -xvzf helm-v2.13.1-linux-amd64.tar.gz; \
|
||||||
|
mv linux-amd64/helm $(MYGOBIN); \
|
||||||
|
rm -rf $$d
|
||||||
17
README.md
17
README.md
@@ -1,7 +1,5 @@
|
|||||||
# kustomize
|
# kustomize
|
||||||
|
|
||||||
_[v3.0.2](https://github.com/kubernetes-sigs/kustomize/releases/tag/v3.0.2) is the latest release._
|
|
||||||
|
|
||||||
`kustomize` lets you customize raw, template-free YAML
|
`kustomize` lets you customize raw, template-free YAML
|
||||||
files for multiple purposes, leaving the original YAML
|
files for multiple purposes, leaving the original YAML
|
||||||
untouched and usable as is.
|
untouched and usable as is.
|
||||||
@@ -24,8 +22,17 @@ these [instructions](docs/INSTALL.md).
|
|||||||
Browse the [docs](docs) or jump right into the
|
Browse the [docs](docs) or jump right into the
|
||||||
tested [examples](examples).
|
tested [examples](examples).
|
||||||
|
|
||||||
kustomize [v2.0.3] is available in [kubectl v1.14 and v1.15][kubectl].
|
## kubectl integration
|
||||||
|
|
||||||
|
Since [v1.14][kubectl announcement] the kustomize build system has been included in kubectl.
|
||||||
|
|
||||||
|
| kubectl version | kustomize version |
|
||||||
|
|---------|--------|
|
||||||
|
| v1.16.0 | [v2.0.3](https://github.com/kubernetes-sigs/kustomize/tree/v2.0.3) |
|
||||||
|
| v1.15.x | [v2.0.3](https://github.com/kubernetes-sigs/kustomize/tree/v2.0.3) |
|
||||||
|
| v1.14.x | [v2.0.3](https://github.com/kubernetes-sigs/kustomize/tree/v2.0.3) |
|
||||||
|
|
||||||
|
For examples and guides for using the kubectl integration please see the [kubectl book] or the [kubernetes documentation].
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -161,7 +168,9 @@ is governed by the [Kubernetes Code of Conduct].
|
|||||||
[imageBase]: docs/images/base.jpg
|
[imageBase]: docs/images/base.jpg
|
||||||
[imageOverlay]: docs/images/overlay.jpg
|
[imageOverlay]: docs/images/overlay.jpg
|
||||||
[kind/feature]: https://github.com/kubernetes-sigs/kustomize/labels/kind%2Ffeature
|
[kind/feature]: https://github.com/kubernetes-sigs/kustomize/labels/kind%2Ffeature
|
||||||
[kubectl]: https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement
|
[kubectl announcement]: https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement
|
||||||
|
[kubectl book]: https://kubectl.docs.kubernetes.io/pages/app_customization/introduction.html
|
||||||
|
[kubernetes documentation]: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
|
||||||
[kubernetes style]: docs/glossary.md#kubernetes-style-object
|
[kubernetes style]: docs/glossary.md#kubernetes-style-object
|
||||||
[kustomization]: docs/glossary.md#kustomization
|
[kustomization]: docs/glossary.md#kustomization
|
||||||
[overlay]: docs/glossary.md#overlay
|
[overlay]: docs/glossary.md#overlay
|
||||||
|
|||||||
39
api/builtins/annotationstransformer.go
Normal file
39
api/builtins/annotationstransformer.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Code generated by pluginator on AnnotationsTransformer; DO NOT EDIT.
|
||||||
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add the given annotations to the given field specifications.
|
||||||
|
type AnnotationsTransformerPlugin struct {
|
||||||
|
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||||
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AnnotationsTransformerPlugin) Config(
|
||||||
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
|
p.Annotations = nil
|
||||||
|
p.FieldSpecs = nil
|
||||||
|
return yaml.Unmarshal(c, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
t, err := transform.NewMapTransformer(
|
||||||
|
p.FieldSpecs,
|
||||||
|
p.Annotations,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return t.Transform(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &AnnotationsTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,28 +1,24 @@
|
|||||||
// Code generated by pluginator on ConfigMapGenerator; DO NOT EDIT.
|
// Code generated by pluginator on ConfigMapGenerator; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigMapGeneratorPlugin struct {
|
type ConfigMapGeneratorPlugin struct {
|
||||||
ldr ifc.Loader
|
h *resmap.PluginHelpers
|
||||||
rf *resmap.Factory
|
|
||||||
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||||
types.GeneratorOptions
|
types.GeneratorOptions
|
||||||
types.ConfigMapArgs
|
types.ConfigMapArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewConfigMapGeneratorPlugin() *ConfigMapGeneratorPlugin {
|
|
||||||
return &ConfigMapGeneratorPlugin{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConfigMapGeneratorPlugin) Config(
|
func (p *ConfigMapGeneratorPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
|
h *resmap.PluginHelpers, config []byte) (err error) {
|
||||||
p.GeneratorOptions = types.GeneratorOptions{}
|
p.GeneratorOptions = types.GeneratorOptions{}
|
||||||
p.ConfigMapArgs = types.ConfigMapArgs{}
|
p.ConfigMapArgs = types.ConfigMapArgs{}
|
||||||
err = yaml.Unmarshal(config, p)
|
err = yaml.Unmarshal(config, p)
|
||||||
@@ -32,11 +28,16 @@ func (p *ConfigMapGeneratorPlugin) Config(
|
|||||||
if p.ConfigMapArgs.Namespace == "" {
|
if p.ConfigMapArgs.Namespace == "" {
|
||||||
p.ConfigMapArgs.Namespace = p.Namespace
|
p.ConfigMapArgs.Namespace = p.Namespace
|
||||||
}
|
}
|
||||||
p.ldr = ldr
|
p.h = h
|
||||||
p.rf = rf
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ConfigMapGeneratorPlugin) Generate() (resmap.ResMap, error) {
|
func (p *ConfigMapGeneratorPlugin) Generate() (resmap.ResMap, error) {
|
||||||
return p.rf.FromConfigMapArgs(p.ldr, &p.GeneratorOptions, p.ConfigMapArgs)
|
return p.h.ResmapFactory().FromConfigMapArgs(
|
||||||
|
kv.NewLoader(p.h.Loader(), p.h.Validator()),
|
||||||
|
&p.GeneratorOptions, p.ConfigMapArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfigMapGeneratorPlugin() resmap.GeneratorPlugin {
|
||||||
|
return &ConfigMapGeneratorPlugin{}
|
||||||
}
|
}
|
||||||
8
api/builtins/doc.go
Normal file
8
api/builtins/doc.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Package builtins holds code generated from the builtin plugins.
|
||||||
|
// The "builtin" plugins are written as normal plugins and can
|
||||||
|
// be used as such, but they are also used to generate the code
|
||||||
|
// in this package so they can be statically linked to client code.
|
||||||
|
package builtins
|
||||||
@@ -1,25 +1,22 @@
|
|||||||
// Code generated by pluginator on HashTransformer; DO NOT EDIT.
|
// Code generated by pluginator on HashTransformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HashTransformerPlugin struct {
|
type HashTransformerPlugin struct {
|
||||||
hasher ifc.KunstructuredHasher
|
hasher ifc.KunstructuredHasher
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewHashTransformerPlugin() *HashTransformerPlugin {
|
|
||||||
return &HashTransformerPlugin{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *HashTransformerPlugin) Config(
|
func (p *HashTransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
|
h *resmap.PluginHelpers, config []byte) (err error) {
|
||||||
p.hasher = rf.RF().Hasher()
|
p.hasher = h.ResmapFactory().RF().Hasher()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,3 +33,7 @@ func (p *HashTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewHashTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &HashTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,34 +1,30 @@
|
|||||||
// Code generated by pluginator on ImageTagTransformer; DO NOT EDIT.
|
// Code generated by pluginator on ImageTagTransformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/image"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Find matching image declarations and replace
|
// Find matching image declarations and replace
|
||||||
// the name, tag and/or digest.
|
// the name, tag and/or digest.
|
||||||
type ImageTagTransformerPlugin struct {
|
type ImageTagTransformerPlugin struct {
|
||||||
ImageTag image.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
|
ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
|
||||||
FieldSpecs []config.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewImageTagTransformerPlugin() *ImageTagTransformerPlugin {
|
|
||||||
return &ImageTagTransformerPlugin{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ImageTagTransformerPlugin) Config(
|
func (p *ImageTagTransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
p.ImageTag = image.Image{}
|
p.ImageTag = types.Image{}
|
||||||
p.FieldSpecs = nil
|
p.FieldSpecs = nil
|
||||||
return yaml.Unmarshal(c, p)
|
return yaml.Unmarshal(c, p)
|
||||||
}
|
}
|
||||||
@@ -39,7 +35,7 @@ func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
if !r.OrgId().IsSelected(&path.Gvk) {
|
if !r.OrgId().IsSelected(&path.Gvk) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := transformers.MutateField(
|
err := transform.MutateField(
|
||||||
r.Map(), path.PathSlice(), false, p.mutateImage)
|
r.Map(), path.PathSlice(), false, p.mutateImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -183,3 +179,7 @@ func split(imageName string) (name string, tag string) {
|
|||||||
tag = imageName[i:]
|
tag = imageName[i:]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewImageTagTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &ImageTagTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,36 +1,30 @@
|
|||||||
// Code generated by pluginator on InventoryTransformer; DO NOT EDIT.
|
// Code generated by pluginator on InventoryTransformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/hasher"
|
||||||
|
"sigs.k8s.io/kustomize/api/inventory"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/hasher"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/inventory"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InventoryTransformerPlugin struct {
|
type InventoryTransformerPlugin struct {
|
||||||
ldr ifc.Loader
|
h *resmap.PluginHelpers
|
||||||
rf *resmap.Factory
|
|
||||||
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||||
Policy string `json:"policy,omitempty" yaml:"policy,omitempty"`
|
Policy string `json:"policy,omitempty" yaml:"policy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewInventoryTransformerPlugin() *InventoryTransformerPlugin {
|
|
||||||
return &InventoryTransformerPlugin{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *InventoryTransformerPlugin) Config(
|
func (p *InventoryTransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
p.ldr = ldr
|
p.h = h
|
||||||
p.rf = rf
|
|
||||||
err = yaml.Unmarshal(c, p)
|
err = yaml.Unmarshal(c, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -79,7 +73,8 @@ func (p *InventoryTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, err := p.rf.RF().MakeConfigMap(p.ldr, opts, &args)
|
cm, err := p.h.ResmapFactory().RF().MakeConfigMap(
|
||||||
|
kv.NewLoader(p.h.Loader(), p.h.Validator()), opts, &args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -127,3 +122,7 @@ func computeRefs(
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewInventoryTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &InventoryTransformerPlugin{}
|
||||||
|
}
|
||||||
39
api/builtins/labeltransformer.go
Normal file
39
api/builtins/labeltransformer.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Code generated by pluginator on LabelTransformer; DO NOT EDIT.
|
||||||
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add the given labels to the given field specifications.
|
||||||
|
type LabelTransformerPlugin struct {
|
||||||
|
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||||
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *LabelTransformerPlugin) Config(
|
||||||
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
|
p.Labels = nil
|
||||||
|
p.FieldSpecs = nil
|
||||||
|
return yaml.Unmarshal(c, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
t, err := transform.NewMapTransformer(
|
||||||
|
p.FieldSpecs,
|
||||||
|
p.Labels,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return t.Transform(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLabelTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &LabelTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
// Code generated by pluginator on LegacyOrderTransformer; DO NOT EDIT.
|
// Code generated by pluginator on LegacyOrderTransformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sort the resources using an ordering defined in the Gvk class.
|
// Sort the resources using an ordering defined in the Gvk class.
|
||||||
@@ -16,14 +18,9 @@ import (
|
|||||||
// (like ValidatingWebhookConfiguration) last.
|
// (like ValidatingWebhookConfiguration) last.
|
||||||
type LegacyOrderTransformerPlugin struct{}
|
type LegacyOrderTransformerPlugin struct{}
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewLegacyOrderTransformerPlugin() *LegacyOrderTransformerPlugin {
|
|
||||||
return &LegacyOrderTransformerPlugin{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing needed for configuration.
|
// Nothing needed for configuration.
|
||||||
func (p *LegacyOrderTransformerPlugin) Config(
|
func (p *LegacyOrderTransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,3 +40,7 @@ func (p *LegacyOrderTransformerPlugin) Transform(m resmap.ResMap) (err error) {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewLegacyOrderTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &LegacyOrderTransformerPlugin{}
|
||||||
|
}
|
||||||
131
api/builtins/namespacetransformer.go
Normal file
131
api/builtins/namespacetransformer.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
// Code generated by pluginator on NamespaceTransformer; DO NOT EDIT.
|
||||||
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Change or set the namespace of non-cluster level resources.
|
||||||
|
type NamespaceTransformerPlugin struct {
|
||||||
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||||
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *NamespaceTransformerPlugin) Config(
|
||||||
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
|
p.Namespace = ""
|
||||||
|
p.FieldSpecs = nil
|
||||||
|
return yaml.Unmarshal(c, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
if len(p.Namespace) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, r := range m.Resources() {
|
||||||
|
if len(r.Map()) == 0 {
|
||||||
|
// Don't mutate empty objects?
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
id := r.OrgId()
|
||||||
|
applicableFs := p.applicableFieldSpecs(id)
|
||||||
|
|
||||||
|
for _, fs := range applicableFs {
|
||||||
|
err := transform.MutateField(
|
||||||
|
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
|
||||||
|
p.changeNamespace(r))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
|
||||||
|
if len(matches) != 1 {
|
||||||
|
return fmt.Errorf("namespace tranformation produces ID conflict: %#v", matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const metaNamespace = "metadata/namespace"
|
||||||
|
|
||||||
|
// Special casing metadata.namespace since
|
||||||
|
// all objects have it, even "ClusterKind" objects
|
||||||
|
// that don't exist in a namespace (the Namespace
|
||||||
|
// object itself doesn't live in a namespace).
|
||||||
|
func (p *NamespaceTransformerPlugin) applicableFieldSpecs(id resid.ResId) []types.FieldSpec {
|
||||||
|
var res []types.FieldSpec
|
||||||
|
for _, fs := range p.FieldSpecs {
|
||||||
|
if id.IsSelected(&fs.Gvk) && (fs.Path != metaNamespace || (fs.Path == metaNamespace && id.IsNamespaceableKind())) {
|
||||||
|
res = append(res, fs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *NamespaceTransformerPlugin) changeNamespace(
|
||||||
|
referrer *resource.Resource) func(in interface{}) (interface{}, error) {
|
||||||
|
return func(in interface{}) (interface{}, error) {
|
||||||
|
switch in.(type) {
|
||||||
|
case string:
|
||||||
|
// will happen when the metadata/namespace
|
||||||
|
// value is replaced
|
||||||
|
return p.Namespace, nil
|
||||||
|
case []interface{}:
|
||||||
|
l, _ := in.([]interface{})
|
||||||
|
for idx, item := range l {
|
||||||
|
switch item.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Will happen when mutating the subjects
|
||||||
|
// field of ClusterRoleBinding and RoleBinding
|
||||||
|
inMap, _ := item.(map[string]interface{})
|
||||||
|
if _, ok := inMap["name"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, ok := inMap["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The only case we need to force the namespace
|
||||||
|
// if for the "service account". "default" is
|
||||||
|
// kind of hardcoded here for right now.
|
||||||
|
if name != "default" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inMap["namespace"] = p.Namespace
|
||||||
|
l[idx] = inMap
|
||||||
|
default:
|
||||||
|
// nothing to do for right now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return in, nil
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Will happen if the createField=true
|
||||||
|
// when the namespace is added to the
|
||||||
|
// object
|
||||||
|
inMap := in.(map[string]interface{})
|
||||||
|
if len(inMap) == 0 {
|
||||||
|
return p.Namespace, nil
|
||||||
|
} else {
|
||||||
|
return in, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return in, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNamespaceTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &NamespaceTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
// Code generated by pluginator on PatchJson6902Transformer; DO NOT EDIT.
|
// Code generated by pluginator on PatchJson6902Transformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
jsonpatch "github.com/evanphx/json-patch"
|
|
||||||
|
"github.com/evanphx/json-patch"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,14 +23,9 @@ type PatchJson6902TransformerPlugin struct {
|
|||||||
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
|
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewPatchJson6902TransformerPlugin() *PatchJson6902TransformerPlugin {
|
|
||||||
return &PatchJson6902TransformerPlugin{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PatchJson6902TransformerPlugin) Config(
|
func (p *PatchJson6902TransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
p.ldr = ldr
|
p.ldr = h.Loader()
|
||||||
err = yaml.Unmarshal(c, p)
|
err = yaml.Unmarshal(c, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -74,7 +71,7 @@ func (p *PatchJson6902TransformerPlugin) Config(
|
|||||||
|
|
||||||
func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
|
func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
id := resid.NewResIdWithNamespace(
|
id := resid.NewResIdWithNamespace(
|
||||||
gvk.Gvk{
|
resid.Gvk{
|
||||||
Group: p.Target.Group,
|
Group: p.Target.Group,
|
||||||
Version: p.Target.Version,
|
Version: p.Target.Version,
|
||||||
Kind: p.Target.Kind,
|
Kind: p.Target.Kind,
|
||||||
@@ -97,3 +94,7 @@ func (p *PatchJson6902TransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
return obj.UnmarshalJSON(modifiedObj)
|
return obj.UnmarshalJSON(modifiedObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPatchJson6902TransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &PatchJson6902TransformerPlugin{}
|
||||||
|
}
|
||||||
90
api/builtins/patchstrategicmergetransformer.go
Normal file
90
api/builtins/patchstrategicmergetransformer.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// Code generated by pluginator on PatchStrategicMergeTransformer; DO NOT EDIT.
|
||||||
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PatchStrategicMergeTransformerPlugin struct {
|
||||||
|
h *resmap.PluginHelpers
|
||||||
|
loadedPatches []*resource.Resource
|
||||||
|
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
|
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PatchStrategicMergeTransformerPlugin) Config(
|
||||||
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
|
p.h = h
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(p.Paths) == 0 && p.Patches == "" {
|
||||||
|
return fmt.Errorf("empty file path and empty patch content")
|
||||||
|
}
|
||||||
|
if len(p.Paths) != 0 {
|
||||||
|
for _, onePath := range p.Paths {
|
||||||
|
res, err := p.h.ResmapFactory().RF().SliceFromBytes([]byte(onePath))
|
||||||
|
if err == nil {
|
||||||
|
p.loadedPatches = append(p.loadedPatches, res...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res, err = p.h.ResmapFactory().RF().SliceFromPatches(
|
||||||
|
p.h.Loader(), []types.PatchStrategicMerge{onePath})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.loadedPatches = append(p.loadedPatches, res...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Patches != "" {
|
||||||
|
res, err := p.h.ResmapFactory().RF().SliceFromBytes([]byte(p.Patches))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.loadedPatches = append(p.loadedPatches, res...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.loadedPatches) == 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"patch appears to be empty; files=%v, Patch=%s", p.Paths, p.Patches)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PatchStrategicMergeTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
patches, err := p.h.ResmapFactory().MergePatches(p.loadedPatches)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, patch := range patches.Resources() {
|
||||||
|
target, err := m.GetById(patch.OrgId())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = target.Patch(patch.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// remove the resource from resmap
|
||||||
|
// when the patch is to $patch: delete that target
|
||||||
|
if len(target.Map()) == 0 {
|
||||||
|
err = m.Remove(target.CurId())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPatchStrategicMergeTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &PatchStrategicMergeTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,36 +1,29 @@
|
|||||||
// Code generated by pluginator on PatchTransformer; DO NOT EDIT.
|
// Code generated by pluginator on PatchTransformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/evanphx/json-patch"
|
"github.com/evanphx/json-patch"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PatchTransformerPlugin struct {
|
type PatchTransformerPlugin struct {
|
||||||
ldr ifc.Loader
|
|
||||||
rf *resmap.Factory
|
|
||||||
loadedPatch *resource.Resource
|
loadedPatch *resource.Resource
|
||||||
decodedPatch jsonpatch.Patch
|
decodedPatch jsonpatch.Patch
|
||||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||||
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||||
Target *types.Selector `json:"target,omitempty", yaml:"target,omitempty"`
|
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewPatchTransformerPlugin() *PatchTransformerPlugin {
|
|
||||||
return &PatchTransformerPlugin{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PatchTransformerPlugin) Config(
|
func (p *PatchTransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
p.ldr = ldr
|
|
||||||
p.rf = rf
|
|
||||||
err = yaml.Unmarshal(c, p)
|
err = yaml.Unmarshal(c, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -47,7 +40,7 @@ func (p *PatchTransformerPlugin) Config(
|
|||||||
}
|
}
|
||||||
var in []byte
|
var in []byte
|
||||||
if p.Path != "" {
|
if p.Path != "" {
|
||||||
in, err = ldr.Load(p.Path)
|
in, err = h.Loader().Load(p.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -56,7 +49,7 @@ func (p *PatchTransformerPlugin) Config(
|
|||||||
in = []byte(p.Patch)
|
in = []byte(p.Patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
patchSM, errSM := p.rf.RF().FromBytes(in)
|
patchSM, errSM := h.ResmapFactory().RF().FromBytes(in)
|
||||||
patchJson, errJson := jsonPatchFromBytes(in)
|
patchJson, errJson := jsonPatchFromBytes(in)
|
||||||
if errSM != nil && errJson != nil {
|
if errSM != nil && errJson != nil {
|
||||||
err = fmt.Errorf(
|
err = fmt.Errorf(
|
||||||
@@ -87,6 +80,7 @@ func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Target == nil {
|
if p.Target == nil {
|
||||||
@@ -97,9 +91,9 @@ func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, resource := range resources {
|
for _, res := range resources {
|
||||||
if p.decodedPatch != nil {
|
if p.decodedPatch != nil {
|
||||||
rawObj, err := resource.MarshalJSON()
|
rawObj, err := res.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -108,17 +102,17 @@ func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err, "failed to apply json patch '%s'", p.Patch)
|
err, "failed to apply json patch '%s'", p.Patch)
|
||||||
}
|
}
|
||||||
err = resource.UnmarshalJSON(modifiedObj)
|
err = res.UnmarshalJSON(modifiedObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.loadedPatch != nil {
|
if p.loadedPatch != nil {
|
||||||
patchCopy := p.loadedPatch.DeepCopy()
|
patchCopy := p.loadedPatch.DeepCopy()
|
||||||
patchCopy.SetName(resource.GetName())
|
patchCopy.SetName(res.GetName())
|
||||||
patchCopy.SetNamespace(resource.GetNamespace())
|
patchCopy.SetNamespace(res.GetNamespace())
|
||||||
patchCopy.SetGvk(resource.GetGvk())
|
patchCopy.SetGvk(res.GetGvk())
|
||||||
err = resource.Patch(patchCopy.Kunstructured)
|
err = res.Patch(patchCopy.Kunstructured)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -145,3 +139,7 @@ func jsonPatchFromBytes(
|
|||||||
}
|
}
|
||||||
return jsonpatch.DecodePatch([]byte(ops))
|
return jsonpatch.DecodePatch([]byte(ops))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPatchTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &PatchTransformerPlugin{}
|
||||||
|
}
|
||||||
123
api/builtins/prefixsuffixtransformer.go
Normal file
123
api/builtins/prefixsuffixtransformer.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
// Code generated by pluginator on PrefixSuffixTransformer; DO NOT EDIT.
|
||||||
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add the given prefix and suffix to the field.
|
||||||
|
type PrefixSuffixTransformerPlugin struct {
|
||||||
|
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
|
||||||
|
Suffix string `json:"suffix,omitempty" yaml:"suffix,omitempty"`
|
||||||
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not placed in a file yet due to lack of demand.
|
||||||
|
var prefixSuffixFieldSpecsToSkip = []types.FieldSpec{
|
||||||
|
{
|
||||||
|
Gvk: resid.Gvk{Kind: "CustomResourceDefinition"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Gvk: resid.Gvk{Group: "apiregistration.k8s.io", Kind: "APIService"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PrefixSuffixTransformerPlugin) Config(
|
||||||
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
|
p.Prefix = ""
|
||||||
|
p.Suffix = ""
|
||||||
|
p.FieldSpecs = nil
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.FieldSpecs == nil {
|
||||||
|
return errors.New("fieldSpecs is not expected to be nil")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
|
||||||
|
// Even if both the Prefix and Suffix are empty we want
|
||||||
|
// to proceed with the transformation. This allows to add contextual
|
||||||
|
// information to the resources (AddNamePrefix and AddNameSuffix).
|
||||||
|
|
||||||
|
for _, r := range m.Resources() {
|
||||||
|
if p.shouldSkip(r.OrgId()) {
|
||||||
|
// Don't change the actual definition
|
||||||
|
// of a CRD.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
id := r.OrgId()
|
||||||
|
// current default configuration contains
|
||||||
|
// only one entry: "metadata/name" with no GVK
|
||||||
|
for _, path := range p.FieldSpecs {
|
||||||
|
if !id.IsSelected(&path.Gvk) {
|
||||||
|
// With the currrent default configuration,
|
||||||
|
// because no Gvk is specified, so a wild
|
||||||
|
// card
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if smellsLikeANameChange(&path) {
|
||||||
|
// "metadata/name" is the only field.
|
||||||
|
// this will add a prefix and a suffix
|
||||||
|
// to the resource even if those are
|
||||||
|
// empty
|
||||||
|
r.AddNamePrefix(p.Prefix)
|
||||||
|
r.AddNameSuffix(p.Suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the addPrefixSuffix method will not
|
||||||
|
// change the name if both the prefix and suffix
|
||||||
|
// are empty.
|
||||||
|
err := transform.MutateField(
|
||||||
|
r.Map(),
|
||||||
|
path.PathSlice(),
|
||||||
|
path.CreateIfNotPresent,
|
||||||
|
p.addPrefixSuffix)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func smellsLikeANameChange(fs *types.FieldSpec) bool {
|
||||||
|
return fs.Path == "metadata/name"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PrefixSuffixTransformerPlugin) shouldSkip(
|
||||||
|
id resid.ResId) bool {
|
||||||
|
for _, path := range prefixSuffixFieldSpecsToSkip {
|
||||||
|
if id.IsSelected(&path.Gvk) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PrefixSuffixTransformerPlugin) addPrefixSuffix(
|
||||||
|
in interface{}) (interface{}, error) {
|
||||||
|
s, ok := in.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%#v is expected to be %T", in, s)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s%s%s", p.Prefix, s, p.Suffix), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPrefixSuffixTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &PrefixSuffixTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,32 +1,28 @@
|
|||||||
// Code generated by pluginator on ReplicaCountTransformer; DO NOT EDIT.
|
// Code generated by pluginator on ReplicaCountTransformer; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Find matching replicas declarations and replace the count.
|
// Find matching replicas declarations and replace the count.
|
||||||
// Eases the kustomization configuration of replica changes.
|
// Eases the kustomization configuration of replica changes.
|
||||||
type ReplicaCountTransformerPlugin struct {
|
type ReplicaCountTransformerPlugin struct {
|
||||||
Replica types.Replica `json:"replica,omitempty" yaml:"replica,omitempty"`
|
Replica types.Replica `json:"replica,omitempty" yaml:"replica,omitempty"`
|
||||||
FieldSpecs []config.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
|
||||||
func NewReplicaCountTransformerPlugin() *ReplicaCountTransformerPlugin {
|
|
||||||
return &ReplicaCountTransformerPlugin{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReplicaCountTransformerPlugin) Config(
|
func (p *ReplicaCountTransformerPlugin) Config(
|
||||||
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
h *resmap.PluginHelpers, c []byte) (err error) {
|
||||||
|
|
||||||
p.Replica = types.Replica{}
|
p.Replica = types.Replica{}
|
||||||
p.FieldSpecs = nil
|
p.FieldSpecs = nil
|
||||||
@@ -34,9 +30,15 @@ func (p *ReplicaCountTransformerPlugin) Config(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
|
func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
found := false
|
||||||
for i, replicaSpec := range p.FieldSpecs {
|
for i, replicaSpec := range p.FieldSpecs {
|
||||||
for _, res := range m.GetMatchingResourcesByOriginalId(p.createMatcher(i)) {
|
matcher := p.createMatcher(i)
|
||||||
err := transformers.MutateField(
|
matchOriginal := m.GetMatchingResourcesByOriginalId(matcher)
|
||||||
|
matchCurrent := m.GetMatchingResourcesByCurrentId(matcher)
|
||||||
|
|
||||||
|
for _, res := range append(matchOriginal, matchCurrent...) {
|
||||||
|
found = true
|
||||||
|
err := transform.MutateField(
|
||||||
res.Map(), replicaSpec.PathSlice(),
|
res.Map(), replicaSpec.PathSlice(),
|
||||||
replicaSpec.CreateIfNotPresent, p.addReplicas)
|
replicaSpec.CreateIfNotPresent, p.addReplicas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,6 +47,15 @@ func (p *ReplicaCountTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
gvks := make([]string, len(p.FieldSpecs))
|
||||||
|
for i, replicaSpec := range p.FieldSpecs {
|
||||||
|
gvks[i] = replicaSpec.Gvk.String()
|
||||||
|
}
|
||||||
|
return fmt.Errorf("resource with name %s does not match a config with the following GVK %v",
|
||||||
|
p.Replica.Name, gvks)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,3 +83,7 @@ func (p *ReplicaCountTransformerPlugin) addReplicas(in interface{}) (interface{}
|
|||||||
}
|
}
|
||||||
return p.Replica.Count, nil
|
return p.Replica.Count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewReplicaCountTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
return &ReplicaCountTransformerPlugin{}
|
||||||
|
}
|
||||||
@@ -1,28 +1,23 @@
|
|||||||
// Code generated by pluginator on SecretGenerator; DO NOT EDIT.
|
// Code generated by pluginator on SecretGenerator; DO NOT EDIT.
|
||||||
package builtin
|
// pluginator {Version:unknown GitCommit:$Format:%H$ BuildDate:1970-01-01T00:00:00Z GoOs:linux GoArch:amd64}
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretGeneratorPlugin struct {
|
type SecretGeneratorPlugin struct {
|
||||||
ldr ifc.Loader
|
h *resmap.PluginHelpers
|
||||||
rf *resmap.Factory
|
|
||||||
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||||
types.GeneratorOptions
|
types.GeneratorOptions
|
||||||
types.SecretArgs
|
types.SecretArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection GoUnusedGlobalVariable
|
func (p *SecretGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
|
||||||
func NewSecretGeneratorPlugin() *SecretGeneratorPlugin {
|
|
||||||
return &SecretGeneratorPlugin{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *SecretGeneratorPlugin) Config(
|
|
||||||
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
|
|
||||||
p.GeneratorOptions = types.GeneratorOptions{}
|
p.GeneratorOptions = types.GeneratorOptions{}
|
||||||
p.SecretArgs = types.SecretArgs{}
|
p.SecretArgs = types.SecretArgs{}
|
||||||
err = yaml.Unmarshal(config, p)
|
err = yaml.Unmarshal(config, p)
|
||||||
@@ -32,11 +27,16 @@ func (p *SecretGeneratorPlugin) Config(
|
|||||||
if p.SecretArgs.Namespace == "" {
|
if p.SecretArgs.Namespace == "" {
|
||||||
p.SecretArgs.Namespace = p.Namespace
|
p.SecretArgs.Namespace = p.Namespace
|
||||||
}
|
}
|
||||||
p.ldr = ldr
|
p.h = h
|
||||||
p.rf = rf
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SecretGeneratorPlugin) Generate() (resmap.ResMap, error) {
|
func (p *SecretGeneratorPlugin) Generate() (resmap.ResMap, error) {
|
||||||
return p.rf.FromSecretArgs(p.ldr, &p.GeneratorOptions, p.SecretArgs)
|
return p.h.ResmapFactory().FromSecretArgs(
|
||||||
|
kv.NewLoader(p.h.Loader(), p.h.Validator()),
|
||||||
|
&p.GeneratorOptions, p.SecretArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSecretGeneratorPlugin() resmap.GeneratorPlugin {
|
||||||
|
return &SecretGeneratorPlugin{}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package filesys
|
||||||
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 fs
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -27,7 +14,7 @@ import (
|
|||||||
type ConfirmedDir string
|
type ConfirmedDir string
|
||||||
|
|
||||||
// NewTmpConfirmedDir returns a temporary dir, else error.
|
// NewTmpConfirmedDir returns a temporary dir, else error.
|
||||||
// The directory is cleaned, no symlinks, etc. so its
|
// The directory is cleaned, no symlinks, etc. so it's
|
||||||
// returned as a ConfirmedDir.
|
// returned as a ConfirmedDir.
|
||||||
func NewTmpConfirmedDir() (ConfirmedDir, error) {
|
func NewTmpConfirmedDir() (ConfirmedDir, error) {
|
||||||
n, err := ioutil.TempDir("", "kustomize-")
|
n, err := ioutil.TempDir("", "kustomize-")
|
||||||
@@ -36,13 +23,12 @@ func NewTmpConfirmedDir() (ConfirmedDir, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In MacOs `ioutil.TempDir` creates a directory
|
// In MacOs `ioutil.TempDir` creates a directory
|
||||||
// with root in the `/var` folder, which is in turn a symlinked path
|
// with root in the `/var` folder, which is in turn
|
||||||
// to `/private/var`.
|
// a symlinked path to `/private/var`.
|
||||||
// Function `filepath.EvalSymlinks`is used to
|
// Function `filepath.EvalSymlinks`is used to
|
||||||
// resolve the real absolute path.
|
// resolve the real absolute path.
|
||||||
deLinked, err := filepath.EvalSymlinks(n)
|
deLinked, err := filepath.EvalSymlinks(n)
|
||||||
return ConfirmedDir(deLinked), err
|
return ConfirmedDir(deLinked), err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasPrefix returns true if the directory argument
|
// HasPrefix returns true if the directory argument
|
||||||
@@ -1,28 +1,17 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package filesys_test
|
||||||
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 fs
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
. "sigs.k8s.io/kustomize/api/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestJoin(t *testing.T) {
|
func TestJoin(t *testing.T) {
|
||||||
fSys := MakeFakeFS()
|
fSys := MakeFsInMemory()
|
||||||
err := fSys.Mkdir("/foo")
|
err := fSys.Mkdir("/foo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
@@ -40,7 +29,8 @@ func TestJoin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasPrefix_Slash(t *testing.T) {
|
func TestHasPrefix_Slash(t *testing.T) {
|
||||||
d, f, err := MakeFakeFS().CleanedAbs("/")
|
fSys := MakeFsInMemory()
|
||||||
|
d, f, err := fSys.CleanedAbs("/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
@@ -56,7 +46,7 @@ func TestHasPrefix_Slash(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasPrefix_SlashFoo(t *testing.T) {
|
func TestHasPrefix_SlashFoo(t *testing.T) {
|
||||||
fSys := MakeFakeFS()
|
fSys := MakeFsInMemory()
|
||||||
err := fSys.Mkdir("/foo")
|
err := fSys.Mkdir("/foo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
@@ -77,7 +67,7 @@ func TestHasPrefix_SlashFoo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasPrefix_SlashFooBar(t *testing.T) {
|
func TestHasPrefix_SlashFooBar(t *testing.T) {
|
||||||
fSys := MakeFakeFS()
|
fSys := MakeFsInMemory()
|
||||||
err := fSys.MkdirAll("/foo/bar")
|
err := fSys.MkdirAll("/foo/bar")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
41
api/filesys/file.go
Normal file
41
api/filesys/file.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ os.FileInfo = &fileInfo{}
|
||||||
|
|
||||||
|
// fileInfo implements os.FileInfo for a fileInMemory instance.
|
||||||
|
type fileInfo struct {
|
||||||
|
*fileInMemory
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the file
|
||||||
|
func (fi *fileInfo) Name() string { return fi.name }
|
||||||
|
|
||||||
|
// Size returns the size of the file
|
||||||
|
func (fi *fileInfo) Size() int64 { return int64(len(fi.content)) }
|
||||||
|
|
||||||
|
// Mode returns the file mode
|
||||||
|
func (fi *fileInfo) Mode() os.FileMode { return 0777 }
|
||||||
|
|
||||||
|
// ModTime returns the modification time
|
||||||
|
func (fi *fileInfo) ModTime() time.Time { return time.Time{} }
|
||||||
|
|
||||||
|
// IsDir returns if it is a directory
|
||||||
|
func (fi *fileInfo) IsDir() bool { return fi.dir }
|
||||||
|
|
||||||
|
// Sys should return underlying data source, but it now returns nil
|
||||||
|
func (fi *fileInfo) Sys() interface{} { return nil }
|
||||||
|
|
||||||
|
// File groups the basic os.File methods.
|
||||||
|
type File interface {
|
||||||
|
io.ReadWriteCloser
|
||||||
|
Stat() (os.FileInfo, error)
|
||||||
|
}
|
||||||
56
api/filesys/fileinmemory.go
Normal file
56
api/filesys/fileinmemory.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ File = &fileInMemory{}
|
||||||
|
|
||||||
|
// fileInMemory implements File in-memory for tests.
|
||||||
|
type fileInMemory struct {
|
||||||
|
name string
|
||||||
|
content []byte
|
||||||
|
dir bool
|
||||||
|
open bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeDir makes a fake directory.
|
||||||
|
func makeDir(name string) *fileInMemory {
|
||||||
|
return &fileInMemory{name: name, dir: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close marks the fake file closed.
|
||||||
|
func (f *fileInMemory) Close() error {
|
||||||
|
f.open = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read never fails, and doesn't mutate p.
|
||||||
|
func (f *fileInMemory) Read(p []byte) (n int, err error) {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write saves the contents of the argument to memory.
|
||||||
|
func (f *fileInMemory) Write(p []byte) (n int, err error) {
|
||||||
|
f.content = p
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentMatches returns true if v matches fake file's content.
|
||||||
|
func (f *fileInMemory) ContentMatches(v []byte) bool {
|
||||||
|
return bytes.Equal(v, f.content)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContent the content of a fake file.
|
||||||
|
func (f *fileInMemory) GetContent() []byte {
|
||||||
|
return f.content
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns nil.
|
||||||
|
func (f *fileInMemory) Stat() (os.FileInfo, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
27
api/filesys/fileondisk.go
Normal file
27
api/filesys/fileondisk.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ File = &fileOnDisk{}
|
||||||
|
|
||||||
|
// fileOnDisk implements File using the local filesystem.
|
||||||
|
type fileOnDisk struct {
|
||||||
|
file *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes a file.
|
||||||
|
func (f *fileOnDisk) Close() error { return f.file.Close() }
|
||||||
|
|
||||||
|
// Read reads a file's content.
|
||||||
|
func (f *fileOnDisk) Read(p []byte) (n int, err error) { return f.file.Read(p) }
|
||||||
|
|
||||||
|
// Write writes bytes to a file
|
||||||
|
func (f *fileOnDisk) Write(p []byte) (n int, err error) { return f.file.Write(p) }
|
||||||
|
|
||||||
|
// Stat returns an interface which has all the information regarding the file.
|
||||||
|
func (f *fileOnDisk) Stat() (os.FileInfo, error) { return f.file.Stat() }
|
||||||
41
api/filesys/filesystem.go
Normal file
41
api/filesys/filesystem.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Package filesys provides a file system abstraction layer.
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileSystem groups basic os filesystem methods.
|
||||||
|
type FileSystem interface {
|
||||||
|
// Create a file.
|
||||||
|
Create(name string) (File, error)
|
||||||
|
// MkDir makes a directory.
|
||||||
|
Mkdir(path string) error
|
||||||
|
// MkDir makes a directory path, creating intervening directories.
|
||||||
|
MkdirAll(path string) error
|
||||||
|
// RemoveAll removes path and any children it contains.
|
||||||
|
RemoveAll(path string) error
|
||||||
|
// Open opens the named file for reading.
|
||||||
|
Open(path string) (File, error)
|
||||||
|
// IsDir returns true if the path is a directory.
|
||||||
|
IsDir(path string) bool
|
||||||
|
// CleanedAbs converts the given path into a
|
||||||
|
// directory and a file name, where the directory
|
||||||
|
// is represented as a ConfirmedDir and all that implies.
|
||||||
|
// If the entire path is a directory, the file component
|
||||||
|
// is an empty string.
|
||||||
|
CleanedAbs(path string) (ConfirmedDir, string, error)
|
||||||
|
// Exists is true if the path exists in the file system.
|
||||||
|
Exists(path string) bool
|
||||||
|
// Glob returns the list of matching files
|
||||||
|
Glob(pattern string) ([]string, error)
|
||||||
|
// ReadFile returns the contents of the file at the given path.
|
||||||
|
ReadFile(path string) ([]byte, error)
|
||||||
|
// WriteFile writes the data to a file at the given path.
|
||||||
|
WriteFile(path string, data []byte) error
|
||||||
|
// Walk walks the file system with the given WalkFunc.
|
||||||
|
Walk(path string, walkFn filepath.WalkFunc) error
|
||||||
|
}
|
||||||
223
api/filesys/fsinmemory.go
Normal file
223
api/filesys/fsinmemory.go
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ FileSystem = &fsInMemory{}
|
||||||
|
|
||||||
|
// fsInMemory implements FileSystem using a in-memory filesystem
|
||||||
|
// primarily for use in tests.
|
||||||
|
type fsInMemory struct {
|
||||||
|
m map[string]*fileInMemory
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeFsInMemory returns an instance of fsInMemory with no files in it.
|
||||||
|
func MakeFsInMemory() FileSystem {
|
||||||
|
result := &fsInMemory{m: map[string]*fileInMemory{}}
|
||||||
|
result.Mkdir(separator)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
separator = string(filepath.Separator)
|
||||||
|
doubleSep = separator + separator
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create assures a fake file appears in the in-memory file system.
|
||||||
|
func (fs *fsInMemory) Create(name string) (File, error) {
|
||||||
|
f := &fileInMemory{}
|
||||||
|
f.open = true
|
||||||
|
fs.m[name] = f
|
||||||
|
return fs.m[name], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdir assures a fake directory appears in the in-memory file system.
|
||||||
|
func (fs *fsInMemory) Mkdir(name string) error {
|
||||||
|
fs.m[name] = makeDir(name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MkdirAll delegates to Mkdir
|
||||||
|
func (fs *fsInMemory) MkdirAll(name string) error {
|
||||||
|
return fs.Mkdir(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAll presumably does rm -r on a path.
|
||||||
|
// There's no error.
|
||||||
|
func (fs *fsInMemory) RemoveAll(name string) error {
|
||||||
|
var toRemove []string
|
||||||
|
for k := range fs.m {
|
||||||
|
if strings.HasPrefix(k, name) {
|
||||||
|
toRemove = append(toRemove, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, k := range toRemove {
|
||||||
|
delete(fs.m, k)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open returns a fake file in the open state.
|
||||||
|
func (fs *fsInMemory) Open(name string) (File, error) {
|
||||||
|
if _, found := fs.m[name]; !found {
|
||||||
|
return nil, fmt.Errorf("file %q cannot be opened", name)
|
||||||
|
}
|
||||||
|
return fs.m[name], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanedAbs cannot fail.
|
||||||
|
func (fs *fsInMemory) CleanedAbs(path string) (ConfirmedDir, string, error) {
|
||||||
|
if fs.IsDir(path) {
|
||||||
|
return ConfirmedDir(path), "", nil
|
||||||
|
}
|
||||||
|
d := filepath.Dir(path)
|
||||||
|
if d == path {
|
||||||
|
return ConfirmedDir(d), "", nil
|
||||||
|
}
|
||||||
|
return ConfirmedDir(d), filepath.Base(path), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exists returns true if file is known.
|
||||||
|
func (fs *fsInMemory) Exists(name string) bool {
|
||||||
|
_, found := fs.m[name]
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glob returns the list of matching files
|
||||||
|
func (fs *fsInMemory) Glob(pattern string) ([]string, error) {
|
||||||
|
var result []string
|
||||||
|
for p := range fs.m {
|
||||||
|
if fs.pathMatch(p, pattern) {
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(result)
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDir returns true if the file exists and is a directory.
|
||||||
|
func (fs *fsInMemory) IsDir(name string) bool {
|
||||||
|
f, found := fs.m[name]
|
||||||
|
if found && f.dir {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(name, separator) {
|
||||||
|
name = name + separator
|
||||||
|
}
|
||||||
|
for k := range fs.m {
|
||||||
|
if strings.HasPrefix(k, name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFile always returns an empty bytes and error depending on content of m.
|
||||||
|
func (fs *fsInMemory) ReadFile(name string) ([]byte, error) {
|
||||||
|
if ff, found := fs.m[name]; found {
|
||||||
|
return ff.content, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("cannot read file %q", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteFile always succeeds and does nothing.
|
||||||
|
func (fs *fsInMemory) WriteFile(name string, c []byte) error {
|
||||||
|
ff := &fileInMemory{}
|
||||||
|
ff.Write(c)
|
||||||
|
fs.m[name] = ff
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk implements filepath.Walk using the fake filesystem.
|
||||||
|
func (fs *fsInMemory) Walk(path string, walkFn filepath.WalkFunc) error {
|
||||||
|
info, err := fs.lstat(path)
|
||||||
|
if err != nil {
|
||||||
|
err = walkFn(path, info, err)
|
||||||
|
} else {
|
||||||
|
err = fs.walk(path, info, walkFn)
|
||||||
|
}
|
||||||
|
if err == filepath.SkipDir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *fsInMemory) pathMatch(path, pattern string) bool {
|
||||||
|
match, _ := filepath.Match(pattern, path)
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *fsInMemory) lstat(path string) (*fileInfo, error) {
|
||||||
|
f, found := fs.m[path]
|
||||||
|
if !found {
|
||||||
|
return nil, os.ErrNotExist
|
||||||
|
}
|
||||||
|
return &fileInfo{f}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *fsInMemory) join(elem ...string) string {
|
||||||
|
for i, e := range elem {
|
||||||
|
if e != "" {
|
||||||
|
return strings.Replace(
|
||||||
|
strings.Join(elem[i:], separator), doubleSep, separator, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *fsInMemory) readDirNames(path string) []string {
|
||||||
|
var names []string
|
||||||
|
if !strings.HasSuffix(path, separator) {
|
||||||
|
path += separator
|
||||||
|
}
|
||||||
|
pathSegments := strings.Count(path, separator)
|
||||||
|
for name := range fs.m {
|
||||||
|
if name == path {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Count(name, separator) > pathSegments {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(name, path) {
|
||||||
|
names = append(names, filepath.Base(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *fsInMemory) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
|
||||||
|
if !info.IsDir() {
|
||||||
|
return walkFn(path, info, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
names := fs.readDirNames(path)
|
||||||
|
if err := walkFn(path, info, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, name := range names {
|
||||||
|
filename := fs.join(path, name)
|
||||||
|
fileInfo, err := fs.lstat(filename)
|
||||||
|
if err != nil {
|
||||||
|
if err := walkFn(filename, fileInfo, os.ErrNotExist); err != nil && err != filepath.SkipDir {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = fs.walk(filename, fileInfo, walkFn)
|
||||||
|
if err != nil {
|
||||||
|
if !fileInfo.IsDir() || err != filepath.SkipDir {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
149
api/filesys/fsinmemory_test.go
Normal file
149
api/filesys/fsinmemory_test.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filesys_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExists(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
if fSys.Exists("foo") {
|
||||||
|
t.Fatalf("expected no foo")
|
||||||
|
}
|
||||||
|
fSys.Mkdir("/")
|
||||||
|
if !fSys.IsDir("/") {
|
||||||
|
t.Fatalf("expected dir at /")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsDir(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
expectedName := "my-dir"
|
||||||
|
err := fSys.Mkdir(expectedName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
shouldExist(t, fSys, expectedName)
|
||||||
|
if !fSys.IsDir(expectedName) {
|
||||||
|
t.Fatalf(expectedName + " should be a dir")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldExist(t *testing.T, fSys FileSystem, name string) {
|
||||||
|
if !fSys.Exists(name) {
|
||||||
|
t.Fatalf(name + " should exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldNotExist(t *testing.T, fSys FileSystem, name string) {
|
||||||
|
if fSys.Exists(name) {
|
||||||
|
t.Fatalf(name + " should not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAll(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
fSys.WriteFile("/foo/project/file.yaml", []byte("Unused"))
|
||||||
|
fSys.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused"))
|
||||||
|
fSys.WriteFile("/foo/apple/subdir/file.yaml", []byte("Unused"))
|
||||||
|
shouldExist(t, fSys, "/foo/project/file.yaml")
|
||||||
|
shouldExist(t, fSys, "/foo/project/subdir/file.yaml")
|
||||||
|
shouldExist(t, fSys, "/foo/apple/subdir/file.yaml")
|
||||||
|
err := fSys.RemoveAll("/foo/project")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
shouldNotExist(t, fSys, "/foo/project/file.yaml")
|
||||||
|
shouldNotExist(t, fSys, "/foo/project/subdir/file.yaml")
|
||||||
|
shouldExist(t, fSys, "/foo/apple/subdir/file.yaml")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsDirDeeper(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
fSys.WriteFile("/foo/project/file.yaml", []byte("Unused"))
|
||||||
|
fSys.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused"))
|
||||||
|
if !fSys.IsDir("/") {
|
||||||
|
t.Fatalf("/ should be a dir")
|
||||||
|
}
|
||||||
|
if !fSys.IsDir("/foo") {
|
||||||
|
t.Fatalf("/foo should be a dir")
|
||||||
|
}
|
||||||
|
if !fSys.IsDir("/foo/project") {
|
||||||
|
t.Fatalf("/foo/project should be a dir")
|
||||||
|
}
|
||||||
|
if fSys.IsDir("/fo") {
|
||||||
|
t.Fatalf("/fo should not be a dir")
|
||||||
|
}
|
||||||
|
if fSys.IsDir("/x") {
|
||||||
|
t.Fatalf("/x should not be a dir")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
f, err := fSys.Create("foo")
|
||||||
|
if f == nil {
|
||||||
|
t.Fatalf("expected file")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error")
|
||||||
|
}
|
||||||
|
shouldExist(t, fSys, "foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadFile(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
f, err := fSys.Create("foo")
|
||||||
|
if f == nil {
|
||||||
|
t.Fatalf("expected file")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error")
|
||||||
|
}
|
||||||
|
content, err := fSys.ReadFile("foo")
|
||||||
|
if len(content) != 0 {
|
||||||
|
t.Fatalf("expected no content")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteFile(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
c := []byte("heybuddy")
|
||||||
|
err := fSys.WriteFile("foo", c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error")
|
||||||
|
}
|
||||||
|
content, err := fSys.ReadFile("foo")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected read to work: %v", err)
|
||||||
|
}
|
||||||
|
if bytes.Compare(c, content) != 0 {
|
||||||
|
t.Fatalf("incorrect content: %v", content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGlob(t *testing.T) {
|
||||||
|
fSys := MakeFsInMemory()
|
||||||
|
fSys.Create("dir/foo")
|
||||||
|
fSys.Create("dir/bar")
|
||||||
|
files, err := fSys.Glob("dir/*")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error")
|
||||||
|
}
|
||||||
|
expected := []string{
|
||||||
|
"dir/bar",
|
||||||
|
"dir/foo",
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(files, expected) {
|
||||||
|
t.Fatalf("incorrect files found by glob: %v", files)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package filesys
|
||||||
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 fs
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -24,43 +11,43 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ FileSystem = realFS{}
|
var _ FileSystem = fsOnDisk{}
|
||||||
|
|
||||||
// realFS implements FileSystem using the local filesystem.
|
// fsOnDisk implements FileSystem using the local filesystem.
|
||||||
type realFS struct{}
|
type fsOnDisk struct{}
|
||||||
|
|
||||||
// MakeRealFS makes an instance of realFS.
|
// MakeFsOnDisk makes an instance of fsOnDisk.
|
||||||
func MakeRealFS() FileSystem {
|
func MakeFsOnDisk() FileSystem {
|
||||||
return realFS{}
|
return fsOnDisk{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create delegates to os.Create.
|
// Create delegates to os.Create.
|
||||||
func (realFS) Create(name string) (File, error) { return os.Create(name) }
|
func (fsOnDisk) Create(name string) (File, error) { return os.Create(name) }
|
||||||
|
|
||||||
// Mkdir delegates to os.Mkdir.
|
// Mkdir delegates to os.Mkdir.
|
||||||
func (realFS) Mkdir(name string) error {
|
func (fsOnDisk) Mkdir(name string) error {
|
||||||
return os.Mkdir(name, 0777|os.ModeDir)
|
return os.Mkdir(name, 0777|os.ModeDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MkdirAll delegates to os.MkdirAll.
|
// MkdirAll delegates to os.MkdirAll.
|
||||||
func (realFS) MkdirAll(name string) error {
|
func (fsOnDisk) MkdirAll(name string) error {
|
||||||
return os.MkdirAll(name, 0777|os.ModeDir)
|
return os.MkdirAll(name, 0777|os.ModeDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAll delegates to os.RemoveAll.
|
// RemoveAll delegates to os.RemoveAll.
|
||||||
func (realFS) RemoveAll(name string) error {
|
func (fsOnDisk) RemoveAll(name string) error {
|
||||||
return os.RemoveAll(name)
|
return os.RemoveAll(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open delegates to os.Open.
|
// Open delegates to os.Open.
|
||||||
func (realFS) Open(name string) (File, error) { return os.Open(name) }
|
func (fsOnDisk) Open(name string) (File, error) { return os.Open(name) }
|
||||||
|
|
||||||
// CleanedAbs returns a cleaned, absolute path
|
// CleanedAbs converts the given path into a
|
||||||
// with no symbolic links split into directory
|
// directory and a file name, where the directory
|
||||||
// and file components. If the entire path is
|
// is represented as a ConfirmedDir and all that implies.
|
||||||
// a directory, the file component is an empty
|
// If the entire path is a directory, the file component
|
||||||
// string.
|
// is an empty string.
|
||||||
func (x realFS) CleanedAbs(
|
func (x fsOnDisk) CleanedAbs(
|
||||||
path string) (ConfirmedDir, string, error) {
|
path string) (ConfirmedDir, string, error) {
|
||||||
absRoot, err := filepath.Abs(path)
|
absRoot, err := filepath.Abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -94,18 +81,18 @@ func (x realFS) CleanedAbs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exists returns true if os.Stat succeeds.
|
// Exists returns true if os.Stat succeeds.
|
||||||
func (realFS) Exists(name string) bool {
|
func (fsOnDisk) Exists(name string) bool {
|
||||||
_, err := os.Stat(name)
|
_, err := os.Stat(name)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Glob returns the list of matching files
|
// Glob returns the list of matching files
|
||||||
func (realFS) Glob(pattern string) ([]string, error) {
|
func (fsOnDisk) Glob(pattern string) ([]string, error) {
|
||||||
return filepath.Glob(pattern)
|
return filepath.Glob(pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDir delegates to os.Stat and FileInfo.IsDir
|
// IsDir delegates to os.Stat and FileInfo.IsDir
|
||||||
func (realFS) IsDir(name string) bool {
|
func (fsOnDisk) IsDir(name string) bool {
|
||||||
info, err := os.Stat(name)
|
info, err := os.Stat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
@@ -114,9 +101,14 @@ func (realFS) IsDir(name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadFile delegates to ioutil.ReadFile.
|
// ReadFile delegates to ioutil.ReadFile.
|
||||||
func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) }
|
func (fsOnDisk) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) }
|
||||||
|
|
||||||
// WriteFile delegates to ioutil.WriteFile with read/write permissions.
|
// WriteFile delegates to ioutil.WriteFile with read/write permissions.
|
||||||
func (realFS) WriteFile(name string, c []byte) error {
|
func (fsOnDisk) WriteFile(name string, c []byte) error {
|
||||||
return ioutil.WriteFile(name, c, 0666)
|
return ioutil.WriteFile(name, c, 0666)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Walk delegates to filepath.Walk.
|
||||||
|
func (fsOnDisk) Walk(path string, walkFn filepath.WalkFunc) error {
|
||||||
|
return filepath.Walk(path, walkFn)
|
||||||
|
}
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package filesys_test
|
||||||
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 fs
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -23,10 +10,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
. "sigs.k8s.io/kustomize/api/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeTestDir(t *testing.T) (FileSystem, string) {
|
func makeTestDir(t *testing.T) (FileSystem, string) {
|
||||||
x := MakeRealFS()
|
fSys := MakeFsOnDisk()
|
||||||
td, err := ioutil.TempDir("", "kustomize_testing_dir")
|
td, err := ioutil.TempDir("", "kustomize_testing_dir")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
@@ -35,20 +24,20 @@ func makeTestDir(t *testing.T) (FileSystem, string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
}
|
}
|
||||||
if !x.Exists(testDir) {
|
if !fSys.Exists(testDir) {
|
||||||
t.Fatalf("expected existence")
|
t.Fatalf("expected existence")
|
||||||
}
|
}
|
||||||
if !x.IsDir(testDir) {
|
if !fSys.IsDir(testDir) {
|
||||||
t.Fatalf("expected directory")
|
t.Fatalf("expected directory")
|
||||||
}
|
}
|
||||||
return x, testDir
|
return fSys, testDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanedAbs_1(t *testing.T) {
|
func TestCleanedAbs_1(t *testing.T) {
|
||||||
x, testDir := makeTestDir(t)
|
fSys, testDir := makeTestDir(t)
|
||||||
defer os.RemoveAll(testDir)
|
defer os.RemoveAll(testDir)
|
||||||
|
|
||||||
d, f, err := x.CleanedAbs("")
|
d, f, err := fSys.CleanedAbs("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
}
|
}
|
||||||
@@ -65,10 +54,10 @@ func TestCleanedAbs_1(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanedAbs_2(t *testing.T) {
|
func TestCleanedAbs_2(t *testing.T) {
|
||||||
x, testDir := makeTestDir(t)
|
fSys, testDir := makeTestDir(t)
|
||||||
defer os.RemoveAll(testDir)
|
defer os.RemoveAll(testDir)
|
||||||
|
|
||||||
d, f, err := x.CleanedAbs("/")
|
d, f, err := fSys.CleanedAbs("/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
}
|
}
|
||||||
@@ -81,16 +70,16 @@ func TestCleanedAbs_2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanedAbs_3(t *testing.T) {
|
func TestCleanedAbs_3(t *testing.T) {
|
||||||
x, testDir := makeTestDir(t)
|
fSys, testDir := makeTestDir(t)
|
||||||
defer os.RemoveAll(testDir)
|
defer os.RemoveAll(testDir)
|
||||||
|
|
||||||
err := x.WriteFile(
|
err := fSys.WriteFile(
|
||||||
filepath.Join(testDir, "foo"), []byte(`foo`))
|
filepath.Join(testDir, "foo"), []byte(`foo`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d, f, err := x.CleanedAbs(filepath.Join(testDir, "foo"))
|
d, f, err := fSys.CleanedAbs(filepath.Join(testDir, "foo"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
}
|
}
|
||||||
@@ -100,25 +89,24 @@ func TestCleanedAbs_3(t *testing.T) {
|
|||||||
if f != "foo" {
|
if f != "foo" {
|
||||||
t.Fatalf("unexpected f=%s", f)
|
t.Fatalf("unexpected f=%s", f)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanedAbs_4(t *testing.T) {
|
func TestCleanedAbs_4(t *testing.T) {
|
||||||
x, testDir := makeTestDir(t)
|
fSys, testDir := makeTestDir(t)
|
||||||
defer os.RemoveAll(testDir)
|
defer os.RemoveAll(testDir)
|
||||||
|
|
||||||
err := x.MkdirAll(filepath.Join(testDir, "d1", "d2"))
|
err := fSys.MkdirAll(filepath.Join(testDir, "d1", "d2"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
}
|
}
|
||||||
err = x.WriteFile(
|
err = fSys.WriteFile(
|
||||||
filepath.Join(testDir, "d1", "d2", "bar"),
|
filepath.Join(testDir, "d1", "d2", "bar"),
|
||||||
[]byte(`bar`))
|
[]byte(`bar`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d, f, err := x.CleanedAbs(
|
d, f, err := fSys.CleanedAbs(
|
||||||
filepath.Join(testDir, "d1", "d2"))
|
filepath.Join(testDir, "d1", "d2"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
@@ -130,7 +118,7 @@ func TestCleanedAbs_4(t *testing.T) {
|
|||||||
t.Fatalf("unexpected f=%s", f)
|
t.Fatalf("unexpected f=%s", f)
|
||||||
}
|
}
|
||||||
|
|
||||||
d, f, err = x.CleanedAbs(
|
d, f, err = fSys.CleanedAbs(
|
||||||
filepath.Join(testDir, "d1", "d2", "bar"))
|
filepath.Join(testDir, "d1", "d2", "bar"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err=%v", err)
|
t.Fatalf("unexpected err=%v", err)
|
||||||
@@ -144,26 +132,26 @@ func TestCleanedAbs_4(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReadFilesRealFS(t *testing.T) {
|
func TestReadFilesRealFS(t *testing.T) {
|
||||||
x, testDir := makeTestDir(t)
|
fSys, testDir := makeTestDir(t)
|
||||||
defer os.RemoveAll(testDir)
|
defer os.RemoveAll(testDir)
|
||||||
|
|
||||||
err := x.WriteFile(path.Join(testDir, "foo"), []byte(`foo`))
|
err := fSys.WriteFile(path.Join(testDir, "foo"), []byte(`foo`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
}
|
}
|
||||||
if !x.Exists(path.Join(testDir, "foo")) {
|
if !fSys.Exists(path.Join(testDir, "foo")) {
|
||||||
t.Fatalf("expected foo")
|
t.Fatalf("expected foo")
|
||||||
}
|
}
|
||||||
if x.IsDir(path.Join(testDir, "foo")) {
|
if fSys.IsDir(path.Join(testDir, "foo")) {
|
||||||
t.Fatalf("expected foo not to be a directory")
|
t.Fatalf("expected foo not to be a directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = x.WriteFile(path.Join(testDir, "bar"), []byte(`bar`))
|
err = fSys.WriteFile(path.Join(testDir, "bar"), []byte(`bar`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := x.Glob(path.Join("testDir", "*"))
|
files, err := fSys.Glob(path.Join("testDir", "*"))
|
||||||
expected := []string{
|
expected := []string{
|
||||||
path.Join(testDir, "bar"),
|
path.Join(testDir, "bar"),
|
||||||
path.Join(testDir, "foo"),
|
path.Join(testDir, "foo"),
|
||||||
12
api/filesys/rpath.go
Normal file
12
api/filesys/rpath.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import "path/filepath"
|
||||||
|
|
||||||
|
// RootedPath returns a rooted path, e.g. "/foo/bar" as
|
||||||
|
// opposed to "foo/bar".
|
||||||
|
func RootedPath(elem ...string) string {
|
||||||
|
return separator + filepath.Join(elem...)
|
||||||
|
}
|
||||||
18
api/go.mod
Normal file
18
api/go.mod
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
module sigs.k8s.io/kustomize/api
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/emicklei/go-restful v2.9.6+incompatible // indirect
|
||||||
|
github.com/evanphx/json-patch v4.5.0+incompatible
|
||||||
|
github.com/go-openapi/spec v0.19.4
|
||||||
|
github.com/golangci/golangci-lint v1.19.1
|
||||||
|
github.com/googleapis/gnostic v0.3.0 // indirect
|
||||||
|
github.com/monopole/mdrip v1.0.0
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
|
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678
|
||||||
|
gopkg.in/yaml.v2 v2.2.4
|
||||||
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
||||||
|
sigs.k8s.io/kustomize/pseudo/k8s v0.0.0-20191108212413-1f86a0ca5d6c
|
||||||
|
sigs.k8s.io/yaml v1.1.0
|
||||||
|
)
|
||||||
461
api/go.sum
Normal file
461
api/go.sum
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
|
||||||
|
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||||
|
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||||
|
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||||
|
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
|
||||||
|
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
|
||||||
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
|
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
|
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
|
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||||
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
|
github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
|
||||||
|
github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
|
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
||||||
|
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
|
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||||
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db h1:GYXWx7Vr3+zv833u+8IoXbNnQY0AdXsxAgI0kX7xcwA=
|
||||||
|
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0=
|
||||||
|
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
|
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
|
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||||
|
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
|
||||||
|
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||||
|
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||||
|
github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo=
|
||||||
|
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||||
|
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||||
|
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
|
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||||
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
|
||||||
|
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
|
||||||
|
github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8=
|
||||||
|
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
|
||||||
|
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||||
|
github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ=
|
||||||
|
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||||
|
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
|
||||||
|
github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
|
||||||
|
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
|
||||||
|
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
|
||||||
|
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
|
||||||
|
github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
|
||||||
|
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
|
||||||
|
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
|
||||||
|
github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg=
|
||||||
|
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
|
||||||
|
github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
|
||||||
|
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||||
|
github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA=
|
||||||
|
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||||
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||||
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0=
|
||||||
|
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
|
||||||
|
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
|
||||||
|
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
|
||||||
|
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w=
|
||||||
|
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
|
||||||
|
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw=
|
||||||
|
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
|
||||||
|
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8=
|
||||||
|
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
|
||||||
|
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8=
|
||||||
|
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
|
||||||
|
github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98 h1:0OkFarm1Zy2CjCiDKfK9XHgmc2wbDlRMD2hD8anAJHU=
|
||||||
|
github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
|
||||||
|
github.com/golangci/golangci-lint v1.19.1 h1:g9xL8KW7UZDCkVlgHYJMA6F4Sj/sRVa0FoCeXI+Z3iM=
|
||||||
|
github.com/golangci/golangci-lint v1.19.1/go.mod h1:2CEc4Fxx3vxDv7g8DyXkHCBF73AOzAymcJAprs2vCps=
|
||||||
|
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI=
|
||||||
|
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
|
||||||
|
github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217 h1:En/tZdwhAn0JNwLuXzP3k2RVtMqMmOEK7Yu/g3tmtJE=
|
||||||
|
github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
|
||||||
|
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
|
||||||
|
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
|
||||||
|
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk=
|
||||||
|
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
|
||||||
|
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us=
|
||||||
|
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
|
||||||
|
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg=
|
||||||
|
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
||||||
|
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
|
||||||
|
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
|
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
|
||||||
|
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkHBdPZU4jo9bSmrLpII768arSyMFgk=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.0 h1:UykbtMB/w5No2LmE16gINgLj+r/vbziTgaoERQv6U+0=
|
||||||
|
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a h1:YH0IojQwndMQdeRWdw1aPT8bkbiWaYR3WD+Zf5e09DU=
|
||||||
|
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
|
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741 h1:OuuPl66BpF1q3OEkaPpp+VfzxrBBY62ATGdWqql/XX8=
|
||||||
|
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
|
||||||
|
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
|
||||||
|
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||||
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
|
||||||
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
|
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
|
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
|
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||||
|
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
|
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||||
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86 h1:q6SrfsK4FojRnJ1j8+8OJzyq3g9Y1oSVyL6nYGJXXBk=
|
||||||
|
github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
|
||||||
|
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||||
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/monopole/mdrip v1.0.0 h1:RFDBa+tab6mW+gX4Ww2SZDc4kS6p01FwnLtgz64Il+I=
|
||||||
|
github.com/monopole/mdrip v1.0.0/go.mod h1:N1/ppRG9CaPeUKAUHZ3dUlfOT81lTpKZLkyhCvTETwM=
|
||||||
|
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
|
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
|
||||||
|
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||||
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||||
|
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
|
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||||
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
|
||||||
|
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218 h1:O0yPHYL49quNL4Oj2wVq+zbGMu4dAM6iLoOQtm49TrQ=
|
||||||
|
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218/go.mod h1:q6oYAujd2qyeU4cJqIri4LBIgdHXGvxWHZ1E29HNFRE=
|
||||||
|
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
|
||||||
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
|
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM=
|
||||||
|
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||||
|
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=
|
||||||
|
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs=
|
||||||
|
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
|
||||||
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||||
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
|
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
|
||||||
|
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
|
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||||
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec h1:AmoEvWAO3nDx1MEcMzPh+GzOOIA5Znpv6++c7bePPY0=
|
||||||
|
github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||||
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
|
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
|
||||||
|
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
||||||
|
github.com/ultraware/whitespace v0.0.3 h1:S5BCRRB5sttNy0bSOhbpw+0mb+cHiCmWfrvxpEzuUk0=
|
||||||
|
github.com/ultraware/whitespace v0.0.3/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||||
|
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
||||||
|
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc=
|
||||||
|
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5 h1:SW/0nsKCUaozCUtZTakri5laocGx/5bkDSSLrFUsa5s=
|
||||||
|
golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||||
|
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678 h1:rM1Udd0CgtYI3KUIhu9ROz0QCqjW+n/ODp/hH7c60Xc=
|
||||||
|
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||||
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||||
|
k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
|
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
|
||||||
|
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||||
|
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
|
||||||
|
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||||
|
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
|
||||||
|
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||||
|
sigs.k8s.io/kustomize/pseudo/k8s v0.0.0-20191108212413-1f86a0ca5d6c h1:t7fk+ljA3Ru4pro+/0RuOAZcODDhByL1fvIdyHLhjTY=
|
||||||
|
sigs.k8s.io/kustomize/pseudo/k8s v0.0.0-20191108212413-1f86a0ca5d6c/go.mod h1:bl/gVJgYYhJZCZdYU2BfnaKYAlqFkgbJEkpl302jEss=
|
||||||
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||||
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=
|
||||||
|
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||||
@@ -6,7 +6,7 @@ package hasher_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/hasher"
|
. "sigs.k8s.io/kustomize/api/hasher"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSortArrayAndComputeHash(t *testing.T) {
|
func TestSortArrayAndComputeHash(t *testing.T) {
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
package ifc
|
package ifc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validator provides functions to validate annotations and labels
|
// Validator provides functions to validate annotations and labels
|
||||||
@@ -20,6 +20,12 @@ type Validator interface {
|
|||||||
IsEnvVarName(k string) error
|
IsEnvVarName(k string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KvLoader reads and validates KV pairs.
|
||||||
|
type KvLoader interface {
|
||||||
|
Validator() Validator
|
||||||
|
Load(args types.KvPairSources) (all []types.Pair, err error)
|
||||||
|
}
|
||||||
|
|
||||||
// Loader interface exposes methods to read bytes.
|
// Loader interface exposes methods to read bytes.
|
||||||
type Loader interface {
|
type Loader interface {
|
||||||
// Root returns the root location for this Loader.
|
// Root returns the root location for this Loader.
|
||||||
@@ -30,10 +36,6 @@ type Loader interface {
|
|||||||
Load(location string) ([]byte, error)
|
Load(location string) ([]byte, error)
|
||||||
// Cleanup cleans the loader
|
// Cleanup cleans the loader
|
||||||
Cleanup() error
|
Cleanup() error
|
||||||
// Validator validates data for use in various k8s fields.
|
|
||||||
Validator() Validator
|
|
||||||
// Loads pairs.
|
|
||||||
LoadKvPairs(args types.GeneratorArgs) ([]types.Pair, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kunstructured allows manipulation of k8s objects
|
// Kunstructured allows manipulation of k8s objects
|
||||||
@@ -53,8 +55,8 @@ type Kunstructured interface {
|
|||||||
GetMap(path string) (map[string]interface{}, error)
|
GetMap(path string) (map[string]interface{}, error)
|
||||||
MarshalJSON() ([]byte, error)
|
MarshalJSON() ([]byte, error)
|
||||||
UnmarshalJSON([]byte) error
|
UnmarshalJSON([]byte) error
|
||||||
GetGvk() gvk.Gvk
|
GetGvk() resid.Gvk
|
||||||
SetGvk(gvk.Gvk)
|
SetGvk(resid.Gvk)
|
||||||
GetKind() string
|
GetKind() string
|
||||||
GetName() string
|
GetName() string
|
||||||
SetName(string)
|
SetName(string)
|
||||||
@@ -74,11 +76,11 @@ type KunstructuredFactory interface {
|
|||||||
FromMap(m map[string]interface{}) Kunstructured
|
FromMap(m map[string]interface{}) Kunstructured
|
||||||
Hasher() KunstructuredHasher
|
Hasher() KunstructuredHasher
|
||||||
MakeConfigMap(
|
MakeConfigMap(
|
||||||
ldr Loader,
|
kvLdr KvLoader,
|
||||||
options *types.GeneratorOptions,
|
options *types.GeneratorOptions,
|
||||||
args *types.ConfigMapArgs) (Kunstructured, error)
|
args *types.ConfigMapArgs) (Kunstructured, error)
|
||||||
MakeSecret(
|
MakeSecret(
|
||||||
ldr Loader,
|
kvLdr KvLoader,
|
||||||
options *types.GeneratorOptions,
|
options *types.GeneratorOptions,
|
||||||
args *types.SecretArgs) (Kunstructured, error)
|
args *types.SecretArgs) (Kunstructured, error)
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 expansion provides functions find and replace $(FOO) style variables in strings.
|
// Package expansion provides functions find and replace $(FOO) style variables in strings.
|
||||||
package expansion
|
package expansion
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 expansion_test
|
package expansion_test
|
||||||
|
|
||||||
@@ -20,7 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/expansion"
|
. "sigs.k8s.io/kustomize/api/internal/accumulator/expansion"
|
||||||
)
|
)
|
||||||
|
|
||||||
type expected struct {
|
type expected struct {
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package accumulator
|
||||||
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 config
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -23,8 +10,10 @@ import (
|
|||||||
"github.com/go-openapi/spec"
|
"github.com/go-openapi/spec"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/kube-openapi/pkg/common"
|
"k8s.io/kube-openapi/pkg/common"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,8 +22,8 @@ type nameToApiMap map[string]common.OpenAPIDefinition
|
|||||||
|
|
||||||
// LoadConfigFromCRDs parse CRD schemas from paths into a TransformerConfig
|
// LoadConfigFromCRDs parse CRD schemas from paths into a TransformerConfig
|
||||||
func LoadConfigFromCRDs(
|
func LoadConfigFromCRDs(
|
||||||
ldr ifc.Loader, paths []string) (*TransformerConfig, error) {
|
ldr ifc.Loader, paths []string) (*builtinconfig.TransformerConfig, error) {
|
||||||
tc := MakeEmptyConfig()
|
tc := builtinconfig.MakeEmptyConfig()
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
content, err := ldr.Load(path)
|
content, err := ldr.Load(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -65,13 +54,13 @@ func makeNameToApiMap(content []byte) (result nameToApiMap, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeConfigFromApiMap(m nameToApiMap) (*TransformerConfig, error) {
|
func makeConfigFromApiMap(m nameToApiMap) (*builtinconfig.TransformerConfig, error) {
|
||||||
result := MakeEmptyConfig()
|
result := builtinconfig.MakeEmptyConfig()
|
||||||
for name, api := range m {
|
for name, api := range m {
|
||||||
if !looksLikeAk8sType(api.Schema.SchemaProps.Properties) {
|
if !looksLikeAk8sType(api.Schema.SchemaProps.Properties) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tc := MakeEmptyConfig()
|
tc := builtinconfig.MakeEmptyConfig()
|
||||||
err := loadCrdIntoConfig(
|
err := loadCrdIntoConfig(
|
||||||
tc, makeGvkFromTypeName(name), m, name, []string{})
|
tc, makeGvkFromTypeName(name), m, name, []string{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,10 +77,10 @@ func makeConfigFromApiMap(m nameToApiMap) (*TransformerConfig, error) {
|
|||||||
// TODO: Get Group and Version for CRD from the
|
// TODO: Get Group and Version for CRD from the
|
||||||
// openAPI definition once
|
// openAPI definition once
|
||||||
// "x-kubernetes-group-version-kind" is available in CRD
|
// "x-kubernetes-group-version-kind" is available in CRD
|
||||||
func makeGvkFromTypeName(n string) gvk.Gvk {
|
func makeGvkFromTypeName(n string) resid.Gvk {
|
||||||
names := strings.Split(n, ".")
|
names := strings.Split(n, ".")
|
||||||
kind := names[len(names)-1]
|
kind := names[len(names)-1]
|
||||||
return gvk.Gvk{Kind: kind}
|
return resid.Gvk{Kind: kind}
|
||||||
}
|
}
|
||||||
|
|
||||||
func looksLikeAk8sType(properties myProperties) bool {
|
func looksLikeAk8sType(properties myProperties) bool {
|
||||||
@@ -133,7 +122,7 @@ const (
|
|||||||
|
|
||||||
// loadCrdIntoConfig loads a CRD spec into a TransformerConfig
|
// loadCrdIntoConfig loads a CRD spec into a TransformerConfig
|
||||||
func loadCrdIntoConfig(
|
func loadCrdIntoConfig(
|
||||||
theConfig *TransformerConfig, theGvk gvk.Gvk, theMap nameToApiMap,
|
theConfig *builtinconfig.TransformerConfig, theGvk resid.Gvk, theMap nameToApiMap,
|
||||||
typeName string, path []string) (err error) {
|
typeName string, path []string) (err error) {
|
||||||
api, ok := theMap[typeName]
|
api, ok := theMap[typeName]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -173,9 +162,9 @@ func loadCrdIntoConfig(
|
|||||||
nameKey = "name"
|
nameKey = "name"
|
||||||
}
|
}
|
||||||
err = theConfig.AddNamereferenceFieldSpec(
|
err = theConfig.AddNamereferenceFieldSpec(
|
||||||
NameBackReferences{
|
builtinconfig.NameBackReferences{
|
||||||
Gvk: gvk.Gvk{Kind: kind, Version: version},
|
Gvk: resid.Gvk{Kind: kind, Version: version},
|
||||||
FieldSpecs: []FieldSpec{
|
FieldSpecs: []types.FieldSpec{
|
||||||
makeFs(theGvk, append(path, propName, nameKey))},
|
makeFs(theGvk, append(path, propName, nameKey))},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -192,8 +181,8 @@ func loadCrdIntoConfig(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeFs(in gvk.Gvk, path []string) FieldSpec {
|
func makeFs(in resid.Gvk, path []string) types.FieldSpec {
|
||||||
return FieldSpec{
|
return types.FieldSpec{
|
||||||
CreateIfNotPresent: false,
|
CreateIfNotPresent: false,
|
||||||
Gvk: in,
|
Gvk: in,
|
||||||
Path: strings.Join(path, "/"),
|
Path: strings.Join(path, "/"),
|
||||||
@@ -1,28 +1,18 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package accumulator_test
|
||||||
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 config
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/internal/loadertest"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/internal/loadertest"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This defines two CRD's: Bee and MyKind.
|
// This defines two CRD's: Bee and MyKind.
|
||||||
@@ -51,7 +41,7 @@ More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#ty
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec"
|
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec"
|
||||||
@@ -64,7 +54,7 @@ More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#ty
|
|||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec",
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec",
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus",
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus",
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec": {
|
||||||
@@ -96,7 +86,7 @@ In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-con
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec"
|
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec"
|
||||||
@@ -109,7 +99,7 @@ In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-con
|
|||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec",
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec",
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus",
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus",
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec": {
|
||||||
@@ -126,13 +116,13 @@ In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-con
|
|||||||
If it is not set we generate a secret dynamically",
|
If it is not set we generate a secret dynamically",
|
||||||
"x-kubernetes-object-ref-api-version": "v1",
|
"x-kubernetes-object-ref-api-version": "v1",
|
||||||
"x-kubernetes-object-ref-kind": "Secret",
|
"x-kubernetes-object-ref-kind": "Secret",
|
||||||
"$ref": "k8s.io/api/core/v1.LocalObjectReference"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1.LocalObjectReference"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.Bee",
|
"github.com/example/pkg/apis/jingfang/v1beta1.Bee",
|
||||||
"k8s.io/api/core/v1.LocalObjectReference"
|
"sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1.LocalObjectReference"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus": {
|
||||||
@@ -155,30 +145,30 @@ func makeLoader(t *testing.T) ifc.Loader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadCRDs(t *testing.T) {
|
func TestLoadCRDs(t *testing.T) {
|
||||||
nbrs := []NameBackReferences{
|
nbrs := []builtinconfig.NameBackReferences{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{Kind: "Secret", Version: "v1"},
|
Gvk: resid.Gvk{Kind: "Secret", Version: "v1"},
|
||||||
FieldSpecs: []FieldSpec{
|
FieldSpecs: []types.FieldSpec{
|
||||||
{
|
{
|
||||||
CreateIfNotPresent: false,
|
CreateIfNotPresent: false,
|
||||||
Gvk: gvk.Gvk{Kind: "MyKind"},
|
Gvk: resid.Gvk{Kind: "MyKind"},
|
||||||
Path: "spec/secretRef/name",
|
Path: "spec/secretRef/name",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{Kind: "Bee", Version: "v1beta1"},
|
Gvk: resid.Gvk{Kind: "Bee", Version: "v1beta1"},
|
||||||
FieldSpecs: []FieldSpec{
|
FieldSpecs: []types.FieldSpec{
|
||||||
{
|
{
|
||||||
CreateIfNotPresent: false,
|
CreateIfNotPresent: false,
|
||||||
Gvk: gvk.Gvk{Kind: "MyKind"},
|
Gvk: resid.Gvk{Kind: "MyKind"},
|
||||||
Path: "spec/beeRef/name",
|
Path: "spec/beeRef/name",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedTc := &TransformerConfig{
|
expectedTc := &builtinconfig.TransformerConfig{
|
||||||
NameReference: nbrs,
|
NameReference: nbrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,28 +1,28 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package transformers
|
package accumulator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
)
|
)
|
||||||
|
|
||||||
type nameReferenceTransformer struct {
|
type nameReferenceTransformer struct {
|
||||||
backRefs []config.NameBackReferences
|
backRefs []builtinconfig.NameBackReferences
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Transformer = &nameReferenceTransformer{}
|
var _ resmap.Transformer = &nameReferenceTransformer{}
|
||||||
|
|
||||||
// NewNameReferenceTransformer constructs a nameReferenceTransformer
|
// newNameReferenceTransformer constructs a nameReferenceTransformer
|
||||||
// with a given slice of NameBackReferences.
|
// with a given slice of NameBackReferences.
|
||||||
func NewNameReferenceTransformer(br []config.NameBackReferences) Transformer {
|
func newNameReferenceTransformer(br []builtinconfig.NameBackReferences) resmap.Transformer {
|
||||||
if br == nil {
|
if br == nil {
|
||||||
log.Fatal("backrefs not expected to be nil")
|
log.Fatal("backrefs not expected to be nil")
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error {
|
|||||||
if candidates == nil {
|
if candidates == nil {
|
||||||
candidates = m.SubsetThatCouldBeReferencedByResource(referrer)
|
candidates = m.SubsetThatCouldBeReferencedByResource(referrer)
|
||||||
}
|
}
|
||||||
err := MutateField(
|
err := transform.MutateField(
|
||||||
referrer.Map(),
|
referrer.Map(),
|
||||||
fSpec.PathSlice(),
|
fSpec.PathSlice(),
|
||||||
fSpec.CreateIfNotPresent,
|
fSpec.CreateIfNotPresent,
|
||||||
@@ -115,7 +115,7 @@ func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error {
|
|||||||
func (o *nameReferenceTransformer) selectReferral(
|
func (o *nameReferenceTransformer) selectReferral(
|
||||||
oldName string,
|
oldName string,
|
||||||
referrer *resource.Resource,
|
referrer *resource.Resource,
|
||||||
target gvk.Gvk,
|
target resid.Gvk,
|
||||||
referralCandidates resmap.ResMap,
|
referralCandidates resmap.ResMap,
|
||||||
referralCandidateSubset []*resource.Resource) (interface{}, interface{}, error) {
|
referralCandidateSubset []*resource.Resource) (interface{}, interface{}, error) {
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ func (o *nameReferenceTransformer) selectReferral(
|
|||||||
func (o *nameReferenceTransformer) getSimpleNameField(
|
func (o *nameReferenceTransformer) getSimpleNameField(
|
||||||
oldName string,
|
oldName string,
|
||||||
referrer *resource.Resource,
|
referrer *resource.Resource,
|
||||||
target gvk.Gvk,
|
target resid.Gvk,
|
||||||
referralCandidates resmap.ResMap,
|
referralCandidates resmap.ResMap,
|
||||||
referralCandidateSubset []*resource.Resource) (interface{}, error) {
|
referralCandidateSubset []*resource.Resource) (interface{}, error) {
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ func (o *nameReferenceTransformer) getSimpleNameField(
|
|||||||
func (o *nameReferenceTransformer) getNameAndNsStruct(
|
func (o *nameReferenceTransformer) getNameAndNsStruct(
|
||||||
inMap map[string]interface{},
|
inMap map[string]interface{},
|
||||||
referrer *resource.Resource,
|
referrer *resource.Resource,
|
||||||
target gvk.Gvk,
|
target resid.Gvk,
|
||||||
referralCandidates resmap.ResMap) (interface{}, error) {
|
referralCandidates resmap.ResMap) (interface{}, error) {
|
||||||
|
|
||||||
// Example:
|
// Example:
|
||||||
@@ -191,6 +191,11 @@ func (o *nameReferenceTransformer) getNameAndNsStruct(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newname == oldName) && (newnamespace == nil) {
|
||||||
|
// no candidate found.
|
||||||
|
return inMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
inMap["name"] = newname
|
inMap["name"] = newname
|
||||||
if newnamespace != "" {
|
if newnamespace != "" {
|
||||||
// We don't want value "" to replace value "default" since
|
// We don't want value "" to replace value "default" since
|
||||||
@@ -204,7 +209,7 @@ func (o *nameReferenceTransformer) getNameAndNsStruct(
|
|||||||
|
|
||||||
func (o *nameReferenceTransformer) getNewNameFunc(
|
func (o *nameReferenceTransformer) getNewNameFunc(
|
||||||
referrer *resource.Resource,
|
referrer *resource.Resource,
|
||||||
target gvk.Gvk,
|
target resid.Gvk,
|
||||||
referralCandidates resmap.ResMap) func(in interface{}) (interface{}, error) {
|
referralCandidates resmap.ResMap) func(in interface{}) (interface{}, error) {
|
||||||
return func(in interface{}) (interface{}, error) {
|
return func(in interface{}) (interface{}, error) {
|
||||||
switch in.(type) {
|
switch in.(type) {
|
||||||
@@ -212,6 +217,12 @@ func (o *nameReferenceTransformer) getNewNameFunc(
|
|||||||
oldName, _ := in.(string)
|
oldName, _ := in.(string)
|
||||||
return o.getSimpleNameField(oldName, referrer, target,
|
return o.getSimpleNameField(oldName, referrer, target,
|
||||||
referralCandidates, referralCandidates.Resources())
|
referralCandidates, referralCandidates.Resources())
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Kind: ValidatingWebhookConfiguration
|
||||||
|
// FieldSpec is webhooks/clientConfig/service
|
||||||
|
oldMap, _ := in.(map[string]interface{})
|
||||||
|
return o.getNameAndNsStruct(oldMap, referrer, target,
|
||||||
|
referralCandidates)
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
l, _ := in.([]interface{})
|
l, _ := in.([]interface{})
|
||||||
for idx, item := range l {
|
for idx, item := range l {
|
||||||
@@ -254,16 +265,6 @@ func (o *nameReferenceTransformer) getNewNameFunc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexOf(s string, slice []string) []int {
|
|
||||||
var index []int
|
|
||||||
for i, item := range slice {
|
|
||||||
if item == s {
|
|
||||||
index = append(index, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIds(rs []*resource.Resource) []string {
|
func getIds(rs []*resource.Resource) []string {
|
||||||
var result []string
|
var result []string
|
||||||
for _, r := range rs {
|
for _, r := range rs {
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package transformers
|
package accumulator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNameReferenceHappyRun(t *testing.T) {
|
func TestNameReferenceHappyRun(t *testing.T) {
|
||||||
@@ -52,7 +52,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}).Add(
|
}).Add(
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"group": "extensions",
|
"group": "networking.k8s.io",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta1",
|
||||||
"kind": "Ingress",
|
"kind": "Ingress",
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
@@ -375,7 +375,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}).ReplaceResource(
|
}).ReplaceResource(
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"group": "extensions",
|
"group": "networking.k8s.io",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta1",
|
||||||
"kind": "Ingress",
|
"kind": "Ingress",
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
@@ -463,7 +463,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}).ResMap()
|
}).ResMap()
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
err := nrt.Transform(m)
|
err := nrt.Transform(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -520,10 +520,10 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).ResMap(),
|
}).ResMap(),
|
||||||
expectedErr: "is expected to be"},
|
expectedErr: "is expected to contain a name field"},
|
||||||
}
|
}
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
err := nrt.Transform(test.resMap)
|
err := nrt.Transform(test.resMap)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -581,7 +581,7 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
|
|||||||
|
|
||||||
m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(v1).AddR(c1).ResMap()
|
m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(v1).AddR(c1).ResMap()
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
if err := nrt.Transform(m1); err != nil {
|
if err := nrt.Transform(m1); err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -652,6 +652,7 @@ const (
|
|||||||
ns1 = "ns1"
|
ns1 = "ns1"
|
||||||
ns2 = "ns2"
|
ns2 = "ns2"
|
||||||
ns3 = "ns3"
|
ns3 = "ns3"
|
||||||
|
ns4 = "ns4"
|
||||||
|
|
||||||
orgname = "uniquename"
|
orgname = "uniquename"
|
||||||
prefixedname = "prefix-uniquename"
|
prefixedname = "prefix-uniquename"
|
||||||
@@ -719,7 +720,7 @@ func TestNameReferenceNamespace(t *testing.T) {
|
|||||||
ReplaceResource(deploymentMap(ns1, prefixedname, prefixedname, prefixedname)).
|
ReplaceResource(deploymentMap(ns1, prefixedname, prefixedname, prefixedname)).
|
||||||
ReplaceResource(deploymentMap(ns2, suffixedname, suffixedname, suffixedname)).ResMap()
|
ReplaceResource(deploymentMap(ns2, suffixedname, suffixedname, suffixedname)).ResMap()
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
err := nrt.Transform(m)
|
err := nrt.Transform(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -808,6 +809,11 @@ func TestNameReferenceClusterWide(t *testing.T) {
|
|||||||
"name": orgname,
|
"name": orgname,
|
||||||
"namespace": ns2,
|
"namespace": ns2,
|
||||||
},
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": "random",
|
||||||
|
},
|
||||||
}}).ResMap()
|
}}).ResMap()
|
||||||
|
|
||||||
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
||||||
@@ -862,17 +868,22 @@ func TestNameReferenceClusterWide(t *testing.T) {
|
|||||||
"name": suffixedname,
|
"name": suffixedname,
|
||||||
"namespace": ns2,
|
"namespace": ns2,
|
||||||
},
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": "random",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}).ResMap()
|
}).ResMap()
|
||||||
|
|
||||||
clusterRoleId := resid.NewResId(
|
clusterRoleId := resid.NewResId(
|
||||||
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
||||||
clusterRoleBindingId := resid.NewResId(
|
clusterRoleBindingId := resid.NewResId(
|
||||||
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
||||||
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
||||||
clusterRole.AppendRefBy(clusterRoleBindingId)
|
clusterRole.AppendRefBy(clusterRoleBindingId)
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
err := nrt.Transform(m)
|
err := nrt.Transform(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -890,6 +901,13 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
|||||||
rf := resource.NewFactory(
|
rf := resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl())
|
kunstruct.NewKunstructuredFactoryImpl())
|
||||||
m := resmaptest_test.NewRmBuilder(t, rf).
|
m := resmaptest_test.NewRmBuilder(t, rf).
|
||||||
|
AddWithNsAndName(ns4, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns4,
|
||||||
|
}}).
|
||||||
// Add ServiceAccount with the same org name in "ns1" namespaces
|
// Add ServiceAccount with the same org name in "ns1" namespaces
|
||||||
AddWithNsAndName(ns1, orgname, map[string]interface{}{
|
AddWithNsAndName(ns1, orgname, map[string]interface{}{
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
@@ -934,6 +952,16 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
|||||||
"name": orgname,
|
"name": orgname,
|
||||||
"namespace": ns3,
|
"namespace": ns3,
|
||||||
},
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": "random",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns4,
|
||||||
|
},
|
||||||
}}).ResMap()
|
}}).ResMap()
|
||||||
|
|
||||||
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
||||||
@@ -963,17 +991,27 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
|||||||
"name": suffixedname,
|
"name": suffixedname,
|
||||||
"namespace": ns2,
|
"namespace": ns2,
|
||||||
},
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": "random",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns4,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}).ResMap()
|
}).ResMap()
|
||||||
|
|
||||||
clusterRoleId := resid.NewResId(
|
clusterRoleId := resid.NewResId(
|
||||||
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
||||||
clusterRoleBindingId := resid.NewResId(
|
clusterRoleBindingId := resid.NewResId(
|
||||||
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
||||||
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
||||||
clusterRole.AppendRefBy(clusterRoleBindingId)
|
clusterRole.AppendRefBy(clusterRoleBindingId)
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
err := nrt.Transform(m)
|
err := nrt.Transform(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -1011,7 +1049,7 @@ func TestNameReferenceCandidateSelection(t *testing.T) {
|
|||||||
ReplaceResource(deploymentMap("", "p1-deploy1", "p1-cm1-hash", "p1-secret1-hash")).
|
ReplaceResource(deploymentMap("", "p1-deploy1", "p1-cm1-hash", "p1-secret1-hash")).
|
||||||
ResMap()
|
ResMap()
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := newNameReferenceTransformer(builtinconfig.MakeDefaultConfig().NameReference)
|
||||||
err := nrt.Transform(m)
|
err := nrt.Transform(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -1,41 +1,31 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package accumulator
|
||||||
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 transformers
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/expansion"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
expansion2 "sigs.k8s.io/kustomize/api/internal/accumulator/expansion"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RefVarTransformer struct {
|
type refVarTransformer struct {
|
||||||
varMap map[string]interface{}
|
varMap map[string]interface{}
|
||||||
replacementCounts map[string]int
|
replacementCounts map[string]int
|
||||||
fieldSpecs []config.FieldSpec
|
fieldSpecs []types.FieldSpec
|
||||||
mappingFunc func(string) interface{}
|
mappingFunc func(string) interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRefVarTransformer returns a new RefVarTransformer
|
// newRefVarTransformer returns a new refVarTransformer
|
||||||
// that replaces $(VAR) style variables with values.
|
// that replaces $(VAR) style variables with values.
|
||||||
// The fieldSpecs are the places to look for occurrences of $(VAR).
|
// The fieldSpecs are the places to look for occurrences of $(VAR).
|
||||||
func NewRefVarTransformer(
|
func newRefVarTransformer(
|
||||||
varMap map[string]interface{}, fs []config.FieldSpec) *RefVarTransformer {
|
varMap map[string]interface{}, fs []types.FieldSpec) *refVarTransformer {
|
||||||
return &RefVarTransformer{
|
return &refVarTransformer{
|
||||||
varMap: varMap,
|
varMap: varMap,
|
||||||
fieldSpecs: fs,
|
fieldSpecs: fs,
|
||||||
}
|
}
|
||||||
@@ -45,12 +35,12 @@ func NewRefVarTransformer(
|
|||||||
// embedded instances of $VAR style variables, e.g. a container command string.
|
// embedded instances of $VAR style variables, e.g. a container command string.
|
||||||
// The function returns the string with the variables expanded to their final
|
// The function returns the string with the variables expanded to their final
|
||||||
// values.
|
// values.
|
||||||
func (rv *RefVarTransformer) replaceVars(in interface{}) (interface{}, error) {
|
func (rv *refVarTransformer) replaceVars(in interface{}) (interface{}, error) {
|
||||||
switch vt := in.(type) {
|
switch vt := in.(type) {
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
var xs []interface{}
|
var xs []interface{}
|
||||||
for _, a := range in.([]interface{}) {
|
for _, a := range in.([]interface{}) {
|
||||||
xs = append(xs, expansion.Expand(a.(string), rv.mappingFunc))
|
xs = append(xs, expansion2.Expand(a.(string), rv.mappingFunc))
|
||||||
}
|
}
|
||||||
return xs, nil
|
return xs, nil
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
@@ -67,7 +57,7 @@ func (rv *RefVarTransformer) replaceVars(in interface{}) (interface{}, error) {
|
|||||||
// This field can potentially contains a $(VAR) since it is
|
// This field can potentially contains a $(VAR) since it is
|
||||||
// of string type. For instance .spec.replicas: $(REPLICAS)
|
// of string type. For instance .spec.replicas: $(REPLICAS)
|
||||||
// in a Deployment object
|
// in a Deployment object
|
||||||
xs[k] = expansion.Expand(s, rv.mappingFunc)
|
xs[k] = expansion2.Expand(s, rv.mappingFunc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return xs, nil
|
return xs, nil
|
||||||
@@ -79,7 +69,7 @@ func (rv *RefVarTransformer) replaceVars(in interface{}) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
// This field can potentially contain a $(VAR) since it is
|
// This field can potentially contain a $(VAR) since it is
|
||||||
// of string type.
|
// of string type.
|
||||||
return expansion.Expand(s, rv.mappingFunc), nil
|
return expansion2.Expand(s, rv.mappingFunc), nil
|
||||||
case nil:
|
case nil:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
@@ -89,7 +79,7 @@ func (rv *RefVarTransformer) replaceVars(in interface{}) (interface{}, error) {
|
|||||||
|
|
||||||
// UnusedVars returns slice of Var names that were unused
|
// UnusedVars returns slice of Var names that were unused
|
||||||
// after a Transform run.
|
// after a Transform run.
|
||||||
func (rv *RefVarTransformer) UnusedVars() []string {
|
func (rv *refVarTransformer) UnusedVars() []string {
|
||||||
var unused []string
|
var unused []string
|
||||||
for k := range rv.varMap {
|
for k := range rv.varMap {
|
||||||
_, ok := rv.replacementCounts[k]
|
_, ok := rv.replacementCounts[k]
|
||||||
@@ -101,14 +91,14 @@ func (rv *RefVarTransformer) UnusedVars() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transform replaces $(VAR) style variables with values.
|
// Transform replaces $(VAR) style variables with values.
|
||||||
func (rv *RefVarTransformer) Transform(m resmap.ResMap) error {
|
func (rv *refVarTransformer) Transform(m resmap.ResMap) error {
|
||||||
rv.replacementCounts = make(map[string]int)
|
rv.replacementCounts = make(map[string]int)
|
||||||
rv.mappingFunc = expansion.MappingFuncFor(
|
rv.mappingFunc = expansion2.MappingFuncFor(
|
||||||
rv.replacementCounts, rv.varMap)
|
rv.replacementCounts, rv.varMap)
|
||||||
for _, res := range m.Resources() {
|
for _, res := range m.Resources() {
|
||||||
for _, fieldSpec := range rv.fieldSpecs {
|
for _, fieldSpec := range rv.fieldSpecs {
|
||||||
if res.OrgId().IsSelected(&fieldSpec.Gvk) {
|
if res.OrgId().IsSelected(&fieldSpec.Gvk) {
|
||||||
if err := MutateField(
|
if err := transform.MutateField(
|
||||||
res.Map(), fieldSpec.PathSlice(),
|
res.Map(), fieldSpec.PathSlice(),
|
||||||
false, rv.replaceVars); err != nil {
|
false, rv.replaceVars); err != nil {
|
||||||
return err
|
return err
|
||||||
137
api/internal/accumulator/refvartransformer_test.go
Normal file
137
api/internal/accumulator/refvartransformer_test.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package accumulator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRefVarTransformer(t *testing.T) {
|
||||||
|
type given struct {
|
||||||
|
varMap map[string]interface{}
|
||||||
|
fs []types.FieldSpec
|
||||||
|
res resmap.ResMap
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
res resmap.ResMap
|
||||||
|
unused []string
|
||||||
|
}
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "var replacement in map[string]",
|
||||||
|
given: given{
|
||||||
|
varMap: map[string]interface{}{
|
||||||
|
"FOO": "replacementForFoo",
|
||||||
|
"BAR": "replacementForBar",
|
||||||
|
"BAZ": int64(5),
|
||||||
|
"BOO": true,
|
||||||
|
},
|
||||||
|
fs: []types.FieldSpec{
|
||||||
|
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/map"},
|
||||||
|
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/slice"},
|
||||||
|
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/interface"},
|
||||||
|
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/nil"},
|
||||||
|
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/num"},
|
||||||
|
},
|
||||||
|
res: resmaptest_test.NewRmBuilder(
|
||||||
|
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
|
||||||
|
Add(map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "cm1",
|
||||||
|
},
|
||||||
|
"data": map[string]interface{}{
|
||||||
|
"map": map[string]interface{}{
|
||||||
|
"item1": "$(FOO)",
|
||||||
|
"item2": "bla",
|
||||||
|
"item3": "$(BAZ)",
|
||||||
|
"item4": "$(BAZ)+$(BAZ)",
|
||||||
|
"item5": "$(BOO)",
|
||||||
|
"item6": "if $(BOO)",
|
||||||
|
"item7": 2019,
|
||||||
|
},
|
||||||
|
"slice": []interface{}{
|
||||||
|
"$(FOO)",
|
||||||
|
"bla",
|
||||||
|
"$(BAZ)",
|
||||||
|
"$(BAZ)+$(BAZ)",
|
||||||
|
"$(BOO)",
|
||||||
|
"if $(BOO)",
|
||||||
|
},
|
||||||
|
"interface": "$(FOO)",
|
||||||
|
"nil": nil,
|
||||||
|
"num": 2019,
|
||||||
|
}}).ResMap(),
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
res: resmaptest_test.NewRmBuilder(
|
||||||
|
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
|
||||||
|
Add(map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "cm1",
|
||||||
|
},
|
||||||
|
"data": map[string]interface{}{
|
||||||
|
"map": map[string]interface{}{
|
||||||
|
"item1": "replacementForFoo",
|
||||||
|
"item2": "bla",
|
||||||
|
"item3": int64(5),
|
||||||
|
"item4": "5+5",
|
||||||
|
"item5": true,
|
||||||
|
"item6": "if true",
|
||||||
|
"item7": 2019,
|
||||||
|
},
|
||||||
|
"slice": []interface{}{
|
||||||
|
"replacementForFoo",
|
||||||
|
"bla",
|
||||||
|
int64(5),
|
||||||
|
"5+5",
|
||||||
|
true,
|
||||||
|
"if true",
|
||||||
|
},
|
||||||
|
"interface": "replacementForFoo",
|
||||||
|
"nil": nil,
|
||||||
|
"num": 2019,
|
||||||
|
}}).ResMap(),
|
||||||
|
unused: []string{"BAR"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
tr := newRefVarTransformer(tc.given.varMap, tc.given.fs)
|
||||||
|
|
||||||
|
// act
|
||||||
|
err := tr.Transform(tc.given.res)
|
||||||
|
|
||||||
|
// assert
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
a, e := tc.given.res, tc.expected.res
|
||||||
|
if !reflect.DeepEqual(a, e) {
|
||||||
|
err = e.ErrorIfNotEqualLists(a)
|
||||||
|
t.Fatalf("actual doesn't match expected: \nACTUAL:\n%v\nEXPECTED:\n%v\nERR: %v", a, e, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,11 +8,10 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResAccumulator accumulates resources and the rules
|
// ResAccumulator accumulates resources and the rules
|
||||||
@@ -20,14 +19,14 @@ import (
|
|||||||
// plus stuff needed to modify the ResMap.
|
// plus stuff needed to modify the ResMap.
|
||||||
type ResAccumulator struct {
|
type ResAccumulator struct {
|
||||||
resMap resmap.ResMap
|
resMap resmap.ResMap
|
||||||
tConfig *config.TransformerConfig
|
tConfig *builtinconfig.TransformerConfig
|
||||||
varSet types.VarSet
|
varSet types.VarSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeEmptyAccumulator() *ResAccumulator {
|
func MakeEmptyAccumulator() *ResAccumulator {
|
||||||
ra := &ResAccumulator{}
|
ra := &ResAccumulator{}
|
||||||
ra.resMap = resmap.New()
|
ra.resMap = resmap.New()
|
||||||
ra.tConfig = &config.TransformerConfig{}
|
ra.tConfig = &builtinconfig.TransformerConfig{}
|
||||||
ra.varSet = types.NewVarSet()
|
ra.varSet = types.NewVarSet()
|
||||||
return ra
|
return ra
|
||||||
}
|
}
|
||||||
@@ -53,19 +52,25 @@ func (ra *ResAccumulator) AbsorbAll(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ra *ResAccumulator) MergeConfig(
|
func (ra *ResAccumulator) MergeConfig(
|
||||||
tConfig *config.TransformerConfig) (err error) {
|
tConfig *builtinconfig.TransformerConfig) (err error) {
|
||||||
ra.tConfig, err = ra.tConfig.Merge(tConfig)
|
ra.tConfig, err = ra.tConfig.Merge(tConfig)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ra *ResAccumulator) GetTransformerConfig() *config.TransformerConfig {
|
func (ra *ResAccumulator) GetTransformerConfig() *builtinconfig.TransformerConfig {
|
||||||
return ra.tConfig
|
return ra.tConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
|
func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
|
||||||
for _, v := range incoming {
|
for _, v := range incoming {
|
||||||
matched := ra.resMap.GetMatchingResourcesByOriginalId(
|
targetId := resid.NewResIdWithNamespace(v.ObjRef.GVK(), v.ObjRef.Name, v.ObjRef.Namespace)
|
||||||
resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name).GvknEquals)
|
idMatcher := targetId.GvknEquals
|
||||||
|
if targetId.Namespace != "" || !targetId.IsNamespaceableKind() {
|
||||||
|
// Preserve backward compatibility. An empty namespace means
|
||||||
|
// wildcard search on the namespace hence we still use GvknEquals
|
||||||
|
idMatcher = targetId.Equals
|
||||||
|
}
|
||||||
|
matched := ra.resMap.GetMatchingResourcesByOriginalId(idMatcher)
|
||||||
if len(matched) > 1 {
|
if len(matched) > 1 {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"found %d resId matches for var %s "+
|
"found %d resId matches for var %s "+
|
||||||
@@ -129,7 +134,7 @@ func (ra *ResAccumulator) makeVarReplacementMap() (map[string]interface{}, error
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ra *ResAccumulator) Transform(t transformers.Transformer) error {
|
func (ra *ResAccumulator) Transform(t resmap.Transformer) error {
|
||||||
return t.Transform(ra.resMap)
|
return t.Transform(ra.resMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +146,7 @@ func (ra *ResAccumulator) ResolveVars() error {
|
|||||||
if len(replacementMap) == 0 {
|
if len(replacementMap) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
t := transformers.NewRefVarTransformer(
|
t := newRefVarTransformer(
|
||||||
replacementMap, ra.tConfig.VarReference)
|
replacementMap, ra.tConfig.VarReference)
|
||||||
err = ra.Transform(t)
|
err = ra.Transform(t)
|
||||||
if len(t.UnusedVars()) > 0 {
|
if len(t.UnusedVars()) > 0 {
|
||||||
@@ -156,6 +161,6 @@ func (ra *ResAccumulator) FixBackReferences() (err error) {
|
|||||||
if ra.tConfig.NameReference == nil {
|
if ra.tConfig.NameReference == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ra.Transform(transformers.NewNameReferenceTransformer(
|
return ra.Transform(newNameReferenceTransformer(
|
||||||
ra.tConfig.NameReference))
|
ra.tConfig.NameReference))
|
||||||
}
|
}
|
||||||
@@ -10,19 +10,19 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/accumulator"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
"sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeResAccumulator(t *testing.T) (*ResAccumulator, *resource.Factory) {
|
func makeResAccumulator(t *testing.T) (*ResAccumulator, *resource.Factory) {
|
||||||
ra := MakeEmptyAccumulator()
|
ra := MakeEmptyAccumulator()
|
||||||
err := ra.MergeConfig(config.MakeDefaultConfig())
|
err := ra.MergeConfig(builtinconfig.MakeDefaultConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
@@ -75,13 +75,13 @@ func TestResolveVarsHappy(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SERVICE_ONE",
|
Name: "SERVICE_ONE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendOne"},
|
Name: "backendOne"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "SERVICE_TWO",
|
Name: "SERVICE_TWO",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendTwo"},
|
Name: "backendTwo"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -104,13 +104,13 @@ func TestResolveVarsOneUnused(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SERVICE_ONE",
|
Name: "SERVICE_ONE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendOne"},
|
Name: "backendOne"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "SERVICE_UNUSED",
|
Name: "SERVICE_UNUSED",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendTwo"},
|
Name: "backendTwo"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -165,7 +165,7 @@ func TestResolveVarsVarNeedsDisambiguation(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SERVICE_ONE",
|
Name: "SERVICE_ONE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendOne",
|
Name: "backendOne",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -179,13 +179,94 @@ func TestResolveVarsVarNeedsDisambiguation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeNamespacedConfigMapWithDataProviderValue(
|
||||||
|
namespace string,
|
||||||
|
value string,
|
||||||
|
) map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "environment",
|
||||||
|
"namespace": namespace,
|
||||||
|
},
|
||||||
|
"data": map[string]interface{}{
|
||||||
|
"provider": value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeVarToNamepaceAndPath(
|
||||||
|
name string,
|
||||||
|
namespace string,
|
||||||
|
path string,
|
||||||
|
) types.Var {
|
||||||
|
return types.Var{
|
||||||
|
Name: name,
|
||||||
|
ObjRef: types.Target{
|
||||||
|
Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"},
|
||||||
|
Name: "environment",
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
FieldRef: types.FieldSelector{FieldPath: path},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveVarConflicts(t *testing.T) {
|
||||||
|
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
|
||||||
|
// create configmaps in foo and bar namespaces with `data.provider` values.
|
||||||
|
fooAws := makeNamespacedConfigMapWithDataProviderValue("foo", "aws")
|
||||||
|
barAws := makeNamespacedConfigMapWithDataProviderValue("bar", "aws")
|
||||||
|
barGcp := makeNamespacedConfigMapWithDataProviderValue("bar", "gcp")
|
||||||
|
|
||||||
|
// create two variables with (apparently) conflicting names that point to
|
||||||
|
// fieldpaths that could be generalized.
|
||||||
|
varFoo := makeVarToNamepaceAndPath("PROVIDER", "foo", "data.provider")
|
||||||
|
varBar := makeVarToNamepaceAndPath("PROVIDER", "bar", "data.provider")
|
||||||
|
|
||||||
|
// create accumulators holding apparently conflicting vars that are not
|
||||||
|
// actually in conflict because they point to the same concrete value.
|
||||||
|
rm0 := resmap.New()
|
||||||
|
rm0.Append(rf.FromMap(fooAws))
|
||||||
|
ac0 := MakeEmptyAccumulator()
|
||||||
|
ac0.AppendAll(rm0)
|
||||||
|
ac0.MergeVars([]types.Var{varFoo})
|
||||||
|
|
||||||
|
rm1 := resmap.New()
|
||||||
|
rm1.Append(rf.FromMap(barAws))
|
||||||
|
ac1 := MakeEmptyAccumulator()
|
||||||
|
ac1.AppendAll(rm1)
|
||||||
|
ac1.MergeVars([]types.Var{varBar})
|
||||||
|
|
||||||
|
// validate that two vars of the same name which reference the same concrete
|
||||||
|
// value do not produce a conflict.
|
||||||
|
err := ac0.MergeAccumulator(ac1)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("see bug gh-1600")
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an accumulator will have an actually conflicting value with the
|
||||||
|
// two above (because it contains a variable whose name is used in the other
|
||||||
|
// accumulators AND whose concrete values are different).
|
||||||
|
rm2 := resmap.New()
|
||||||
|
rm2.Append(rf.FromMap(barGcp))
|
||||||
|
ac2 := MakeEmptyAccumulator()
|
||||||
|
ac2.AppendAll(rm2)
|
||||||
|
ac2.MergeVars([]types.Var{varBar})
|
||||||
|
err = ac1.MergeAccumulator(ac2)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("dupe vars w/ different concrete values should conflict")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestResolveVarsGoodResIdBadField(t *testing.T) {
|
func TestResolveVarsGoodResIdBadField(t *testing.T) {
|
||||||
ra, _ := makeResAccumulator(t)
|
ra, _ := makeResAccumulator(t)
|
||||||
err := ra.MergeVars([]types.Var{
|
err := ra.MergeVars([]types.Var{
|
||||||
{
|
{
|
||||||
Name: "SERVICE_ONE",
|
Name: "SERVICE_ONE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendOne"},
|
Name: "backendOne"},
|
||||||
FieldRef: types.FieldSelector{FieldPath: "nope_nope_nope"},
|
FieldRef: types.FieldSelector{FieldPath: "nope_nope_nope"},
|
||||||
},
|
},
|
||||||
@@ -210,7 +291,7 @@ func TestResolveVarsUnmappableVar(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SERVICE_THREE",
|
Name: "SERVICE_THREE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "doesNotExist"},
|
Name: "doesNotExist"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -234,7 +315,7 @@ func TestResolveVarsWithNoambiguation(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SERVICE_ONE",
|
Name: "SERVICE_ONE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendOne",
|
Name: "backendOne",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -289,7 +370,7 @@ func TestResolveVarsWithNoambiguation(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SUB_SERVICE_ONE",
|
Name: "SUB_SERVICE_ONE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
|
Gvk: resid.Gvk{Version: "v1", Kind: "Service"},
|
||||||
Name: "backendOne",
|
Name: "backendOne",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1,27 +1,15 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cloner is a function that can clone a git repo.
|
// Cloner is a function that can clone a git repo.
|
||||||
@@ -35,22 +23,24 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "no 'git' program on path")
|
return errors.Wrap(err, "no 'git' program on path")
|
||||||
}
|
}
|
||||||
repoSpec.cloneDir, err = fs.NewTmpConfirmedDir()
|
repoSpec.Dir, err = filesys.NewTmpConfirmedDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmd := exec.Command(
|
cmd := exec.Command(
|
||||||
gitProgram,
|
gitProgram,
|
||||||
"init",
|
"init",
|
||||||
repoSpec.cloneDir.String())
|
repoSpec.Dir.String())
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
|
cmd.Stderr = &out
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Error initializing empty git repo: %s", out.String())
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err,
|
err,
|
||||||
"trouble initializing empty git repo in %s",
|
"trouble initializing empty git repo in %s",
|
||||||
repoSpec.cloneDir.String())
|
repoSpec.Dir.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command(
|
cmd = exec.Command(
|
||||||
@@ -60,28 +50,32 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
|||||||
"origin",
|
"origin",
|
||||||
repoSpec.CloneSpec())
|
repoSpec.CloneSpec())
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Dir = repoSpec.cloneDir.String()
|
cmd.Stderr = &out
|
||||||
|
cmd.Dir = repoSpec.Dir.String()
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Error setting git remote: %s", out.String())
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err,
|
err,
|
||||||
"trouble adding remote %s",
|
"trouble adding remote %s",
|
||||||
repoSpec.CloneSpec())
|
repoSpec.CloneSpec())
|
||||||
}
|
}
|
||||||
if repoSpec.ref == "" {
|
if repoSpec.Ref == "" {
|
||||||
repoSpec.ref = "master"
|
repoSpec.Ref = "master"
|
||||||
}
|
}
|
||||||
cmd = exec.Command(
|
cmd = exec.Command(
|
||||||
gitProgram,
|
gitProgram,
|
||||||
"fetch",
|
"fetch",
|
||||||
"--depth=1",
|
"--depth=1",
|
||||||
"origin",
|
"origin",
|
||||||
repoSpec.ref)
|
repoSpec.Ref)
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Dir = repoSpec.cloneDir.String()
|
cmd.Stderr = &out
|
||||||
|
cmd.Dir = repoSpec.Dir.String()
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "trouble fetching %s", repoSpec.ref)
|
log.Printf("Error performing git fetch: %s", out.String())
|
||||||
|
return errors.Wrapf(err, "trouble fetching %s", repoSpec.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command(
|
cmd = exec.Command(
|
||||||
@@ -90,12 +84,28 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
|||||||
"--hard",
|
"--hard",
|
||||||
"FETCH_HEAD")
|
"FETCH_HEAD")
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Dir = repoSpec.cloneDir.String()
|
cmd.Stderr = &out
|
||||||
|
cmd.Dir = repoSpec.Dir.String()
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Error performing git reset: %s", out.String())
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err, "trouble hard resetting empty repository to %s", repoSpec.ref)
|
err, "trouble hard resetting empty repository to %s", repoSpec.Ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd = exec.Command(
|
||||||
|
gitProgram,
|
||||||
|
"submodule",
|
||||||
|
"update",
|
||||||
|
"--init",
|
||||||
|
"--recursive")
|
||||||
|
cmd.Stdout = &out
|
||||||
|
cmd.Dir = repoSpec.Dir.String()
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "trouble fetching submodules for %s", repoSpec.Ref)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,9 +113,9 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
|||||||
// cloneDir field in the repoSpec. It's assumed that
|
// cloneDir field in the repoSpec. It's assumed that
|
||||||
// the cloneDir is associated with some fake filesystem
|
// the cloneDir is associated with some fake filesystem
|
||||||
// used in a test.
|
// used in a test.
|
||||||
func DoNothingCloner(dir fs.ConfirmedDir) Cloner {
|
func DoNothingCloner(dir filesys.ConfirmedDir) Cloner {
|
||||||
return func(rs *RepoSpec) error {
|
return func(rs *RepoSpec) error {
|
||||||
rs.cloneDir = dir
|
rs.Dir = dir
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 git
|
package git
|
||||||
|
|
||||||
@@ -22,7 +9,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used as a temporary non-empty occupant of the cloneDir
|
// Used as a temporary non-empty occupant of the cloneDir
|
||||||
@@ -30,7 +17,7 @@ import (
|
|||||||
// in various outputs (especially tests). Not using an
|
// in various outputs (especially tests). Not using an
|
||||||
// actual directory name here, as that's a temporary directory
|
// actual directory name here, as that's a temporary directory
|
||||||
// with a unique name that isn't created until clone time.
|
// with a unique name that isn't created until clone time.
|
||||||
const notCloned = fs.ConfirmedDir("/notCloned")
|
const notCloned = filesys.ConfirmedDir("/notCloned")
|
||||||
|
|
||||||
// RepoSpec specifies a git repository and a branch and path therein.
|
// RepoSpec specifies a git repository and a branch and path therein.
|
||||||
type RepoSpec struct {
|
type RepoSpec struct {
|
||||||
@@ -39,36 +26,36 @@ type RepoSpec struct {
|
|||||||
raw string
|
raw string
|
||||||
|
|
||||||
// Host, e.g. github.com
|
// Host, e.g. github.com
|
||||||
host string
|
Host string
|
||||||
|
|
||||||
// orgRepo name (organization/repoName),
|
// orgRepo name (organization/repoName),
|
||||||
// e.g. kubernetes-sigs/kustomize
|
// e.g. kubernetes-sigs/kustomize
|
||||||
orgRepo string
|
OrgRepo string
|
||||||
|
|
||||||
// ConfirmedDir where the orgRepo is cloned to.
|
// Dir where the orgRepo is cloned to.
|
||||||
cloneDir fs.ConfirmedDir
|
Dir filesys.ConfirmedDir
|
||||||
|
|
||||||
// Relative path in the repository, and in the cloneDir,
|
// Relative path in the repository, and in the cloneDir,
|
||||||
// to a Kustomization.
|
// to a Kustomization.
|
||||||
path string
|
Path string
|
||||||
|
|
||||||
// Branch or tag reference.
|
// Branch or tag reference.
|
||||||
ref string
|
Ref string
|
||||||
|
|
||||||
// e.g. .git or empty in case of _git is present
|
// e.g. .git or empty in case of _git is present
|
||||||
gitSuffix string
|
GitSuffix string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloneSpec returns a string suitable for "git clone {spec}".
|
// CloneSpec returns a string suitable for "git clone {spec}".
|
||||||
func (x *RepoSpec) CloneSpec() string {
|
func (x *RepoSpec) CloneSpec() string {
|
||||||
if isAzureHost(x.host) || isAWSHost(x.host) {
|
if isAzureHost(x.Host) || isAWSHost(x.Host) {
|
||||||
return x.host + x.orgRepo
|
return x.Host + x.OrgRepo
|
||||||
}
|
}
|
||||||
return x.host + x.orgRepo + x.gitSuffix
|
return x.Host + x.OrgRepo + x.GitSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RepoSpec) CloneDir() fs.ConfirmedDir {
|
func (x *RepoSpec) CloneDir() filesys.ConfirmedDir {
|
||||||
return x.cloneDir
|
return x.Dir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RepoSpec) Raw() string {
|
func (x *RepoSpec) Raw() string {
|
||||||
@@ -76,11 +63,11 @@ func (x *RepoSpec) Raw() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (x *RepoSpec) AbsPath() string {
|
func (x *RepoSpec) AbsPath() string {
|
||||||
return x.cloneDir.Join(x.path)
|
return x.Dir.Join(x.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RepoSpec) Cleaner(fSys fs.FileSystem) func() error {
|
func (x *RepoSpec) Cleaner(fSys filesys.FileSystem) func() error {
|
||||||
return func() error { return fSys.RemoveAll(x.cloneDir.String()) }
|
return func() error { return fSys.RemoveAll(x.Dir.String()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// From strings like git@github.com:someOrg/someRepo.git or
|
// From strings like git@github.com:someOrg/someRepo.git or
|
||||||
@@ -90,7 +77,7 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
|
|||||||
if filepath.IsAbs(n) {
|
if filepath.IsAbs(n) {
|
||||||
return nil, fmt.Errorf("uri looks like abs path: %s", n)
|
return nil, fmt.Errorf("uri looks like abs path: %s", n)
|
||||||
}
|
}
|
||||||
host, orgRepo, path, gitRef, gitSuffix := parseGithubUrl(n)
|
host, orgRepo, path, gitRef, gitSuffix := parseGitUrl(n)
|
||||||
if orgRepo == "" {
|
if orgRepo == "" {
|
||||||
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
|
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
|
||||||
}
|
}
|
||||||
@@ -98,8 +85,8 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
|
|||||||
return nil, fmt.Errorf("url lacks host: %s", n)
|
return nil, fmt.Errorf("url lacks host: %s", n)
|
||||||
}
|
}
|
||||||
return &RepoSpec{
|
return &RepoSpec{
|
||||||
raw: n, host: host, orgRepo: orgRepo,
|
raw: n, Host: host, OrgRepo: orgRepo,
|
||||||
cloneDir: notCloned, path: path, ref: gitRef, gitSuffix: gitSuffix}, nil
|
Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: gitSuffix}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -112,13 +99,13 @@ const (
|
|||||||
// From strings like git@github.com:someOrg/someRepo.git or
|
// From strings like git@github.com:someOrg/someRepo.git or
|
||||||
// https://github.com/someOrg/someRepo?ref=someHash, extract
|
// https://github.com/someOrg/someRepo?ref=someHash, extract
|
||||||
// the parts.
|
// the parts.
|
||||||
func parseGithubUrl(n string) (
|
func parseGitUrl(n string) (
|
||||||
host string, orgRepo string, path string, gitRef string, gitSuff string) {
|
host string, orgRepo string, path string, gitRef string, gitSuff string) {
|
||||||
|
|
||||||
if strings.Contains(n, gitDelimiter) {
|
if strings.Contains(n, gitDelimiter) {
|
||||||
index := strings.Index(n, gitDelimiter)
|
index := strings.Index(n, gitDelimiter)
|
||||||
// Adding _git/ to host
|
// Adding _git/ to host
|
||||||
host = n[:index+len(gitDelimiter)]
|
host = normalizeGitHostSpec(n[:index+len(gitDelimiter)])
|
||||||
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
|
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
|
||||||
path, gitRef = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
|
path, gitRef = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
|
||||||
return
|
return
|
||||||
@@ -213,7 +200,7 @@ func normalizeGitHostSpec(host string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(s, "git::") {
|
if strings.HasPrefix(s, "git::") {
|
||||||
host = strings.TrimLeft(s, "git::")
|
host = strings.TrimPrefix(s, "git::")
|
||||||
}
|
}
|
||||||
return host
|
return host
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 git
|
package git
|
||||||
|
|
||||||
@@ -72,17 +59,17 @@ func TestNewRepoSpecFromUrl(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("problem %v", err)
|
t.Errorf("problem %v", err)
|
||||||
}
|
}
|
||||||
if rs.host != hostSpec {
|
if rs.Host != hostSpec {
|
||||||
bad = append(bad, []string{"host", uri, rs.host, hostSpec})
|
bad = append(bad, []string{"host", uri, rs.Host, hostSpec})
|
||||||
}
|
}
|
||||||
if rs.orgRepo != orgRepo {
|
if rs.OrgRepo != orgRepo {
|
||||||
bad = append(bad, []string{"orgRepo", uri, rs.orgRepo, orgRepo})
|
bad = append(bad, []string{"orgRepo", uri, rs.OrgRepo, orgRepo})
|
||||||
}
|
}
|
||||||
if rs.path != pathName {
|
if rs.Path != pathName {
|
||||||
bad = append(bad, []string{"path", uri, rs.path, pathName})
|
bad = append(bad, []string{"path", uri, rs.Path, pathName})
|
||||||
}
|
}
|
||||||
if rs.ref != hrefArg {
|
if rs.Ref != hrefArg {
|
||||||
bad = append(bad, []string{"ref", uri, rs.ref, hrefArg})
|
bad = append(bad, []string{"ref", uri, rs.Ref, hrefArg})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,6 +174,12 @@ func TestNewRepoSpecFromUrl_CloneSpecs(t *testing.T) {
|
|||||||
absPath: notCloned.Join("somedir"),
|
absPath: notCloned.Join("somedir"),
|
||||||
ref: "v1.0.0",
|
ref: "v1.0.0",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: "git::https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
|
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
|
absPath: notCloned.String(),
|
||||||
|
ref: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, testcase := range testcases {
|
for _, testcase := range testcases {
|
||||||
rs, err := NewRepoSpecFromUrl(testcase.input)
|
rs, err := NewRepoSpecFromUrl(testcase.input)
|
||||||
@@ -201,9 +194,9 @@ func TestNewRepoSpecFromUrl_CloneSpecs(t *testing.T) {
|
|||||||
t.Errorf("AbsPath expected to be %v, but got %v on %s",
|
t.Errorf("AbsPath expected to be %v, but got %v on %s",
|
||||||
testcase.absPath, rs.AbsPath(), testcase.input)
|
testcase.absPath, rs.AbsPath(), testcase.input)
|
||||||
}
|
}
|
||||||
if rs.ref != testcase.ref {
|
if rs.Ref != testcase.ref {
|
||||||
t.Errorf("ref expected to be %v, but got %v on %s",
|
t.Errorf("ref expected to be %v, but got %v on %s",
|
||||||
testcase.ref, rs.ref, testcase.input)
|
testcase.ref, rs.Ref, testcase.input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,8 +8,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeFreshConfigMap(
|
func makeFreshConfigMap(
|
||||||
@@ -26,15 +27,15 @@ func makeFreshConfigMap(
|
|||||||
// MakeConfigMap returns a new ConfigMap, or nil and an error.
|
// MakeConfigMap returns a new ConfigMap, or nil and an error.
|
||||||
func (f *Factory) MakeConfigMap(
|
func (f *Factory) MakeConfigMap(
|
||||||
args *types.ConfigMapArgs) (*v1.ConfigMap, error) {
|
args *types.ConfigMapArgs) (*v1.ConfigMap, error) {
|
||||||
all, err := f.ldr.LoadKvPairs(args.GeneratorArgs)
|
all, err := f.kvLdr.Load(args.KvPairSources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "loading KV pairs")
|
||||||
}
|
}
|
||||||
cm := makeFreshConfigMap(args)
|
cm := makeFreshConfigMap(args)
|
||||||
for _, p := range all {
|
for _, p := range all {
|
||||||
err = f.addKvToConfigMap(cm, p)
|
err = f.addKvToConfigMap(cm, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "trouble mapping")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.options != nil {
|
if f.options != nil {
|
||||||
@@ -47,7 +48,7 @@ func (f *Factory) MakeConfigMap(
|
|||||||
// addKvToConfigMap adds the given key and data to the given config map.
|
// addKvToConfigMap adds the given key and data to the given config map.
|
||||||
// Error if key invalid, or already exists.
|
// Error if key invalid, or already exists.
|
||||||
func (f *Factory) addKvToConfigMap(configMap *v1.ConfigMap, p types.Pair) error {
|
func (f *Factory) addKvToConfigMap(configMap *v1.ConfigMap, p types.Pair) error {
|
||||||
if err := f.ldr.Validator().ErrIfInvalidKey(p.Key); err != nil {
|
if err := f.kvLdr.Validator().ErrIfInvalidKey(p.Key); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// If the configmap data contains byte sequences that are all in the UTF-8
|
// If the configmap data contains byte sequences that are all in the UTF-8
|
||||||
@@ -4,15 +4,17 @@
|
|||||||
package configmapandsecret
|
package configmapandsecret
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/validators"
|
corev1 "sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1"
|
||||||
|
metav1 "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeEnvConfigMap(name string) *corev1.ConfigMap {
|
func makeEnvConfigMap(name string) *corev1.ConfigMap {
|
||||||
@@ -85,8 +87,10 @@ func TestConstructConfigMap(t *testing.T) {
|
|||||||
input: types.ConfigMapArgs{
|
input: types.ConfigMapArgs{
|
||||||
GeneratorArgs: types.GeneratorArgs{
|
GeneratorArgs: types.GeneratorArgs{
|
||||||
Name: "envConfigMap",
|
Name: "envConfigMap",
|
||||||
DataSources: types.DataSources{
|
KvPairSources: types.KvPairSources{
|
||||||
EnvSources: []string{"configmap/app.env"},
|
EnvSources: []string{
|
||||||
|
filepath.Join("configmap", "app.env"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -98,8 +102,11 @@ func TestConstructConfigMap(t *testing.T) {
|
|||||||
input: types.ConfigMapArgs{
|
input: types.ConfigMapArgs{
|
||||||
GeneratorArgs: types.GeneratorArgs{
|
GeneratorArgs: types.GeneratorArgs{
|
||||||
Name: "fileConfigMap",
|
Name: "fileConfigMap",
|
||||||
DataSources: types.DataSources{
|
KvPairSources: types.KvPairSources{
|
||||||
FileSources: []string{"configmap/app-init.ini", "configmap/app.bin"},
|
FileSources: []string{
|
||||||
|
filepath.Join("configmap", "app-init.ini"),
|
||||||
|
filepath.Join("configmap", "app.bin"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -111,7 +118,7 @@ func TestConstructConfigMap(t *testing.T) {
|
|||||||
input: types.ConfigMapArgs{
|
input: types.ConfigMapArgs{
|
||||||
GeneratorArgs: types.GeneratorArgs{
|
GeneratorArgs: types.GeneratorArgs{
|
||||||
Name: "literalConfigMap",
|
Name: "literalConfigMap",
|
||||||
DataSources: types.DataSources{
|
KvPairSources: types.KvPairSources{
|
||||||
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -125,13 +132,21 @@ func TestConstructConfigMap(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fSys := fs.MakeFakeFS()
|
fSys := filesys.MakeFsInMemory()
|
||||||
fSys.WriteFile("/configmap/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
|
fSys.WriteFile(
|
||||||
fSys.WriteFile("/configmap/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
|
filesys.RootedPath("configmap", "app.env"),
|
||||||
fSys.WriteFile("/configmap/app.bin", []byte{0xff, 0xfd})
|
[]byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
|
||||||
ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys)
|
fSys.WriteFile(
|
||||||
|
filesys.RootedPath("configmap", "app-init.ini"),
|
||||||
|
[]byte("FOO=bar\nBAR=baz\n"))
|
||||||
|
fSys.WriteFile(
|
||||||
|
filesys.RootedPath("configmap", "app.bin"),
|
||||||
|
[]byte{0xff, 0xfd})
|
||||||
|
kvLdr := kv.NewLoader(
|
||||||
|
loader.NewFileLoaderAtRoot(fSys),
|
||||||
|
valtest_test.MakeFakeValidator())
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
f := NewFactory(ldr, tc.options)
|
f := NewFactory(kvLdr, tc.options)
|
||||||
cm, err := f.MakeConfigMap(&tc.input)
|
cm, err := f.MakeConfigMap(&tc.input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -4,20 +4,20 @@
|
|||||||
package configmapandsecret
|
package configmapandsecret
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Factory makes ConfigMaps and Secrets.
|
// Factory makes ConfigMaps and Secrets.
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
ldr ifc.Loader
|
kvLdr ifc.KvLoader
|
||||||
options *types.GeneratorOptions
|
options *types.GeneratorOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactory returns a new factory that makes ConfigMaps and Secrets.
|
// NewFactory returns a new factory that makes ConfigMaps and Secrets.
|
||||||
func NewFactory(
|
func NewFactory(
|
||||||
ldr ifc.Loader, o *types.GeneratorOptions) *Factory {
|
kvLdr ifc.KvLoader, o *types.GeneratorOptions) *Factory {
|
||||||
return &Factory{ldr: ldr, options: o}
|
return &Factory{kvLdr: kvLdr, options: o}
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v"
|
const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v"
|
||||||
@@ -6,8 +6,8 @@ package configmapandsecret
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
corev1 "sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeFreshSecret(
|
func makeFreshSecret(
|
||||||
@@ -28,7 +28,7 @@ func makeFreshSecret(
|
|||||||
// MakeSecret returns a new secret.
|
// MakeSecret returns a new secret.
|
||||||
func (f *Factory) MakeSecret(
|
func (f *Factory) MakeSecret(
|
||||||
args *types.SecretArgs) (*corev1.Secret, error) {
|
args *types.SecretArgs) (*corev1.Secret, error) {
|
||||||
all, err := f.ldr.LoadKvPairs(args.GeneratorArgs)
|
all, err := f.kvLdr.Load(args.KvPairSources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ func (f *Factory) MakeSecret(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Factory) addKvToSecret(secret *corev1.Secret, keyName, data string) error {
|
func (f *Factory) addKvToSecret(secret *corev1.Secret, keyName, data string) error {
|
||||||
if err := f.ldr.Validator().ErrIfInvalidKey(keyName); err != nil {
|
if err := f.kvLdr.Validator().ErrIfInvalidKey(keyName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, entryExists := secret.Data[keyName]; entryExists {
|
if _, entryExists := secret.Data[keyName]; entryExists {
|
||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/validators"
|
corev1 "sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1"
|
||||||
|
metav1 "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeEnvSecret(name string) *corev1.Secret {
|
func makeEnvSecret(name string) *corev1.Secret {
|
||||||
@@ -83,7 +84,7 @@ func TestConstructSecret(t *testing.T) {
|
|||||||
input: types.SecretArgs{
|
input: types.SecretArgs{
|
||||||
GeneratorArgs: types.GeneratorArgs{
|
GeneratorArgs: types.GeneratorArgs{
|
||||||
Name: "envSecret",
|
Name: "envSecret",
|
||||||
DataSources: types.DataSources{
|
KvPairSources: types.KvPairSources{
|
||||||
EnvSources: []string{"secret/app.env"},
|
EnvSources: []string{"secret/app.env"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -96,7 +97,7 @@ func TestConstructSecret(t *testing.T) {
|
|||||||
input: types.SecretArgs{
|
input: types.SecretArgs{
|
||||||
GeneratorArgs: types.GeneratorArgs{
|
GeneratorArgs: types.GeneratorArgs{
|
||||||
Name: "fileSecret",
|
Name: "fileSecret",
|
||||||
DataSources: types.DataSources{
|
KvPairSources: types.KvPairSources{
|
||||||
FileSources: []string{"secret/app-init.ini"},
|
FileSources: []string{"secret/app-init.ini"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -109,7 +110,7 @@ func TestConstructSecret(t *testing.T) {
|
|||||||
input: types.SecretArgs{
|
input: types.SecretArgs{
|
||||||
GeneratorArgs: types.GeneratorArgs{
|
GeneratorArgs: types.GeneratorArgs{
|
||||||
Name: "literalSecret",
|
Name: "literalSecret",
|
||||||
DataSources: types.DataSources{
|
KvPairSources: types.KvPairSources{
|
||||||
LiteralSources: []string{"a=x", "b=y"},
|
LiteralSources: []string{"a=x", "b=y"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -123,12 +124,14 @@ func TestConstructSecret(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fSys := fs.MakeFakeFS()
|
fSys := filesys.MakeFsInMemory()
|
||||||
fSys.WriteFile("/secret/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
|
fSys.WriteFile("/secret/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
|
||||||
fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
|
fSys.WriteFile("/secret/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
|
||||||
ldr := loader.NewFileLoaderAtRoot(validators.MakeFakeValidator(), fSys)
|
kvLdr := kv.NewLoader(
|
||||||
|
loader.NewFileLoaderAtRoot(fSys),
|
||||||
|
valtest_test.MakeFakeValidator())
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
f := NewFactory(ldr, tc.options)
|
f := NewFactory(kvLdr, tc.options)
|
||||||
cm, err := f.MakeSecret(&tc.input)
|
cm, err := f.MakeSecret(&tc.input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@@ -5,9 +5,9 @@
|
|||||||
package transformer
|
package transformer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer/patch"
|
"sigs.k8s.io/kustomize/api/internal/k8sdeps/transformer/patch"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FactoryImpl makes patch transformer and name hash transformer
|
// FactoryImpl makes patch transformer and name hash transformer
|
||||||
@@ -6,16 +6,16 @@ package patch
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
|
||||||
|
|
||||||
"github.com/evanphx/json-patch"
|
jsonpatch "github.com/evanphx/json-patch"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"k8s.io/apimachinery/pkg/util/mergepatch"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/runtime"
|
||||||
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/runtime/schema"
|
||||||
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/util/mergepatch"
|
||||||
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/util/strategicpatch"
|
||||||
|
"sigs.k8s.io/kustomize/pseudo/k8s/client-go/kubernetes/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
type conflictDetector interface {
|
type conflictDetector interface {
|
||||||
@@ -45,7 +45,7 @@ func (jmp *jsonMergePatch) findConflict(
|
|||||||
if i == conflictingPatchIdx {
|
if i == conflictingPatchIdx {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !patches[conflictingPatchIdx].OrgId().GvknEquals(patch.OrgId()) {
|
if !patches[conflictingPatchIdx].OrgId().Equals(patch.OrgId()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
conflict, err := mergepatch.HasConflicts(
|
conflict, err := mergepatch.HasConflicts(
|
||||||
@@ -105,7 +105,7 @@ func (smp *strategicMergePatch) findConflict(
|
|||||||
if i == conflictingPatchIdx {
|
if i == conflictingPatchIdx {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !patches[conflictingPatchIdx].OrgId().GvknEquals(patch.OrgId()) {
|
if !patches[conflictingPatchIdx].OrgId().Equals(patch.OrgId()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
conflict, err := strategicpatch.MergingMapsHaveConflicts(
|
conflict, err := strategicpatch.MergingMapsHaveConflicts(
|
||||||
@@ -123,19 +123,25 @@ func (smp *strategicMergePatch) findConflict(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) {
|
func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) {
|
||||||
|
if hasDeleteDirectiveMarker(patch2.Map()) {
|
||||||
|
if hasDeleteDirectiveMarker(patch1.Map()) {
|
||||||
|
return nil, fmt.Errorf("cannot merge patches both containing '$patch: delete' directives")
|
||||||
|
}
|
||||||
|
patch1, patch2 = patch2, patch1
|
||||||
|
}
|
||||||
mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
|
mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
|
||||||
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
|
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
|
||||||
return smp.rf.FromMap(mergeJSONMap), err
|
return smp.rf.FromMap(mergeJSONMap), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// mergePatches merge and index patches by OrgId.
|
// MergePatches merge and index patches by OrgId.
|
||||||
// It errors out if there is conflict between patches.
|
// It errors out if there is conflict between patches.
|
||||||
func MergePatches(patches []*resource.Resource,
|
func MergePatches(patches []*resource.Resource,
|
||||||
rf *resource.Factory) (resmap.ResMap, error) {
|
rf *resource.Factory) (resmap.ResMap, error) {
|
||||||
rc := resmap.New()
|
rc := resmap.New()
|
||||||
for ix, patch := range patches {
|
for ix, patch := range patches {
|
||||||
id := patch.OrgId()
|
id := patch.OrgId()
|
||||||
existing := rc.GetMatchingResourcesByOriginalId(id.GvknEquals)
|
existing := rc.GetMatchingResourcesByOriginalId(id.Equals)
|
||||||
if len(existing) == 0 {
|
if len(existing) == 0 {
|
||||||
rc.Append(patch)
|
rc.Append(patch)
|
||||||
continue
|
continue
|
||||||
@@ -181,10 +187,35 @@ func MergePatches(patches []*resource.Resource,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// toSchemaGvk converts to a schema.GroupVersionKind.
|
// toSchemaGvk converts to a schema.GroupVersionKind.
|
||||||
func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind {
|
func toSchemaGvk(x resid.Gvk) schema.GroupVersionKind {
|
||||||
return schema.GroupVersionKind{
|
return schema.GroupVersionKind{
|
||||||
Group: x.Group,
|
Group: x.Group,
|
||||||
Version: x.Version,
|
Version: x.Version,
|
||||||
Kind: x.Kind,
|
Kind: x.Kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasDeleteDirectiveMarker(patch map[string]interface{}) bool {
|
||||||
|
if v, ok := patch["$patch"]; ok && v == "delete" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, v := range patch {
|
||||||
|
switch typedV := v.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
if hasDeleteDirectiveMarker(typedV) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case []interface{}:
|
||||||
|
for _, sv := range typedV {
|
||||||
|
typedE, ok := sv.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if hasDeleteDirectiveMarker(typedE) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 error has contextual error types.
|
// Package error has contextual error types.
|
||||||
package kusterr
|
package kusterr
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 kusterr
|
package kusterr
|
||||||
|
|
||||||
@@ -6,16 +6,15 @@ package loadertest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/validators"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FakeLoader encapsulates the delegate Loader and the fake file system.
|
// FakeLoader encapsulates the delegate Loader and the fake file system.
|
||||||
type FakeLoader struct {
|
type FakeLoader struct {
|
||||||
fs fs.FileSystem
|
fs filesys.FileSystem
|
||||||
delegate ifc.Loader
|
delegate ifc.Loader
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,10 +32,9 @@ func NewFakeLoader(initialDir string) FakeLoader {
|
|||||||
func NewFakeLoaderWithRestrictor(
|
func NewFakeLoaderWithRestrictor(
|
||||||
lr loader.LoadRestrictorFunc, initialDir string) FakeLoader {
|
lr loader.LoadRestrictorFunc, initialDir string) FakeLoader {
|
||||||
// Create fake filesystem and inject it into initial Loader.
|
// Create fake filesystem and inject it into initial Loader.
|
||||||
fSys := fs.MakeFakeFS()
|
fSys := filesys.MakeFsInMemory()
|
||||||
fSys.Mkdir(initialDir)
|
fSys.Mkdir(initialDir)
|
||||||
ldr, err := loader.NewLoader(
|
ldr, err := loader.NewLoader(lr, initialDir, fSys)
|
||||||
lr, validators.MakeFakeValidator(), initialDir, fSys)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to make loader: %v", err)
|
log.Fatalf("Unable to make loader: %v", err)
|
||||||
}
|
}
|
||||||
@@ -76,13 +74,3 @@ func (f FakeLoader) Load(location string) ([]byte, error) {
|
|||||||
func (f FakeLoader) Cleanup() error {
|
func (f FakeLoader) Cleanup() error {
|
||||||
return f.delegate.Cleanup()
|
return f.delegate.Cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator delegates.
|
|
||||||
func (f FakeLoader) Validator() ifc.Validator {
|
|
||||||
return f.delegate.Validator()
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadKvPairs delegates.
|
|
||||||
func (f FakeLoader) LoadKvPairs(args types.GeneratorArgs) ([]types.Pair, error) {
|
|
||||||
return f.delegate.LoadKvPairs(args)
|
|
||||||
}
|
|
||||||
10
api/internal/plugins/builtinconfig/doc.go
Normal file
10
api/internal/plugins/builtinconfig/doc.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Package builtinconfig provides legacy methods for
|
||||||
|
// configuring builtin plugins from a common config file.
|
||||||
|
// As a user, its best to configure plugins individually
|
||||||
|
// with plugin config files specified in the `transformers:`
|
||||||
|
// or `generators:` field, than to use this legacy
|
||||||
|
// configuration technique.
|
||||||
|
package builtinconfig
|
||||||
42
api/internal/plugins/builtinconfig/loaddefaultconfig.go
Normal file
42
api/internal/plugins/builtinconfig/loaddefaultconfig.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package builtinconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// loadDefaultConfig returns a TranformerConfig
|
||||||
|
// object from a list of files.
|
||||||
|
func loadDefaultConfig(
|
||||||
|
ldr ifc.Loader, paths []string) (*TransformerConfig, error) {
|
||||||
|
result := &TransformerConfig{}
|
||||||
|
for _, path := range paths {
|
||||||
|
data, err := ldr.Load(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t, err := makeTransformerConfigFromBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result, err = result.Merge(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeTransformerConfigFromBytes returns a TransformerConfig object from bytes
|
||||||
|
func makeTransformerConfigFromBytes(data []byte) (*TransformerConfig, error) {
|
||||||
|
var t TransformerConfig
|
||||||
|
err := yaml.Unmarshal(data, &t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t.sortFields()
|
||||||
|
return &t, nil
|
||||||
|
}
|
||||||
@@ -1,37 +1,32 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package config
|
package builtinconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/internal/loadertest"
|
"sigs.k8s.io/kustomize/api/internal/loadertest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMakeDefaultConfig(t *testing.T) {
|
func TestLoadDefaultConfigsFromFiles(t *testing.T) {
|
||||||
// Confirm default can be made without fatal error inside call.
|
|
||||||
_ = MakeDefaultConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromFiles(t *testing.T) {
|
|
||||||
|
|
||||||
ldr := loadertest.NewFakeLoader("/app")
|
ldr := loadertest.NewFakeLoader("/app")
|
||||||
ldr.AddFile("/app/config.yaml", []byte(`
|
ldr.AddFile("/app/config.yaml", []byte(`
|
||||||
namePrefix:
|
namePrefix:
|
||||||
- path: nameprefix/path
|
- path: nameprefix/path
|
||||||
kind: SomeKind
|
kind: SomeKind
|
||||||
`))
|
`))
|
||||||
tcfg, err := NewFactory(ldr).FromFiles([]string{"/app/config.yaml"})
|
tcfg, err := loadDefaultConfig(ldr, []string{"/app/config.yaml"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
expected := &TransformerConfig{
|
expected := &TransformerConfig{
|
||||||
NamePrefix: []FieldSpec{
|
NamePrefix: []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{Kind: "SomeKind"},
|
Gvk: resid.Gvk{Kind: "SomeKind"},
|
||||||
Path: "nameprefix/path",
|
Path: "nameprefix/path",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1,25 +1,13 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package builtinconfig
|
||||||
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 config
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NameBackReferences is an association between a gvk.GVK and a list
|
// NameBackReferences is an association between a gvk.GVK and a list
|
||||||
@@ -51,8 +39,8 @@ import (
|
|||||||
// (etc.)
|
// (etc.)
|
||||||
// }
|
// }
|
||||||
type NameBackReferences struct {
|
type NameBackReferences struct {
|
||||||
gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
|
resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
|
||||||
FieldSpecs fsSlice `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"`
|
FieldSpecs types.FsSlice `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n NameBackReferences) String() string {
|
func (n NameBackReferences) String() string {
|
||||||
@@ -89,7 +77,7 @@ func (s nbrSlice) mergeOne(other NameBackReferences) (nbrSlice, error) {
|
|||||||
found := false
|
found := false
|
||||||
for _, c := range s {
|
for _, c := range s {
|
||||||
if c.Gvk.Equals(other.Gvk) {
|
if c.Gvk.Equals(other.Gvk) {
|
||||||
c.FieldSpecs, err = c.FieldSpecs.mergeAll(other.FieldSpecs)
|
c.FieldSpecs, err = c.FieldSpecs.MergeAll(other.FieldSpecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1,54 +1,43 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package builtinconfig
|
||||||
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 config
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMergeAll(t *testing.T) {
|
func TestMergeAll(t *testing.T) {
|
||||||
fsSlice1 := []FieldSpec{
|
fsSlice1 := []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
},
|
},
|
||||||
Path: "path/to/a/name",
|
Path: "path/to/a/name",
|
||||||
CreateIfNotPresent: false,
|
CreateIfNotPresent: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
},
|
},
|
||||||
Path: "another/path/to/some/name",
|
Path: "another/path/to/some/name",
|
||||||
CreateIfNotPresent: false,
|
CreateIfNotPresent: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fsSlice2 := []FieldSpec{
|
fsSlice2 := []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "Job",
|
Kind: "Job",
|
||||||
},
|
},
|
||||||
Path: "morepath/to/name",
|
Path: "morepath/to/name",
|
||||||
CreateIfNotPresent: false,
|
CreateIfNotPresent: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "StatefulSet",
|
Kind: "StatefulSet",
|
||||||
},
|
},
|
||||||
Path: "yet/another/path/to/a/name",
|
Path: "yet/another/path/to/a/name",
|
||||||
@@ -58,13 +47,13 @@ func TestMergeAll(t *testing.T) {
|
|||||||
|
|
||||||
nbrsSlice1 := nbrSlice{
|
nbrsSlice1 := nbrSlice{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "ConfigMap",
|
Kind: "ConfigMap",
|
||||||
},
|
},
|
||||||
FieldSpecs: fsSlice1,
|
FieldSpecs: fsSlice1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "Secret",
|
Kind: "Secret",
|
||||||
},
|
},
|
||||||
FieldSpecs: fsSlice2,
|
FieldSpecs: fsSlice2,
|
||||||
@@ -72,13 +61,13 @@ func TestMergeAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
nbrsSlice2 := nbrSlice{
|
nbrsSlice2 := nbrSlice{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "ConfigMap",
|
Kind: "ConfigMap",
|
||||||
},
|
},
|
||||||
FieldSpecs: fsSlice1,
|
FieldSpecs: fsSlice1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "Secret",
|
Kind: "Secret",
|
||||||
},
|
},
|
||||||
FieldSpecs: fsSlice2,
|
FieldSpecs: fsSlice2,
|
||||||
@@ -86,13 +75,13 @@ func TestMergeAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
expected := nbrSlice{
|
expected := nbrSlice{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "ConfigMap",
|
Kind: "ConfigMap",
|
||||||
},
|
},
|
||||||
FieldSpecs: fsSlice1,
|
FieldSpecs: fsSlice1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "Secret",
|
Kind: "Secret",
|
||||||
},
|
},
|
||||||
FieldSpecs: fsSlice2,
|
FieldSpecs: fsSlice2,
|
||||||
148
api/internal/plugins/builtinconfig/transformerconfig.go
Normal file
148
api/internal/plugins/builtinconfig/transformerconfig.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package builtinconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TransformerConfig holds the data needed to perform transformations.
|
||||||
|
type TransformerConfig struct {
|
||||||
|
NamePrefix types.FsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
|
||||||
|
NameSuffix types.FsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
|
||||||
|
NameSpace types.FsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||||
|
CommonLabels types.FsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`
|
||||||
|
CommonAnnotations types.FsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
|
||||||
|
NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
|
||||||
|
VarReference types.FsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
|
||||||
|
Images types.FsSlice `json:"images,omitempty" yaml:"images,omitempty"`
|
||||||
|
Replicas types.FsSlice `json:"replicas,omitempty" yaml:"replicas,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeEmptyConfig returns an empty TransformerConfig object
|
||||||
|
func MakeEmptyConfig() *TransformerConfig {
|
||||||
|
return &TransformerConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeDefaultConfig returns a default TransformerConfig.
|
||||||
|
func MakeDefaultConfig() *TransformerConfig {
|
||||||
|
c, err := makeTransformerConfigFromBytes(
|
||||||
|
builtinpluginconsts.GetDefaultFieldSpecs())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to make default transformconfig: %v", err)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeTransformerConfig returns a merger of custom config,
|
||||||
|
// if any, with default config.
|
||||||
|
func MakeTransformerConfig(
|
||||||
|
ldr ifc.Loader, paths []string) (*TransformerConfig, error) {
|
||||||
|
t1 := MakeDefaultConfig()
|
||||||
|
if len(paths) == 0 {
|
||||||
|
return t1, nil
|
||||||
|
}
|
||||||
|
t2, err := loadDefaultConfig(ldr, paths)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t1.Merge(t2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sortFields provides determinism in logging, tests, etc.
|
||||||
|
func (t *TransformerConfig) sortFields() {
|
||||||
|
sort.Sort(t.NamePrefix)
|
||||||
|
sort.Sort(t.NameSpace)
|
||||||
|
sort.Sort(t.CommonLabels)
|
||||||
|
sort.Sort(t.CommonAnnotations)
|
||||||
|
sort.Sort(t.NameReference)
|
||||||
|
sort.Sort(t.VarReference)
|
||||||
|
sort.Sort(t.Images)
|
||||||
|
sort.Sort(t.Replicas)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPrefixFieldSpec adds a FieldSpec to NamePrefix
|
||||||
|
func (t *TransformerConfig) AddPrefixFieldSpec(fs types.FieldSpec) (err error) {
|
||||||
|
t.NamePrefix, err = t.NamePrefix.MergeOne(fs)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSuffixFieldSpec adds a FieldSpec to NameSuffix
|
||||||
|
func (t *TransformerConfig) AddSuffixFieldSpec(fs types.FieldSpec) (err error) {
|
||||||
|
t.NameSuffix, err = t.NameSuffix.MergeOne(fs)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLabelFieldSpec adds a FieldSpec to CommonLabels
|
||||||
|
func (t *TransformerConfig) AddLabelFieldSpec(fs types.FieldSpec) (err error) {
|
||||||
|
t.CommonLabels, err = t.CommonLabels.MergeOne(fs)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAnnotationFieldSpec adds a FieldSpec to CommonAnnotations
|
||||||
|
func (t *TransformerConfig) AddAnnotationFieldSpec(fs types.FieldSpec) (err error) {
|
||||||
|
t.CommonAnnotations, err = t.CommonAnnotations.MergeOne(fs)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNamereferenceFieldSpec adds a NameBackReferences to NameReference
|
||||||
|
func (t *TransformerConfig) AddNamereferenceFieldSpec(
|
||||||
|
nbrs NameBackReferences) (err error) {
|
||||||
|
t.NameReference, err = t.NameReference.mergeOne(nbrs)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges two TransformerConfigs objects into
|
||||||
|
// a new TransformerConfig object
|
||||||
|
func (t *TransformerConfig) Merge(input *TransformerConfig) (
|
||||||
|
merged *TransformerConfig, err error) {
|
||||||
|
if input == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
merged = &TransformerConfig{}
|
||||||
|
merged.NamePrefix, err = t.NamePrefix.MergeAll(input.NamePrefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.NameSuffix, err = t.NameSuffix.MergeAll(input.NameSuffix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.NameSpace, err = t.NameSpace.MergeAll(input.NameSpace)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.CommonAnnotations, err = t.CommonAnnotations.MergeAll(
|
||||||
|
input.CommonAnnotations)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.CommonLabels, err = t.CommonLabels.MergeAll(input.CommonLabels)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.VarReference, err = t.VarReference.MergeAll(input.VarReference)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.NameReference, err = t.NameReference.mergeAll(input.NameReference)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.Images, err = t.Images.MergeAll(input.Images)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.Replicas, err = t.Replicas.MergeAll(input.Replicas)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
merged.sortFields()
|
||||||
|
return merged, nil
|
||||||
|
}
|
||||||
@@ -1,39 +1,32 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package builtinconfig_test
|
||||||
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 config
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"reflect"
|
. "sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestMakeDefaultConfig(t *testing.T) {
|
||||||
|
// Confirm default can be made without fatal error inside call.
|
||||||
|
_ = MakeDefaultConfig()
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddNamereferenceFieldSpec(t *testing.T) {
|
func TestAddNamereferenceFieldSpec(t *testing.T) {
|
||||||
cfg := &TransformerConfig{}
|
cfg := &TransformerConfig{}
|
||||||
|
|
||||||
nbrs := NameBackReferences{
|
nbrs := NameBackReferences{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "KindA",
|
Kind: "KindA",
|
||||||
},
|
},
|
||||||
FieldSpecs: []FieldSpec{
|
FieldSpecs: []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "KindB",
|
Kind: "KindB",
|
||||||
},
|
},
|
||||||
Path: "path/to/a/field",
|
Path: "path/to/a/field",
|
||||||
@@ -54,8 +47,8 @@ func TestAddNamereferenceFieldSpec(t *testing.T) {
|
|||||||
func TestAddFieldSpecs(t *testing.T) {
|
func TestAddFieldSpecs(t *testing.T) {
|
||||||
cfg := &TransformerConfig{}
|
cfg := &TransformerConfig{}
|
||||||
|
|
||||||
fieldSpec := FieldSpec{
|
fieldSpec := types.FieldSpec{
|
||||||
Gvk: gvk.Gvk{Group: "GroupA", Kind: "KindB"},
|
Gvk: resid.Gvk{Group: "GroupA", Kind: "KindB"},
|
||||||
Path: "path/to/a/field",
|
Path: "path/to/a/field",
|
||||||
CreateIfNotPresent: true,
|
CreateIfNotPresent: true,
|
||||||
}
|
}
|
||||||
@@ -93,12 +86,12 @@ func TestAddFieldSpecs(t *testing.T) {
|
|||||||
func TestMerge(t *testing.T) {
|
func TestMerge(t *testing.T) {
|
||||||
nameReference := []NameBackReferences{
|
nameReference := []NameBackReferences{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "KindA",
|
Kind: "KindA",
|
||||||
},
|
},
|
||||||
FieldSpecs: []FieldSpec{
|
FieldSpecs: []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "KindB",
|
Kind: "KindB",
|
||||||
},
|
},
|
||||||
Path: "path/to/a/field",
|
Path: "path/to/a/field",
|
||||||
@@ -107,12 +100,12 @@ func TestMerge(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "KindA",
|
Kind: "KindA",
|
||||||
},
|
},
|
||||||
FieldSpecs: []FieldSpec{
|
FieldSpecs: []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{
|
Gvk: resid.Gvk{
|
||||||
Kind: "KindC",
|
Kind: "KindC",
|
||||||
},
|
},
|
||||||
Path: "path/to/a/field",
|
Path: "path/to/a/field",
|
||||||
@@ -121,14 +114,14 @@ func TestMerge(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fieldSpecs := []FieldSpec{
|
fieldSpecs := []types.FieldSpec{
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{Group: "GroupA", Kind: "KindB"},
|
Gvk: resid.Gvk{Group: "GroupA", Kind: "KindB"},
|
||||||
Path: "path/to/a/field",
|
Path: "path/to/a/field",
|
||||||
CreateIfNotPresent: true,
|
CreateIfNotPresent: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Gvk: gvk.Gvk{Group: "GroupA", Kind: "KindC"},
|
Gvk: resid.Gvk{Group: "GroupA", Kind: "KindC"},
|
||||||
Path: "path/to/a/field",
|
Path: "path/to/a/field",
|
||||||
CreateIfNotPresent: true,
|
CreateIfNotPresent: true,
|
||||||
},
|
},
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// Code generated by "stringer -type=BuiltinPluginType"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package builtinhelpers
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[Unknown-0]
|
||||||
|
_ = x[AnnotationsTransformer-1]
|
||||||
|
_ = x[ConfigMapGenerator-2]
|
||||||
|
_ = x[HashTransformer-3]
|
||||||
|
_ = x[ImageTagTransformer-4]
|
||||||
|
_ = x[InventoryTransformer-5]
|
||||||
|
_ = x[LabelTransformer-6]
|
||||||
|
_ = x[LegacyOrderTransformer-7]
|
||||||
|
_ = x[NamespaceTransformer-8]
|
||||||
|
_ = x[PatchJson6902Transformer-9]
|
||||||
|
_ = x[PatchStrategicMergeTransformer-10]
|
||||||
|
_ = x[PatchTransformer-11]
|
||||||
|
_ = x[PrefixSuffixTransformer-12]
|
||||||
|
_ = x[ReplicaCountTransformer-13]
|
||||||
|
_ = x[SecretGenerator-14]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerInventoryTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGenerator"
|
||||||
|
|
||||||
|
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 101, 117, 139, 159, 183, 213, 229, 252, 275, 290}
|
||||||
|
|
||||||
|
func (i BuiltinPluginType) String() string {
|
||||||
|
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {
|
||||||
|
return "BuiltinPluginType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _BuiltinPluginType_name[_BuiltinPluginType_index[i]:_BuiltinPluginType_index[i+1]]
|
||||||
|
}
|
||||||
75
api/internal/plugins/builtinhelpers/builtins.go
Normal file
75
api/internal/plugins/builtinhelpers/builtins.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package builtinhelpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/builtins"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate stringer -type=BuiltinPluginType
|
||||||
|
type BuiltinPluginType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Unknown BuiltinPluginType = iota
|
||||||
|
AnnotationsTransformer
|
||||||
|
ConfigMapGenerator
|
||||||
|
HashTransformer
|
||||||
|
ImageTagTransformer
|
||||||
|
InventoryTransformer
|
||||||
|
LabelTransformer
|
||||||
|
LegacyOrderTransformer
|
||||||
|
NamespaceTransformer
|
||||||
|
PatchJson6902Transformer
|
||||||
|
PatchStrategicMergeTransformer
|
||||||
|
PatchTransformer
|
||||||
|
PrefixSuffixTransformer
|
||||||
|
ReplicaCountTransformer
|
||||||
|
SecretGenerator
|
||||||
|
)
|
||||||
|
|
||||||
|
var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
stringToBuiltinPluginTypeMap = makeStringToBuiltinPluginTypeMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeStringToBuiltinPluginTypeMap() (result map[string]BuiltinPluginType) {
|
||||||
|
result = make(map[string]BuiltinPluginType, 23)
|
||||||
|
for k := range GeneratorFactories {
|
||||||
|
result[k.String()] = k
|
||||||
|
}
|
||||||
|
for k := range TransformerFactories {
|
||||||
|
result[k.String()] = k
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBuiltinPluginType(n string) BuiltinPluginType {
|
||||||
|
result, ok := stringToBuiltinPluginTypeMap[n]
|
||||||
|
if ok {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
var GeneratorFactories = map[BuiltinPluginType]func() resmap.GeneratorPlugin{
|
||||||
|
ConfigMapGenerator: builtins.NewConfigMapGeneratorPlugin,
|
||||||
|
SecretGenerator: builtins.NewSecretGeneratorPlugin,
|
||||||
|
}
|
||||||
|
|
||||||
|
var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin{
|
||||||
|
AnnotationsTransformer: builtins.NewAnnotationsTransformerPlugin,
|
||||||
|
HashTransformer: builtins.NewHashTransformerPlugin,
|
||||||
|
ImageTagTransformer: builtins.NewImageTagTransformerPlugin,
|
||||||
|
InventoryTransformer: builtins.NewInventoryTransformerPlugin,
|
||||||
|
LabelTransformer: builtins.NewLabelTransformerPlugin,
|
||||||
|
LegacyOrderTransformer: builtins.NewLegacyOrderTransformerPlugin,
|
||||||
|
NamespaceTransformer: builtins.NewNamespaceTransformerPlugin,
|
||||||
|
PatchJson6902Transformer: builtins.NewPatchJson6902TransformerPlugin,
|
||||||
|
PatchStrategicMergeTransformer: builtins.NewPatchStrategicMergeTransformerPlugin,
|
||||||
|
PatchTransformer: builtins.NewPatchTransformerPlugin,
|
||||||
|
PrefixSuffixTransformer: builtins.NewPrefixSuffixTransformerPlugin,
|
||||||
|
ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin,
|
||||||
|
}
|
||||||
@@ -3,10 +3,11 @@
|
|||||||
# Generate the Go code for the generator and
|
# Generate the Go code for the generator and
|
||||||
# transformer factory functions in
|
# transformer factory functions in
|
||||||
#
|
#
|
||||||
# sigs.k8s.io/kustomize/v3/plugin/builtin
|
# sigs.k8s.io/kustomize/api/builtins
|
||||||
#
|
#
|
||||||
# from the raw plugin directories found _below_
|
# from the raw plugin directories found under
|
||||||
# that directory.
|
#
|
||||||
|
# sigs.k8s.io/kustomize/plugin/builtin
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -27,15 +28,11 @@ if [ ! -d "$dir" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo Generating linkable plugins...
|
for goMod in $(find ./plugin/builtin -name 'go.mod'); do
|
||||||
|
dir=$(dirname "${goMod}")
|
||||||
pushd $dir >& /dev/null
|
(cd $dir; GOPATH=$myGoPath go generate ./...)
|
||||||
|
echo "Formatting $dir"
|
||||||
GOPATH=$myGoPath go generate \
|
(cd $dir; GOPATH=$myGoPath go fmt ./...)
|
||||||
sigs.k8s.io/kustomize/v3/plugin/builtin/...
|
done
|
||||||
GOPATH=$myGoPath go fmt \
|
|
||||||
sigs.k8s.io/kustomize/v3/plugin/builtin
|
|
||||||
|
|
||||||
popd >& /dev/null
|
|
||||||
|
|
||||||
echo All done.
|
echo All done.
|
||||||
@@ -1,22 +1,10 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2019 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package compiler
|
||||||
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 plugins
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -25,7 +13,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
"github.com/pkg/errors"
|
||||||
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Compiler creates Go plugin object files.
|
// Compiler creates Go plugin object files.
|
||||||
@@ -42,36 +32,36 @@ type Compiler struct {
|
|||||||
|
|
||||||
// DefaultSrcRoot guesses where the user
|
// DefaultSrcRoot guesses where the user
|
||||||
// has her ${g}/${v}/$lower(${k})/${k}.go files.
|
// has her ${g}/${v}/$lower(${k})/${k}.go files.
|
||||||
func DefaultSrcRoot() (string, error) {
|
func DefaultSrcRoot(fSys filesys.FileSystem) (string, error) {
|
||||||
var nope []string
|
return konfig.FirstDirThatExistsElseError(
|
||||||
var root string
|
"source directory", fSys, []konfig.NotedFunc{
|
||||||
|
{
|
||||||
root = filepath.Join(
|
Note: "old style $GOPATH",
|
||||||
os.Getenv("GOPATH"), "src",
|
F: func() string {
|
||||||
pgmconfig.DomainName,
|
return filepath.Join(
|
||||||
pgmconfig.ProgramName, pgmconfig.PluginRoot)
|
os.Getenv("GOPATH"),
|
||||||
|
"src", konfig.DomainName,
|
||||||
if FileExists(root) {
|
konfig.ProgramName, konfig.RelPluginHome)
|
||||||
return root, nil
|
},
|
||||||
}
|
},
|
||||||
nope = append(nope, root)
|
{
|
||||||
|
Note: "HOME with literal 'gopath'",
|
||||||
root = DefaultPluginConfig().DirectoryPath
|
F: func() string {
|
||||||
if FileExists(root) {
|
return filepath.Join(
|
||||||
return root, nil
|
konfig.HomeDir(), "gopath",
|
||||||
}
|
"src", konfig.DomainName,
|
||||||
nope = append(nope, root)
|
konfig.ProgramName, konfig.RelPluginHome)
|
||||||
|
},
|
||||||
root = filepath.Join(
|
},
|
||||||
pgmconfig.HomeDir(),
|
{
|
||||||
pgmconfig.ProgramName, pgmconfig.PluginRoot)
|
Note: "home directory",
|
||||||
if FileExists(root) {
|
F: func() string {
|
||||||
return root, nil
|
return filepath.Join(
|
||||||
}
|
konfig.HomeDir(), konfig.DomainName,
|
||||||
nope = append(nope, root)
|
konfig.ProgramName, konfig.RelPluginHome)
|
||||||
|
},
|
||||||
return "", fmt.Errorf(
|
},
|
||||||
"no default src root; tried %v", nope)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCompiler returns a new compiler instance.
|
// NewCompiler returns a new compiler instance.
|
||||||
@@ -130,10 +120,12 @@ func (b *Compiler) Compile(g, v, k string) error {
|
|||||||
"cannot find go compiler %s", goBin)
|
"cannot find go compiler %s", goBin)
|
||||||
}
|
}
|
||||||
cmd := exec.Command(goBin, commands...)
|
cmd := exec.Command(goBin, commands...)
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
cmd.Stderr = &stderr
|
||||||
cmd.Env = os.Environ()
|
cmd.Env = os.Environ()
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
return fmt.Errorf(
|
return errors.Wrapf(
|
||||||
"compiler error building %s: %v", srcFile, err)
|
err, "cannot compile %s:\nSTDERR\n%s\n", srcFile, stderr.String())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2019 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package compiler_test
|
||||||
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 plugins_test
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -22,7 +9,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
. "sigs.k8s.io/kustomize/api/internal/plugins/compiler"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Regression coverage over compiler behavior.
|
// Regression coverage over compiler behavior.
|
||||||
@@ -31,7 +19,7 @@ func TestCompiler(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to make temp dir: %v", err)
|
t.Errorf("failed to make temp dir: %v", err)
|
||||||
}
|
}
|
||||||
srcRoot, err := DefaultSrcRoot()
|
srcRoot, err := DefaultSrcRoot(filesys.MakeFsOnDisk())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
See docs/plugins.md to learn about plugins.
|
Read docs/plugins.md first for an overview of kustomize plugins.
|
||||||
|
|
||||||
|
|
||||||
BUILTIN PLUGIN CONFIGURATION
|
BUILTIN PLUGIN CONFIGURATION
|
||||||
|
|
||||||
For performance and semantic sanity reasons, all
|
There are two kinds of plugins, Go plugins (shared
|
||||||
|
object library) and exec plugins (independent binary).
|
||||||
|
For performance and standardized testing reasons, all
|
||||||
builtin plugins are Go plugins (not exec plugins).
|
builtin plugins are Go plugins (not exec plugins).
|
||||||
|
|
||||||
Using "SecretGenerator" as an example in what
|
Using "SecretGenerator" as an example in what
|
||||||
@@ -31,7 +33,7 @@ The kind is the CamelCase name of the plugin.
|
|||||||
The source for a builtin plugin must be at:
|
The source for a builtin plugin must be at:
|
||||||
|
|
||||||
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
||||||
${repo}/v3/plugin/builtin/LOWERCASE(${kind})/${kind}
|
${repo}/plugin/builtin/LOWERCASE(${kind})/${kind}
|
||||||
|
|
||||||
k8s wants 'kind' values to follow CamelCase, while
|
k8s wants 'kind' values to follow CamelCase, while
|
||||||
Go style doesn't like but does allow such names.
|
Go style doesn't like but does allow such names.
|
||||||
@@ -67,8 +69,8 @@ It arises from following requirements:
|
|||||||
`go get` and should run where Go
|
`go get` and should run where Go
|
||||||
programs are expected to run.
|
programs are expected to run.
|
||||||
|
|
||||||
The extension requirement led to the creation
|
The extension requirement led to building
|
||||||
of a framework that accommodates writing a
|
a framework that accommodates writing a
|
||||||
G or T as either
|
G or T as either
|
||||||
|
|
||||||
* an 'exec' plugin (any executable file
|
* an 'exec' plugin (any executable file
|
||||||
@@ -89,25 +91,28 @@ code, hence this program.
|
|||||||
TO GENERATE CODE
|
TO GENERATE CODE
|
||||||
|
|
||||||
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
repo=$GOPATH/src/sigs.k8s.io/kustomize
|
||||||
cd $repo/v3/plugin/builtin
|
cd $repo/plugin/builtin
|
||||||
go generate ./...
|
go generate ./...
|
||||||
|
|
||||||
|
See travis/pre-commit.sh for canonical way
|
||||||
|
to execute the above.
|
||||||
|
|
||||||
This creates
|
This creates
|
||||||
|
|
||||||
$repo/plugin/builtin/SecretGenerator.go
|
$repo/api/plugins/builtins/SecretGenerator.go
|
||||||
|
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
Generated plugins are used in kustomize via
|
Generated plugins are used in kustomize via
|
||||||
|
|
||||||
package whatever
|
package whatever
|
||||||
import "sigs.k8s.io/kustomize/v3/plugin/builtin
|
import sigs.k8s.io/kustomize/api/plugins/builtins
|
||||||
...
|
...
|
||||||
g := builtin.NewSecretGenerator()
|
g := builtin.NewSecretGenerator()
|
||||||
g.Config(l, rf, k)
|
g.Config(h, k)
|
||||||
resources, err := g.Generate()
|
resources, err := g.Generate()
|
||||||
err = g.Transform(resources)
|
err = g.Transform(resources)
|
||||||
// Eventually emit resources.
|
// Eventually emit resources.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package plugin
|
package plugins
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2019 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
package execplugin
|
||||||
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 plugins
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -22,17 +9,21 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
idAnnotation = "kustomize.config.k8s.io/id"
|
idAnnotation = "kustomize.config.k8s.io/id"
|
||||||
|
HashAnnotation = "kustomize.config.k8s.io/needs-hash"
|
||||||
|
BehaviorAnnotation = "kustomize.config.k8s.io/behavior"
|
||||||
|
tmpConfigFilePrefix = "kust-plugin-config-"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExecPlugin record the name and args of an executable
|
// ExecPlugin record the name and args of an executable
|
||||||
@@ -49,30 +40,39 @@ type ExecPlugin struct {
|
|||||||
// Plugin configuration data.
|
// Plugin configuration data.
|
||||||
cfg []byte
|
cfg []byte
|
||||||
|
|
||||||
// resmap Factory to make resources
|
// PluginHelpers
|
||||||
rf *resmap.Factory
|
h *resmap.PluginHelpers
|
||||||
|
|
||||||
// loader to load files
|
|
||||||
ldr ifc.Loader
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExecPlugin(p string) *ExecPlugin {
|
func NewExecPlugin(p string) *ExecPlugin {
|
||||||
return &ExecPlugin{path: p}
|
return &ExecPlugin{path: p}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isAvailable checks to see if the plugin is available
|
func (p *ExecPlugin) ErrIfNotExecutable() error {
|
||||||
func (p *ExecPlugin) isAvailable() bool {
|
|
||||||
f, err := os.Stat(p.path)
|
f, err := os.Stat(p.path)
|
||||||
if os.IsNotExist(err) {
|
if err != nil {
|
||||||
return false
|
return err
|
||||||
}
|
}
|
||||||
return f.Mode()&0111 != 0000
|
if f.Mode()&0111 == 0000 {
|
||||||
|
return fmt.Errorf("unexecutable plugin at: %s", p.path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecPlugin) Config(
|
func (p *ExecPlugin) Path() string {
|
||||||
ldr ifc.Loader, rf *resmap.Factory, config []byte) error {
|
return p.path
|
||||||
p.rf = rf
|
}
|
||||||
p.ldr = ldr
|
|
||||||
|
func (p *ExecPlugin) Args() []string {
|
||||||
|
return p.args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ExecPlugin) Cfg() []byte {
|
||||||
|
return p.cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ExecPlugin) Config(h *resmap.PluginHelpers, config []byte) error {
|
||||||
|
p.h = h
|
||||||
p.cfg = config
|
p.cfg = config
|
||||||
return p.processOptionalArgsFields()
|
return p.processOptionalArgsFields()
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ func (p *ExecPlugin) processOptionalArgsFields() error {
|
|||||||
p.args = strings.Split(c.ArgsOneLiner, " ")
|
p.args = strings.Split(c.ArgsOneLiner, " ")
|
||||||
}
|
}
|
||||||
if c.ArgsFromFile != "" {
|
if c.ArgsFromFile != "" {
|
||||||
content, err := p.ldr.Load(c.ArgsFromFile)
|
content, err := p.h.Loader().Load(c.ArgsFromFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -103,33 +103,16 @@ func (p *ExecPlugin) processOptionalArgsFields() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecPlugin) writeConfig() (string, error) {
|
|
||||||
tmpFile, err := ioutil.TempFile("", "kust-pipe")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
syscall.Mkfifo(tmpFile.Name(), 0600)
|
|
||||||
stdout, err := os.OpenFile(tmpFile.Name(), os.O_RDWR, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
_, err = stdout.Write(p.cfg)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
err = stdout.Close()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return tmpFile.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ExecPlugin) Generate() (resmap.ResMap, error) {
|
func (p *ExecPlugin) Generate() (resmap.ResMap, error) {
|
||||||
output, err := p.invokePlugin(nil)
|
output, err := p.invokePlugin(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return p.rf.NewResMapFromBytes(output)
|
rm, err := p.h.ResmapFactory().NewResMapFromBytes(output)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p.UpdateResourceOptions(rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
|
func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
|
||||||
@@ -155,37 +138,47 @@ func (p *ExecPlugin) Transform(rm resmap.ResMap) error {
|
|||||||
return p.updateResMapValues(output, rm)
|
return p.updateResMapValues(output, rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// invokePlugin invokes the plugin
|
// invokePlugin writes plugin config to a temp file, then
|
||||||
|
// passes the full temp file path as the first arg to a process
|
||||||
|
// running the plugin binary. Process output is returned.
|
||||||
func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
|
func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
|
||||||
args, err := p.getArgs()
|
f, err := ioutil.TempFile("", tmpConfigFilePrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(
|
||||||
|
err, "creating tmp plugin config file")
|
||||||
}
|
}
|
||||||
cmd := exec.Command(p.path, args...)
|
_, err = f.Write(p.cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(
|
||||||
|
err, "writing plugin config to "+f.Name())
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(
|
||||||
|
err, "closing plugin config file "+f.Name())
|
||||||
|
}
|
||||||
|
cmd := exec.Command(
|
||||||
|
p.path, append([]string{f.Name()}, p.args...)...)
|
||||||
cmd.Env = p.getEnv()
|
cmd.Env = p.getEnv()
|
||||||
cmd.Stdin = bytes.NewReader(input)
|
cmd.Stdin = bytes.NewReader(input)
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if _, err := os.Stat(p.ldr.Root()); err == nil {
|
if _, err := os.Stat(p.h.Loader().Root()); err == nil {
|
||||||
cmd.Dir = p.ldr.Root()
|
cmd.Dir = p.h.Loader().Root()
|
||||||
}
|
}
|
||||||
return cmd.Output()
|
result, err := cmd.Output()
|
||||||
}
|
|
||||||
|
|
||||||
// The first arg is always the absolute path to a temporary file
|
|
||||||
// holding the YAML form of the plugin config.
|
|
||||||
func (p *ExecPlugin) getArgs() ([]string, error) {
|
|
||||||
configFileName, err := p.writeConfig()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrapf(
|
||||||
|
err, "failure in plugin configured via %s; %v",
|
||||||
|
f.Name(), err.Error())
|
||||||
}
|
}
|
||||||
return append([]string{configFileName}, p.args...), nil
|
return result, os.Remove(f.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecPlugin) getEnv() []string {
|
func (p *ExecPlugin) getEnv() []string {
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env,
|
env = append(env,
|
||||||
"KUSTOMIZE_PLUGIN_CONFIG_STRING="+string(p.cfg),
|
"KUSTOMIZE_PLUGIN_CONFIG_STRING="+string(p.cfg),
|
||||||
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.ldr.Root())
|
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.h.Loader().Root())
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,12 +200,10 @@ func (p *ExecPlugin) getResMapWithIdAnnotation(rm resmap.ResMap) (resmap.ResMap,
|
|||||||
return inputRM, nil
|
return inputRM, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// updateResMapValues updates the Resource value in the given ResMap
|
||||||
updateResMapValues updates the Resource value in the given ResMap
|
// with the emitted Resource values in output.
|
||||||
with the emitted Resource values in output.
|
|
||||||
*/
|
|
||||||
func (p *ExecPlugin) updateResMapValues(output []byte, rm resmap.ResMap) error {
|
func (p *ExecPlugin) updateResMapValues(output []byte, rm resmap.ResMap) error {
|
||||||
outputRM, err := p.rf.NewResMapFromBytes(output)
|
outputRM, err := p.h.ResmapFactory().NewResMapFromBytes(output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -246,3 +237,34 @@ func (p *ExecPlugin) updateResMapValues(output []byte, rm resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateResourceOptions updates the generator options for each resource in the
|
||||||
|
// given ResMap based on plugin provided annotations.
|
||||||
|
func (p *ExecPlugin) UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {
|
||||||
|
for _, r := range rm.Resources() {
|
||||||
|
// Disable name hashing by default and require plugin to explicitly
|
||||||
|
// request it for each resource.
|
||||||
|
annotations := r.GetAnnotations()
|
||||||
|
behavior := annotations[BehaviorAnnotation]
|
||||||
|
var needsHash bool
|
||||||
|
if val, ok := annotations[HashAnnotation]; ok {
|
||||||
|
b, err := strconv.ParseBool(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"the annotation %q contains an invalid value (%q)",
|
||||||
|
HashAnnotation, val)
|
||||||
|
}
|
||||||
|
needsHash = b
|
||||||
|
}
|
||||||
|
delete(annotations, HashAnnotation)
|
||||||
|
delete(annotations, BehaviorAnnotation)
|
||||||
|
if len(annotations) == 0 {
|
||||||
|
annotations = nil
|
||||||
|
}
|
||||||
|
r.SetAnnotations(annotations)
|
||||||
|
r.SetOptions(types.NewGenArgs(
|
||||||
|
&types.GeneratorArgs{Behavior: behavior},
|
||||||
|
&types.GeneratorOptions{DisableNameSuffixHash: !needsHash}))
|
||||||
|
}
|
||||||
|
return rm, nil
|
||||||
|
}
|
||||||
190
api/internal/plugins/execplugin/execplugin_test.go
Normal file
190
api/internal/plugins/execplugin/execplugin_test.go
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package execplugin_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/loadertest"
|
||||||
|
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExecPluginConfig(t *testing.T) {
|
||||||
|
path := "/app"
|
||||||
|
rf := resmap.NewFactory(
|
||||||
|
resource.NewFactory(
|
||||||
|
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
ldr := loadertest.NewFakeLoader(path)
|
||||||
|
v := valtest_test.MakeFakeValidator()
|
||||||
|
pluginConfig := rf.RF().FromMap(
|
||||||
|
map[string]interface{}{
|
||||||
|
"apiVersion": "someteam.example.com/v1",
|
||||||
|
"kind": "SedTransformer",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "some-random-name",
|
||||||
|
},
|
||||||
|
"argsOneLiner": "one two",
|
||||||
|
"argsFromFile": "sed-input.txt",
|
||||||
|
})
|
||||||
|
|
||||||
|
ldr.AddFile("/app/sed-input.txt", []byte(`
|
||||||
|
s/$FOO/foo/g
|
||||||
|
s/$BAR/bar/g
|
||||||
|
\ \ \
|
||||||
|
`))
|
||||||
|
|
||||||
|
p := NewExecPlugin(
|
||||||
|
loader.AbsolutePluginPath(
|
||||||
|
konfig.DisabledPluginConfig(),
|
||||||
|
pluginConfig.OrgId()))
|
||||||
|
// Not checking to see if the plugin is executable,
|
||||||
|
// because this test does not run it.
|
||||||
|
// This tests only covers sending configuration
|
||||||
|
// to the plugin wrapper object and confirming
|
||||||
|
// that it's properly prepared for execution.
|
||||||
|
|
||||||
|
yaml, err := pluginConfig.AsYAML()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
p.Config(resmap.NewPluginHelpers(ldr, v, rf), yaml)
|
||||||
|
|
||||||
|
expected := "someteam.example.com/v1/sedtransformer/SedTransformer"
|
||||||
|
if !strings.HasSuffix(p.Path(), expected) {
|
||||||
|
t.Fatalf("expected suffix '%s', got '%s'", expected, p.Path())
|
||||||
|
}
|
||||||
|
|
||||||
|
expected = `apiVersion: someteam.example.com/v1
|
||||||
|
argsFromFile: sed-input.txt
|
||||||
|
argsOneLiner: one two
|
||||||
|
kind: SedTransformer
|
||||||
|
metadata:
|
||||||
|
name: some-random-name
|
||||||
|
`
|
||||||
|
if expected != string(p.Cfg()) {
|
||||||
|
t.Fatalf("expected cfg '%s', got '%s'", expected, string(p.Cfg()))
|
||||||
|
|
||||||
|
}
|
||||||
|
if len(p.Args()) != 5 {
|
||||||
|
t.Fatalf("unexpected arg len %d, %v", len(p.Args()), p.Args())
|
||||||
|
}
|
||||||
|
if p.Args()[0] != "one" ||
|
||||||
|
p.Args()[1] != "two" ||
|
||||||
|
p.Args()[2] != "s/$FOO/foo/g" ||
|
||||||
|
p.Args()[3] != "s/$BAR/bar/g" ||
|
||||||
|
p.Args()[4] != "\\ \\ \\ " {
|
||||||
|
t.Fatalf("unexpected arg array: %v", p.Args())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeConfigMap(rf *resource.Factory, name, behavior string, hashValue *string) *resource.Resource {
|
||||||
|
r := rf.FromMap(map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{"name": name},
|
||||||
|
})
|
||||||
|
annotations := map[string]string{}
|
||||||
|
if behavior != "" {
|
||||||
|
annotations[BehaviorAnnotation] = behavior
|
||||||
|
}
|
||||||
|
if hashValue != nil {
|
||||||
|
annotations[HashAnnotation] = *hashValue
|
||||||
|
}
|
||||||
|
if len(annotations) > 0 {
|
||||||
|
r.SetAnnotations(annotations)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHash bool) *resource.Resource {
|
||||||
|
return rf.FromMapAndOption(map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{"name": name},
|
||||||
|
}, &types.GeneratorArgs{Behavior: behavior}, &types.GeneratorOptions{DisableNameSuffixHash: disableHash})
|
||||||
|
}
|
||||||
|
|
||||||
|
func strptr(s string) *string {
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateResourceOptions(t *testing.T) {
|
||||||
|
p := NewExecPlugin("")
|
||||||
|
if err := p.ErrIfNotExecutable(); err == nil {
|
||||||
|
t.Fatalf("expected unexecutable error")
|
||||||
|
}
|
||||||
|
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
in := resmap.New()
|
||||||
|
expected := resmap.New()
|
||||||
|
cases := []struct {
|
||||||
|
behavior string
|
||||||
|
needsHash bool
|
||||||
|
hashValue *string
|
||||||
|
}{
|
||||||
|
{hashValue: strptr("false")},
|
||||||
|
{hashValue: strptr("true"), needsHash: true},
|
||||||
|
{behavior: "replace"},
|
||||||
|
{behavior: "merge"},
|
||||||
|
{behavior: "create"},
|
||||||
|
{behavior: "nonsense"},
|
||||||
|
{behavior: "merge", hashValue: strptr("false")},
|
||||||
|
{behavior: "merge", hashValue: strptr("true"), needsHash: true},
|
||||||
|
}
|
||||||
|
for i, c := range cases {
|
||||||
|
name := fmt.Sprintf("test%d", i)
|
||||||
|
in.Append(makeConfigMap(rf, name, c.behavior, c.hashValue))
|
||||||
|
expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
|
||||||
|
}
|
||||||
|
actual, err := p.UpdateResourceOptions(in)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
for i, a := range expected.Resources() {
|
||||||
|
b := actual.GetByIndex(i)
|
||||||
|
if b == nil {
|
||||||
|
t.Fatalf("resource %d missing from processed map", i)
|
||||||
|
}
|
||||||
|
if !a.Equals(b) {
|
||||||
|
t.Errorf("expected %v got %v", a, b)
|
||||||
|
}
|
||||||
|
if a.NeedHashSuffix() != b.NeedHashSuffix() {
|
||||||
|
t.Errorf("")
|
||||||
|
}
|
||||||
|
if a.Behavior() != b.Behavior() {
|
||||||
|
t.Errorf("expected %v got %v", a.Behavior(), b.Behavior())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
|
||||||
|
p := NewExecPlugin("")
|
||||||
|
if err := p.ErrIfNotExecutable(); err == nil {
|
||||||
|
t.Fatalf("expected unexecutable error")
|
||||||
|
}
|
||||||
|
rf := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
cases := []string{
|
||||||
|
"",
|
||||||
|
"FaLsE",
|
||||||
|
"TrUe",
|
||||||
|
"potato",
|
||||||
|
}
|
||||||
|
for i, c := range cases {
|
||||||
|
name := fmt.Sprintf("test%d", i)
|
||||||
|
in := resmap.New()
|
||||||
|
in.Append(makeConfigMap(rf, name, "", &c))
|
||||||
|
_, err := p.UpdateResourceOptions(in)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected error from value %q", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
211
api/internal/plugins/loader/loader.go
Normal file
211
api/internal/plugins/loader/loader.go
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package loader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"plugin"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||||
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Loader struct {
|
||||||
|
pc *types.PluginConfig
|
||||||
|
rf *resmap.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLoader(
|
||||||
|
pc *types.PluginConfig, rf *resmap.Factory) *Loader {
|
||||||
|
return &Loader{pc: pc, rf: rf}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) LoadGenerators(
|
||||||
|
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Generator, error) {
|
||||||
|
var result []resmap.Generator
|
||||||
|
for _, res := range rm.Resources() {
|
||||||
|
g, err := l.LoadGenerator(ldr, v, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, g)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) LoadGenerator(
|
||||||
|
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (resmap.Generator, error) {
|
||||||
|
c, err := l.loadAndConfigurePlugin(ldr, v, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
g, ok := c.(resmap.Generator)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("plugin %s not a generator", res.OrgId())
|
||||||
|
}
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) LoadTransformers(
|
||||||
|
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Transformer, error) {
|
||||||
|
var result []resmap.Transformer
|
||||||
|
for _, res := range rm.Resources() {
|
||||||
|
t, err := l.LoadTransformer(ldr, v, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, t)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) LoadTransformer(
|
||||||
|
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (resmap.Transformer, error) {
|
||||||
|
c, err := l.loadAndConfigurePlugin(ldr, v, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t, ok := c.(resmap.Transformer)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("plugin %s not a transformer", res.OrgId())
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func relativePluginPath(id resid.ResId) string {
|
||||||
|
return filepath.Join(
|
||||||
|
id.Group,
|
||||||
|
id.Version,
|
||||||
|
strings.ToLower(id.Kind))
|
||||||
|
}
|
||||||
|
|
||||||
|
func AbsolutePluginPath(pc *types.PluginConfig, id resid.ResId) string {
|
||||||
|
return filepath.Join(
|
||||||
|
pc.AbsPluginHome, relativePluginPath(id), id.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) absolutePluginPath(id resid.ResId) string {
|
||||||
|
return AbsolutePluginPath(l.pc, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBuiltinPlugin(res *resource.Resource) bool {
|
||||||
|
// TODO: the special string should appear in Group, not Version.
|
||||||
|
return res.GetGvk().Group == "" &&
|
||||||
|
res.GetGvk().Version == konfig.BuiltinPluginApiVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) loadAndConfigurePlugin(
|
||||||
|
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (c resmap.Configurable, err error) {
|
||||||
|
if isBuiltinPlugin(res) {
|
||||||
|
// Instead of looking for and loading a .so file, just
|
||||||
|
// instantiate the plugin from a generated factory
|
||||||
|
// function (see "pluginator"). Being able to do this
|
||||||
|
// is what makes a plugin "builtin".
|
||||||
|
c, err = l.makeBuiltinPlugin(res.GetGvk())
|
||||||
|
} else if l.pc.PluginRestrictions == types.PluginRestrictionsNone {
|
||||||
|
c, err = l.loadPlugin(res.OrgId())
|
||||||
|
} else {
|
||||||
|
err = types.NewErrOnlyBuiltinPluginsAllowed(res.OrgId().Kind)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
yaml, err := res.AsYAML()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "marshalling yaml from res %s", res.OrgId())
|
||||||
|
}
|
||||||
|
err = c.Config(resmap.NewPluginHelpers(ldr, v, l.rf), yaml)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(
|
||||||
|
err, "plugin %s fails configuration", res.OrgId())
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) makeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
|
||||||
|
bpt := builtinhelpers.GetBuiltinPluginType(r.Kind)
|
||||||
|
if f, ok := builtinhelpers.GeneratorFactories[bpt]; ok {
|
||||||
|
return f(), nil
|
||||||
|
}
|
||||||
|
if f, ok := builtinhelpers.TransformerFactories[bpt]; ok {
|
||||||
|
return f(), nil
|
||||||
|
}
|
||||||
|
return nil, errors.Errorf("unable to load builtin %s", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Loader) loadPlugin(resId resid.ResId) (resmap.Configurable, error) {
|
||||||
|
// First try to load the plugin as an executable.
|
||||||
|
p := execplugin.NewExecPlugin(l.absolutePluginPath(resId))
|
||||||
|
err := p.ErrIfNotExecutable()
|
||||||
|
if err == nil {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
// The file exists, but something else is wrong,
|
||||||
|
// likely it's not executable.
|
||||||
|
// Assume the user forgot to set the exec bit,
|
||||||
|
// and return an error, rather than adding ".so"
|
||||||
|
// to the name and attempting to load it as a Go
|
||||||
|
// plugin, which will likely fail and result
|
||||||
|
// in an obscure message.
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Failing the above, try loading it as a Go plugin.
|
||||||
|
c, err := l.loadGoPlugin(resId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// registry is a means to avoid trying to load the same .so file
|
||||||
|
// into memory more than once, which results in an error.
|
||||||
|
// Each test makes its own loader, and tries to load its own plugins,
|
||||||
|
// but the loaded .so files are in shared memory, so one will get
|
||||||
|
// "this plugin already loaded" errors if the registry is maintained
|
||||||
|
// as a Loader instance variable. So make it a package variable.
|
||||||
|
var registry = make(map[string]resmap.Configurable)
|
||||||
|
|
||||||
|
func (l *Loader) loadGoPlugin(id resid.ResId) (resmap.Configurable, error) {
|
||||||
|
regId := relativePluginPath(id)
|
||||||
|
if c, ok := registry[regId]; ok {
|
||||||
|
return copyPlugin(c), nil
|
||||||
|
}
|
||||||
|
absPath := l.absolutePluginPath(id)
|
||||||
|
p, err := plugin.Open(absPath + ".so")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "plugin %s fails to load", absPath)
|
||||||
|
}
|
||||||
|
symbol, err := p.Lookup(konfig.PluginSymbol)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(
|
||||||
|
err, "plugin %s doesn't have symbol %s",
|
||||||
|
regId, konfig.PluginSymbol)
|
||||||
|
}
|
||||||
|
c, ok := symbol.(resmap.Configurable)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("plugin '%s' not configurable", regId)
|
||||||
|
}
|
||||||
|
registry[regId] = c
|
||||||
|
return copyPlugin(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyPlugin(c resmap.Configurable) resmap.Configurable {
|
||||||
|
indirect := reflect.Indirect(reflect.ValueOf(c))
|
||||||
|
newIndirect := reflect.New(indirect.Type())
|
||||||
|
newIndirect.Elem().Set(reflect.ValueOf(indirect.Interface()))
|
||||||
|
newNamed := newIndirect.Interface()
|
||||||
|
return newNamed.(resmap.Configurable)
|
||||||
|
}
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package plugins_test
|
package loader_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/internal/loadertest"
|
"sigs.k8s.io/kustomize/api/internal/loadertest"
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -42,7 +44,7 @@ port: "12345"
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLoader(t *testing.T) {
|
func TestLoader(t *testing.T) {
|
||||||
tc := plugins_test.NewEnvForTest(t).Set()
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -53,12 +55,17 @@ func TestLoader(t *testing.T) {
|
|||||||
rmF := resmap.NewFactory(resource.NewFactory(
|
rmF := resmap.NewFactory(resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
|
||||||
l := NewLoader(ActivePluginConfig(), rmF)
|
ldr := loadertest.NewFakeLoader("/foo")
|
||||||
if l == nil {
|
|
||||||
t.Fatal("expect non-nil loader")
|
c, err := konfig.EnabledPluginConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ldr := loadertest.NewFakeLoader("/foo")
|
pLdr := NewLoader(c, rmF)
|
||||||
|
if pLdr == nil {
|
||||||
|
t.Fatal("expect non-nil loader")
|
||||||
|
}
|
||||||
|
|
||||||
m, err := rmF.NewResMapFromBytes([]byte(
|
m, err := rmF.NewResMapFromBytes([]byte(
|
||||||
someServiceGenerator + "---\n" + secretGenerator))
|
someServiceGenerator + "---\n" + secretGenerator))
|
||||||
@@ -66,7 +73,7 @@ func TestLoader(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = l.LoadGenerators(ldr, m)
|
_, err = pLdr.LoadGenerators(ldr, valtest_test.MakeFakeValidator(), m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
60
api/internal/target/accumulation_test.go
Normal file
60
api/internal/target/accumulation_test.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "sigs.k8s.io/kustomize/api/internal/target"
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTargetMustHaveKustomizationFile(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app")
|
||||||
|
th.WriteF("/app/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: aService
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/deeper/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: anotherService
|
||||||
|
`)
|
||||||
|
_, err := th.MakeKustTargetOrErr()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected an error")
|
||||||
|
}
|
||||||
|
if !IsMissingKustomizationFileError(err) {
|
||||||
|
t.Fatalf("unexpected error: %q", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourceDirectoryMustHaveKustomizationFile(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app")
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- base
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/base/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myService
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
backend: bungie
|
||||||
|
ports:
|
||||||
|
- port: 7002
|
||||||
|
`)
|
||||||
|
_, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected an error")
|
||||||
|
}
|
||||||
|
if !IsMissingKustomizationFileError(err) {
|
||||||
|
t.Fatalf("unexpected error: %q", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func writeMediumBase(th *kusttest_test.KustTestHarness) {
|
func writeMediumBase(th *kusttest_test.KustTestHarness) {
|
||||||
@@ -132,8 +132,8 @@ patchesStrategicMerge:
|
|||||||
- deployment/deployment.yaml
|
- deployment/deployment.yaml
|
||||||
configMapGenerator:
|
configMapGenerator:
|
||||||
- name: app-env
|
- name: app-env
|
||||||
env: configmap/db.env
|
|
||||||
envs:
|
envs:
|
||||||
|
- configmap/db.env
|
||||||
- configmap/units.ini
|
- configmap/units.ini
|
||||||
- configmap/food.ini
|
- configmap/food.ini
|
||||||
- name: app-config
|
- name: app-config
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
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 target_test
|
package target_test
|
||||||
|
|
||||||
@@ -20,9 +7,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOrderPreserved(t *testing.T) {
|
func TestOrderPreserved(t *testing.T) {
|
||||||
@@ -313,7 +300,7 @@ spec:
|
|||||||
func TestSharedPatchDisAllowed(t *testing.T) {
|
func TestSharedPatchDisAllowed(t *testing.T) {
|
||||||
th := kusttest_test.NewKustTestHarnessFull(
|
th := kusttest_test.NewKustTestHarnessFull(
|
||||||
t, "/app/overlay",
|
t, "/app/overlay",
|
||||||
loader.RestrictionRootOnly, plugins.DefaultPluginConfig())
|
loader.RestrictionRootOnly, konfig.DisabledPluginConfig())
|
||||||
writeSmallBase(th)
|
writeSmallBase(th)
|
||||||
th.WriteK("/app/overlay", `
|
th.WriteK("/app/overlay", `
|
||||||
commonLabels:
|
commonLabels:
|
||||||
@@ -345,7 +332,7 @@ spec:
|
|||||||
func TestSharedPatchAllowed(t *testing.T) {
|
func TestSharedPatchAllowed(t *testing.T) {
|
||||||
th := kusttest_test.NewKustTestHarnessFull(
|
th := kusttest_test.NewKustTestHarnessFull(
|
||||||
t, "/app/overlay",
|
t, "/app/overlay",
|
||||||
loader.RestrictionNone, plugins.DefaultPluginConfig())
|
loader.RestrictionNone, konfig.DisabledPluginConfig())
|
||||||
writeSmallBase(th)
|
writeSmallBase(th)
|
||||||
th.WriteK("/app/overlay", `
|
th.WriteK("/app/overlay", `
|
||||||
commonLabels:
|
commonLabels:
|
||||||
199
api/internal/target/basereusenameprefix_test.go
Normal file
199
api/internal/target/basereusenameprefix_test.go
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Here is a structure of a kustomization of two components, component1
|
||||||
|
// and component2, that both use a shared postgres definition, which
|
||||||
|
// they would individually adjust. This test case checks that the name
|
||||||
|
// prefix does not cause a name reference conflict.
|
||||||
|
//
|
||||||
|
// root
|
||||||
|
// / \
|
||||||
|
// component1/overlay component2/overlay
|
||||||
|
// | |
|
||||||
|
// component1/base component2/base
|
||||||
|
// \ /
|
||||||
|
// base
|
||||||
|
//
|
||||||
|
// This is the directory layout:
|
||||||
|
//
|
||||||
|
// ├── component1
|
||||||
|
// │ ├── base
|
||||||
|
// │ │ └── kustomization.yaml
|
||||||
|
// │ └── overlay
|
||||||
|
// │ └── kustomization.yaml
|
||||||
|
// ├── component2
|
||||||
|
// │ ├── base
|
||||||
|
// │ │ └── kustomization.yaml
|
||||||
|
// │ └── overlay
|
||||||
|
// │ └── kustomization.yaml
|
||||||
|
// ├── shared
|
||||||
|
// │ ├── kustomization.yaml
|
||||||
|
// │ └── resources.yaml
|
||||||
|
// ├── kustomization.yaml
|
||||||
|
|
||||||
|
func TestBaseReuseNameConflict(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app")
|
||||||
|
th.WriteK("/app/component1/base", `
|
||||||
|
resources:
|
||||||
|
- ../../shared
|
||||||
|
|
||||||
|
namePrefix: component1-
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/component1/overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
|
||||||
|
namePrefix: overlay-
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK("/app/component2/base", `
|
||||||
|
resources:
|
||||||
|
- ../../shared
|
||||||
|
|
||||||
|
namePrefix: component2-
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/component2/overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
|
||||||
|
namePrefix: overlay-
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK("/app/shared", `
|
||||||
|
resources:
|
||||||
|
- resources.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/shared/resources.yaml", `
|
||||||
|
---
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels: {}
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/lib/postgresql
|
||||||
|
name: data
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
containerPort: 5432
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: postgres
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- component1/overlay
|
||||||
|
- component2/overlay
|
||||||
|
`)
|
||||||
|
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: overlay-component1-postgres
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: overlay-component1-postgres
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels: {}
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: postgres
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
name: postgres
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: postgres
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/lib/postgresql
|
||||||
|
name: data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: overlay-component1-postgres
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: overlay-component2-postgres
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: overlay-component2-postgres
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels: {}
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: postgres
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
name: postgres
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: postgres
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/lib/postgresql
|
||||||
|
name: data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: overlay-component2-postgres
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -8,10 +8,10 @@
|
|||||||
package target_test
|
package target_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is an example of using a helm chart as a base,
|
// This is an example of using a helm chart as a base,
|
||||||
@@ -28,13 +28,13 @@ import (
|
|||||||
// TODO: Download and inflate the chart, and check that
|
// TODO: Download and inflate the chart, and check that
|
||||||
// in for the test.
|
// in for the test.
|
||||||
func TestChartInflatorPlugin(t *testing.T) {
|
func TestChartInflatorPlugin(t *testing.T) {
|
||||||
tc := plugins_test.NewEnvForTest(t).Set()
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
"someteam.example.com", "v1", "ChartInflator")
|
"someteam.example.com", "v1", "ChartInflator")
|
||||||
|
|
||||||
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app")
|
||||||
th.WriteK("/app", `
|
th.WriteK("/app", `
|
||||||
generators:
|
generators:
|
||||||
- chartInflator.yaml
|
- chartInflator.yaml
|
||||||
@@ -53,7 +53,11 @@ chartName: minecraft
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
th.AssertActualEqualsExpected(m, `
|
chartName := regexp.MustCompile("chart: minecraft-[0-9.]+")
|
||||||
|
th.AssertActualEqualsExpectedWithTweak(m,
|
||||||
|
func(x []byte) []byte {
|
||||||
|
return chartName.ReplaceAll(x, []byte("chart: minecraft-SOMEVERSION"))
|
||||||
|
}, `
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
rcon-password: Q0hBTkdFTUUh
|
rcon-password: Q0hBTkdFTUUh
|
||||||
@@ -61,7 +65,7 @@ kind: Secret
|
|||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: release-name-minecraft
|
app: release-name-minecraft
|
||||||
chart: minecraft-1.0.3
|
chart: minecraft-SOMEVERSION
|
||||||
heritage: Tiller
|
heritage: Tiller
|
||||||
release: release-name
|
release: release-name
|
||||||
name: LOOOOOOOONG-release-name-minecraft
|
name: LOOOOOOOONG-release-name-minecraft
|
||||||
@@ -74,7 +78,7 @@ metadata:
|
|||||||
volume.alpha.kubernetes.io/storage-class: default
|
volume.alpha.kubernetes.io/storage-class: default
|
||||||
labels:
|
labels:
|
||||||
app: release-name-minecraft
|
app: release-name-minecraft
|
||||||
chart: minecraft-1.0.3
|
chart: minecraft-SOMEVERSION
|
||||||
heritage: Tiller
|
heritage: Tiller
|
||||||
release: release-name
|
release: release-name
|
||||||
name: LOOOOOOOONG-release-name-minecraft-datadir
|
name: LOOOOOOOONG-release-name-minecraft-datadir
|
||||||
@@ -90,7 +94,7 @@ kind: Service
|
|||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: release-name-minecraft
|
app: release-name-minecraft
|
||||||
chart: minecraft-1.0.3
|
chart: minecraft-SOMEVERSION
|
||||||
heritage: Tiller
|
heritage: Tiller
|
||||||
release: release-name
|
release: release-name
|
||||||
name: LOOOOOOOONG-release-name-minecraft
|
name: LOOOOOOOONG-release-name-minecraft
|
||||||
557
api/internal/target/complexcomposition_test.go
Normal file
557
api/internal/target/complexcomposition_test.go
Normal file
@@ -0,0 +1,557 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
const httpsService = `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: my-https-svc
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 443
|
||||||
|
protocol: TCP
|
||||||
|
name: https
|
||||||
|
selector:
|
||||||
|
app: my-app
|
||||||
|
`
|
||||||
|
|
||||||
|
func writeStatefulSetBase(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
resources:
|
||||||
|
- statefulset.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/base/statefulset.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
serviceName: my-svc
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: my-app
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: my-app
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: my-image
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- spec:
|
||||||
|
storageClassName: default
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeHTTPSOverlay(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/https", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
- https-svc.yaml
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- sts-patch.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/https/https-svc.yaml", httpsService)
|
||||||
|
th.WriteF("/app/https/sts-patch.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
serviceName: my-https-svc
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeHTTPSTransformerRaw(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteF("/app/https/service/https-svc.yaml", httpsService)
|
||||||
|
th.WriteF("/app/https/transformer/transformer.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: svcNameTran
|
||||||
|
target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: StatefulSet
|
||||||
|
name: my-sts
|
||||||
|
patch: |-
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
serviceName: my-https-svc
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeHTTPSTransformerBase(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/https/service", `
|
||||||
|
resources:
|
||||||
|
- https-svc.yaml
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/https/transformer", `
|
||||||
|
resources:
|
||||||
|
- transformer.yaml
|
||||||
|
`)
|
||||||
|
writeHTTPSTransformerRaw(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeConfigFromEnvOverlay(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/config", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
configMapGenerator:
|
||||||
|
- name: my-config
|
||||||
|
literals:
|
||||||
|
- MY_ENV=foo
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- sts-patch.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/config/sts-patch.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: my-config
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeConfigFromEnvTransformerRaw(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteF("/app/config/map/generator.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: ConfigMapGenerator
|
||||||
|
metadata:
|
||||||
|
name: my-config
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
literals:
|
||||||
|
- MY_ENV=foo
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/config/transformer/transformer.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: envFromConfigTrans
|
||||||
|
target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: StatefulSet
|
||||||
|
name: my-sts
|
||||||
|
patch: |-
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: my-config
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
func writeConfigFromEnvTransformerBase(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/config/map", `
|
||||||
|
resources:
|
||||||
|
- generator.yaml
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/config/transformer", `
|
||||||
|
resources:
|
||||||
|
- transformer.yaml
|
||||||
|
`)
|
||||||
|
writeConfigFromEnvTransformerRaw(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTolerationsOverlay(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/tolerations", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- sts-patch.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/tolerations/sts-patch.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
tolerations:
|
||||||
|
- effect: NoExecute
|
||||||
|
key: node.kubernetes.io/not-ready
|
||||||
|
tolerationSeconds: 30
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTolerationsTransformerRaw(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteF("/app/tolerations/transformer.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: tolTrans
|
||||||
|
target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: StatefulSet
|
||||||
|
name: my-sts
|
||||||
|
patch: |-
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
tolerations:
|
||||||
|
- effect: NoExecute
|
||||||
|
key: node.kubernetes.io/not-ready
|
||||||
|
tolerationSeconds: 30
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTolerationsTransformerBase(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/tolerations", `
|
||||||
|
resources:
|
||||||
|
- transformer.yaml
|
||||||
|
`)
|
||||||
|
writeTolerationsTransformerRaw(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeStorageOverlay(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/storage", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
patchesJson6902:
|
||||||
|
- target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: StatefulSet
|
||||||
|
name: my-sts
|
||||||
|
path: sts-patch.json
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/storage/sts-patch.json", `
|
||||||
|
[{"op": "replace", "path": "/spec/volumeClaimTemplates/0/spec/storageClassName", "value": "my-sc"}]
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeStorageTransformerRaw(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteF("/app/storage/transformer.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: storageTrans
|
||||||
|
target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: StatefulSet
|
||||||
|
name: my-sts
|
||||||
|
patch: |-
|
||||||
|
[{"op": "replace", "path": "/spec/volumeClaimTemplates/0/spec/storageClassName", "value": "my-sc"}]
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeStorageTransformerBase(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteK("/app/storage", `
|
||||||
|
resources:
|
||||||
|
- transformer.yaml
|
||||||
|
`)
|
||||||
|
writeStorageTransformerRaw(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePatchingOverlays(th *kusttest_test.KustTestHarness) {
|
||||||
|
writeStorageOverlay(th)
|
||||||
|
writeConfigFromEnvOverlay(th)
|
||||||
|
writeTolerationsOverlay(th)
|
||||||
|
writeHTTPSOverlay(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePatchingTransformersRaw(th *kusttest_test.KustTestHarness) {
|
||||||
|
writeStorageTransformerRaw(th)
|
||||||
|
writeConfigFromEnvTransformerRaw(th)
|
||||||
|
writeTolerationsTransformerRaw(th)
|
||||||
|
writeHTTPSTransformerRaw(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar to writePatchingTransformersRaw, except here the
|
||||||
|
// transformers and related artifacts are addressable as _bases_.
|
||||||
|
// They are listed in a kustomization file, and consumers of
|
||||||
|
// the plugin refer to the kustomization instead of to the local
|
||||||
|
// file in the "transformers:" field.
|
||||||
|
//
|
||||||
|
// Using bases makes the set of files relocatable with
|
||||||
|
// respect to the overlays, and avoids the need to relax load
|
||||||
|
// restrictions on file paths reaching outside the `dev` and
|
||||||
|
// `prod` kustomization roots. I.e. with bases tests can use
|
||||||
|
// NewKustTestHarness instead of NewKustTestHarnessNoLoadRestrictor.
|
||||||
|
//
|
||||||
|
// Using transformer plugins from _bases_ means the plugin config
|
||||||
|
// must be self-contained, i.e. the config may not have fields that
|
||||||
|
// refer to local files, since those files won't be present when
|
||||||
|
// the plugin is instantiated and used.
|
||||||
|
func writePatchingTransformerBases(th *kusttest_test.KustTestHarness) {
|
||||||
|
writeStorageTransformerBase(th)
|
||||||
|
writeConfigFromEnvTransformerBase(th)
|
||||||
|
writeTolerationsTransformerBase(th)
|
||||||
|
writeHTTPSTransformerBase(th)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here's a complex kustomization scenario that combines multiple overlays
|
||||||
|
// on a common base:
|
||||||
|
//
|
||||||
|
// dev prod
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// + ------- + + ------------ + ------------- +
|
||||||
|
// | | | | |
|
||||||
|
// | | | | |
|
||||||
|
// v | v v v
|
||||||
|
// storage + -----> config tolerations https
|
||||||
|
// | | | |
|
||||||
|
// | | | |
|
||||||
|
// | + --- + + --- + |
|
||||||
|
// | | | |
|
||||||
|
// | v v |
|
||||||
|
// + -----------------------> base <------------------ +
|
||||||
|
//
|
||||||
|
// The base resource is a statefulset. Each intermediate overlay manages or
|
||||||
|
// generates new resources and patches different aspects of the same base
|
||||||
|
// resource, without using any of the `namePrefix`, `nameSuffix` or `namespace`
|
||||||
|
// kustomization keywords.
|
||||||
|
//
|
||||||
|
// Intermediate overlays:
|
||||||
|
// - storage: Changes the storage class of the stateful set with a JSON patch.
|
||||||
|
// - config: Generates a config map and adds a field as an environment
|
||||||
|
// variable.
|
||||||
|
// - tolerations: Adds a new tolerations field in the spec.
|
||||||
|
// - https: Adds a new service resource and changes the service name in the
|
||||||
|
// stateful set.
|
||||||
|
//
|
||||||
|
// Top overlays:
|
||||||
|
// - dev: Combines the storage and config intermediate overlays.
|
||||||
|
// - prod: Combines the config, tolerations and https intermediate overlays.
|
||||||
|
|
||||||
|
func TestComplexComposition_Dev_Failure(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/dev")
|
||||||
|
writeStatefulSetBase(th)
|
||||||
|
writePatchingOverlays(th)
|
||||||
|
th.WriteK("/app/dev", `
|
||||||
|
resources:
|
||||||
|
- ../storage
|
||||||
|
- ../config
|
||||||
|
`)
|
||||||
|
_, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Expected resource accumulation error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(
|
||||||
|
err.Error(), "already registered id: apps_v1_StatefulSet|~X|my-sts") {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const devDesiredResult = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: my-app
|
||||||
|
serviceName: my-svc
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: my-app
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: my-config
|
||||||
|
image: my-image
|
||||||
|
name: app
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- spec:
|
||||||
|
storageClassName: my-sc
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
MY_ENV: foo
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: my-config
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestComplexComposition_Dev_SuccessWithRawTransformers(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/dev")
|
||||||
|
writeStatefulSetBase(th)
|
||||||
|
writePatchingTransformersRaw(th)
|
||||||
|
th.WriteK("/app/dev", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
generators:
|
||||||
|
- ../config/map/generator.yaml
|
||||||
|
transformers:
|
||||||
|
- ../config/transformer/transformer.yaml
|
||||||
|
- ../storage/transformer.yaml
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, devDesiredResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComplexComposition_Dev_SuccessWithBaseTransformers(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/dev")
|
||||||
|
writeStatefulSetBase(th)
|
||||||
|
writePatchingTransformerBases(th)
|
||||||
|
th.WriteK("/app/dev", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
generators:
|
||||||
|
- ../config/map
|
||||||
|
transformers:
|
||||||
|
- ../config/transformer
|
||||||
|
- ../storage
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, devDesiredResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComplexComposition_Prod_Failure(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
|
||||||
|
writeStatefulSetBase(th)
|
||||||
|
writePatchingOverlays(th)
|
||||||
|
th.WriteK("/app/prod", `
|
||||||
|
resources:
|
||||||
|
- ../config
|
||||||
|
- ../tolerations
|
||||||
|
- ../https
|
||||||
|
`)
|
||||||
|
_, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Expected resource accumulation error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(
|
||||||
|
err.Error(), "already registered id: apps_v1_StatefulSet|~X|my-sts") {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const prodDesiredResult = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: my-sts
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: my-app
|
||||||
|
serviceName: my-https-svc
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: my-app
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: my-config
|
||||||
|
image: my-image
|
||||||
|
name: app
|
||||||
|
tolerations:
|
||||||
|
- effect: NoExecute
|
||||||
|
key: node.kubernetes.io/not-ready
|
||||||
|
tolerationSeconds: 30
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- spec:
|
||||||
|
storageClassName: default
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: my-https-svc
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: https
|
||||||
|
port: 443
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
app: my-app
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
MY_ENV: foo
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: my-config
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestComplexComposition_Prod_SuccessWithRawTransformers(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/prod")
|
||||||
|
writeStatefulSetBase(th)
|
||||||
|
writePatchingTransformersRaw(th)
|
||||||
|
th.WriteK("/app/prod", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
- ../https/service/https-svc.yaml
|
||||||
|
generators:
|
||||||
|
- ../config/map/generator.yaml
|
||||||
|
transformers:
|
||||||
|
- ../config/transformer/transformer.yaml
|
||||||
|
- ../https/transformer/transformer.yaml
|
||||||
|
- ../tolerations/transformer.yaml
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, prodDesiredResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComplexComposition_Prod_SuccessWithBaseTransformers(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
|
||||||
|
writeStatefulSetBase(th)
|
||||||
|
writePatchingTransformerBases(th)
|
||||||
|
th.WriteK("/app/prod", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
- ../https/service
|
||||||
|
generators:
|
||||||
|
- ../config/map
|
||||||
|
transformers:
|
||||||
|
- ../config/transformer
|
||||||
|
- ../https/transformer
|
||||||
|
- ../tolerations
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, prodDesiredResult)
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Generate a Secret and a ConfigMap from the same data
|
// Generate a Secret and a ConfigMap from the same data
|
||||||
@@ -251,3 +251,63 @@ metadata:
|
|||||||
name: p2-com2-c4b8md75k9
|
name: p2-com2-c4b8md75k9
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigMapGeneratorMergeNamePrefix(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app")
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
configMapGenerator:
|
||||||
|
- name: cm
|
||||||
|
behavior: create
|
||||||
|
literals:
|
||||||
|
- foo=bar
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/o1", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
namePrefix: o1-
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/o2", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
nameSuffix: -o2
|
||||||
|
`)
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- o1
|
||||||
|
- o2
|
||||||
|
configMapGenerator:
|
||||||
|
- name: o1-cm
|
||||||
|
behavior: merge
|
||||||
|
literals:
|
||||||
|
- big=bang
|
||||||
|
- name: cm-o2
|
||||||
|
behavior: merge
|
||||||
|
literals:
|
||||||
|
- big=crunch
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
big: bang
|
||||||
|
foo: bar
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
annotations: {}
|
||||||
|
labels: {}
|
||||||
|
name: o1-cm-28g596k77k
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
big: crunch
|
||||||
|
foo: bar
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
annotations: {}
|
||||||
|
labels: {}
|
||||||
|
name: cm-o2-gfcc59fg5m
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func writeBaseWithCrd(th *kusttest_test.KustTestHarness) {
|
func writeBaseWithCrd(th *kusttest_test.KustTestHarness) {
|
||||||
@@ -78,7 +78,7 @@ data:
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec"
|
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec"
|
||||||
@@ -91,7 +91,7 @@ data:
|
|||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec",
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec",
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus",
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus",
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeList": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeList": {
|
||||||
@@ -115,13 +115,13 @@ data:
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ListMeta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.Bee",
|
"github.com/example/pkg/apis/jingfang/v1beta1.Bee",
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ListMeta"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference": {
|
||||||
@@ -159,7 +159,7 @@ data:
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec"
|
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec"
|
||||||
@@ -172,7 +172,7 @@ data:
|
|||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec",
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec",
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus",
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus",
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindList": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindList": {
|
||||||
@@ -196,13 +196,13 @@ data:
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ListMeta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKind",
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKind",
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"
|
"sigs.k8s.io/kustomize/pseudo/k8s/apimachinery/pkg/apis/meta/v1.ListMeta"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec": {
|
||||||
@@ -218,13 +218,13 @@ data:
|
|||||||
"description": "If defined, use this secret for configuring the MYSQL_ROOT_PASSWORD",
|
"description": "If defined, use this secret for configuring the MYSQL_ROOT_PASSWORD",
|
||||||
"x-kubernetes-object-ref-api-version": "v1",
|
"x-kubernetes-object-ref-api-version": "v1",
|
||||||
"x-kubernetes-object-ref-kind": "Secret",
|
"x-kubernetes-object-ref-kind": "Secret",
|
||||||
"$ref": "k8s.io/api/core/v1.LocalObjectReference"
|
"$ref": "sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1.LocalObjectReference"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference",
|
"github.com/example/pkg/apis/jingfang/v1beta1.BeeObjectReference",
|
||||||
"k8s.io/api/core/v1.LocalObjectReference"
|
"sigs.k8s.io/kustomize/pseudo/k8s/api/core/v1.LocalObjectReference"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus": {
|
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus": {
|
||||||
@@ -19,7 +19,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeBaseReferencingCustomConfig(th *kusttest_test.KustTestHarness) {
|
func makeBaseReferencingCustomConfig(th *kusttest_test.KustTestHarness) {
|
||||||
216
api/internal/target/customconfigofbuiltinplugin_test.go
Normal file
216
api/internal/target/customconfigofbuiltinplugin_test.go
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Demo custom configuration of a builtin transformation.
|
||||||
|
// This is a NamePrefixer that only touches Deployments
|
||||||
|
// and Services.
|
||||||
|
func TestCustomNamePrefixer(t *testing.T) {
|
||||||
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PrefixSuffixTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app")
|
||||||
|
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- role.yaml
|
||||||
|
- service.yaml
|
||||||
|
transformers:
|
||||||
|
- prefixer.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/prefixer.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PrefixSuffixTransformer
|
||||||
|
metadata:
|
||||||
|
name: customPrefixer
|
||||||
|
prefix: zzz-
|
||||||
|
fieldSpecs:
|
||||||
|
- kind: Deployment
|
||||||
|
path: metadata/name
|
||||||
|
- kind: Service
|
||||||
|
path: metadata/name
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/deployment.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
backend: awesome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: whatever
|
||||||
|
image: whatever
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/role.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: myRole
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myService
|
||||||
|
`)
|
||||||
|
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: zzz-myDeployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
backend: awesome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: whatever
|
||||||
|
name: whatever
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: myRole
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: zzz-myService
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demo custom configuration as a base.
|
||||||
|
func TestReusableCustomNamePrefixer(t *testing.T) {
|
||||||
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PrefixSuffixTransformer")
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "LabelTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/foo")
|
||||||
|
|
||||||
|
// This kustomization file contains resources that
|
||||||
|
// all happen to be plugin configurations. This makes
|
||||||
|
// these plugins all available as part of a base,
|
||||||
|
// re-usable in any number of other kustomizations.
|
||||||
|
// Just specify the path (or URL) to this base in the
|
||||||
|
// "transformers:" field (not the "resources" field).
|
||||||
|
th.WriteK("/app/mytransformers", `
|
||||||
|
resources:
|
||||||
|
- prefixer.yaml
|
||||||
|
- labeller.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/mytransformers/prefixer.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PrefixSuffixTransformer
|
||||||
|
metadata:
|
||||||
|
name: myPrefixer
|
||||||
|
prefix: zzz-
|
||||||
|
fieldSpecs:
|
||||||
|
- kind: Deployment
|
||||||
|
path: metadata/name
|
||||||
|
- kind: Service
|
||||||
|
path: metadata/name
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/mytransformers/labeller.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: LabelTransformer
|
||||||
|
metadata:
|
||||||
|
name: myLabeller
|
||||||
|
labels:
|
||||||
|
company: acmeCorp
|
||||||
|
fieldSpecs:
|
||||||
|
- path: spec/template/metadata/labels
|
||||||
|
kind: Deployment
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK("/app/foo", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- role.yaml
|
||||||
|
- service.yaml
|
||||||
|
transformers:
|
||||||
|
- ../mytransformers
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/foo/deployment.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
backend: awesome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: whatever
|
||||||
|
image: whatever
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/foo/role.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: myRole
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/foo/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myService
|
||||||
|
`)
|
||||||
|
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: zzz-myDeployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
backend: awesome
|
||||||
|
company: acmeCorp
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: whatever
|
||||||
|
name: whatever
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: myRole
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: zzz-myService
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -9,8 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const patchAddProbe = `
|
const patchAddProbe = `
|
||||||
@@ -232,7 +231,7 @@ func definePatchDirStructure(th *kusttest_test.KustTestHarness) {
|
|||||||
|
|
||||||
// Fails due to file load restrictor.
|
// Fails due to file load restrictor.
|
||||||
func TestIssue1251_Patches_ProdVsDev_Failure(t *testing.T) {
|
func TestIssue1251_Patches_ProdVsDev_Failure(t *testing.T) {
|
||||||
th := kusttest_test.NewKustTestPluginHarness(t, "/app/prod")
|
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
|
||||||
definePatchDirStructure(th)
|
definePatchDirStructure(th)
|
||||||
|
|
||||||
th.WriteK("/app/prod", `
|
th.WriteK("/app/prod", `
|
||||||
@@ -305,7 +304,7 @@ spec:
|
|||||||
// the kustomization root), opening the user to whatever
|
// the kustomization root), opening the user to whatever
|
||||||
// threat the load restrictor was meant to address.
|
// threat the load restrictor was meant to address.
|
||||||
func TestIssue1251_Patches_ProdVsDev(t *testing.T) {
|
func TestIssue1251_Patches_ProdVsDev(t *testing.T) {
|
||||||
th := kusttest_test.NewKustTestNoLoadRestrictorHarness(t, "/app/prod")
|
th := kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/prod")
|
||||||
definePatchDirStructure(th)
|
definePatchDirStructure(th)
|
||||||
|
|
||||||
th.WriteK("/app/prod", `
|
th.WriteK("/app/prod", `
|
||||||
@@ -321,7 +320,7 @@ patchesStrategicMerge:
|
|||||||
}
|
}
|
||||||
th.AssertActualEqualsExpected(m, prodDevMergeResult1)
|
th.AssertActualEqualsExpected(m, prodDevMergeResult1)
|
||||||
|
|
||||||
th = kusttest_test.NewKustTestNoLoadRestrictorHarness(t, "/app/dev")
|
th = kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/dev")
|
||||||
definePatchDirStructure(th)
|
definePatchDirStructure(th)
|
||||||
|
|
||||||
th.WriteK("/app/dev", `
|
th.WriteK("/app/dev", `
|
||||||
@@ -340,13 +339,13 @@ patchesStrategicMerge:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue1251_Plugins_ProdVsDev(t *testing.T) {
|
func TestIssue1251_Plugins_ProdVsDev(t *testing.T) {
|
||||||
tc := plugins_test.NewEnvForTest(t).Set()
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
"builtin", "", "PatchJson6902Transformer")
|
"builtin", "", "PatchJson6902Transformer")
|
||||||
|
|
||||||
th := kusttest_test.NewKustTestPluginHarness(t, "/app/prod")
|
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/prod")
|
||||||
defineTransformerDirStructure(th)
|
defineTransformerDirStructure(th)
|
||||||
th.WriteK("/app/prod", `
|
th.WriteK("/app/prod", `
|
||||||
resources:
|
resources:
|
||||||
@@ -362,7 +361,7 @@ transformers:
|
|||||||
}
|
}
|
||||||
th.AssertActualEqualsExpected(m, prodDevMergeResult1)
|
th.AssertActualEqualsExpected(m, prodDevMergeResult1)
|
||||||
|
|
||||||
th = kusttest_test.NewKustTestPluginHarness(t, "/app/dev")
|
th = kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/dev")
|
||||||
defineTransformerDirStructure(th)
|
defineTransformerDirStructure(th)
|
||||||
th.WriteK("/app/dev", `
|
th.WriteK("/app/dev", `
|
||||||
resources:
|
resources:
|
||||||
@@ -380,13 +379,13 @@ transformers:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue1251_Plugins_Local(t *testing.T) {
|
func TestIssue1251_Plugins_Local(t *testing.T) {
|
||||||
tc := plugins_test.NewEnvForTest(t).Set()
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
"builtin", "", "PatchJson6902Transformer")
|
"builtin", "", "PatchJson6902Transformer")
|
||||||
|
|
||||||
th := kusttest_test.NewKustTestPluginHarness(t, "/app/composite")
|
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/composite")
|
||||||
writeDeploymentBase(th)
|
writeDeploymentBase(th)
|
||||||
|
|
||||||
writeJsonTransformerPluginConfig(
|
writeJsonTransformerPluginConfig(
|
||||||
@@ -430,13 +429,13 @@ jsonOp: '%s'
|
|||||||
|
|
||||||
// Remote in the sense that they are bundled in a different kustomization.
|
// Remote in the sense that they are bundled in a different kustomization.
|
||||||
func TestIssue1251_Plugins_Bundled(t *testing.T) {
|
func TestIssue1251_Plugins_Bundled(t *testing.T) {
|
||||||
tc := plugins_test.NewEnvForTest(t).Set()
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
"builtin", "", "PatchJson6902Transformer")
|
"builtin", "", "PatchJson6902Transformer")
|
||||||
|
|
||||||
th := kusttest_test.NewKustTestPluginHarness(t, "/app/composite")
|
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/composite")
|
||||||
writeDeploymentBase(th)
|
writeDeploymentBase(th)
|
||||||
|
|
||||||
th.WriteK("/app/patches", `
|
th.WriteK("/app/patches", `
|
||||||
@@ -4,8 +4,9 @@
|
|||||||
package target_test
|
package target_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Here's a structure of two kustomizations,
|
// Here's a structure of two kustomizations,
|
||||||
@@ -6,7 +6,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeCommonFileForExtendedPatchTest(th *kusttest_test.KustTestHarness) {
|
func makeCommonFileForExtendedPatchTest(th *kusttest_test.KustTestHarness) {
|
||||||
@@ -923,6 +923,107 @@ spec:
|
|||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExtendedPatchWithoutTarget(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
||||||
|
makeCommonFileForExtendedPatchTest(th)
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
patches:
|
||||||
|
- path: patch.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/base/patch.yaml", `
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: busybox
|
||||||
|
annotations:
|
||||||
|
new-key: new-value
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
new-key: new-value
|
||||||
|
labels:
|
||||||
|
app: busybox
|
||||||
|
name: busybox
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: busybox
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: busybox
|
||||||
|
name: busybox
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: busybox-persistent-storage
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: busybox-persistent-storage
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: busybox
|
||||||
|
name: busybox
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
selector:
|
||||||
|
app: busybox
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestExtendedPatchNoMatchMultiplePatch(t *testing.T) {
|
func TestExtendedPatchNoMatchMultiplePatch(t *testing.T) {
|
||||||
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
||||||
makeCommonFileForExtendedPatchTest(th)
|
makeCommonFileForExtendedPatchTest(th)
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSimpleBase(t *testing.T) {
|
func TestSimpleBase(t *testing.T) {
|
||||||
@@ -19,7 +19,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSecretGenerator(t *testing.T) {
|
func TestSecretGenerator(t *testing.T) {
|
||||||
244
api/internal/target/inlinepatch_test.go
Normal file
244
api/internal/target/inlinepatch_test.go
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeResourcesForPatchTest(th *kusttest_test.KustTestHarness) {
|
||||||
|
th.WriteF("/app/base/deployment.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- name: nginx-persistent-storage
|
||||||
|
mountPath: /tmp/ps
|
||||||
|
volumes:
|
||||||
|
- name: nginx-persistent-storage
|
||||||
|
emptyDir: {}
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrategicMergePatchInline(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
||||||
|
makeResourcesForPatchTest(th)
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- |-
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: image1
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: image1
|
||||||
|
name: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONPatchInline(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
||||||
|
makeResourcesForPatchTest(th)
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
|
||||||
|
patchesJson6902:
|
||||||
|
- target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: Deployment
|
||||||
|
name: nginx
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/template/spec/containers/0/image
|
||||||
|
value: image1
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: image1
|
||||||
|
name: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtendedPatchInlineJSON(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
||||||
|
makeResourcesForPatchTest(th)
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
name: nginx
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/template/spec/containers/0/image
|
||||||
|
value: image1
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: image1
|
||||||
|
name: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtendedPatchInlineYAML(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/base")
|
||||||
|
makeResourcesForPatchTest(th)
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
name: nginx
|
||||||
|
patch: |-
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: image1
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: image1
|
||||||
|
name: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
- configMap:
|
||||||
|
name: configmap-in-base
|
||||||
|
name: configmap-in-base
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -9,18 +9,20 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/accumulator"
|
"sigs.k8s.io/kustomize/api/builtins"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
"sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers"
|
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/transformers/config"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/plugin/builtin"
|
"sigs.k8s.io/kustomize/api/transform"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,17 +30,19 @@ import (
|
|||||||
type KustTarget struct {
|
type KustTarget struct {
|
||||||
kustomization *types.Kustomization
|
kustomization *types.Kustomization
|
||||||
ldr ifc.Loader
|
ldr ifc.Loader
|
||||||
|
validator ifc.Validator
|
||||||
rFactory *resmap.Factory
|
rFactory *resmap.Factory
|
||||||
tFactory resmap.PatchFactory
|
tFactory resmap.PatchFactory
|
||||||
pLdr *plugins.Loader
|
pLdr *loader.Loader
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKustTarget returns a new instance of KustTarget primed with a Loader.
|
// NewKustTarget returns a new instance of KustTarget primed with a Loader.
|
||||||
func NewKustTarget(
|
func NewKustTarget(
|
||||||
ldr ifc.Loader,
|
ldr ifc.Loader,
|
||||||
|
validator ifc.Validator,
|
||||||
rFactory *resmap.Factory,
|
rFactory *resmap.Factory,
|
||||||
tFactory resmap.PatchFactory,
|
tFactory resmap.PatchFactory,
|
||||||
pLdr *plugins.Loader) (*KustTarget, error) {
|
pLdr *loader.Loader) (*KustTarget, error) {
|
||||||
content, err := loadKustFile(ldr)
|
content, err := loadKustFile(ldr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -59,6 +63,7 @@ func NewKustTarget(
|
|||||||
return &KustTarget{
|
return &KustTarget{
|
||||||
kustomization: &k,
|
kustomization: &k,
|
||||||
ldr: ldr,
|
ldr: ldr,
|
||||||
|
validator: validator,
|
||||||
rFactory: rFactory,
|
rFactory: rFactory,
|
||||||
tFactory: tFactory,
|
tFactory: tFactory,
|
||||||
pLdr: pLdr,
|
pLdr: pLdr,
|
||||||
@@ -80,7 +85,7 @@ func commaOr(q []string) string {
|
|||||||
func loadKustFile(ldr ifc.Loader) ([]byte, error) {
|
func loadKustFile(ldr ifc.Loader) ([]byte, error) {
|
||||||
var content []byte
|
var content []byte
|
||||||
match := 0
|
match := 0
|
||||||
for _, kf := range pgmconfig.KustomizationFileNames {
|
for _, kf := range konfig.RecognizedKustomizationFileNames() {
|
||||||
c, err := ldr.Load(kf)
|
c, err := ldr.Load(kf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
match += 1
|
match += 1
|
||||||
@@ -89,9 +94,7 @@ func loadKustFile(ldr ifc.Loader) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
switch match {
|
switch match {
|
||||||
case 0:
|
case 0:
|
||||||
return nil, fmt.Errorf(
|
return nil, NewErrMissingKustomization(ldr.Root())
|
||||||
"unable to find one of %v in directory '%s'",
|
|
||||||
commaOr(quoted(pgmconfig.KustomizationFileNames)), ldr.Root())
|
|
||||||
case 1:
|
case 1:
|
||||||
return content, nil
|
return content, nil
|
||||||
default:
|
default:
|
||||||
@@ -100,6 +103,30 @@ func loadKustFile(ldr ifc.Loader) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type errMissingKustomization struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errMissingKustomization) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"unable to find one of %v in directory '%s'",
|
||||||
|
commaOr(quoted(konfig.RecognizedKustomizationFileNames())),
|
||||||
|
e.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewErrMissingKustomization(p string) *errMissingKustomization {
|
||||||
|
return &errMissingKustomization{path: p}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsMissingKustomizationFileError(err error) bool {
|
||||||
|
_, ok := err.(*errMissingKustomization)
|
||||||
|
if ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_, ok = errors.Cause(err).(*errMissingKustomization)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func unmarshal(y []byte, o interface{}) error {
|
func unmarshal(y []byte, o interface{}) error {
|
||||||
j, err := yaml.YAMLToJSON(y)
|
j, err := yaml.YAMLToJSON(y)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -158,8 +185,8 @@ func (kt *KustTarget) makeCustomizedResMap(
|
|||||||
|
|
||||||
func (kt *KustTarget) addHashesToNames(
|
func (kt *KustTarget) addHashesToNames(
|
||||||
ra *accumulator.ResAccumulator) error {
|
ra *accumulator.ResAccumulator) error {
|
||||||
p := builtin.NewHashTransformerPlugin()
|
p := builtins.NewHashTransformerPlugin()
|
||||||
err := kt.configureBuiltinPlugin(p, nil, "hash")
|
err := kt.configureBuiltinPlugin(p, nil, builtinhelpers.HashTransformer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -180,7 +207,6 @@ func (kt *KustTarget) computeInventory(
|
|||||||
return fmt.Errorf("namespace mismatch")
|
return fmt.Errorf("namespace mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
p := builtin.NewInventoryTransformerPlugin()
|
|
||||||
var c struct {
|
var c struct {
|
||||||
Policy string
|
Policy string
|
||||||
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
||||||
@@ -188,8 +214,8 @@ func (kt *KustTarget) computeInventory(
|
|||||||
c.Name = inv.ConfigMap.Name
|
c.Name = inv.ConfigMap.Name
|
||||||
c.Namespace = inv.ConfigMap.Namespace
|
c.Namespace = inv.ConfigMap.Namespace
|
||||||
c.Policy = garbagePolicy.String()
|
c.Policy = garbagePolicy.String()
|
||||||
|
p := builtins.NewInventoryTransformerPlugin()
|
||||||
err := kt.configureBuiltinPlugin(p, c, "inventory")
|
err := kt.configureBuiltinPlugin(p, c, builtinhelpers.InventoryTransformer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -212,7 +238,7 @@ func (kt *KustTarget) AccumulateTarget() (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "accumulating resources")
|
return nil, errors.Wrap(err, "accumulating resources")
|
||||||
}
|
}
|
||||||
tConfig, err := config.MakeTransformerConfig(
|
tConfig, err := builtinconfig.MakeTransformerConfig(
|
||||||
kt.ldr, kt.kustomization.Configurations)
|
kt.ldr, kt.kustomization.Configurations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -222,7 +248,7 @@ func (kt *KustTarget) AccumulateTarget() (
|
|||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
err, "merging config %v", tConfig)
|
err, "merging config %v", tConfig)
|
||||||
}
|
}
|
||||||
crdTc, err := config.LoadConfigFromCRDs(kt.ldr, kt.kustomization.Crds)
|
crdTc, err := accumulator.LoadConfigFromCRDs(kt.ldr, kt.kustomization.Crds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
err, "loading CRDs %v", kt.kustomization.Crds)
|
err, "loading CRDs %v", kt.kustomization.Crds)
|
||||||
@@ -250,31 +276,23 @@ func (kt *KustTarget) AccumulateTarget() (
|
|||||||
|
|
||||||
func (kt *KustTarget) runGenerators(
|
func (kt *KustTarget) runGenerators(
|
||||||
ra *accumulator.ResAccumulator) error {
|
ra *accumulator.ResAccumulator) error {
|
||||||
generators, err := kt.configureBuiltinGenerators()
|
var generators []resmap.Generator
|
||||||
|
gs, err := kt.configureBuiltinGenerators()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, g := range generators {
|
generators = append(generators, gs...)
|
||||||
resMap, err := g.Generate()
|
gs, err = kt.configureExternalGenerators()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// The legacy generators allow override.
|
|
||||||
err = ra.AbsorbAll(resMap)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "merging from generator %v", g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
generators, err = kt.configureExternalGenerators()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "loading generator plugins")
|
return errors.Wrap(err, "loading generator plugins")
|
||||||
}
|
}
|
||||||
|
generators = append(generators, gs...)
|
||||||
for _, g := range generators {
|
for _, g := range generators {
|
||||||
resMap, err := g.Generate()
|
resMap, err := g.Generate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = ra.AppendAll(resMap)
|
err = ra.AbsorbAll(resMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "merging from generator %v", g)
|
return errors.Wrapf(err, "merging from generator %v", g)
|
||||||
}
|
}
|
||||||
@@ -282,17 +300,17 @@ func (kt *KustTarget) runGenerators(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) configureExternalGenerators() ([]transformers.Generator, error) {
|
func (kt *KustTarget) configureExternalGenerators() ([]resmap.Generator, error) {
|
||||||
ra := accumulator.MakeEmptyAccumulator()
|
ra := accumulator.MakeEmptyAccumulator()
|
||||||
err := kt.accumulateResources(ra, kt.kustomization.Generators)
|
err := kt.accumulateResources(ra, kt.kustomization.Generators)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return kt.pLdr.LoadGenerators(kt.ldr, ra.ResMap())
|
return kt.pLdr.LoadGenerators(kt.ldr, kt.validator, ra.ResMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
||||||
var r []transformers.Transformer
|
var r []resmap.Transformer
|
||||||
tConfig := ra.GetTransformerConfig()
|
tConfig := ra.GetTransformerConfig()
|
||||||
lts, err := kt.configureBuiltinTransformers(tConfig)
|
lts, err := kt.configureBuiltinTransformers(tConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -304,17 +322,17 @@ func (kt *KustTarget) runTransformers(ra *accumulator.ResAccumulator) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r = append(r, lts...)
|
r = append(r, lts...)
|
||||||
t := transformers.NewMultiTransformer(r)
|
t := transform.NewMultiTransformer(r)
|
||||||
return ra.Transform(t)
|
return ra.Transform(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) configureExternalTransformers() ([]transformers.Transformer, error) {
|
func (kt *KustTarget) configureExternalTransformers() ([]resmap.Transformer, error) {
|
||||||
ra := accumulator.MakeEmptyAccumulator()
|
ra := accumulator.MakeEmptyAccumulator()
|
||||||
err := kt.accumulateResources(ra, kt.kustomization.Transformers)
|
err := kt.accumulateResources(ra, kt.kustomization.Transformers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return kt.pLdr.LoadTransformers(kt.ldr, ra.ResMap())
|
return kt.pLdr.LoadTransformers(kt.ldr, kt.validator, ra.ResMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
// accumulateResources fills the given resourceAccumulator
|
// accumulateResources fills the given resourceAccumulator
|
||||||
@@ -324,14 +342,16 @@ func (kt *KustTarget) accumulateResources(
|
|||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
ldr, err := kt.ldr.New(path)
|
ldr, err := kt.ldr.New(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = kt.accumulateDirectory(ra, ldr, path)
|
err = kt.accumulateDirectory(ra, ldr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = kt.accumulateFile(ra, path)
|
err2 := kt.accumulateFile(ra, path)
|
||||||
if err != nil {
|
if err2 != nil {
|
||||||
return err
|
// Log ldr.New() error to highlight git failures.
|
||||||
|
log.Print(err.Error())
|
||||||
|
return err2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,22 +359,23 @@ func (kt *KustTarget) accumulateResources(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) accumulateDirectory(
|
func (kt *KustTarget) accumulateDirectory(
|
||||||
ra *accumulator.ResAccumulator, ldr ifc.Loader, path string) error {
|
ra *accumulator.ResAccumulator, ldr ifc.Loader) error {
|
||||||
defer ldr.Cleanup()
|
defer ldr.Cleanup()
|
||||||
subKt, err := NewKustTarget(
|
subKt, err := NewKustTarget(
|
||||||
ldr, kt.rFactory, kt.tFactory, kt.pLdr)
|
ldr, kt.validator, kt.rFactory, kt.tFactory, kt.pLdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "couldn't make target for path '%s'", path)
|
return errors.Wrapf(
|
||||||
|
err, "couldn't make target for path '%s'", ldr.Root())
|
||||||
}
|
}
|
||||||
subRa, err := subKt.AccumulateTarget()
|
subRa, err := subKt.AccumulateTarget()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err, "recursed accumulation of path '%s'", path)
|
err, "recursed accumulation of path '%s'", ldr.Root())
|
||||||
}
|
}
|
||||||
err = ra.MergeAccumulator(subRa)
|
err = ra.MergeAccumulator(subRa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err, "recursed merging from path '%s'", path)
|
err, "recursed merging from path '%s'", ldr.Root())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -371,3 +392,20 @@ func (kt *KustTarget) accumulateFile(
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (kt *KustTarget) configureBuiltinPlugin(
|
||||||
|
p resmap.Configurable, c interface{}, bpt builtinhelpers.BuiltinPluginType) (err error) {
|
||||||
|
var y []byte
|
||||||
|
if c != nil {
|
||||||
|
y, err = yaml.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(
|
||||||
|
err, "builtin %s marshal", bpt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = p.Config(resmap.NewPluginHelpers(kt.ldr, kt.validator, kt.rFactory), y)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "builtin %s config: %v", bpt, y)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
297
api/internal/target/kusttarget_configplugin.go
Normal file
297
api/internal/target/kusttarget_configplugin.go
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Functions dedicated to configuring the builtin
|
||||||
|
// transformer and generator plugins using config data
|
||||||
|
// read from a kustomization file and from the
|
||||||
|
// config.TransformerConfig, whose data may be a
|
||||||
|
// mix of hardcoded values and data read from file.
|
||||||
|
//
|
||||||
|
// Non-builtin plugins will get their configuration
|
||||||
|
// from their own dedicated structs and YAML files.
|
||||||
|
//
|
||||||
|
// There are some loops in the functions below because
|
||||||
|
// the kustomization file would, say, allow someone to
|
||||||
|
// request multiple secrets be made, or run multiple
|
||||||
|
// image tag transforms. In these cases, we'll need
|
||||||
|
// N plugin instances with differing configurations.
|
||||||
|
|
||||||
|
func (kt *KustTarget) configureBuiltinGenerators() (
|
||||||
|
result []resmap.Generator, err error) {
|
||||||
|
for _, bpt := range []builtinhelpers.BuiltinPluginType{
|
||||||
|
builtinhelpers.ConfigMapGenerator,
|
||||||
|
builtinhelpers.SecretGenerator,
|
||||||
|
} {
|
||||||
|
r, err := generatorConfigurators[bpt](
|
||||||
|
kt, bpt, builtinhelpers.GeneratorFactories[bpt])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, r...)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kt *KustTarget) configureBuiltinTransformers(
|
||||||
|
tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
for _, bpt := range []builtinhelpers.BuiltinPluginType{
|
||||||
|
builtinhelpers.PatchStrategicMergeTransformer,
|
||||||
|
builtinhelpers.PatchTransformer,
|
||||||
|
builtinhelpers.NamespaceTransformer,
|
||||||
|
builtinhelpers.PrefixSuffixTransformer,
|
||||||
|
builtinhelpers.LabelTransformer,
|
||||||
|
builtinhelpers.AnnotationsTransformer,
|
||||||
|
builtinhelpers.PatchJson6902Transformer,
|
||||||
|
builtinhelpers.ReplicaCountTransformer,
|
||||||
|
builtinhelpers.ImageTagTransformer,
|
||||||
|
} {
|
||||||
|
r, err := transformerConfigurators[bpt](
|
||||||
|
kt, bpt, builtinhelpers.TransformerFactories[bpt], tc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, r...)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type gFactory func() resmap.GeneratorPlugin
|
||||||
|
|
||||||
|
var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
|
||||||
|
kt *KustTarget,
|
||||||
|
bpt builtinhelpers.BuiltinPluginType,
|
||||||
|
factory gFactory) (result []resmap.Generator, err error){
|
||||||
|
builtinhelpers.SecretGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
|
||||||
|
result []resmap.Generator, err error) {
|
||||||
|
var c struct {
|
||||||
|
types.GeneratorOptions
|
||||||
|
types.SecretArgs
|
||||||
|
}
|
||||||
|
if kt.kustomization.GeneratorOptions != nil {
|
||||||
|
c.GeneratorOptions = *kt.kustomization.GeneratorOptions
|
||||||
|
}
|
||||||
|
for _, args := range kt.kustomization.SecretGenerator {
|
||||||
|
c.SecretArgs = args
|
||||||
|
p := f()
|
||||||
|
err := kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
|
||||||
|
builtinhelpers.ConfigMapGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
|
||||||
|
result []resmap.Generator, err error) {
|
||||||
|
var c struct {
|
||||||
|
types.GeneratorOptions
|
||||||
|
types.ConfigMapArgs
|
||||||
|
}
|
||||||
|
if kt.kustomization.GeneratorOptions != nil {
|
||||||
|
c.GeneratorOptions = *kt.kustomization.GeneratorOptions
|
||||||
|
}
|
||||||
|
for _, args := range kt.kustomization.ConfigMapGenerator {
|
||||||
|
c.ConfigMapArgs = args
|
||||||
|
p := f()
|
||||||
|
err := kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type tFactory func() resmap.TransformerPlugin
|
||||||
|
|
||||||
|
var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
|
||||||
|
kt *KustTarget,
|
||||||
|
bpt builtinhelpers.BuiltinPluginType,
|
||||||
|
f tFactory,
|
||||||
|
tc *builtinconfig.TransformerConfig) (result []resmap.Transformer, err error){
|
||||||
|
builtinhelpers.NamespaceTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
||||||
|
FieldSpecs []types.FieldSpec
|
||||||
|
}
|
||||||
|
c.Namespace = kt.kustomization.Namespace
|
||||||
|
c.FieldSpecs = tc.NameSpace
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
|
||||||
|
builtinhelpers.PatchJson6902Transformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
Target types.PatchTarget `json:"target,omitempty" yaml:"target,omitempty"`
|
||||||
|
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||||
|
JsonOp string `json:"jsonOp,omitempty" yaml:"jsonOp,omitempty"`
|
||||||
|
}
|
||||||
|
for _, args := range kt.kustomization.PatchesJson6902 {
|
||||||
|
c.Target = *args.Target
|
||||||
|
c.Path = args.Path
|
||||||
|
c.JsonOp = args.Patch
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.PatchStrategicMergeTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
if len(kt.kustomization.PatchesStrategicMerge) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var c struct {
|
||||||
|
Paths []types.PatchStrategicMerge `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
|
Patches string `json:"patches,omitempty" yaml:"patches,omitempty"`
|
||||||
|
}
|
||||||
|
c.Paths = kt.kustomization.PatchesStrategicMerge
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.PatchTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
if len(kt.kustomization.Patches) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var c struct {
|
||||||
|
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||||
|
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||||
|
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
||||||
|
}
|
||||||
|
for _, pc := range kt.kustomization.Patches {
|
||||||
|
c.Target = pc.Target
|
||||||
|
c.Patch = pc.Patch
|
||||||
|
c.Path = pc.Path
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.LabelTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
Labels map[string]string
|
||||||
|
FieldSpecs []types.FieldSpec
|
||||||
|
}
|
||||||
|
c.Labels = kt.kustomization.CommonLabels
|
||||||
|
c.FieldSpecs = tc.CommonLabels
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.AnnotationsTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
Annotations map[string]string
|
||||||
|
FieldSpecs []types.FieldSpec
|
||||||
|
}
|
||||||
|
c.Annotations = kt.kustomization.CommonAnnotations
|
||||||
|
c.FieldSpecs = tc.CommonAnnotations
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.PrefixSuffixTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
Prefix string
|
||||||
|
Suffix string
|
||||||
|
FieldSpecs []types.FieldSpec
|
||||||
|
}
|
||||||
|
c.Prefix = kt.kustomization.NamePrefix
|
||||||
|
c.Suffix = kt.kustomization.NameSuffix
|
||||||
|
c.FieldSpecs = tc.NamePrefix
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.ImageTagTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
ImageTag types.Image
|
||||||
|
FieldSpecs []types.FieldSpec
|
||||||
|
}
|
||||||
|
for _, args := range kt.kustomization.Images {
|
||||||
|
c.ImageTag = args
|
||||||
|
c.FieldSpecs = tc.Images
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
builtinhelpers.ReplicaCountTransformer: func(
|
||||||
|
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
|
||||||
|
result []resmap.Transformer, err error) {
|
||||||
|
var c struct {
|
||||||
|
Replica types.Replica
|
||||||
|
FieldSpecs []types.FieldSpec
|
||||||
|
}
|
||||||
|
for _, args := range kt.kustomization.Replicas {
|
||||||
|
c.Replica = args
|
||||||
|
c.FieldSpecs = tc.Replicas
|
||||||
|
p := f()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, bpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -6,18 +6,18 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/internal/loadertest"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
"sigs.k8s.io/kustomize/api/internal/loadertest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/ifc"
|
. "sigs.k8s.io/kustomize/api/internal/target"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/target"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -185,7 +185,8 @@ func TestResources(t *testing.T) {
|
|||||||
|
|
||||||
func TestKustomizationNotFound(t *testing.T) {
|
func TestKustomizationNotFound(t *testing.T) {
|
||||||
_, err := NewKustTarget(
|
_, err := NewKustTarget(
|
||||||
loadertest.NewFakeLoader("/foo"), nil, nil, nil)
|
loadertest.NewFakeLoader("/foo"),
|
||||||
|
valtest_test.MakeFakeValidator(), nil, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected an error")
|
t.Fatalf("expected an error")
|
||||||
}
|
}
|
||||||
@@ -280,7 +281,7 @@ var someVars = []types.Var{
|
|||||||
Name: "AWARD",
|
Name: "AWARD",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
APIVersion: "v7",
|
APIVersion: "v7",
|
||||||
Gvk: gvk.Gvk{Kind: "Service"},
|
Gvk: resid.Gvk{Kind: "Service"},
|
||||||
Name: "nobelPrize"},
|
Name: "nobelPrize"},
|
||||||
FieldRef: types.FieldSelector{FieldPath: "some.arbitrary.path"},
|
FieldRef: types.FieldSelector{FieldPath: "some.arbitrary.path"},
|
||||||
},
|
},
|
||||||
@@ -288,21 +289,21 @@ var someVars = []types.Var{
|
|||||||
Name: "BIRD",
|
Name: "BIRD",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
APIVersion: "v300",
|
APIVersion: "v300",
|
||||||
Gvk: gvk.Gvk{Kind: "Service"},
|
Gvk: resid.Gvk{Kind: "Service"},
|
||||||
Name: "heron"},
|
Name: "heron"},
|
||||||
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
|
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "FRUIT",
|
Name: "FRUIT",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Kind: "Service"},
|
Gvk: resid.Gvk{Kind: "Service"},
|
||||||
Name: "apple"},
|
Name: "apple"},
|
||||||
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
|
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "VEGETABLE",
|
Name: "VEGETABLE",
|
||||||
ObjRef: types.Target{
|
ObjRef: types.Target{
|
||||||
Gvk: gvk.Gvk{Kind: "Leafy"},
|
Gvk: resid.Gvk{Kind: "Leafy"},
|
||||||
Name: "kale"},
|
Name: "kale"},
|
||||||
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
|
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
|
||||||
},
|
},
|
||||||
@@ -334,7 +335,10 @@ vars:
|
|||||||
t.Fatalf("unexpected size %d", len(vars))
|
t.Fatalf("unexpected size %d", len(vars))
|
||||||
}
|
}
|
||||||
for i := range vars[:2] {
|
for i := range vars[:2] {
|
||||||
if !reflect.DeepEqual(vars[i], someVars[i]) {
|
// By using Var.DeepEqual, we are protecting the code
|
||||||
|
// from a potential invocation of vars[i].ObjRef.GVK()
|
||||||
|
// during AccumulateTarget
|
||||||
|
if !vars[i].DeepEqual(someVars[i]) {
|
||||||
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
|
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +391,10 @@ resources:
|
|||||||
t.Fatalf("expected 4 vars, got %d", len(vars))
|
t.Fatalf("expected 4 vars, got %d", len(vars))
|
||||||
}
|
}
|
||||||
for i := range vars {
|
for i := range vars {
|
||||||
if !reflect.DeepEqual(vars[i], someVars[i]) {
|
// By using Var.DeepEqual, we are protecting the code
|
||||||
|
// from a potential invocation of vars[i].ObjRef.GVK()
|
||||||
|
// during AccumulateTarget
|
||||||
|
if !vars[i].DeepEqual(someVars[i]) {
|
||||||
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
|
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeCommonFileForMultiplePatchTest(th *kusttest_test.KustTestHarness) {
|
func makeCommonFileForMultiplePatchTest(th *kusttest_test.KustTestHarness) {
|
||||||
@@ -294,16 +294,8 @@ spec:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMultiplePatchesWithPatchDeleteIgnored demonstrates that if the
|
func TestMultiplePatchesWithOnePatchDeleteDirective(t *testing.T) {
|
||||||
// patch containing the $patch:delete directive is second in the list,
|
additivePatch := `apiVersion: apps/v1beta2
|
||||||
// the behavior of kustomize is incorrect, and the sidecar container is
|
|
||||||
// not removed from the final output. No conflict, nor error is reported
|
|
||||||
// even so the patch is ignored. See issue #1354
|
|
||||||
func TestMultiplePatchesWithPatchDeleteIgnored(t *testing.T) {
|
|
||||||
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
|
|
||||||
makeCommonFileForMultiplePatchTest(th)
|
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
|
||||||
apiVersion: apps/v1beta2
|
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -315,9 +307,8 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: SOME_NAME
|
- name: SOME_NAME
|
||||||
value: somevalue
|
value: somevalue
|
||||||
`)
|
`
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
deletePatch := `apiVersion: apps/v1beta2
|
||||||
apiVersion: apps/v1beta2
|
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: nginx
|
name: nginx
|
||||||
@@ -327,12 +318,36 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- $patch: delete
|
- $patch: delete
|
||||||
name: sidecar
|
name: sidecar
|
||||||
`)
|
`
|
||||||
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
cases := []struct {
|
||||||
if err != nil {
|
name string
|
||||||
t.Fatalf("Err: %v", err)
|
patch1 string
|
||||||
|
patch2 string
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Patch with delete directive first",
|
||||||
|
patch1: deletePatch,
|
||||||
|
patch2: additivePatch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Patch with delete directive second",
|
||||||
|
patch1: additivePatch,
|
||||||
|
patch2: deletePatch,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1beta2
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
|
||||||
|
|
||||||
|
makeCommonFileForMultiplePatchTest(th)
|
||||||
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", c.patch1)
|
||||||
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", c.patch2)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -369,8 +384,6 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
- image: sidecar:latest
|
|
||||||
name: sidecar
|
|
||||||
volumes:
|
volumes:
|
||||||
- emptyDir: {}
|
- emptyDir: {}
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
@@ -421,13 +434,11 @@ metadata:
|
|||||||
env: staging
|
env: staging
|
||||||
name: staging-configmap-in-overlay-k7cbc75tg8
|
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||||
`)
|
`)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMultiplePatchesWithPatchDeleteApplied demonstrates that if the
|
func TestMultiplePatchesBothWithPatchDeleteDirective(t *testing.T) {
|
||||||
// patch containing the $patch:delete directive is first in the list,
|
|
||||||
// the behavior of kustomize is correct, and the sidecar container
|
|
||||||
// is removed from the final output. See issue #1354
|
|
||||||
func TestMultiplePatchesWithPatchDeleteApplied(t *testing.T) {
|
|
||||||
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
|
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
|
||||||
makeCommonFileForMultiplePatchTest(th)
|
makeCommonFileForMultiplePatchTest(th)
|
||||||
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
||||||
@@ -451,100 +462,16 @@ spec:
|
|||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: nginx
|
- $patch: delete
|
||||||
env:
|
|
||||||
- name: SOME_NAME
|
|
||||||
value: somevalue
|
|
||||||
`)
|
|
||||||
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Err: %v", err)
|
|
||||||
}
|
|
||||||
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1beta2
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
note: This is a test annotation
|
|
||||||
labels:
|
|
||||||
app: mynginx
|
|
||||||
env: staging
|
|
||||||
org: example.com
|
|
||||||
team: foo
|
|
||||||
name: staging-team-foo-nginx
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: mynginx
|
|
||||||
env: staging
|
|
||||||
org: example.com
|
|
||||||
team: foo
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
note: This is a test annotation
|
|
||||||
labels:
|
|
||||||
app: mynginx
|
|
||||||
env: staging
|
|
||||||
org: example.com
|
|
||||||
team: foo
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: SOME_NAME
|
|
||||||
value: somevalue
|
|
||||||
image: nginx
|
|
||||||
name: nginx
|
name: nginx
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /tmp/ps
|
|
||||||
name: nginx-persistent-storage
|
|
||||||
volumes:
|
|
||||||
- emptyDir: {}
|
|
||||||
name: nginx-persistent-storage
|
|
||||||
- configMap:
|
|
||||||
name: staging-team-foo-configmap-in-base-g7k6gt2889
|
|
||||||
name: configmap-in-base
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
note: This is a test annotation
|
|
||||||
labels:
|
|
||||||
app: mynginx
|
|
||||||
env: staging
|
|
||||||
org: example.com
|
|
||||||
team: foo
|
|
||||||
name: staging-team-foo-nginx
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
selector:
|
|
||||||
app: mynginx
|
|
||||||
env: staging
|
|
||||||
org: example.com
|
|
||||||
team: foo
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
data:
|
|
||||||
foo: bar
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
note: This is a test annotation
|
|
||||||
labels:
|
|
||||||
app: mynginx
|
|
||||||
env: staging
|
|
||||||
org: example.com
|
|
||||||
team: foo
|
|
||||||
name: staging-team-foo-configmap-in-base-g7k6gt2889
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
data:
|
|
||||||
hello: world
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
env: staging
|
|
||||||
name: staging-configmap-in-overlay-k7cbc75tg8
|
|
||||||
`)
|
`)
|
||||||
|
_, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(
|
||||||
|
err.Error(), "both containing ") {
|
||||||
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNamespacedGenerator(t *testing.T) {
|
func TestNamespacedGenerator(t *testing.T) {
|
||||||
602
api/internal/target/namespaces_test.go
Normal file
602
api/internal/target/namespaces_test.go
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package target_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNamespacedSecrets(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/secrets.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: dummy
|
||||||
|
namespace: default
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
dummy: ""
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: dummy
|
||||||
|
namespace: kube-system
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
dummy: ""
|
||||||
|
`)
|
||||||
|
|
||||||
|
// This should find the proper secret.
|
||||||
|
th.WriteF("/app/role.yaml", `
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: dummy
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
resourceNames: ["dummy"]
|
||||||
|
verbs: ["get"]
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- secrets.yaml
|
||||||
|
- role.yaml
|
||||||
|
`)
|
||||||
|
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
// This validates Fix #1444. This should not be an error anymore -
|
||||||
|
// the secrets have the same name but are in different namespaces.
|
||||||
|
// The ClusterRole (by def) is not in a namespace,
|
||||||
|
// an in this case applies to *any* Secret resource
|
||||||
|
// named "dummy"
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
dummy: ""
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: dummy
|
||||||
|
namespace: default
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
dummy: ""
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: dummy
|
||||||
|
namespace: kube-system
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: dummy
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resourceNames:
|
||||||
|
- dummy
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNameAndNsTransformation validates that NamespaceTransformer,
|
||||||
|
// PrefixSuffixTransformer and namereference transformers are
|
||||||
|
// able to deal with simultaneous change of namespace and name.
|
||||||
|
func TestNameAndNsTransformation(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/nameandns")
|
||||||
|
|
||||||
|
th.WriteK("/nameandns", `
|
||||||
|
namePrefix: p1-
|
||||||
|
nameSuffix: -s1
|
||||||
|
namespace: newnamespace
|
||||||
|
resources:
|
||||||
|
- resources.yaml
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteF("/nameandns/resources.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm2
|
||||||
|
namespace: ns1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: svc1
|
||||||
|
namespace: ns1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: svc2
|
||||||
|
namespace: ns1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: sa1
|
||||||
|
namespace: ns1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: sa2
|
||||||
|
namespace: ns1
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: manager-rolebinding
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: sa1
|
||||||
|
namespace: ns1
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: sa2
|
||||||
|
namespace: ns1
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: sa3
|
||||||
|
namespace: random
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: irrelevant
|
||||||
|
---
|
||||||
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
|
kind: ValidatingWebhookConfiguration
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
webhooks:
|
||||||
|
- name: example1
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc1
|
||||||
|
namespace: ns1
|
||||||
|
- name: example2
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc2
|
||||||
|
namespace: ns1
|
||||||
|
- name: example3
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc3
|
||||||
|
namespace: random
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: crds.my.org
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: cr1
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: crb1
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: irrelevant
|
||||||
|
---
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: pv1
|
||||||
|
`)
|
||||||
|
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: p1-cm1-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: p1-cm2-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: p1-svc1-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: p1-svc2-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: p1-sa1-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: p1-sa2-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: p1-manager-rolebinding-s1
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: p1-sa1-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: p1-sa2-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: sa3
|
||||||
|
namespace: random
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
|
kind: ValidatingWebhookConfiguration
|
||||||
|
metadata:
|
||||||
|
name: p1-example-s1
|
||||||
|
webhooks:
|
||||||
|
- clientConfig:
|
||||||
|
service:
|
||||||
|
name: p1-svc1-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
name: example1
|
||||||
|
- clientConfig:
|
||||||
|
service:
|
||||||
|
name: p1-svc2-s1
|
||||||
|
namespace: newnamespace
|
||||||
|
name: example2
|
||||||
|
- clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc3
|
||||||
|
namespace: random
|
||||||
|
name: example3
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: crds.my.org
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: p1-cr1-s1
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: p1-crb1-s1
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: newnamespace
|
||||||
|
---
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: p1-pv1-s1
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This serie of constants is used to prove the need of
|
||||||
|
// the namespace field in the objref field of the var declaration.
|
||||||
|
// The following tests demonstrate that it creates umbiguous variable
|
||||||
|
// declaration if two entities of the kind with the same name
|
||||||
|
// but in different namespaces are declared.
|
||||||
|
// This is tracking the following issue:
|
||||||
|
// https://github.com/kubernetes-sigs/kustomize/issues/1298
|
||||||
|
const namespaceNeedInVarMyApp string = `
|
||||||
|
resources:
|
||||||
|
- elasticsearch-dev-service.yaml
|
||||||
|
- elasticsearch-test-service.yaml
|
||||||
|
vars:
|
||||||
|
- name: elasticsearch-test-service-name
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: metadata.name
|
||||||
|
- name: elasticsearch-test-protocol
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: spec.ports[0].protocol
|
||||||
|
- name: elasticsearch-dev-service-name
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: metadata.name
|
||||||
|
- name: elasticsearch-dev-protocol
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: spec.ports[0].protocol
|
||||||
|
`
|
||||||
|
|
||||||
|
const namespaceNeedInVarDevResources string = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: dev
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: elasticsearch
|
||||||
|
env:
|
||||||
|
- name: DISCOVERY_SERVICE
|
||||||
|
value: "$(elasticsearch-dev-service-name).monitoring.svc.cluster.local"
|
||||||
|
- name: DISCOVERY_PROTOCOL
|
||||||
|
value: "$(elasticsearch-dev-protocol)"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: dev
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: transport
|
||||||
|
port: 9300
|
||||||
|
protocol: TCP
|
||||||
|
clusterIP: None
|
||||||
|
`
|
||||||
|
|
||||||
|
const namespaceNeedInVarTestResources string = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: test
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: elasticsearch
|
||||||
|
env:
|
||||||
|
- name: DISCOVERY_SERVICE
|
||||||
|
value: "$(elasticsearch-test-service-name).monitoring.svc.cluster.local"
|
||||||
|
- name: DISCOVERY_PROTOCOL
|
||||||
|
value: "$(elasticsearch-test-protocol)"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: test
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: transport
|
||||||
|
port: 9300
|
||||||
|
protocol: UDP
|
||||||
|
clusterIP: None
|
||||||
|
`
|
||||||
|
|
||||||
|
const namespaceNeedInVarExpectedOutput string = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: dev
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
- name: DISCOVERY_SERVICE
|
||||||
|
value: elasticsearch.monitoring.svc.cluster.local
|
||||||
|
- name: DISCOVERY_PROTOCOL
|
||||||
|
value: TCP
|
||||||
|
name: elasticsearch
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: dev
|
||||||
|
spec:
|
||||||
|
clusterIP: None
|
||||||
|
ports:
|
||||||
|
- name: transport
|
||||||
|
port: 9300
|
||||||
|
protocol: TCP
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: test
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
- name: DISCOVERY_SERVICE
|
||||||
|
value: elasticsearch.monitoring.svc.cluster.local
|
||||||
|
- name: DISCOVERY_PROTOCOL
|
||||||
|
value: UDP
|
||||||
|
name: elasticsearch
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: test
|
||||||
|
spec:
|
||||||
|
clusterIP: None
|
||||||
|
ports:
|
||||||
|
- name: transport
|
||||||
|
port: 9300
|
||||||
|
protocol: UDP
|
||||||
|
`
|
||||||
|
|
||||||
|
// TestVariablesAmbiguous demonstrates how two variables pointing at two different resources
|
||||||
|
// using the same name in different namespaces are treated as ambiguous if the namespace is
|
||||||
|
// not specified
|
||||||
|
func TestVariablesAmbiguous(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/namespaceNeedInVar/myapp")
|
||||||
|
th.WriteK("/namespaceNeedInVar/myapp", namespaceNeedInVarMyApp)
|
||||||
|
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
|
||||||
|
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
|
||||||
|
_, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "unable to disambiguate") {
|
||||||
|
t.Fatalf("unexpected error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const namespaceNeedInVarDevFolder string = `
|
||||||
|
resources:
|
||||||
|
- elasticsearch-dev-service.yaml
|
||||||
|
vars:
|
||||||
|
- name: elasticsearch-dev-service-name
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: metadata.name
|
||||||
|
- name: elasticsearch-dev-protocol
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: spec.ports[0].protocol
|
||||||
|
`
|
||||||
|
|
||||||
|
const namespaceNeedInVarTestFolder string = `
|
||||||
|
resources:
|
||||||
|
- elasticsearch-test-service.yaml
|
||||||
|
vars:
|
||||||
|
- name: elasticsearch-test-service-name
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: metadata.name
|
||||||
|
- name: elasticsearch-test-protocol
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: spec.ports[0].protocol
|
||||||
|
`
|
||||||
|
|
||||||
|
// TestVariablesAmbiguousWorkaround demonstrates a possible workaround
|
||||||
|
// to TestVariablesAmbiguous problem. It requires to separate the variables
|
||||||
|
// and resources into multiple kustomization context/folders instead of one.
|
||||||
|
func TestVariablesAmbiguousWorkaround(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/namespaceNeedInVar/workaround")
|
||||||
|
th.WriteK("/namespaceNeedInVar/dev", namespaceNeedInVarDevFolder)
|
||||||
|
th.WriteF("/namespaceNeedInVar/dev/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
|
||||||
|
th.WriteK("/namespaceNeedInVar/test", namespaceNeedInVarTestFolder)
|
||||||
|
th.WriteF("/namespaceNeedInVar/test/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
|
||||||
|
th.WriteK("/namespaceNeedInVar/workaround", `
|
||||||
|
resources:
|
||||||
|
- ../dev
|
||||||
|
- ../test
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
|
||||||
|
}
|
||||||
|
|
||||||
|
const namespaceNeedInVarMyAppWithNamespace string = `
|
||||||
|
resources:
|
||||||
|
- elasticsearch-dev-service.yaml
|
||||||
|
- elasticsearch-test-service.yaml
|
||||||
|
vars:
|
||||||
|
- name: elasticsearch-test-service-name
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: test
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: metadata.name
|
||||||
|
- name: elasticsearch-test-protocol
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: test
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: spec.ports[0].protocol
|
||||||
|
- name: elasticsearch-dev-service-name
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: dev
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: metadata.name
|
||||||
|
- name: elasticsearch-dev-protocol
|
||||||
|
objref:
|
||||||
|
kind: Service
|
||||||
|
name: elasticsearch
|
||||||
|
namespace: dev
|
||||||
|
apiVersion: v1
|
||||||
|
fieldref:
|
||||||
|
fieldpath: spec.ports[0].protocol
|
||||||
|
`
|
||||||
|
|
||||||
|
// TestVariablesDisambiguatedWithNamespace demonstrates that adding the namespace
|
||||||
|
// to the variable declarations allows to disambiguate the variables.
|
||||||
|
func TestVariablesDisambiguatedWithNamespace(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/namespaceNeedInVar/myapp")
|
||||||
|
th.WriteK("/namespaceNeedInVar/myapp", namespaceNeedInVarMyAppWithNamespace)
|
||||||
|
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
|
||||||
|
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNullValues(t *testing.T) {
|
func TestNullValues(t *testing.T) {
|
||||||
@@ -9,21 +9,21 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
|
"sigs.k8s.io/kustomize/api/internal/k8sdeps/transformer"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
. "sigs.k8s.io/kustomize/api/internal/target"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/target"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/validators"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPluginDir(t *testing.T) {
|
func TestPluginDir(t *testing.T) {
|
||||||
tc := plugins_test.NewEnvForTest(t).Set()
|
tc := kusttest_test.NewPluginTestEnv(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
@@ -39,7 +39,7 @@ func TestPluginDir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
fSys := fs.MakeRealFS()
|
fSys := filesys.MakeFsOnDisk()
|
||||||
err = fSys.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(`
|
err = fSys.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(`
|
||||||
generators:
|
generators:
|
||||||
- config.yaml
|
- config.yaml
|
||||||
@@ -57,16 +57,21 @@ metadata:
|
|||||||
t.Fatalf("err %v", err)
|
t.Fatalf("err %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ldr, err := loader.NewLoader(
|
ldr, err := fLdr.NewLoader(
|
||||||
loader.RestrictionRootOnly, validators.MakeFakeValidator(), dir, fSys)
|
fLdr.RestrictionRootOnly, dir, fSys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
rf := resmap.NewFactory(resource.NewFactory(
|
rf := resmap.NewFactory(resource.NewFactory(
|
||||||
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
|
||||||
pl := plugins.NewLoader(plugins.ActivePluginConfig(), rf)
|
c, err := konfig.EnabledPluginConfig()
|
||||||
tg, err := target.NewKustTarget(ldr, rf, transformer.NewFactoryImpl(), pl)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
pl := pLdr.NewLoader(c, rf)
|
||||||
|
tg, err := NewKustTarget(
|
||||||
|
ldr, valtest_test.MakeFakeValidator(), rf, transformer.NewFactoryImpl(), pl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err %v", err)
|
t.Fatalf("err %v", err)
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user