mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 17:41:13 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30b378a924 | ||
|
|
3a843f1eca | ||
|
|
9b40f8ab47 | ||
|
|
dc6dcd8150 | ||
|
|
3cb6c7f1f4 | ||
|
|
7632839bc8 | ||
|
|
c3ea109b59 | ||
|
|
579995dc8a | ||
|
|
b43bd5440d | ||
|
|
c4d899f7f3 | ||
|
|
7998ee7036 | ||
|
|
878960d7b1 | ||
|
|
ed0cfc685b | ||
|
|
b0a7345123 | ||
|
|
580963ea76 | ||
|
|
0707deae95 | ||
|
|
fb44880b8c | ||
|
|
e5ebca6604 | ||
|
|
f5fc9acb84 | ||
|
|
28d1bad3cb | ||
|
|
6f74419628 | ||
|
|
8121467c1e | ||
|
|
a85f297f31 | ||
|
|
76a7816aeb | ||
|
|
7872405379 | ||
|
|
6c17a3409f | ||
|
|
f1dbab9dee | ||
|
|
bfafbbf47f | ||
|
|
08d7c35da7 | ||
|
|
f12704f6c1 | ||
|
|
0edab60b30 | ||
|
|
3c05e2d664 | ||
|
|
095333ffb1 | ||
|
|
0d8d9e2f2b | ||
|
|
120ba6b870 |
@@ -1,6 +1,6 @@
|
|||||||
# kustomize
|
# kustomize
|
||||||
|
|
||||||
_[v3.0.0](https://github.com/kubernetes-sigs/kustomize/releases/tag/v3.0.0) is the latest release._
|
_[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
|
||||||
@@ -24,7 +24,7 @@ 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.15][kubectl].
|
kustomize [v2.0.3] is available in [kubectl v1.14 and v1.15][kubectl].
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
28
docs/FAQ.md
28
docs/FAQ.md
@@ -28,3 +28,31 @@ To disable this, use v3, and the `load_restrictor` flag:
|
|||||||
```
|
```
|
||||||
kustomize build --load_restrictor none $target
|
kustomize build --load_restrictor none $target
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Some field is not transformed by kustomize
|
||||||
|
|
||||||
|
Example: [#1319](https://github.com/kubernetes-sigs/kustomize/issues/1319), [#1322](https://github.com/kubernetes-sigs/kustomize/issues/1322), [#1347](https://github.com/kubernetes-sigs/kustomize/issues/1347) and etc.
|
||||||
|
|
||||||
|
The fields transformed by kustomize is configured explicitly in [defaultconfig](https://github.com/kubernetes-sigs/kustomize/tree/master/pkg/transformers/config/defaultconfig). The configuration itself can be customized by including `configurations` in `kustomization.yaml`, e.g.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
configurations:
|
||||||
|
- kustomizeconfig.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
The configuration directive allows customization of the following transformers:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
commonAnnotations: []
|
||||||
|
commonLabels: []
|
||||||
|
nameprefix: []
|
||||||
|
namespace: []
|
||||||
|
varreference: []
|
||||||
|
namereference: []
|
||||||
|
images: []
|
||||||
|
replicas: []
|
||||||
|
```
|
||||||
|
|
||||||
|
To persist the changes to default configuration, submit a PR like [#1338](https://github.com/kubernetes-sigs/kustomize/pull/1338), [#1348](https://github.com/kubernetes-sigs/kustomize/pull/1348) and etc.
|
||||||
|
|||||||
@@ -5,12 +5,11 @@
|
|||||||
[Go plugin caveats]: goPluginCaveats.md
|
[Go plugin caveats]: goPluginCaveats.md
|
||||||
|
|
||||||
This is a (no reading allowed!) 60 second copy/paste guided
|
This is a (no reading allowed!) 60 second copy/paste guided
|
||||||
example.
|
example.
|
||||||
|
|
||||||
Full plugin docs [here](README.md).
|
Full plugin docs [here](README.md).
|
||||||
Be sure to read the [Go plugin caveats].
|
Be sure to read the [Go plugin caveats].
|
||||||
|
|
||||||
|
|
||||||
This demo uses a Go plugin, `SopsEncodedSecrets`,
|
This demo uses a Go plugin, `SopsEncodedSecrets`,
|
||||||
that lives in the [sopsencodedsecrets repository].
|
that lives in the [sopsencodedsecrets repository].
|
||||||
This is an inprocess [Go plugin], not an
|
This is an inprocess [Go plugin], not an
|
||||||
@@ -22,14 +21,20 @@ current setup.
|
|||||||
|
|
||||||
#### requirements
|
#### requirements
|
||||||
|
|
||||||
* linux, git, curl, Go 1.12
|
* linux, git, curl, Go 1.12
|
||||||
* Google cloud (gcloud) install
|
|
||||||
* a Google account (will use Google kms -
|
For encryption
|
||||||
volunteers needed to convert to a GPG example).
|
|
||||||
|
* gpg
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
* Google cloud (gcloud) install
|
||||||
|
* a Google account with KMS permission
|
||||||
|
|
||||||
## Make a place to work
|
## Make a place to work
|
||||||
|
|
||||||
```
|
```shell
|
||||||
# Keeping these separate to avoid cluttering the DEMO dir.
|
# Keeping these separate to avoid cluttering the DEMO dir.
|
||||||
DEMO=$(mktemp -d)
|
DEMO=$(mktemp -d)
|
||||||
tmpGoPath=$(mktemp -d)
|
tmpGoPath=$(mktemp -d)
|
||||||
@@ -40,7 +45,7 @@ tmpGoPath=$(mktemp -d)
|
|||||||
Need v3.0.0 for what follows, and you must _compile_
|
Need v3.0.0 for what follows, and you must _compile_
|
||||||
it (not download the binary from the release page):
|
it (not download the binary from the release page):
|
||||||
|
|
||||||
```
|
```shell
|
||||||
GOPATH=$tmpGoPath go install sigs.k8s.io/kustomize/v3/cmd/kustomize
|
GOPATH=$tmpGoPath go install sigs.k8s.io/kustomize/v3/cmd/kustomize
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -62,7 +67,7 @@ The kustomize program reads the config file
|
|||||||
kustomization file), then locates the Go plugin's
|
kustomization file), then locates the Go plugin's
|
||||||
object code at the following location:
|
object code at the following location:
|
||||||
|
|
||||||
> ```
|
> ```shell
|
||||||
> $XGD_CONFIG_HOME/kustomize/plugin/$apiVersion/$lKind/$kind.so
|
> $XGD_CONFIG_HOME/kustomize/plugin/$apiVersion/$lKind/$kind.so
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
@@ -82,7 +87,7 @@ left to plugins to find their own config.
|
|||||||
This demo will house the plugin it uses at the
|
This demo will house the plugin it uses at the
|
||||||
ephemeral directory
|
ephemeral directory
|
||||||
|
|
||||||
```
|
```shell
|
||||||
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -105,10 +110,10 @@ to a plugin.
|
|||||||
This demo uses a plugin called _SopsEncodedSecrets_,
|
This demo uses a plugin called _SopsEncodedSecrets_,
|
||||||
and it lives in the [SopsEncodedSecrets repository].
|
and it lives in the [SopsEncodedSecrets repository].
|
||||||
|
|
||||||
Somewhat arbitrarily, we'll chose to install
|
Somewhat arbitrarily, we'll chose to install
|
||||||
this plugin with
|
this plugin with
|
||||||
|
|
||||||
```
|
```shell
|
||||||
apiVersion=mygenerators
|
apiVersion=mygenerators
|
||||||
kind=SopsEncodedSecrets
|
kind=SopsEncodedSecrets
|
||||||
```
|
```
|
||||||
@@ -119,7 +124,7 @@ By convention, the ultimate home of the plugin
|
|||||||
code and supplemental data, tests, documentation,
|
code and supplemental data, tests, documentation,
|
||||||
etc. is the lowercase form of its kind.
|
etc. is the lowercase form of its kind.
|
||||||
|
|
||||||
```
|
```shell
|
||||||
lKind=$(echo $kind | awk '{print tolower($0)}')
|
lKind=$(echo $kind | awk '{print tolower($0)}')
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -129,7 +134,7 @@ In this case, the repo name matches the lowercase
|
|||||||
kind already, so we just clone the repo and get
|
kind already, so we just clone the repo and get
|
||||||
the proper directory name automatically:
|
the proper directory name automatically:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
mkdir -p $PLUGIN_ROOT/${apiVersion}
|
mkdir -p $PLUGIN_ROOT/${apiVersion}
|
||||||
cd $PLUGIN_ROOT/${apiVersion}
|
cd $PLUGIN_ROOT/${apiVersion}
|
||||||
git clone git@github.com:monopole/sopsencodedsecrets.git
|
git clone git@github.com:monopole/sopsencodedsecrets.git
|
||||||
@@ -137,7 +142,7 @@ git clone git@github.com:monopole/sopsencodedsecrets.git
|
|||||||
|
|
||||||
Remember this directory:
|
Remember this directory:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
MY_PLUGIN_DIR=$PLUGIN_ROOT/${apiVersion}/${lKind}
|
MY_PLUGIN_DIR=$PLUGIN_ROOT/${apiVersion}/${lKind}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -146,14 +151,14 @@ MY_PLUGIN_DIR=$PLUGIN_ROOT/${apiVersion}/${lKind}
|
|||||||
Plugins may come with their own tests.
|
Plugins may come with their own tests.
|
||||||
This one does, and it hopefully passes:
|
This one does, and it hopefully passes:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
cd $MY_PLUGIN_DIR
|
cd $MY_PLUGIN_DIR
|
||||||
go test SopsEncodedSecrets_test.go
|
go test SopsEncodedSecrets_test.go
|
||||||
```
|
```
|
||||||
|
|
||||||
Build the object code for use by kustomize:
|
Build the object code for use by kustomize:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
cd $MY_PLUGIN_DIR
|
cd $MY_PLUGIN_DIR
|
||||||
GOPATH=$tmpGoPath go build -buildmode plugin -o ${kind}.so ${kind}.go
|
GOPATH=$tmpGoPath go build -buildmode plugin -o ${kind}.so ${kind}.go
|
||||||
```
|
```
|
||||||
@@ -171,7 +176,7 @@ On load failure
|
|||||||
version of Go (_go1.12_) on the same `$GOOS`
|
version of Go (_go1.12_) on the same `$GOOS`
|
||||||
(_linux_) and `$GOARCH` (_amd64_) used to build
|
(_linux_) and `$GOARCH` (_amd64_) used to build
|
||||||
the kustomize being [used in this demo].
|
the kustomize being [used in this demo].
|
||||||
|
|
||||||
* change the plugin's dependencies in its `go.mod`
|
* change the plugin's dependencies in its `go.mod`
|
||||||
to match the versions used by kustomize (check
|
to match the versions used by kustomize (check
|
||||||
kustomize's `go.mod` used in its tagged commit).
|
kustomize's `go.mod` used in its tagged commit).
|
||||||
@@ -188,11 +193,11 @@ reusable instead of bizarrely woven throughout the
|
|||||||
code as a individual special cases.
|
code as a individual special cases.
|
||||||
|
|
||||||
## Create a kustomization
|
## Create a kustomization
|
||||||
|
|
||||||
Make a kustomization directory to
|
Make a kustomization directory to
|
||||||
hold all your config:
|
hold all your config:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
MYAPP=$DEMO/myapp
|
MYAPP=$DEMO/myapp
|
||||||
mkdir -p $MYAPP
|
mkdir -p $MYAPP
|
||||||
```
|
```
|
||||||
@@ -202,7 +207,7 @@ Make a config file for the SopsEncodedSecrets plugin.
|
|||||||
Its `apiVersion` and `kind` allow the plugin to be
|
Its `apiVersion` and `kind` allow the plugin to be
|
||||||
found:
|
found:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
cat <<EOF >$MYAPP/secGenerator.yaml
|
cat <<EOF >$MYAPP/secGenerator.yaml
|
||||||
apiVersion: ${apiVersion}
|
apiVersion: ${apiVersion}
|
||||||
kind: ${kind}
|
kind: ${kind}
|
||||||
@@ -223,7 +228,7 @@ This plugin expects to find more data in
|
|||||||
Make a kustomization file referencing the plugin
|
Make a kustomization file referencing the plugin
|
||||||
config:
|
config:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
cat <<EOF >$MYAPP/kustomization.yaml
|
cat <<EOF >$MYAPP/kustomization.yaml
|
||||||
commonLabels:
|
commonLabels:
|
||||||
app: hello
|
app: hello
|
||||||
@@ -232,31 +237,46 @@ generators:
|
|||||||
EOF
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
Now for the hard part. Generate the real encrypted data.
|
Now generate the real encrypted data.
|
||||||
|
|
||||||
|
### Assure you have an encryption tool installed
|
||||||
|
|
||||||
### Assure you have a Google Cloud sops key ring.
|
We're going to use [sops](https://github.com/mozilla/sops) to encode a file. Choose either GPG or Google Cloud KMS as the secret provider to continue.
|
||||||
|
|
||||||
We're going to use [sops](https://github.com/mozilla/sops) to encode a file.
|
#### GPG
|
||||||
|
|
||||||
Try this:
|
Try this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
gpg --list-keys
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If it returns a list, presumably you've already created keys. If not, try import test keys from sops for dev.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl https://raw.githubusercontent.com/mozilla/sops/master/pgp/sops_functional_tests_key.asc | gpg --import
|
||||||
|
SOPS_PGP_FP="1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Google Cloude KMS
|
||||||
|
|
||||||
|
Try this:
|
||||||
|
|
||||||
|
```shell
|
||||||
gcloud kms keys list --location global --keyring sops
|
gcloud kms keys list --location global --keyring sops
|
||||||
```
|
```
|
||||||
|
|
||||||
If it succeeds, presumably you've already
|
If it succeeds, presumably you've already created keys and placed them in a keyring called sops. If not, do this:
|
||||||
created keys and placed them in a keyring called `sops`.
|
|
||||||
If not, do this:
|
|
||||||
|
|
||||||
```
|
```shell
|
||||||
gcloud kms keyrings create sops --location global
|
gcloud kms keyrings create sops --location global
|
||||||
gcloud kms keys create sops-key --location global \
|
gcloud kms keys create sops-key --location global \
|
||||||
--keyring sops --purpose encryption
|
--keyring sops --purpose encryption
|
||||||
```
|
```
|
||||||
|
|
||||||
Extract your keyLocation for use below:
|
Extract your keyLocation for use below:
|
||||||
```
|
|
||||||
|
```shell
|
||||||
keyLocation=$(\
|
keyLocation=$(\
|
||||||
gcloud kms keys list --location global --keyring sops |\
|
gcloud kms keys list --location global --keyring sops |\
|
||||||
grep GOOGLE | cut -d " " -f1)
|
grep GOOGLE | cut -d " " -f1)
|
||||||
@@ -265,14 +285,15 @@ echo $keyLocation
|
|||||||
|
|
||||||
### Install `sops`
|
### Install `sops`
|
||||||
|
|
||||||
```
|
```shell
|
||||||
GOPATH=$tmpGoPath go install go.mozilla.org/sops/cmd/sops
|
GOPATH=$tmpGoPath go install go.mozilla.org/sops/cmd/sops
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create data encrypted with your Google Cloud key
|
### Create data encrypted with your private key
|
||||||
|
|
||||||
Create raw data to encrypt:
|
Create raw data to encrypt:
|
||||||
```
|
|
||||||
|
```shell
|
||||||
cat <<EOF >$MYAPP/myClearData.yaml
|
cat <<EOF >$MYAPP/myClearData.yaml
|
||||||
VEGETABLE: carrot
|
VEGETABLE: carrot
|
||||||
ROCKET: saturn-v
|
ROCKET: saturn-v
|
||||||
@@ -283,21 +304,31 @@ EOF
|
|||||||
|
|
||||||
Encrypt the data into file the plugin wants to read:
|
Encrypt the data into file the plugin wants to read:
|
||||||
|
|
||||||
|
With PGP
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$tmpGoPath/bin/sops --encrypt \
|
||||||
|
--pgp $SOPS_PGP_FP \
|
||||||
|
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or GCP KMS
|
||||||
|
|
||||||
|
```shell
|
||||||
$tmpGoPath/bin/sops --encrypt \
|
$tmpGoPath/bin/sops --encrypt \
|
||||||
--gcp-kms $keyLocation \
|
--gcp-kms $keyLocation \
|
||||||
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
|
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Review the files
|
Review the files
|
||||||
```
|
|
||||||
|
```shell
|
||||||
tree $DEMO
|
tree $DEMO
|
||||||
```
|
```
|
||||||
|
|
||||||
This should look something like:
|
This should look something like:
|
||||||
|
|
||||||
> ```
|
> ```shell
|
||||||
> /tmp/tmp.0kIE9VclPt
|
> /tmp/tmp.0kIE9VclPt
|
||||||
> ├── kustomize
|
> ├── kustomize
|
||||||
> │ └── plugin
|
> │ └── plugin
|
||||||
@@ -319,7 +350,7 @@ This should look something like:
|
|||||||
|
|
||||||
## Build your app, using the plugin:
|
## Build your app, using the plugin:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
XDG_CONFIG_HOME=$DEMO $tmpGoPath/bin/kustomize build --enable_alpha_plugins $MYAPP
|
XDG_CONFIG_HOME=$DEMO $tmpGoPath/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -328,10 +359,9 @@ encrypted data for the names `ROCKET` and `CAR`.
|
|||||||
|
|
||||||
Above, if you had set
|
Above, if you had set
|
||||||
|
|
||||||
> ```
|
> ```shell
|
||||||
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
there would be no need to use `XDG_CONFIG_HOME` in the
|
there would be no need to use `XDG_CONFIG_HOME` in the
|
||||||
_kustomize_ command above.
|
_kustomize_ command above.
|
||||||
|
|
||||||
|
|||||||
@@ -232,11 +232,11 @@ moment forward.
|
|||||||
[beta-level rules]: https://github.com/kubernetes/community/blob/master/contributors/devel/api_changes.md#alpha-beta-and-stable-versions
|
[beta-level rules]: https://github.com/kubernetes/community/blob/master/contributors/devel/api_changes.md#alpha-beta-and-stable-versions
|
||||||
[changes]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
|
[changes]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
|
||||||
[adapt]: https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/types/kustomization.go#L166
|
[adapt]: https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/types/kustomization.go#L166
|
||||||
[special]: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#resources
|
[special]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
[k8s API]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
|
[k8s API]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
|
||||||
[conventions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
|
[conventions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
|
||||||
[release process]: ../releasing/README.md
|
[release process]: ../releasing/README.md
|
||||||
[kustomization]: glossary.md#kustomization
|
[kustomization]: glossary.md#kustomization
|
||||||
[`kind`]: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#types-kinds
|
[`kind`]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
[`apiVersion`]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning
|
[`apiVersion`]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning
|
||||||
[semantic versioning]: https://semver.org
|
[semantic versioning]: https://semver.org
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ func (fs *UnstructAdapter) GetGvk() gvk.Gvk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetGvk set the Gvk of the object to the input Gvk
|
||||||
|
func (fs *UnstructAdapter) SetGvk(g gvk.Gvk) {
|
||||||
|
fs.SetGroupVersionKind(toSchemaGvk(g))
|
||||||
|
}
|
||||||
|
|
||||||
// Copy provides a copy behind an interface.
|
// Copy provides a copy behind an interface.
|
||||||
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
|
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
|
||||||
return &UnstructAdapter{*fs.DeepCopy()}
|
return &UnstructAdapter{*fs.DeepCopy()}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ func NewCmdBuildPrune(
|
|||||||
|
|
||||||
func writeIndividualFiles(
|
func writeIndividualFiles(
|
||||||
fSys fs.FileSystem, folderPath string, m resmap.ResMap) error {
|
fSys fs.FileSystem, folderPath string, m resmap.ResMap) error {
|
||||||
byNamespace := m.GroupedByNamespace()
|
byNamespace := m.GroupedByCurrentNamespace()
|
||||||
for namespace, resList := range byNamespace {
|
for namespace, resList := range byNamespace {
|
||||||
for _, res := range resList {
|
for _, res := range resList {
|
||||||
fName := fileName(res)
|
fName := fileName(res)
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ type Kunstructured interface {
|
|||||||
MarshalJSON() ([]byte, error)
|
MarshalJSON() ([]byte, error)
|
||||||
UnmarshalJSON([]byte) error
|
UnmarshalJSON([]byte) error
|
||||||
GetGvk() gvk.Gvk
|
GetGvk() gvk.Gvk
|
||||||
|
SetGvk(gvk.Gvk)
|
||||||
GetKind() string
|
GetKind() string
|
||||||
GetName() string
|
GetName() string
|
||||||
SetName(string)
|
SetName(string)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/v3/internal/loadertest"
|
"sigs.k8s.io/kustomize/v3/internal/loadertest"
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
||||||
. "sigs.k8s.io/kustomize/v3/pkg/plugins"
|
. "sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
)
|
)
|
||||||
@@ -41,7 +42,7 @@ port: "12345"
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLoader(t *testing.T) {
|
func TestLoader(t *testing.T) {
|
||||||
tc := NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package plugins
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -12,13 +12,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EnvForTest manages the plugin test environment.
|
// EnvForTest manages the plugin test environment.
|
||||||
// It sets/resets XDG_CONFIG_HOME, makes/removes a temp objRoot.
|
// It sets/resets XDG_CONFIG_HOME, makes/removes a temp objRoot.
|
||||||
type EnvForTest struct {
|
type EnvForTest struct {
|
||||||
t *testing.T
|
t *testing.T
|
||||||
compiler *Compiler
|
compiler *plugins.Compiler
|
||||||
workDir string
|
workDir string
|
||||||
oldXdg string
|
oldXdg string
|
||||||
wasSet bool
|
wasSet bool
|
||||||
@@ -61,7 +62,7 @@ func (x *EnvForTest) BuildExecPlugin(g, v, k string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *EnvForTest) makeCompiler() *Compiler {
|
func (x *EnvForTest) makeCompiler() *plugins.Compiler {
|
||||||
// The plugin loader wants to find object code under
|
// The plugin loader wants to find object code under
|
||||||
// $XDG_CONFIG_HOME/kustomize/plugins
|
// $XDG_CONFIG_HOME/kustomize/plugins
|
||||||
// and the compiler writes object code to
|
// and the compiler writes object code to
|
||||||
@@ -73,11 +74,11 @@ func (x *EnvForTest) makeCompiler() *Compiler {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
x.t.Error(err)
|
x.t.Error(err)
|
||||||
}
|
}
|
||||||
srcRoot, err := DefaultSrcRoot()
|
srcRoot, err := plugins.DefaultSrcRoot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
x.t.Error(err)
|
x.t.Error(err)
|
||||||
}
|
}
|
||||||
return NewCompiler(srcRoot, objRoot)
|
return plugins.NewCompiler(srcRoot, objRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *EnvForTest) createWorkDir() {
|
func (x *EnvForTest) createWorkDir() {
|
||||||
@@ -112,13 +112,18 @@ type ResMap interface {
|
|||||||
// match.
|
// match.
|
||||||
GetById(resid.ResId) (*resource.Resource, error)
|
GetById(resid.ResId) (*resource.Resource, error)
|
||||||
|
|
||||||
// GroupedByNamespace returns a map of namespace
|
// GroupedByCurrentNamespace returns a map of namespace
|
||||||
// to a slice of *Resource in that namespace.
|
// to a slice of *Resource in that namespace.
|
||||||
// Resources for whom IsNamespaceableKind is false are
|
// Resources for whom IsNamespaceableKind is false are
|
||||||
// are not included at all (see NonNamespaceable).
|
// are not included at all (see NonNamespaceable).
|
||||||
// Resources with an empty namespace are placed
|
// Resources with an empty namespace are placed
|
||||||
// in the resid.DefaultNamespace entry.
|
// in the resid.DefaultNamespace entry.
|
||||||
GroupedByNamespace() map[string][]*resource.Resource
|
GroupedByCurrentNamespace() map[string][]*resource.Resource
|
||||||
|
|
||||||
|
// GroupByOrginalNamespace performs as GroupByNamespace
|
||||||
|
// but use the original namespace instead of the current
|
||||||
|
// one to perform the grouping.
|
||||||
|
GroupedByOriginalNamespace() map[string][]*resource.Resource
|
||||||
|
|
||||||
// NonNamespaceable returns a slice of resources that
|
// NonNamespaceable returns a slice of resources that
|
||||||
// cannot be placed in a namespace, e.g.
|
// cannot be placed in a namespace, e.g.
|
||||||
@@ -390,19 +395,19 @@ func demandOneMatch(
|
|||||||
return nil, fmt.Errorf("no matches for %sId %s", s, id)
|
return nil, fmt.Errorf("no matches for %sId %s", s, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupedByNamespace implements ResMap.GroupByNamespace
|
// GroupedByCurrentNamespace implements ResMap.GroupByCurrentNamespace
|
||||||
func (m *resWrangler) GroupedByNamespace() map[string][]*resource.Resource {
|
func (m *resWrangler) GroupedByCurrentNamespace() map[string][]*resource.Resource {
|
||||||
items := m.groupedByNamespace()
|
items := m.groupedByCurrentNamespace()
|
||||||
delete(items, resid.TotallyNotANamespace)
|
delete(items, resid.TotallyNotANamespace)
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonNamespaceable implements ResMap.NonNamespaceable
|
// NonNamespaceable implements ResMap.NonNamespaceable
|
||||||
func (m *resWrangler) NonNamespaceable() []*resource.Resource {
|
func (m *resWrangler) NonNamespaceable() []*resource.Resource {
|
||||||
return m.groupedByNamespace()[resid.TotallyNotANamespace]
|
return m.groupedByCurrentNamespace()[resid.TotallyNotANamespace]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *resWrangler) groupedByNamespace() map[string][]*resource.Resource {
|
func (m *resWrangler) groupedByCurrentNamespace() map[string][]*resource.Resource {
|
||||||
byNamespace := make(map[string][]*resource.Resource)
|
byNamespace := make(map[string][]*resource.Resource)
|
||||||
for _, res := range m.rList {
|
for _, res := range m.rList {
|
||||||
namespace := res.CurId().EffectiveNamespace()
|
namespace := res.CurId().EffectiveNamespace()
|
||||||
@@ -414,6 +419,25 @@ func (m *resWrangler) groupedByNamespace() map[string][]*resource.Resource {
|
|||||||
return byNamespace
|
return byNamespace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GroupedByNamespace implements ResMap.GroupByOrginalNamespace
|
||||||
|
func (m *resWrangler) GroupedByOriginalNamespace() map[string][]*resource.Resource {
|
||||||
|
items := m.groupedByOriginalNamespace()
|
||||||
|
delete(items, resid.TotallyNotANamespace)
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *resWrangler) groupedByOriginalNamespace() map[string][]*resource.Resource {
|
||||||
|
byNamespace := make(map[string][]*resource.Resource)
|
||||||
|
for _, res := range m.rList {
|
||||||
|
namespace := res.OrgId().EffectiveNamespace()
|
||||||
|
if _, found := byNamespace[namespace]; !found {
|
||||||
|
byNamespace[namespace] = []*resource.Resource{}
|
||||||
|
}
|
||||||
|
byNamespace[namespace] = append(byNamespace[namespace], res)
|
||||||
|
}
|
||||||
|
return byNamespace
|
||||||
|
}
|
||||||
|
|
||||||
// AsYaml implements ResMap.
|
// AsYaml implements ResMap.
|
||||||
func (m *resWrangler) AsYaml() ([]byte, error) {
|
func (m *resWrangler) AsYaml() ([]byte, error) {
|
||||||
firstObj := true
|
firstObj := true
|
||||||
|
|||||||
@@ -62,6 +62,14 @@ func (rm *rmBuilder) AddWithNs(ns string, m map[string]interface{}) *rmBuilder {
|
|||||||
return rm
|
return rm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rm *rmBuilder) AddWithNsAndName(ns string, n string, m map[string]interface{}) *rmBuilder {
|
||||||
|
err := rm.m.Append(rm.rf.FromMapWithNamespaceAndName(ns, n, m))
|
||||||
|
if err != nil {
|
||||||
|
rm.t.Fatalf("test setup failure: %v", err)
|
||||||
|
}
|
||||||
|
return rm
|
||||||
|
}
|
||||||
|
|
||||||
func (rm *rmBuilder) ReplaceResource(m map[string]interface{}) *rmBuilder {
|
func (rm *rmBuilder) ReplaceResource(m map[string]interface{}) *rmBuilder {
|
||||||
r := rm.rf.FromMap(m)
|
r := rm.rf.FromMap(m)
|
||||||
_, err := rm.m.Replace(r)
|
_, err := rm.m.Replace(r)
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ func (rf *Factory) FromMapWithNamespace(n string, m map[string]interface{}) *Res
|
|||||||
return rf.makeOne(rf.kf.FromMap(m), nil).setOriginalNs(n)
|
return rf.makeOne(rf.kf.FromMap(m), nil).setOriginalNs(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromMapWithNamespaceAndName returns a new instance with the given "original" namespace.
|
||||||
|
func (rf *Factory) FromMapWithNamespaceAndName(ns string, n string, m map[string]interface{}) *Resource {
|
||||||
|
return rf.makeOne(rf.kf.FromMap(m), nil).setOriginalNs(ns).setOriginalName(n)
|
||||||
|
}
|
||||||
|
|
||||||
// FromMapAndOption returns a new instance of Resource with given options.
|
// FromMapAndOption returns a new instance of Resource with given options.
|
||||||
func (rf *Factory) FromMapAndOption(
|
func (rf *Factory) FromMapAndOption(
|
||||||
m map[string]interface{}, args *types.GeneratorArgs, option *types.GeneratorOptions) *Resource {
|
m map[string]interface{}, args *types.GeneratorArgs, option *types.GeneratorOptions) *Resource {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func (r *Resource) GetOutermostNameSuffix() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) InSameFuzzyNamespace(o *Resource) bool {
|
func (r *Resource) InSameFuzzyNamespace(o *Resource) bool {
|
||||||
return r.GetNamespace() == o.GetNamespace() &&
|
return r.CurId().IsNsEquals(o.CurId()) &&
|
||||||
r.GetOutermostNamePrefix() == o.GetOutermostNamePrefix() &&
|
r.GetOutermostNamePrefix() == o.GetOutermostNamePrefix() &&
|
||||||
r.GetOutermostNameSuffix() == o.GetOutermostNameSuffix()
|
r.GetOutermostNameSuffix() == o.GetOutermostNameSuffix()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
package target_test
|
package target_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/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,7 +28,7 @@ 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.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const patchAddProbe = `
|
const patchAddProbe = `
|
||||||
@@ -340,7 +340,7 @@ patchesStrategicMerge:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue1251_Plugins_ProdVsDev(t *testing.T) {
|
func TestIssue1251_Plugins_ProdVsDev(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -380,7 +380,7 @@ transformers:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue1251_Plugins_Local(t *testing.T) {
|
func TestIssue1251_Plugins_Local(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -430,7 +430,7 @@ 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.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
1147
pkg/target/extendedpatch_test.go
Normal file
1147
pkg/target/extendedpatch_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,7 @@ func (kt *KustTarget) configureBuiltinTransformers(
|
|||||||
// - patch SMP
|
// - patch SMP
|
||||||
configurators := []transformerConfigurator{
|
configurators := []transformerConfigurator{
|
||||||
kt.configureBuiltinPatchStrategicMergeTransformer,
|
kt.configureBuiltinPatchStrategicMergeTransformer,
|
||||||
|
kt.configureBuiltinPatchTransformer,
|
||||||
kt.configureBuiltinNamespaceTransformer,
|
kt.configureBuiltinNamespaceTransformer,
|
||||||
kt.configureBuiltinNameTransformer,
|
kt.configureBuiltinNameTransformer,
|
||||||
kt.configureBuiltinLabelTransformer,
|
kt.configureBuiltinLabelTransformer,
|
||||||
@@ -170,7 +171,6 @@ func (kt *KustTarget) configureBuiltinPatchStrategicMergeTransformer(
|
|||||||
tConfig *config.TransformerConfig) (
|
tConfig *config.TransformerConfig) (
|
||||||
result []transformers.Transformer, err error) {
|
result []transformers.Transformer, err error) {
|
||||||
if len(kt.kustomization.PatchesStrategicMerge) == 0 {
|
if len(kt.kustomization.PatchesStrategicMerge) == 0 {
|
||||||
result = append(result, transformers.NewNoOpTransformer())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var c struct {
|
var c struct {
|
||||||
@@ -188,6 +188,31 @@ func (kt *KustTarget) configureBuiltinPatchStrategicMergeTransformer(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (kt *KustTarget) configureBuiltinPatchTransformer(
|
||||||
|
tConfig *config.TransformerConfig) (
|
||||||
|
result []transformers.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 _, patch := range kt.kustomization.Patches {
|
||||||
|
c.Target = &patch.Target
|
||||||
|
c.Patch = patch.Patch
|
||||||
|
c.Path = patch.Path
|
||||||
|
p := builtin.NewPatchTransformerPlugin()
|
||||||
|
err = kt.configureBuiltinPlugin(p, c, "patch")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) configureBuiltinLabelTransformer(
|
func (kt *KustTarget) configureBuiltinLabelTransformer(
|
||||||
tConfig *config.TransformerConfig) (
|
tConfig *config.TransformerConfig) (
|
||||||
result []transformers.Transformer, err error) {
|
result []transformers.Transformer, err error) {
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: nginx-persistent-storage
|
- name: nginx-persistent-storage
|
||||||
mountPath: /tmp/ps
|
mountPath: /tmp/ps
|
||||||
|
- name: sidecar
|
||||||
|
image: sidecar:latest
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- name: nginx-persistent-storage
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
@@ -138,8 +140,6 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: ANOTHERENV
|
- name: ANOTHERENV
|
||||||
value: FOO
|
value: FOO
|
||||||
- name: sidecar
|
|
||||||
image: sidecar
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-persistent-storage
|
- name: nginx-persistent-storage
|
||||||
`)
|
`)
|
||||||
@@ -187,7 +187,7 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
- image: sidecar
|
- image: sidecar:latest
|
||||||
name: sidecar
|
name: sidecar
|
||||||
volumes:
|
volumes:
|
||||||
- gcePersistentDisk:
|
- gcePersistentDisk:
|
||||||
@@ -293,3 +293,258 @@ spec:
|
|||||||
t.Fatalf("Unexpected err: %v", err)
|
t.Fatalf("Unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestMultiplePatchesWithPatchDeleteIgnored demonstrates that if the
|
||||||
|
// patch containing the $patch:delete directive is second in the list,
|
||||||
|
// 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
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
env:
|
||||||
|
- name: SOME_NAME
|
||||||
|
value: somevalue
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- $patch: delete
|
||||||
|
name: sidecar
|
||||||
|
`)
|
||||||
|
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
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/ps
|
||||||
|
name: nginx-persistent-storage
|
||||||
|
- image: sidecar:latest
|
||||||
|
name: sidecar
|
||||||
|
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
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMultiplePatchesWithPatchDeleteApplied demonstrates that if the
|
||||||
|
// 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")
|
||||||
|
makeCommonFileForMultiplePatchTest(th)
|
||||||
|
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- $patch: delete
|
||||||
|
name: sidecar
|
||||||
|
`)
|
||||||
|
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", `
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
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
|
||||||
|
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
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package target_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,19 +50,46 @@ resources:
|
|||||||
- role.yaml
|
- role.yaml
|
||||||
`)
|
`)
|
||||||
|
|
||||||
_, err := th.MakeKustTarget().MakeCustomizedResMap()
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
// TODO: Fix #1044
|
// This validates Fix #1444. This should not be an error anymore -
|
||||||
// This should not be an error -
|
|
||||||
// the secrets have the same name but are in different namespaces.
|
// the secrets have the same name but are in different namespaces.
|
||||||
// The ClusterRole (by def) is not in a namespace,
|
// The ClusterRole (by def) is not in a namespace,
|
||||||
// an in this case applies to *any* Secret resource
|
// an in this case applies to *any* Secret resource
|
||||||
// named "dummy"
|
// named "dummy"
|
||||||
if err == nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected lack of error")
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
|
||||||
if !strings.Contains(
|
|
||||||
err.Error(),
|
|
||||||
"slice case - multiple matches for ~G_v1_Secret|default|dummy") {
|
|
||||||
t.Fatalf("unexpected error: %s", 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
|
||||||
|
`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
"sigs.k8s.io/kustomize/v3/pkg/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/target"
|
"sigs.k8s.io/kustomize/v3/pkg/target"
|
||||||
@@ -22,7 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestPluginDir(t *testing.T) {
|
func TestPluginDir(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func writeDeployment(th *kusttest_test.KustTestHarness, path string) {
|
func writeDeployment(th *kusttest_test.KustTestHarness, path string) {
|
||||||
@@ -50,7 +50,7 @@ metadata:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOrderedTransformers(t *testing.T) {
|
func TestOrderedTransformers(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -96,7 +96,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPluginsNotEnabled(t *testing.T) {
|
func TestPluginsNotEnabled(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -119,7 +119,7 @@ transformers:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSedTransformer(t *testing.T) {
|
func TestSedTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
@@ -187,7 +187,7 @@ metadata:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTransformedTransformers(t *testing.T) {
|
func TestTransformedTransformers(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -299,10 +299,10 @@ nameReference:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
version: v1
|
version: v1
|
||||||
fieldSpecs:
|
fieldSpecs:
|
||||||
- path: subjects/name
|
- path: subjects
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
group: rbac.authorization.k8s.io
|
group: rbac.authorization.k8s.io
|
||||||
- path: subjects/name
|
- path: subjects
|
||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
group: rbac.authorization.k8s.io
|
group: rbac.authorization.k8s.io
|
||||||
- path: spec/serviceAccountName
|
- path: spec/serviceAccountName
|
||||||
@@ -343,6 +343,8 @@ nameReference:
|
|||||||
fieldSpecs:
|
fieldSpecs:
|
||||||
- path: spec/volumeName
|
- path: spec/volumeName
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
|
- path: rules/resourceNames
|
||||||
|
kind: ClusterRole
|
||||||
|
|
||||||
- kind: StorageClass
|
- kind: StorageClass
|
||||||
version: v1
|
version: v1
|
||||||
@@ -352,5 +354,7 @@ nameReference:
|
|||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
- path: spec/storageClassName
|
- path: spec/storageClassName
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
|
- path: spec/volumeClaimTemplates/spec/storageClassName
|
||||||
|
kind: StatefulSet
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -106,6 +106,102 @@ func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// selectReferral picks the referral among a subset of candidates.
|
||||||
|
// It returns the current name and namespace of the selected candidate.
|
||||||
|
// Note that the content of the referricalCandidateSubset slice is most of the time
|
||||||
|
// identical to the referralCandidates resmap. Still in some cases, such
|
||||||
|
// as ClusterRoleBinding, the subset only contains the resources of a specific
|
||||||
|
// namespace.
|
||||||
|
func (o *nameReferenceTransformer) selectReferral(
|
||||||
|
oldName string,
|
||||||
|
referrer *resource.Resource,
|
||||||
|
target gvk.Gvk,
|
||||||
|
referralCandidates resmap.ResMap,
|
||||||
|
referralCandidateSubset []*resource.Resource) (interface{}, interface{}, error) {
|
||||||
|
|
||||||
|
for _, res := range referralCandidateSubset {
|
||||||
|
id := res.OrgId()
|
||||||
|
if id.IsSelected(&target) && res.GetOriginalName() == oldName {
|
||||||
|
matches := referralCandidates.GetMatchingResourcesByOriginalId(id.Equals)
|
||||||
|
// If there's more than one match, there's no way
|
||||||
|
// to know which one to pick, so emit error.
|
||||||
|
if len(matches) > 1 {
|
||||||
|
return nil, nil, fmt.Errorf(
|
||||||
|
"multiple matches for %s:\n %v",
|
||||||
|
id, getIds(matches))
|
||||||
|
}
|
||||||
|
// In the resource, note that it is referenced
|
||||||
|
// by the referrer.
|
||||||
|
res.AppendRefBy(referrer.CurId())
|
||||||
|
// Return transformed name of the object,
|
||||||
|
// complete with prefixes, hashes, etc.
|
||||||
|
return res.GetName(), res.GetNamespace(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldName, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// utility function to replace a simple string by the new name
|
||||||
|
func (o *nameReferenceTransformer) getSimpleNameField(
|
||||||
|
oldName string,
|
||||||
|
referrer *resource.Resource,
|
||||||
|
target gvk.Gvk,
|
||||||
|
referralCandidates resmap.ResMap,
|
||||||
|
referralCandidateSubset []*resource.Resource) (interface{}, error) {
|
||||||
|
|
||||||
|
newName, _, err := o.selectReferral(oldName, referrer, target,
|
||||||
|
referralCandidates, referralCandidateSubset)
|
||||||
|
|
||||||
|
return newName, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// utility function to replace name field within a map[string]interface{}
|
||||||
|
// and leverage the namespace field.
|
||||||
|
func (o *nameReferenceTransformer) getNameAndNsStruct(
|
||||||
|
inMap map[string]interface{},
|
||||||
|
referrer *resource.Resource,
|
||||||
|
target gvk.Gvk,
|
||||||
|
referralCandidates resmap.ResMap) (interface{}, error) {
|
||||||
|
|
||||||
|
// Example:
|
||||||
|
if _, ok := inMap["name"]; !ok {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"%#v is expected to contain a name field", inMap)
|
||||||
|
}
|
||||||
|
oldName, ok := inMap["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"%#v is expected to contain a name field of type string", oldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
subset := referralCandidates.Resources()
|
||||||
|
if namespacevalue, ok := inMap["namespace"]; ok {
|
||||||
|
namespace := namespacevalue.(string)
|
||||||
|
bynamespace := referralCandidates.GroupedByOriginalNamespace()
|
||||||
|
if _, ok := bynamespace[namespace]; !ok {
|
||||||
|
return inMap, nil
|
||||||
|
}
|
||||||
|
subset = bynamespace[namespace]
|
||||||
|
}
|
||||||
|
|
||||||
|
newname, newnamespace, err := o.selectReferral(oldName, referrer, target,
|
||||||
|
referralCandidates, subset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
inMap["name"] = newname
|
||||||
|
if newnamespace != "" {
|
||||||
|
// We don't want value "" to replace value "default" since
|
||||||
|
// the empty string is handled as a wild card here not default namespace
|
||||||
|
// by kubernetes.
|
||||||
|
inMap["namespace"] = newnamespace
|
||||||
|
}
|
||||||
|
return inMap, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (o *nameReferenceTransformer) getNewNameFunc(
|
func (o *nameReferenceTransformer) getNewNameFunc(
|
||||||
referrer *resource.Resource,
|
referrer *resource.Resource,
|
||||||
target gvk.Gvk,
|
target gvk.Gvk,
|
||||||
@@ -114,52 +210,40 @@ func (o *nameReferenceTransformer) getNewNameFunc(
|
|||||||
switch in.(type) {
|
switch in.(type) {
|
||||||
case string:
|
case string:
|
||||||
oldName, _ := in.(string)
|
oldName, _ := in.(string)
|
||||||
for _, res := range referralCandidates.Resources() {
|
return o.getSimpleNameField(oldName, referrer, target,
|
||||||
id := res.OrgId()
|
referralCandidates, referralCandidates.Resources())
|
||||||
if id.IsSelected(&target) && res.GetOriginalName() == oldName {
|
|
||||||
matches := referralCandidates.GetMatchingResourcesByOriginalId(id.GvknEquals)
|
|
||||||
// If there's more than one match, there's no way
|
|
||||||
// to know which one to pick, so emit error.
|
|
||||||
if len(matches) > 1 {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"string case - multiple matches for %s:\n %v",
|
|
||||||
id, getIds(matches))
|
|
||||||
}
|
|
||||||
// In the resource, note that it is referenced
|
|
||||||
// by the referrer.
|
|
||||||
res.AppendRefBy(referrer.CurId())
|
|
||||||
// Return transformed name of the object,
|
|
||||||
// complete with prefixes, hashes, etc.
|
|
||||||
return res.GetName(), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return in, nil
|
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
l, _ := in.([]interface{})
|
l, _ := in.([]interface{})
|
||||||
var names []string
|
for idx, item := range l {
|
||||||
for _, item := range l {
|
switch item.(type) {
|
||||||
name, ok := item.(string)
|
case string:
|
||||||
if !ok {
|
// Kind: Role/ClusterRole
|
||||||
|
// FieldSpec is rules.resourceNames
|
||||||
|
oldName, _ := item.(string)
|
||||||
|
newName, err := o.getSimpleNameField(oldName, referrer, target,
|
||||||
|
referralCandidates, referralCandidates.Resources())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l[idx] = newName
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Kind: RoleBinding/ClusterRoleBinding
|
||||||
|
// FieldSpec is subjects
|
||||||
|
// Note: The corresponding fieldSpec had been changed from
|
||||||
|
// from path: subjects/name to just path: subjects. This is
|
||||||
|
// what get mutatefield to request the mapping of the whole
|
||||||
|
// map containing namespace and name instead of just a simple
|
||||||
|
// string field containing the name
|
||||||
|
oldMap, _ := item.(map[string]interface{})
|
||||||
|
newMap, err := o.getNameAndNsStruct(oldMap, referrer, target,
|
||||||
|
referralCandidates)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l[idx] = newMap
|
||||||
|
default:
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"%#v is expected to be %T", item, name)
|
"%#v is expected to be either a []string or a []map[string]interface{}", in)
|
||||||
}
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
for _, res := range referralCandidates.Resources() {
|
|
||||||
indexes := indexOf(res.GetOriginalName(), names)
|
|
||||||
id := res.OrgId()
|
|
||||||
if id.IsSelected(&target) && len(indexes) > 0 {
|
|
||||||
matches := referralCandidates.GetMatchingResourcesByOriginalId(id.GvknEquals)
|
|
||||||
if len(matches) > 1 {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"slice case - multiple matches for %s:\n %v",
|
|
||||||
id, getIds(matches))
|
|
||||||
}
|
|
||||||
for _, index := range indexes {
|
|
||||||
l[index] = res.GetName()
|
|
||||||
}
|
|
||||||
res.AppendRefBy(referrer.CurId())
|
|
||||||
return l, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return in, nil
|
return in, nil
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/resid"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
|
"sigs.k8s.io/kustomize/v3/pkg/resmaptest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
@@ -466,6 +468,7 @@ func TestNameReferenceHappyRun(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
t.Fatalf("actual doesn't match expected: %v", err)
|
||||||
}
|
}
|
||||||
@@ -497,7 +500,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).ResMap(),
|
}).ResMap(),
|
||||||
expectedErr: "is expected to be string"},
|
expectedErr: "is expected to be"},
|
||||||
{
|
{
|
||||||
resMap: resmaptest_test.NewRmBuilder(t, rf).Add(
|
resMap: resmaptest_test.NewRmBuilder(t, rf).Add(
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
@@ -517,7 +520,7 @@ func TestNameReferenceUnhappyRun(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).ResMap(),
|
}).ResMap(),
|
||||||
expectedErr: "is expected to be either a string or a []interface{}"},
|
expectedErr: "is expected to be"},
|
||||||
}
|
}
|
||||||
|
|
||||||
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
||||||
@@ -590,3 +593,431 @@ func TestNameReferencePersistentVolumeHappyRun(t *testing.T) {
|
|||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
t.Fatalf("actual doesn't match expected: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// utility map to create a deployment object
|
||||||
|
// with (metadatanamespace, metadataname) as key
|
||||||
|
// and pointing to "refname" secret and configmap
|
||||||
|
func deploymentMap(metadatanamespace string, metadataname string,
|
||||||
|
configmapref string, secretref string) map[string]interface{} {
|
||||||
|
deployment := map[string]interface{}{
|
||||||
|
"group": "apps",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": metadataname,
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"template": map[string]interface{}{
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"containers": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "nginx",
|
||||||
|
"image": "nginx:1.7.9",
|
||||||
|
"env": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "CM_FOO",
|
||||||
|
"valueFrom": map[string]interface{}{
|
||||||
|
"configMapKeyRef": map[string]interface{}{
|
||||||
|
"name": configmapref,
|
||||||
|
"key": "somekey",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "SECRET_FOO",
|
||||||
|
"valueFrom": map[string]interface{}{
|
||||||
|
"secretKeyRef": map[string]interface{}{
|
||||||
|
"name": secretref,
|
||||||
|
"key": "somekey",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadatanamespace != "" {
|
||||||
|
metadata := deployment["metadata"].(map[string]interface{})
|
||||||
|
metadata["namespace"] = metadatanamespace
|
||||||
|
}
|
||||||
|
return deployment
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultNs = "default"
|
||||||
|
ns1 = "ns1"
|
||||||
|
ns2 = "ns2"
|
||||||
|
ns3 = "ns3"
|
||||||
|
|
||||||
|
orgname = "uniquename"
|
||||||
|
prefixedname = "prefix-uniquename"
|
||||||
|
suffixedname = "uniquename-suffix"
|
||||||
|
modifiedname = "modifiedname"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestNameReferenceNamespace creates serviceAccount and clusterRoleBinding
|
||||||
|
// object with the same original names (uniquename) in different namespaces
|
||||||
|
// and with different current Id.
|
||||||
|
func TestNameReferenceNamespace(t *testing.T) {
|
||||||
|
rf := resource.NewFactory(
|
||||||
|
kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
m := resmaptest_test.NewRmBuilder(t, rf).
|
||||||
|
// Add ConfigMap with the same org name in noNs, "ns1" and "ns2" namespaces
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName(ns1, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": prefixedname,
|
||||||
|
"namespace": ns1,
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName(ns2, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": suffixedname,
|
||||||
|
"namespace": ns2,
|
||||||
|
}}).
|
||||||
|
// Add Secret with the same org name in noNs, "ns1" and "ns2" namespaces
|
||||||
|
AddWithNsAndName(defaultNs, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
"namespace": defaultNs,
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName(ns1, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": prefixedname,
|
||||||
|
"namespace": ns1,
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName(ns2, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": suffixedname,
|
||||||
|
"namespace": ns2,
|
||||||
|
}}).
|
||||||
|
// Add Deployment with the same org name in noNs, "ns1" and "ns2" namespaces
|
||||||
|
AddWithNsAndName(defaultNs, orgname, deploymentMap(defaultNs, modifiedname, modifiedname, modifiedname)).
|
||||||
|
AddWithNsAndName(ns1, orgname, deploymentMap(ns1, prefixedname, orgname, orgname)).
|
||||||
|
AddWithNsAndName(ns2, orgname, deploymentMap(ns2, suffixedname, orgname, orgname)).ResMap()
|
||||||
|
|
||||||
|
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
||||||
|
ReplaceResource(deploymentMap(defaultNs, modifiedname, modifiedname, modifiedname)).
|
||||||
|
ReplaceResource(deploymentMap(ns1, prefixedname, prefixedname, prefixedname)).
|
||||||
|
ReplaceResource(deploymentMap(ns2, suffixedname, suffixedname, suffixedname)).ResMap()
|
||||||
|
|
||||||
|
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
||||||
|
err := nrt.Transform(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
||||||
|
t.Fatalf("actual doesn't match expected: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNameReferenceNamespace creates serviceAccount and clusterRoleBinding
|
||||||
|
// object with the same original names (uniquename) in different namespaces
|
||||||
|
// and with different current Id.
|
||||||
|
func TestNameReferenceClusterWide(t *testing.T) {
|
||||||
|
rf := resource.NewFactory(
|
||||||
|
kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
m := resmaptest_test.NewRmBuilder(t, rf).
|
||||||
|
// Add ServiceAccount with the same org name in noNs, "ns1" and "ns2" namespaces
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName(ns1, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": prefixedname,
|
||||||
|
"namespace": ns1,
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName(ns2, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": suffixedname,
|
||||||
|
"namespace": ns2,
|
||||||
|
}}).
|
||||||
|
// Add a PersistentVolume to have a clusterwide resource
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "PersistentVolume",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
}}).
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
"rules": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"resources": []interface{}{
|
||||||
|
"persistentvolumes",
|
||||||
|
},
|
||||||
|
"resourceNames": []interface{}{
|
||||||
|
orgname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}).
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRoleBinding",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
"roleRef": map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"name": orgname,
|
||||||
|
},
|
||||||
|
"subjects": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": defaultNs,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns1,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns2,
|
||||||
|
},
|
||||||
|
}}).ResMap()
|
||||||
|
|
||||||
|
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
||||||
|
ReplaceResource(
|
||||||
|
map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
// Behavior of the transformer is still imperfect
|
||||||
|
// It should use the (resources,apigroup,resourceNames) as
|
||||||
|
// combination to select the candidates.
|
||||||
|
"rules": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"resources": []interface{}{
|
||||||
|
"persistentvolumes",
|
||||||
|
},
|
||||||
|
"resourceNames": []interface{}{
|
||||||
|
modifiedname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}).
|
||||||
|
ReplaceResource(
|
||||||
|
map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRoleBinding",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
"roleRef": map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
// The following tests required a change in
|
||||||
|
// getNameFunc implementation in order to leverage
|
||||||
|
// the namespace field.
|
||||||
|
"subjects": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": modifiedname,
|
||||||
|
"namespace": defaultNs,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": prefixedname,
|
||||||
|
"namespace": ns1,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": suffixedname,
|
||||||
|
"namespace": ns2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).ResMap()
|
||||||
|
|
||||||
|
clusterRoleId := resid.NewResId(
|
||||||
|
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
||||||
|
clusterRoleBindingId := resid.NewResId(
|
||||||
|
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
||||||
|
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
||||||
|
clusterRole.AppendRefBy(clusterRoleBindingId)
|
||||||
|
|
||||||
|
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
||||||
|
err := nrt.Transform(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
||||||
|
t.Fatalf("actual doesn't match expected: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNameReferenceNamespaceTransformation creates serviceAccount and clusterRoleBinding
|
||||||
|
// object with the same original names (uniquename) in different namespaces
|
||||||
|
// and with different current Id.
|
||||||
|
func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
||||||
|
rf := resource.NewFactory(
|
||||||
|
kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
m := resmaptest_test.NewRmBuilder(t, rf).
|
||||||
|
// Add ServiceAccount with the same org name in "ns1" namespaces
|
||||||
|
AddWithNsAndName(ns1, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": prefixedname,
|
||||||
|
"namespace": ns1,
|
||||||
|
}}).
|
||||||
|
// Simulate NamespaceTransformer effect (ns3 transformed in ns2)
|
||||||
|
AddWithNsAndName(ns3, orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": suffixedname,
|
||||||
|
"namespace": ns2,
|
||||||
|
}}).
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
}}).
|
||||||
|
AddWithName(orgname, map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRoleBinding",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
"roleRef": map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"name": orgname,
|
||||||
|
},
|
||||||
|
"subjects": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns1,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": orgname,
|
||||||
|
"namespace": ns3,
|
||||||
|
},
|
||||||
|
}}).ResMap()
|
||||||
|
|
||||||
|
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
||||||
|
ReplaceResource(
|
||||||
|
map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRoleBinding",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
"roleRef": map[string]interface{}{
|
||||||
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||||
|
"kind": "ClusterRole",
|
||||||
|
"name": modifiedname,
|
||||||
|
},
|
||||||
|
// The following tests required a change in
|
||||||
|
// getNameFunc implementation in order to leverage
|
||||||
|
// the namespace field.
|
||||||
|
"subjects": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": prefixedname,
|
||||||
|
"namespace": ns1,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"kind": "ServiceAccount",
|
||||||
|
"name": suffixedname,
|
||||||
|
"namespace": ns2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).ResMap()
|
||||||
|
|
||||||
|
clusterRoleId := resid.NewResId(
|
||||||
|
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
||||||
|
clusterRoleBindingId := resid.NewResId(
|
||||||
|
gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
||||||
|
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
||||||
|
clusterRole.AppendRefBy(clusterRoleBindingId)
|
||||||
|
|
||||||
|
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
||||||
|
err := nrt.Transform(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
||||||
|
t.Fatalf("actual doesn't match expected: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNameReferenceNamespace creates configmap, secret, deployment
|
||||||
|
// It validates the change done is IsSameFuzzyNamespace which
|
||||||
|
// uses the IsNsEquals method instead of the simple == operator.
|
||||||
|
func TestNameReferenceCandidateSelection(t *testing.T) {
|
||||||
|
rf := resource.NewFactory(
|
||||||
|
kunstruct.NewKunstructuredFactoryImpl())
|
||||||
|
m := resmaptest_test.NewRmBuilder(t, rf).
|
||||||
|
AddWithName("cm1", map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "p1-cm1-hash",
|
||||||
|
}}).
|
||||||
|
AddWithNsAndName("default", "secret1", map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "p1-secret1-hash",
|
||||||
|
"namespace": "default",
|
||||||
|
}}).
|
||||||
|
AddWithName("deploy1", deploymentMap("", "p1-deploy1", "cm1", "secret1")).
|
||||||
|
ResMap()
|
||||||
|
|
||||||
|
expected := resmaptest_test.NewSeededRmBuilder(t, rf, m.ShallowCopy()).
|
||||||
|
ReplaceResource(deploymentMap("", "p1-deploy1", "p1-cm1-hash", "p1-secret1-hash")).
|
||||||
|
ResMap()
|
||||||
|
|
||||||
|
nrt := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
|
||||||
|
err := nrt.Transform(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
||||||
|
t.Fatalf("actual doesn't match expected: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -200,7 +200,6 @@ func (k *Kustomization) EnforceFields() []string {
|
|||||||
// new field names.
|
// new field names.
|
||||||
func FixKustomizationPreUnmarshalling(data []byte) []byte {
|
func FixKustomizationPreUnmarshalling(data []byte) []byte {
|
||||||
deprecateFieldsMap := map[string]string{
|
deprecateFieldsMap := map[string]string{
|
||||||
"patches:": "patchesStrategicMerge:",
|
|
||||||
"imageTags:": "images:",
|
"imageTags:": "images:",
|
||||||
}
|
}
|
||||||
for oldname, newname := range deprecateFieldsMap {
|
for oldname, newname := range deprecateFieldsMap {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ func (p *ImageTagTransformerPlugin) findContainers(obj map[string]interface{}) e
|
|||||||
|
|
||||||
func isImageMatched(s, t string) bool {
|
func isImageMatched(s, t string) bool {
|
||||||
// Tag values are limited to [a-zA-Z0-9_.-].
|
// Tag values are limited to [a-zA-Z0-9_.-].
|
||||||
pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.-]*)?$")
|
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.-]*)?$")
|
||||||
return pattern.MatchString(s)
|
return pattern.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ func split(imageName string) (name string, tag string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i := ic
|
i := ic
|
||||||
if ic < 0 {
|
if ia > 0 {
|
||||||
i = ia
|
i = ia
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
147
plugin/builtin/PatchTransformer.go
Normal file
147
plugin/builtin/PatchTransformer.go
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
// Code generated by pluginator on PatchTransformer; DO NOT EDIT.
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/evanphx/json-patch"
|
||||||
|
"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"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PatchTransformerPlugin struct {
|
||||||
|
ldr ifc.Loader
|
||||||
|
rf *resmap.Factory
|
||||||
|
loadedPatch *resource.Resource
|
||||||
|
decodedPatch jsonpatch.Patch
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection GoUnusedGlobalVariable
|
||||||
|
func NewPatchTransformerPlugin() *PatchTransformerPlugin {
|
||||||
|
return &PatchTransformerPlugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PatchTransformerPlugin) Config(
|
||||||
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
||||||
|
p.ldr = ldr
|
||||||
|
p.rf = rf
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p.Patch == "" && p.Path == "" {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"must specify one of patch and path in\n%s", string(c))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.Patch != "" && p.Path != "" {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"patch and path can't be set at the same time\n%s", string(c))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var in []byte
|
||||||
|
if p.Path != "" {
|
||||||
|
in, err = ldr.Load(p.Path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Patch != "" {
|
||||||
|
in = []byte(p.Patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
patchSM, errSM := p.rf.RF().FromBytes(in)
|
||||||
|
patchJson, errJson := jsonPatchFromBytes(in)
|
||||||
|
if errSM != nil && errJson != nil {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"unable to get either a Strategic Merge Patch or JSON patch 6902 from %s", p.Patch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if errSM == nil && errJson != nil {
|
||||||
|
p.loadedPatch = patchSM
|
||||||
|
}
|
||||||
|
if errJson == nil && errSM != nil {
|
||||||
|
p.decodedPatch = patchJson
|
||||||
|
}
|
||||||
|
if patchSM != nil && patchJson != nil {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"a patch can't be both a Strategic Merge Patch and JSON patch 6902 %s", p.Patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
if p.loadedPatch != nil && p.Target == nil {
|
||||||
|
target, err := m.GetById(p.loadedPatch.OrgId())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = target.Patch(p.loadedPatch.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Target == nil {
|
||||||
|
return fmt.Errorf("must specify a target for patch %s", p.Patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
resources, err := m.Select(*p.Target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, resource := range resources {
|
||||||
|
if p.decodedPatch != nil {
|
||||||
|
rawObj, err := resource.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
modifiedObj, err := p.decodedPatch.Apply(rawObj)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(
|
||||||
|
err, "failed to apply json patch '%s'", p.Patch)
|
||||||
|
}
|
||||||
|
err = resource.UnmarshalJSON(modifiedObj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.loadedPatch != nil {
|
||||||
|
patchCopy := p.loadedPatch.DeepCopy()
|
||||||
|
patchCopy.SetName(resource.GetName())
|
||||||
|
patchCopy.SetNamespace(resource.GetNamespace())
|
||||||
|
patchCopy.SetGvk(resource.GetGvk())
|
||||||
|
err = resource.Patch(patchCopy.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// jsonPatchFromBytes loads a Json 6902 patch from
|
||||||
|
// a bytes input
|
||||||
|
func jsonPatchFromBytes(
|
||||||
|
in []byte) (jsonpatch.Patch, error) {
|
||||||
|
ops := string(in)
|
||||||
|
if ops == "" {
|
||||||
|
return nil, fmt.Errorf("empty json patch operations")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ops[0] != '[' {
|
||||||
|
jsonOps, err := yaml.YAMLToJSON(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ops = string(jsonOps)
|
||||||
|
}
|
||||||
|
return jsonpatch.DecodePatch([]byte(ops))
|
||||||
|
}
|
||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAnnotationsTransformer(t *testing.T) {
|
func TestAnnotationsTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConfigMapGenerator(t *testing.T) {
|
func TestConfigMapGenerator(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHashTransformer(t *testing.T) {
|
func TestHashTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ func (p *plugin) findContainers(obj map[string]interface{}) error {
|
|||||||
|
|
||||||
func isImageMatched(s, t string) bool {
|
func isImageMatched(s, t string) bool {
|
||||||
// Tag values are limited to [a-zA-Z0-9_.-].
|
// Tag values are limited to [a-zA-Z0-9_.-].
|
||||||
pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.-]*)?$")
|
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.-]*)?$")
|
||||||
return pattern.MatchString(s)
|
return pattern.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ func split(imageName string) (name string, tag string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i := ic
|
i := ic
|
||||||
if ic < 0 {
|
if ia > 0 {
|
||||||
i = ia
|
i = ia
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestImageTagTransformer(t *testing.T) {
|
func TestImageTagTransformerNewTag(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -36,18 +36,22 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
initContainers:
|
|
||||||
- name: nginx2
|
|
||||||
image: my-nginx:1.8.0
|
|
||||||
- name: init-alpine
|
|
||||||
image: alpine:1.8.0
|
|
||||||
containers:
|
containers:
|
||||||
- name: ngnix
|
- image: nginx:1.7.9
|
||||||
image: nginx:1.7.9
|
name: nginx-tagged
|
||||||
- name: repliaced-with-digest
|
- image: nginx:latest
|
||||||
image: foobar:1
|
name: nginx-latest
|
||||||
- name: postgresdb
|
- image: foobar:1
|
||||||
image: postgres:1.8.0
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx-notag
|
||||||
|
- image: nginx@sha256:111111111111111111
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
`)
|
`)
|
||||||
|
|
||||||
th.AssertActualEqualsExpected(rm, `
|
th.AssertActualEqualsExpected(rm, `
|
||||||
@@ -61,14 +65,307 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: nginx:v2
|
- image: nginx:v2
|
||||||
name: ngnix
|
name: nginx-tagged
|
||||||
|
- image: nginx:v2
|
||||||
|
name: nginx-latest
|
||||||
- image: foobar:1
|
- image: foobar:1
|
||||||
name: repliaced-with-digest
|
name: replaced-with-digest
|
||||||
- image: postgres:1.8.0
|
- image: postgres:1.8.0
|
||||||
name: postgresdb
|
name: postgresdb
|
||||||
initContainers:
|
initContainers:
|
||||||
- image: my-nginx:1.8.0
|
- image: nginx:v2
|
||||||
name: nginx2
|
name: nginx-notag
|
||||||
|
- image: nginx:v2
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
func TestImageTagTransformerNewImage(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "ImageTagTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: ImageTagTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
imageTag:
|
||||||
|
name: nginx
|
||||||
|
newName: busybox
|
||||||
|
`, `
|
||||||
|
group: apps
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx-notag
|
||||||
|
- image: nginx@sha256:111111111111111111
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: v1
|
||||||
|
group: apps
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: busybox:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: busybox:latest
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: busybox
|
||||||
|
name: nginx-notag
|
||||||
|
- image: busybox@sha256:111111111111111111
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImageTagTransformerNewImageAndTag(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "ImageTagTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: ImageTagTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
imageTag:
|
||||||
|
name: nginx
|
||||||
|
newName: busybox
|
||||||
|
newTag: v2
|
||||||
|
`, `
|
||||||
|
group: apps
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx-notag
|
||||||
|
- image: nginx@sha256:111111111111111111
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: v1
|
||||||
|
group: apps
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: busybox:v2
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: busybox:v2
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: busybox:v2
|
||||||
|
name: nginx-notag
|
||||||
|
- image: busybox:v2
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImageTagTransformerNewDigest(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "ImageTagTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: ImageTagTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
imageTag:
|
||||||
|
name: nginx
|
||||||
|
Digest: sha256:222222222222222222
|
||||||
|
`, `
|
||||||
|
group: apps
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx-notag
|
||||||
|
- image: nginx@sha256:111111111111111111
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: v1
|
||||||
|
group: apps
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx@sha256:222222222222222222
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: nginx@sha256:222222222222222222
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: nginx@sha256:222222222222222222
|
||||||
|
name: nginx-notag
|
||||||
|
- image: nginx@sha256:222222222222222222
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImageTagTransformerNewImageAndDigest(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "ImageTagTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: ImageTagTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
imageTag:
|
||||||
|
name: nginx
|
||||||
|
newName: busybox
|
||||||
|
Digest: sha256:222222222222222222
|
||||||
|
`, `
|
||||||
|
group: apps
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx-notag
|
||||||
|
- image: nginx@sha256:111111111111111111
|
||||||
|
name: nginx-sha256
|
||||||
|
- image: alpine:1.8.0
|
||||||
|
name: init-alpine
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: v1
|
||||||
|
group: apps
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: busybox@sha256:222222222222222222
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: busybox@sha256:222222222222222222
|
||||||
|
name: nginx-latest
|
||||||
|
- image: foobar:1
|
||||||
|
name: replaced-with-digest
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
initContainers:
|
||||||
|
- image: busybox@sha256:222222222222222222
|
||||||
|
name: nginx-notag
|
||||||
|
- image: busybox@sha256:222222222222222222
|
||||||
|
name: nginx-sha256
|
||||||
- image: alpine:1.8.0
|
- image: alpine:1.8.0
|
||||||
name: init-alpine
|
name: init-alpine
|
||||||
`)
|
`)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ package main_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -59,7 +59,7 @@ metadata:
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestInventoryTransformerCollect(t *testing.T) {
|
func TestInventoryTransformerCollect(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -80,7 +80,7 @@ policy: GarbageCollect
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInventoryTransformerIgnore(t *testing.T) {
|
func TestInventoryTransformerIgnore(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -101,7 +101,7 @@ policy: GarbageIgnore
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInventoryTransformerDefaultPolicy(t *testing.T) {
|
func TestInventoryTransformerDefaultPolicy(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLabelTransformer(t *testing.T) {
|
func TestLabelTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLegacyOrderTransformer(t *testing.T) {
|
func TestLegacyOrderTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNamespaceTransformer1(t *testing.T) {
|
func TestNamespaceTransformer1(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -174,7 +174,7 @@ metadata:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNamespaceTransformerClusterLevelKinds(t *testing.T) {
|
func TestNamespaceTransformerClusterLevelKinds(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const target = `
|
const target = `
|
||||||
@@ -29,7 +29,7 @@ spec:
|
|||||||
`
|
`
|
||||||
|
|
||||||
func TestPatchJson6902TransformerMissingFile(t *testing.T) {
|
func TestPatchJson6902TransformerMissingFile(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -58,7 +58,7 @@ path: jsonpatch.json
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBadPatchJson6902Transformer(t *testing.T) {
|
func TestBadPatchJson6902Transformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -87,7 +87,7 @@ jsonOp: 'thisIsNotAPatch'
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBothEmptyJson6902Transformer(t *testing.T) {
|
func TestBothEmptyJson6902Transformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -115,7 +115,7 @@ target:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBothSpecifiedJson6902Transformer(t *testing.T) {
|
func TestBothSpecifiedJson6902Transformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -151,7 +151,7 @@ jsonOp: '[{"op": "add", "path": "/spec/template/spec/dnsPolicy", "value": "Clust
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPatchJson6902TransformerFromJsonFile(t *testing.T) {
|
func TestPatchJson6902TransformerFromJsonFile(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -201,7 +201,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPatchJson6902TransformerFromYamlFile(t *testing.T) {
|
func TestPatchJson6902TransformerFromYamlFile(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -251,7 +251,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPatchJson6902TransformerWithInline(t *testing.T) {
|
func TestPatchJson6902TransformerWithInline(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -58,7 +58,7 @@ spec:
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestPatchStrategicMergeTransformerMissingFile(t *testing.T) {
|
func TestPatchStrategicMergeTransformerMissingFile(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -83,7 +83,7 @@ paths:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBadPatchStrategicMergeTransformer(t *testing.T) {
|
func TestBadPatchStrategicMergeTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -108,7 +108,7 @@ patches: 'thisIsNotAPatch'
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBothEmptyPatchStrategicMergeTransformer(t *testing.T) {
|
func TestBothEmptyPatchStrategicMergeTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -131,7 +131,7 @@ metadata:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPatchStrategicMergeTransformerFromFiles(t *testing.T) {
|
func TestPatchStrategicMergeTransformerFromFiles(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -181,7 +181,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPatchStrategicMergeTransformerWithInline(t *testing.T) {
|
func TestPatchStrategicMergeTransformerWithInline(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -216,7 +216,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPatchStrategicMergeTransformerMultiplePatches(t *testing.T) {
|
func TestPatchStrategicMergeTransformerMultiplePatches(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -293,7 +293,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStrategicMergeTransformerMultiplePatchesWithConflicts(t *testing.T) {
|
func TestStrategicMergeTransformerMultiplePatchesWithConflicts(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -354,7 +354,7 @@ paths:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStrategicMergeTransformerWrongNamespace(t *testing.T) {
|
func TestStrategicMergeTransformerWrongNamespace(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -397,7 +397,7 @@ paths:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStrategicMergeTransformerNoSchema(t *testing.T) {
|
func TestStrategicMergeTransformerNoSchema(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -437,7 +437,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStrategicMergeTransformerNoSchemaMultiPatches(t *testing.T) {
|
func TestStrategicMergeTransformerNoSchemaMultiPatches(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
@@ -493,7 +493,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStrategicMergeTransformerNoSchemaMultiPatchesWithConflict(t *testing.T) {
|
func TestStrategicMergeTransformerNoSchemaMultiPatchesWithConflict(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
148
plugin/builtin/patchtransformer/PatchTransformer.go
Normal file
148
plugin/builtin/patchtransformer/PatchTransformer.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
//go:generate go run sigs.k8s.io/kustomize/v3/cmd/pluginator
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/evanphx/json-patch"
|
||||||
|
"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"
|
||||||
|
"sigs.k8s.io/kustomize/v3/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type plugin struct {
|
||||||
|
ldr ifc.Loader
|
||||||
|
rf *resmap.Factory
|
||||||
|
loadedPatch *resource.Resource
|
||||||
|
decodedPatch jsonpatch.Patch
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection GoUnusedGlobalVariable
|
||||||
|
var KustomizePlugin plugin
|
||||||
|
|
||||||
|
func (p *plugin) Config(
|
||||||
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
||||||
|
p.ldr = ldr
|
||||||
|
p.rf = rf
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p.Patch == "" && p.Path == "" {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"must specify one of patch and path in\n%s", string(c))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.Patch != "" && p.Path != "" {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"patch and path can't be set at the same time\n%s", string(c))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var in []byte
|
||||||
|
if p.Path != "" {
|
||||||
|
in, err = ldr.Load(p.Path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Patch != "" {
|
||||||
|
in = []byte(p.Patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
patchSM, errSM := p.rf.RF().FromBytes(in)
|
||||||
|
patchJson, errJson := jsonPatchFromBytes(in)
|
||||||
|
if errSM != nil && errJson != nil {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"unable to get either a Strategic Merge Patch or JSON patch 6902 from %s", p.Patch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if errSM == nil && errJson != nil {
|
||||||
|
p.loadedPatch = patchSM
|
||||||
|
}
|
||||||
|
if errJson == nil && errSM != nil {
|
||||||
|
p.decodedPatch = patchJson
|
||||||
|
}
|
||||||
|
if patchSM != nil && patchJson != nil {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"a patch can't be both a Strategic Merge Patch and JSON patch 6902 %s", p.Patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plugin) Transform(m resmap.ResMap) error {
|
||||||
|
if p.loadedPatch != nil && p.Target == nil {
|
||||||
|
target, err := m.GetById(p.loadedPatch.OrgId())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = target.Patch(p.loadedPatch.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Target == nil {
|
||||||
|
return fmt.Errorf("must specify a target for patch %s", p.Patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
resources, err := m.Select(*p.Target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, resource := range resources {
|
||||||
|
if p.decodedPatch != nil {
|
||||||
|
rawObj, err := resource.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
modifiedObj, err := p.decodedPatch.Apply(rawObj)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(
|
||||||
|
err, "failed to apply json patch '%s'", p.Patch)
|
||||||
|
}
|
||||||
|
err = resource.UnmarshalJSON(modifiedObj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.loadedPatch != nil {
|
||||||
|
patchCopy := p.loadedPatch.DeepCopy()
|
||||||
|
patchCopy.SetName(resource.GetName())
|
||||||
|
patchCopy.SetNamespace(resource.GetNamespace())
|
||||||
|
patchCopy.SetGvk(resource.GetGvk())
|
||||||
|
err = resource.Patch(patchCopy.Kunstructured)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// jsonPatchFromBytes loads a Json 6902 patch from
|
||||||
|
// a bytes input
|
||||||
|
func jsonPatchFromBytes(
|
||||||
|
in []byte) (jsonpatch.Patch, error) {
|
||||||
|
ops := string(in)
|
||||||
|
if ops == "" {
|
||||||
|
return nil, fmt.Errorf("empty json patch operations")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ops[0] != '[' {
|
||||||
|
jsonOps, err := yaml.YAMLToJSON(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ops = string(jsonOps)
|
||||||
|
}
|
||||||
|
return jsonpatch.DecodePatch([]byte(ops))
|
||||||
|
}
|
||||||
341
plugin/builtin/patchtransformer/PatchTransformer_test.go
Normal file
341
plugin/builtin/patchtransformer/PatchTransformer_test.go
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
target = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
replica: 2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: yourDeploy
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
kind: Deployment
|
||||||
|
spec:
|
||||||
|
replica: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.7.9
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
label:
|
||||||
|
old-label: old-value
|
||||||
|
kind: MyKind
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPatchTransformerMissingFile(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
path: patch.yaml
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(),
|
||||||
|
"cannot read file \"/app/patch.yaml\"") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchTransformerBadPatch(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
patch: "thisIsNotAPatch"
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(),
|
||||||
|
"unable to get either a Strategic Merge Patch or JSON patch 6902 from") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchTransformerMissingSelector(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
patch: '[{"op": "add", "path": "/spec/template/spec/dnsPolicy", "value": "ClusterFirst"}]'
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(),
|
||||||
|
"must specify a target for patch") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchTransformerBothEmptyPathAndPatch(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "must specify one of patch and path in") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchTransformerBothNonEmptyPathAndPatch(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
_, err := th.RunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
Path: patch.yaml
|
||||||
|
Patch: "something"
|
||||||
|
`, target)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "patch and path can't be set at the same time") {
|
||||||
|
t.Fatalf("unexpected err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchTransformerFromFiles(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
th.WriteF("/app/patch.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 3
|
||||||
|
`)
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
path: patch.yaml
|
||||||
|
target:
|
||||||
|
name: .*Deploy
|
||||||
|
`, target)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 3
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
name: yourDeploy
|
||||||
|
spec:
|
||||||
|
replica: 3
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: MyKind
|
||||||
|
metadata:
|
||||||
|
label:
|
||||||
|
old-label: old-value
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 3
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPatchTransformerWithInline(t *testing.T) {
|
||||||
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "PatchTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
patch: '[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "nginx:latest"}]'
|
||||||
|
target:
|
||||||
|
name: .*Deploy
|
||||||
|
kind: Deployment
|
||||||
|
`, target)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
replica: 2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
name: yourDeploy
|
||||||
|
spec:
|
||||||
|
replica: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
new-label: new-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:latest
|
||||||
|
name: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: MyKind
|
||||||
|
metadata:
|
||||||
|
label:
|
||||||
|
old-label: old-value
|
||||||
|
name: myDeploy
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
old-label: old-value
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPrefixSuffixTransformer(t *testing.T) {
|
func TestPrefixSuffixTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReplicaCountTransformer(t *testing.T) {
|
func TestReplicaCountTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSecretGenerator(t *testing.T) {
|
func TestSecretGenerator(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBashedConfigMapPlugin(t *testing.T) {
|
func TestBashedConfigMapPlugin(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This test requires having the helm binary on the PATH.
|
// This test requires having the helm binary on the PATH.
|
||||||
@@ -19,7 +19,7 @@ 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 TestChartInflator(t *testing.T) {
|
func TestChartInflator(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDatePrefixerPlugin(t *testing.T) {
|
func TestDatePrefixerPlugin(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func shouldContain(t *testing.T, s []byte, x string) {
|
func shouldContain(t *testing.T, s []byte, x string) {
|
||||||
@@ -18,7 +18,7 @@ func shouldContain(t *testing.T, s []byte, x string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPrintWorkDirPlugin(t *testing.T) {
|
func TestPrintWorkDirPlugin(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin(
|
tc.BuildExecPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSecretsFromDatabasePlugin(t *testing.T) {
|
func TestSecretsFromDatabasePlugin(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSedTransformer(t *testing.T) {
|
func TestSedTransformer(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin("someteam.example.com", "v1", "SedTransformer")
|
tc.BuildExecPlugin("someteam.example.com", "v1", "SedTransformer")
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSomeServiceGeneratorPlugin(t *testing.T) {
|
func TestSomeServiceGeneratorPlugin(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStringPrefixerPlugin(t *testing.T) {
|
func TestStringPrefixerPlugin(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildGoPlugin(
|
tc.BuildGoPlugin(
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
"sigs.k8s.io/kustomize/v3/pkg/kusttest"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
plugins_test "sigs.k8s.io/kustomize/v3/pkg/plugins/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidatorHappy(t *testing.T) {
|
func TestValidatorHappy(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin("someteam.example.com", "v1", "Validator")
|
tc.BuildExecPlugin("someteam.example.com", "v1", "Validator")
|
||||||
@@ -49,7 +49,7 @@ metadata:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidatorUnHappy(t *testing.T) {
|
func TestValidatorUnHappy(t *testing.T) {
|
||||||
tc := plugins.NewEnvForTest(t).Set()
|
tc := plugins_test.NewEnvForTest(t).Set()
|
||||||
defer tc.Reset()
|
defer tc.Reset()
|
||||||
|
|
||||||
tc.BuildExecPlugin("someteam.example.com", "v1", "Validator")
|
tc.BuildExecPlugin("someteam.example.com", "v1", "Validator")
|
||||||
|
|||||||
Reference in New Issue
Block a user