Compare commits

...

56 Commits

Author SHA1 Message Date
k8s-ci-robot
58492e2d83 Merge pull request #349 from Liujingfang1/master
fix the release and build files
2018-09-13 12:00:36 -07:00
Jingfang Liu
a9f44aa259 fix the release and build files 2018-09-13 11:51:47 -07:00
k8s-ci-robot
b17d7fbbfd Merge pull request #339 from lswith/master
treat sub paths correctly
2018-09-13 09:24:09 -07:00
Luke Swithenbank
d78e77fb92 fix remote build's for subdirectories 2018-09-13 09:56:04 +10:00
Jingfang Liu
64fdb8d760 change github.com/kubernetes-sigs to sigs.k8s.io (#343)
* change github.com/kubernetes-sigs to sigs.k8s.io

* change go_import_path in .travis.yml
2018-09-12 12:41:38 -07:00
Jeff Regan
a377ec1dde Merge pull request #342 from Liujingfang1/master
remove dependency on internal error
2018-09-12 11:08:52 -07:00
Jingfang Liu
87e9964091 Merge pull request #341 from ebriand/patch-1
Fix typo in multibases readme
2018-09-12 09:17:21 -07:00
Jingfang Liu
60d8334fed remove dependency on internal error 2018-09-11 15:23:30 -07:00
Eric Briand
71f5105a86 Fix typo on staging 2018-09-11 13:33:28 +02:00
Jeff Regan
09a62efe88 Merge pull request #331 from burdiyan/master
Implement support for digests in imageTags
2018-09-10 10:57:53 -07:00
Alexandr Burdiyan
6dbf4b5b60 Apply code review recommendations 2018-09-10 11:48:47 +02:00
Alexandr Burdiyan
5401bd367b Implement support for digests in imageTags
This commit adds a new field to imageTags transformer
so that digests can be used instead of image tags if needed.

Closes https://github.com/kubernetes-sigs/kustomize/issues/326
2018-09-10 11:21:53 +02:00
Jeff Regan
f7def79764 Merge pull request #333 from monopole/deleteCode
Remove duplicate code.
2018-09-09 13:51:54 -07:00
jregan
cda909a609 Remove duplicate code. 2018-09-09 12:33:23 -07:00
k8s-ci-robot
6f61cadf9f Merge pull request #325 from Liujingfang1/master
Add examples and docs for patchesJson6902
2018-09-07 13:14:34 -07:00
Jingfang Liu
1c616b1962 Add examples and docs for patchesJson6902 2018-09-07 11:55:12 -07:00
Jeff Regan
849343fb41 Merge pull request #324 from Liujingfang1/master
Enable jsonpath transformers in application
2018-09-06 14:18:47 -07:00
Jingfang Liu
8810027d89 Enable jsonpath transformers in application 2018-09-06 14:02:30 -07:00
k8s-ci-robot
548ea8a9fb Merge pull request #323 from Liujingfang1/master
remove inline json patch format
2018-09-06 13:36:19 -07:00
Jingfang Liu
81b5cf65d6 remove inline json patch format 2018-09-06 11:18:19 -07:00
Jeff Regan
dc9ae64646 Merge pull request #321 from Liujingfang1/multibases
filter by namespace, prefix and detect conflict when resolving name reference
2018-09-05 16:10:53 -07:00
Jingfang Liu
829cb2baa3 address comments 2018-09-05 16:08:24 -07:00
Jingfang Liu
7b301446fa filter by namespace and nameprefix in namereference transformer 2018-09-05 13:17:44 -07:00
Jingfang Liu
4a297fa138 improve idslice 2018-09-05 13:02:51 -07:00
Jingfang Liu
7811d9f2bc Add multibases test with namereference conflict 2018-09-05 13:01:56 -07:00
Jingfang Liu
21ff81b758 Add multibases test with namereference nonconflict 2018-09-05 13:01:15 -07:00
Jingfang Liu
485bbddd3e Merge pull request #320 from Liujingfang1/master
remove go get varcheck
2018-09-04 15:43:59 -07:00
Jingfang Liu
6dc80293a6 remove go get varcheck 2018-09-04 15:07:38 -07:00
Jeff Regan
b649ad5c69 Merge pull request #310 from Liujingfang1/patchtransformer
Update patch factory and add multi transformer with checking conflicts
2018-09-04 09:32:08 -07:00
Jingfang Liu
d782abb214 Update patch factory and add multi transformer with checking conflicts 2018-09-04 09:13:26 -07:00
k8s-ci-robot
95f5becee1 Merge pull request #312 from monopole/fixSomeImports
Remove some unnecessary import renames.
2018-09-04 08:31:31 -07:00
k8s-ci-robot
694d809f33 Merge pull request #313 from monopole/fixMarkdownLinks
Fix some busted documentation links.
2018-08-31 18:30:41 -07:00
k8s-ci-robot
df3c3c3357 Merge pull request #314 from monopole/noCleanup
Remove unread variable.
2018-08-31 18:29:25 -07:00
Jeffrey Regan
99e770b05a Remove unused variable. 2018-08-31 17:25:00 -07:00
Jeffrey Regan
340cb2b385 Remove unnecessary import aliases. 2018-08-31 17:20:03 -07:00
Jeffrey Regan
cdbd83a645 Fix some busted documentation links. 2018-08-31 17:05:32 -07:00
Jeff Regan
fab2a5a5d7 Merge pull request #311 from monopole/updateDeps
Add gopkg.in/yaml.v2 to Gopkg.lock
2018-08-31 16:24:16 -07:00
Jeffrey Regan
8da2f37181 Add gopkg.in/yaml.v2 to Gopkg.lock 2018-08-31 16:20:18 -07:00
k8s-ci-robot
c906a0c16e Merge pull request #309 from monopole/cleanupAddLabels
Simplify addmetadata.
2018-08-31 16:13:31 -07:00
Jeffrey Regan
93618166b6 Cleanup addmetadata. 2018-08-31 15:58:36 -07:00
k8s-ci-robot
babfb3faa9 Merge pull request #300 from Liujingfang1/patchtransformer
Add transformer to apply json patch6902
2018-08-31 12:07:17 -07:00
Jingfang Liu
cedf215445 add PatchJson6902Factory to make transformer 2018-08-31 10:21:58 -07:00
Jeff Regan
51a4907f89 Merge pull request #307 from khrisrichardson/apimachinery-validation
use apimachinery for annotation/label validation
2018-08-31 09:42:47 -07:00
Khris Richardson
6457162383 use apimachinery for annotation/label validation 2018-08-31 07:40:00 -07:00
Jingfang Liu
7f0e9e3a6a Add patchJson6902 transformer 2018-08-30 15:34:42 -07:00
Jingfang Liu
95cf508b2b Add github.com/krishicks/yaml-patch to vendor 2018-08-30 13:45:25 -07:00
Jeff Regan
4a565ffdb8 Merge pull request #303 from gitirabassi/all-git-repos
if the prefix of the base is 'git::' will make the use of go-getter to download repo
2018-08-30 10:06:46 -07:00
Jeff Regan
17f1779a48 Merge pull request #302 from gitirabassi/storageClassSecret
Storage class secret
2018-08-30 10:03:03 -07:00
gitirabassi
a76cb0b008 force using the git protocol to downlaod every kind of repo non just from github 2018-08-30 11:02:03 +02:00
gitirabassi
9700bc3298 added all the documented secret for storageclasses 2018-08-29 23:05:40 +02:00
gitirabassi
ce31dac24f added storageclass paramether secret for glusterfs configuration with kustomize 2018-08-29 22:55:32 +02:00
k8s-ci-robot
a81b2e32e0 Merge pull request #299 from Liujingfang1/patch
change patches to patchesStrategicMerge in tests and examples
2018-08-28 13:57:00 -07:00
Jingfang Liu
b713d5a1cc change patches to patchesStrategicMerge in tests and examples 2018-08-28 09:40:34 -07:00
k8s-ci-robot
e11ba17248 Merge pull request #286 from Liujingfang1/master
Add patchesJson6902 and patchesStategicMerge to kustomization
2018-08-27 16:09:49 -07:00
Jingfang Liu
3d9d4bd36f address comments 2018-08-27 15:44:42 -07:00
Jingfang Liu
6a3e3c3a71 Add JSONPatch to kustomization 2018-08-27 13:52:21 -07:00
147 changed files with 3864 additions and 570 deletions

View File

@@ -3,12 +3,11 @@ language: go
go:
- 1.10.x
# go_import_path: k8s.io/kubectl
go_import_path: sigs.k8s.io/kustomize
before_install:
- source ./bin/consider-early-travis-exit.sh
- sudo apt-get install tree
- go get -u github.com/opennota/check/cmd/varcheck
- go get -u github.com/golang/lint/golint
- go get -u golang.org/x/tools/cmd/goimports
- go get -u github.com/onsi/ginkgo/ginkgo

18
Gopkg.lock generated
View File

@@ -251,6 +251,14 @@
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
version = "1.1.3"
[[projects]]
digest = "1:10e1dfc240bcd0fce14366215fd2b070e79d9b9460b27382db4423ad74204f2b"
name = "github.com/krishicks/yaml-patch"
packages = ["."]
pruneopts = ""
revision = "83cc9ac50becbbfafb86a89167f3bc5372e8e530"
version = "v0.0.10"
[[projects]]
branch = "master"
digest = "1:d9e483f4b9e306facf126bd90b02d512bd22ea4471e1568867e32221a8abbb16"
@@ -427,9 +435,14 @@
digest = "1:bcb2285bb525712de7903a5d254c2789df65c8b58d2cfac5a26d950ad94c2079"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/equality",
"pkg/api/meta",
"pkg/api/resource",
"pkg/api/validation",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
"pkg/apis/meta/v1/validation",
"pkg/apis/meta/v1beta1",
"pkg/conversion",
"pkg/conversion/queryparams",
"pkg/fields",
@@ -490,17 +503,22 @@
"github.com/ghodss/yaml",
"github.com/golang/glog",
"github.com/hashicorp/go-getter",
"github.com/krishicks/yaml-patch",
"github.com/pkg/errors",
"github.com/spf13/cobra",
"gopkg.in/yaml.v2",
"k8s.io/api/core/v1",
"k8s.io/apimachinery/pkg/api/validation",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"k8s.io/apimachinery/pkg/apis/meta/v1/validation",
"k8s.io/apimachinery/pkg/runtime",
"k8s.io/apimachinery/pkg/runtime/schema",
"k8s.io/apimachinery/pkg/util/mergepatch",
"k8s.io/apimachinery/pkg/util/sets",
"k8s.io/apimachinery/pkg/util/strategicpatch",
"k8s.io/apimachinery/pkg/util/validation",
"k8s.io/apimachinery/pkg/util/validation/field",
"k8s.io/apimachinery/pkg/util/yaml",
"k8s.io/client-go/kubernetes/scheme",
"k8s.io/kube-openapi/pkg/common",

View File

@@ -60,3 +60,7 @@
[[constraint]]
branch = "master"
name = "github.com/hashicorp/go-getter"
[[constraint]]
name = "github.com/krishicks/yaml-patch"
version = "0.0.10"

View File

@@ -23,10 +23,10 @@ set -x
# - Use /go as the default GOPATH because this is what the image uses
# - Link our current directory (containing the source code) to the package location in the GOPATH
OWNER="kubernetes-sigs"
OWNER="sigs.k8s.io"
REPO="kustomize"
GO_PKG_OWNER=$GOPATH/src/github.com/$OWNER
GO_PKG_OWNER=$GOPATH/src/$OWNER
GO_PKG_PATH=$GO_PKG_OWNER/$REPO
mkdir -p $GO_PKG_OWNER

View File

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

View File

@@ -11,12 +11,12 @@
can be considered.
1. Submit an issue describing your proposed change to
the repo in question.
1. The [repo owners](OWNERS) will respond to your issue
1. The [repo owners](../OWNERS) will respond to your issue
promptly.
1. Fork the repo, develop and test your code.
See the [github workflow guide].
1. For _new features_, provide a markdown-based demo following
the pattern established in the [examples](examples) directory.
the pattern established in the [examples](../examples) directory.
Run `bin/pre-commit.sh` to test your demo.
1. Submit a pull request.

View File

@@ -2,6 +2,7 @@
[DAM]: #declarative-application-management
[JSON]: https://www.json.org/
[JSONPatch]: https://tools.ietf.org/html/rfc6902
[Resource]: #resource
[YAML]: http://www.yaml.org/start.html
[application]: #application
@@ -15,16 +16,19 @@
[kubernetes]: #kubernetes
[kustomize]: #kustomize
[kustomization]: #kustomization
[off-the-shelf]: #off-the-shelf
[off-the-shelf]: #off-the-shelf-configuration
[overlay]: #overlay
[overlays]: #overlay
[patch]: #patch
[patches]: #patch
[patchJson6902]: #patchJson6902
[patchesJson6902]: #patchjson6902
[proposal]: https://github.com/kubernetes/community/pull/1629
[rebase]: https://git-scm.com/docs/git-rebase
[resource]: #resource
[resources]: #resource
[rpm]: https://en.wikipedia.org/wiki/Rpm_(software)
[strategic merge]: https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md
[target]: #target
[variant]: #variant
[variants]: #variant
@@ -254,6 +258,15 @@ dependencies. Since any resource file can be used as a
patch, one cannot reliably distinguish a resource from
a patch just by looking at the file's [YAML].
## patchJson6902
A _patchJson6902_ refers to a kubernetes object and a [JSONPatch]
that can patch the object. A [JSONPatch] contains a list of operations to change the object's field directly.
This is different from [patch], which is
applied to a target kubernetes object by [strategic merge].
_patchesJson6902_ is a field in kustomization. It contains a list of
_patchJson6902_.
## resource
A _resource_, in the context of kustomize, is a path to

View File

@@ -138,6 +138,41 @@ patches:
- deployment_increase_replicas.yaml
- deployment_increase_memory.yaml
# Each entry in this list should resolve to
# a kubernetes object and a JSON patch that will be applied
# to the object.
# The JSON patch is documented at https://tools.ietf.org/html/rfc6902
#
# target field points to a kubernetes object within the same kustomization
# by the object's group, version, kind, name and namespace.
# path field is a relative file path of a JSON patch file.
# The content in this patch file can be either in JSON format as
#
# [
# {"op": "add", "path": "/some/new/path", "value": "value"},
# {"op": "replace", "path": "/some/existing/path", "value": "new value"}
# ]
#
# or in YAML format as
#
# - op: add
# path: /some/new/path
# value: value
# - op:replace
# path: /some/existing/path
# value: new value
#
patchesJson6902
- target:
version: v1
kind: Deployment
name: my-deployment
path: add_init_container.yaml
- target:
version: v1
kind: Service
name: my-service
path: add_service_annotation.yaml
# Each entry in this list should be a relative path to
# a file for custom resource definition(CRD).
@@ -212,8 +247,12 @@ vars:
# image: nginx:1.7.9
#```
# one can change the tag of myimage to v1 and the tag of nginx to 1.8.0 with the following:
#
# It also supports digests. If digest is present newTag is ignored.
imageTags:
- name: mycontainerregistry/myimage
newTag: v1
- name: nginx
newTag: 1.8.0
- name: alpine
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3

View File

@@ -1,11 +1,11 @@
[OTS]: glossary.md#off-the-shelf
[OTS]: glossary.md#off-the-shelf-configuration
[apply]: glossary.md#apply
[applying]: glossary.md#apply
[base]: glossary.md#base
[fork]: https://guides.github.com/activities/forking/
[variants]: glossary.md#variant
[kustomization]: glossary.md#kustomization
[off-the-shelf]: glossary.md#off-the-shelf
[off-the-shelf]: glossary.md#off-the-shelf-configuration
[overlays]: glossary.md#overlay
[patch]: glossary.md#patch
[patches]: glossary.md#patch

View File

@@ -7,7 +7,7 @@ tests, and should work with HEAD
<!-- @installkustomize @test -->
```
go get github.com/kubernetes-sigs/kustomize
go get sigs.k8s.io/kustomize
```
* [hello world](helloWorld/README.md) - Deploy multiple
@@ -40,3 +40,5 @@ go get github.com/kubernetes-sigs/kustomize
* [multibases](multibases/README.md) - Composing three variants (dev, staging, production) with a common base.
* [remote target](remoteBuild.md) - Building a kustomization from a github URL
* [json patch](jsonpatch.md) - Apply a json patch in a kustomization

View File

@@ -73,7 +73,7 @@ commonLabels:
who: alice
bases:
- ../../base
patches:
patchesStrategicMerge:
- temperature.yaml
EOF
@@ -96,7 +96,7 @@ commonLabels:
who: bob
bases:
- ../../base
patches:
patchesStrategicMerge:
- topping.yaml
EOF

View File

@@ -1,6 +1,6 @@
[patch]: ../../docs/glossary.md#patch
[resource]: ../../docs/glossary.md#resource
[variant]: ../../docs/glossary.md#variant
[patch]: ../docs/glossary.md#patch
[resource]: ../docs/glossary.md#resource
[variant]: ../docs/glossary.md#variant
## ConfigMap generation and rolling updates
@@ -67,7 +67,7 @@ commonAnnotations:
note: Hello, I am staging!
bases:
- ../../base
patches:
patchesStrategicMerge:
- map.yaml
EOF

View File

@@ -156,7 +156,7 @@ commonAnnotations:
note: Hello, I am staging!
bases:
- ../../base
patches:
patchesStrategicMerge:
- map.yaml
EOF
```
@@ -197,7 +197,7 @@ commonAnnotations:
note: Hello, I am production!
bases:
- ../../base
patches:
patchesStrategicMerge:
- deployment.yaml
EOF
```

77
examples/jsonpatch.md Normal file
View File

@@ -0,0 +1,77 @@
# Demo: applying a json patch
A kustomization file supports customizing resources via [JSON patches](https://tools.ietf.org/html/rfc6902).
The example below modifies an `Ingress` object with such a patch.
Make a `kustomization` containing an ingress resource.
<!-- @createIngress @test -->
```
DEMO_HOME=$(mktemp -d)
cat <<EOF >$DEMO_HOME/kustomization.yaml
resources:
- ingress.yaml
EOF
cat <<EOF >$DEMO_HOME/ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: my-api
servicePort: 80
EOF
```
Declare a JSON patch file to update two fields of the Ingress object:
- change host from `foo.bar.com` to `foo.bar.io`
- change servicePort from `80` to `8080`
<!-- @addJsonPatch @test -->
```
cat <<EOF >$DEMO_HOME/ingress_patch.json
[
{"op": "replace", "path": "/spec/rules/0/host", "value": "foo.bar.io"},
{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/servicePort", "value": 8080}
]
EOF
```
Apply the patch by adding _patchesJson6902_ field in kustomization.yaml
<!-- @applyJsonPatch @test -->
```
cat <<EOF >>$DEMO_HOME/kustomization.yaml
patchesJson6902:
- target:
group: extensions
version: v1beta1
kind: Ingress
name: my-ingress
path: ingress_patch.json
EOF
```
Running `kustomize build $DEMO_HOME`, in the ourput confirm that host has been updated correctly.
<!-- @confirmHost @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep "host: foo.bar.io" | wc -l); \
echo $?
```
Running `kustomize build $DEMO_HOME`, in the ourput confirm that the servicePort has been updated correctly.
<!-- @confirmServicePort @test -->
```
test 1 == \
$(kustomize build $DEMO_HOME | grep "servicePort: 8080" | wc -l); \
echo $?
```

View File

@@ -1,5 +1,5 @@
bases:
- ../../base
patches:
patchesStrategicMerge:
- deployment.yaml
namePrefix: production-

View File

@@ -1,6 +1,6 @@
bases:
- ../../base
patches:
patchesStrategicMerge:
- deployment.yaml
nameprefix: staging-
configMapGenerator:

View File

@@ -107,7 +107,7 @@ Now the workspace has following directories
> └── kustomization.yaml
> ```
Confirm that the `kustomize build` output contains three pod objects from dev, staing and production variants.
Confirm that the `kustomize build` output contains three pod objects from dev, staging and production variants.
<!-- @confirmVariants @test -->
```

View File

@@ -150,7 +150,7 @@ Off the shelf MySQL uses `emptyDir` type volume, which
gets wiped away if the MySQL Pod is recreated, and that
is certainly not desirable for production
environment. So we want to use Persistent Disk in
production. kustomize lets you apply `patches` to the
production. kustomize lets you apply `patchesStrategicMerge` to the
resources.
<!-- @createPatchFile @test -->
@@ -176,7 +176,7 @@ Add the patch file to `kustomization.yaml`:
<!-- @specifyPatch @test -->
```
cat <<'EOF' >> $DEMO_HOME/kustomization.yaml
patches:
patchesStrategicMerge:
- persistent-disk.yaml
EOF
```
@@ -188,7 +188,7 @@ Lets break this down:
in deployment.yaml
- Then we added `persistent-disk.yaml` to list of
`patches` in `kustomization.yaml`. `kustomize build`
`patchesStrategicMerge` in `kustomization.yaml`. `kustomize build`
will apply this patch to the deployment resource with
the name `mysql` as defined in the patch.

View File

@@ -16,6 +16,17 @@ test 3 == \
echo $?
```
Overlays can be remote as well:
<!-- @remoteOverlayBuild @test -->
```
target=github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?ref=v1.0.6
test 1 == \
$(kustomize build $target | grep cluster-a-dev-myapp-pod | wc -l); \
echo $?
```
A base can also be specified as a URL:
<!-- @createOverlay @test -->
@@ -55,4 +66,4 @@ Here are some example urls pointing to Github repos following this convention.
`github.com/Liujingfang1/kustomize//examples/helloWorld?ref=repoUrl2`
- a subdirectory in a repo on commit `7050a45134e9848fca214ad7e7007e96e5042c03`
`github.com/Liujingfang1/kustomize//examples/helloWorld?ref=7050a45134e9848fca214ad7e7007e96e5042c03`
`github.com/Liujingfang1/kustomize//examples/helloWorld?ref=7050a45134e9848fca214ad7e7007e96e5042c03`

View File

@@ -291,7 +291,7 @@ kustomize edit add patch healthcheck_patch.yaml
`kustomization.yaml` should have patches field:
> ```
> patches:
> patchesStrategicMerge:
> - patch.yaml
> - memorylimit_patch.yaml
> - healthcheck_patch.yaml

View File

@@ -1,6 +1,6 @@
bases:
- ../../base
patches:
patchesStrategicMerge:
- patch.yaml
- healthcheck_patch.yaml
- memorylimit_patch.yaml

View File

@@ -53,7 +53,7 @@ bases:
- wordpress
- mysql
namePrefix: demo-
patches:
patchesStrategicMerge:
- patch.yaml
EOF
```

View File

@@ -1,7 +1,7 @@
bases:
- wordpress
- mysql
patches:
patchesStrategicMerge:
- patch.yaml
namePrefix: demo-

View File

@@ -21,7 +21,7 @@ import (
"github.com/golang/glog"
"github.com/kubernetes-sigs/kustomize/pkg/commands"
"sigs.k8s.io/kustomize/pkg/commands"
)
func main() {

View File

@@ -26,17 +26,19 @@ import (
"github.com/ghodss/yaml"
"github.com/golang/glog"
"github.com/kubernetes-sigs/kustomize/pkg/configmapandsecret"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/crds"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
interror "github.com/kubernetes-sigs/kustomize/pkg/internal/error"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/resmap"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"github.com/kubernetes-sigs/kustomize/pkg/transformers"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/crds"
"sigs.k8s.io/kustomize/pkg/fs"
interror "sigs.k8s.io/kustomize/pkg/internal/error"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/patch"
patchtransformer "sigs.k8s.io/kustomize/pkg/patch/transformer"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/types"
)
// Application implements the guts of the kustomize 'build' command.
@@ -61,7 +63,6 @@ func NewApplication(ldr loader.Loader, fSys fs.FileSystem) (*Application, error)
if err != nil {
return nil, err
}
return &Application{kustomization: &m, ldr: ldr, fSys: fSys}, nil
}
@@ -150,7 +151,8 @@ func (a *Application) loadCustomizedResMap() (resmap.ResMap, error) {
return nil, err
}
patches, err := resmap.NewResourceSliceFromPatches(a.ldr, a.kustomization.Patches)
a.kustomization.PatchesStrategicMerge = patch.Append(a.kustomization.PatchesStrategicMerge, a.kustomization.Patches...)
patches, err := resmap.NewResourceSliceFromPatches(a.ldr, a.kustomization.PatchesStrategicMerge)
if err != nil {
errs.Append(errors.Wrap(err, "NewResourceSliceFromPatches"))
}
@@ -165,6 +167,11 @@ func (a *Application) loadCustomizedResMap() (resmap.ResMap, error) {
return nil, err
}
r = append(r, t)
t, err = patchtransformer.NewPatchJson6902Factory(a.ldr).MakePatchJson6902Transformer(a.kustomization.PatchesJson6902)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewImageTagTransformer(a.kustomization.ImageTags)
if err != nil {
return nil, err

View File

@@ -22,14 +22,14 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/internal/loadertest"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/resmap"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
const (
@@ -54,6 +54,13 @@ secretGenerator:
DB_USERNAME: "printf admin"
DB_PASSWORD: "printf somepw"
type: Opaque
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: dply1
path: jsonpatch.json
`
kustomizationContent2 = `
secretGenerator:
@@ -73,6 +80,9 @@ kind: Namespace
metadata:
name: ns1
`
jsonpatchContent = `[
{"op": "add", "path": "/spec/replica", "value": "3"}
]`
)
func makeLoader1(t *testing.T) loader.Loader {
@@ -89,6 +99,10 @@ func makeLoader1(t *testing.T) loader.Loader {
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
err = ldr.AddFile("/testpath/jsonpatch.json", []byte(jsonpatchContent))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
return ldr
}
@@ -114,6 +128,7 @@ func TestResources1(t *testing.T) {
},
},
"spec": map[string]interface{}{
"replica": "3",
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",

View File

@@ -23,8 +23,8 @@ import (
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
type addBaseOptions struct {

View File

@@ -21,8 +21,8 @@ import (
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
const (

View File

@@ -20,21 +20,22 @@ import (
"fmt"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/validate"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
)
// KindOfAdd is the kind of metadata being added: label or annotation
type KindOfAdd int
// kindOfAdd is the kind of metadata being added: label or annotation
type kindOfAdd int
const (
annotation KindOfAdd = iota
annotation kindOfAdd = iota
label
)
func (k KindOfAdd) String() string {
func (k kindOfAdd) String() string {
kinds := [...]string{
"annotation",
"label",
@@ -46,127 +47,129 @@ func (k KindOfAdd) String() string {
}
type addMetadataOptions struct {
metadata map[string]string
metadata map[string]string
mapValidator validators.MapValidatorFunc
kind kindOfAdd
}
// newCmdAddAnnotation adds one or more commonAnnotations to the kustomization file.
func newCmdAddAnnotation(fsys fs.FileSystem) *cobra.Command {
func newCmdAddAnnotation(fSys fs.FileSystem, v validators.MapValidatorFunc) *cobra.Command {
var o addMetadataOptions
o.kind = annotation
o.mapValidator = v
cmd := &cobra.Command{
Use: "annotation",
Short: "Adds one or more commonAnnotations to the kustomization.yaml in current directory",
Short: "Adds one or more commonAnnotations to " + constants.KustomizationFileName,
Example: `
add annotation {annotationKey1:annotationValue1},{annotationKey2:annotationValue2}`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.ValidateAndParse(args, annotation)
if err != nil {
return err
}
return o.RunAddAnnotation(fsys, annotation)
return o.runE(args, fSys, o.addAnnotations)
},
}
return cmd
}
// newCmdAddLabel adds one or more commonLabels to the kustomization file.
func newCmdAddLabel(fsys fs.FileSystem) *cobra.Command {
func newCmdAddLabel(fSys fs.FileSystem, v validators.MapValidatorFunc) *cobra.Command {
var o addMetadataOptions
o.kind = label
o.mapValidator = v
cmd := &cobra.Command{
Use: "label",
Short: "Adds one or more commonLabels to the kustomization.yaml in current directory",
Short: "Adds one or more commonLabels to " + constants.KustomizationFileName,
Example: `
add label {labelKey1:labelValue1},{labelKey2:labelValue2}`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.ValidateAndParse(args, label)
if err != nil {
return err
}
return o.RunAddLabel(fsys, label)
return o.runE(args, fSys, o.addLabels)
},
}
return cmd
}
// ValidateAndParse validates addLabel and addAnnotation commands and parses them into o.metadata
func (o *addMetadataOptions) ValidateAndParse(args []string, k KindOfAdd) error {
o.metadata = make(map[string]string)
func (o *addMetadataOptions) runE(
args []string, fSys fs.FileSystem, adder func(*types.Kustomization) error) error {
err := o.validateAndParse(args)
if err != nil {
return err
}
kf, err := newKustomizationFile(constants.KustomizationFileName, fSys)
if err != nil {
return err
}
m, err := kf.read()
if err != nil {
return err
}
err = adder(m)
if err != nil {
return err
}
return kf.write(m)
}
// validateAndParse validates `add` commands and parses them into o.metadata
func (o *addMetadataOptions) validateAndParse(args []string) error {
if len(args) < 1 {
return fmt.Errorf("must specify %s", k)
return fmt.Errorf("must specify %s", o.kind)
}
if len(args) > 1 {
return fmt.Errorf("%ss must be comma-separated, with no spaces. See help text for example", k)
return fmt.Errorf("%ss must be comma-separated, with no spaces", o.kind)
}
inputs := strings.Split(args[0], ",")
m, err := o.convertToMap(args[0])
if err != nil {
return err
}
if err = o.mapValidator(m); err != nil {
return err
}
o.metadata = m
return nil
}
func (o *addMetadataOptions) convertToMap(arg string) (map[string]string, error) {
result := make(map[string]string)
inputs := strings.Split(arg, ",")
for _, input := range inputs {
switch k {
case label:
valid, err := validate.IsValidLabel(input)
if !valid {
return err
}
case annotation:
valid, err := validate.IsValidAnnotation(input)
if !valid {
return err
}
default:
return fmt.Errorf("unknown metadata kind %s", k)
}
//parse annotation keys and values into metadata
kv := strings.Split(input, ":")
o.metadata[kv[0]] = kv[1]
if len(kv[0]) < 1 {
return nil, o.makeError(input, "empty key")
}
if len(kv) > 2 {
return nil, o.makeError(input, "too many colons")
}
if len(kv) > 1 {
result[kv[0]] = kv[1]
} else {
result[kv[0]] = ""
}
}
return result, nil
}
func (o *addMetadataOptions) addAnnotations(m *types.Kustomization) error {
if m.CommonAnnotations == nil {
m.CommonAnnotations = make(map[string]string)
}
return o.writeToMap(m.CommonAnnotations, annotation)
}
func (o *addMetadataOptions) addLabels(m *types.Kustomization) error {
if m.CommonLabels == nil {
m.CommonLabels = make(map[string]string)
}
return o.writeToMap(m.CommonLabels, label)
}
func (o *addMetadataOptions) writeToMap(m map[string]string, kind kindOfAdd) error {
for k, v := range o.metadata {
if _, ok := m[k]; ok {
return fmt.Errorf("%s %s already in kustomization file", kind, k)
}
m[k] = v
}
return nil
}
// RunAddAnnotation runs addAnnotation command, doing the real work.
func (o *addMetadataOptions) RunAddAnnotation(fsys fs.FileSystem, k KindOfAdd) error {
mf, err := newKustomizationFile(constants.KustomizationFileName, fsys)
if err != nil {
return err
}
m, err := mf.read()
if err != nil {
return err
}
if m.CommonAnnotations == nil {
m.CommonAnnotations = make(map[string]string)
}
for key, value := range o.metadata {
if k == annotation {
if _, ok := m.CommonAnnotations[key]; ok {
return fmt.Errorf("%s %s already in kustomization file", k, key)
}
m.CommonAnnotations[key] = value
}
}
return mf.write(m)
}
// RunAddLabel runs addLabel command, doing the real work.
func (o *addMetadataOptions) RunAddLabel(fsys fs.FileSystem, k KindOfAdd) error {
mf, err := newKustomizationFile(constants.KustomizationFileName, fsys)
if err != nil {
return err
}
m, err := mf.read()
if err != nil {
return err
}
if m.CommonLabels == nil {
m.CommonLabels = make(map[string]string)
}
for key, value := range o.metadata {
if _, ok := m.CommonLabels[key]; ok {
return fmt.Errorf("%s %s already in kustomization file", k, key)
}
m.CommonLabels[key] = value
}
return mf.write(m)
func (o *addMetadataOptions) makeError(input string, message string) error {
return fmt.Errorf("invalid %s: %s (%s)", o.kind, input, message)
}

View File

@@ -17,98 +17,45 @@ limitations under the License.
package commands
import (
"reflect"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/validators"
)
func TestParseValidateInput(t *testing.T) {
var testcases = []struct {
input string
valid bool
name string
expectedData map[string]string
kind KindOfAdd
}{
{
input: "otters:cute",
valid: true,
name: "Adds single input",
expectedData: map[string]string{
"otters": "cute",
},
kind: label,
},
{
input: "owls:great,unicorns:magical",
valid: true,
name: "Adds two items",
expectedData: map[string]string{
"owls": "great",
"unicorns": "magical",
},
kind: label,
},
{
input: "123:45",
valid: true,
name: "Numeric input is allowed",
expectedData: map[string]string{
"123": "45",
},
kind: annotation,
},
{
input: " ",
valid: false,
name: "Empty space input",
expectedData: nil,
kind: annotation,
},
func makeKustomization(t *testing.T) *types.Kustomization {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
kf, err := newKustomizationFile(constants.KustomizationFileName, fakeFS)
if err != nil {
t.Errorf("unexpected new error %v", err)
}
var o addMetadataOptions
for _, tc := range testcases {
args := []string{tc.input}
err := o.ValidateAndParse(args, tc.kind)
if err != nil && tc.valid {
t.Errorf("for test case %s, unexpected cmd error: %v", tc.name, err)
}
if err == nil && !tc.valid {
t.Errorf("unexpected error: expected invalid format error for test case %v", tc.name)
}
//o.metadata should be the same as expectedData
if tc.valid {
if !reflect.DeepEqual(o.metadata, tc.expectedData) {
t.Errorf("unexpected error: for test case %s, unexpected data was added", tc.name)
}
} else {
if len(o.metadata) != 0 {
t.Errorf("unexpected error: for test case %s, expected no data to be added", tc.name)
}
}
m, err := kf.read()
if err != nil {
t.Errorf("unexpected read error %v", err)
}
return m
}
func TestRunAddAnnotation(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
var o addMetadataOptions
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
err := o.RunAddAnnotation(fakeFS, annotation)
m := makeKustomization(t)
err := o.addAnnotations(m)
if err != nil {
t.Errorf("unexpected error: could not write to kustomization file")
}
// adding the same test input should not work
err = o.RunAddAnnotation(fakeFS, annotation)
err = o.addAnnotations(m)
if err == nil {
t.Errorf("expected already in kustomization file error")
}
// adding new annotations should work
o.metadata = map[string]string{"new": "annotation"}
err = o.RunAddAnnotation(fakeFS, annotation)
err = o.addAnnotations(m)
if err != nil {
t.Errorf("unexpected error: could not write to kustomization file")
}
@@ -116,47 +63,122 @@ func TestRunAddAnnotation(t *testing.T) {
func TestAddAnnotationNoArgs(t *testing.T) {
fakeFS := fs.MakeFakeFS()
cmd := newCmdAddAnnotation(fakeFS)
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
err := cmd.Execute()
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error but error is %v", err)
t.Errorf("expected an error")
}
if err != nil && err.Error() != "must specify annotation" {
if err.Error() != "must specify annotation" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddAnnotationInvalidFormat(t *testing.T) {
fakeFS := fs.MakeFakeFS()
v := validators.MakeSadMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
args := []string{"whatever:whatever"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != validators.SAD {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddAnnotationManyArgs(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
args := []string{"k1:v1,k2:v2,k3:v3,k4:v5"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error: %v", err.Error())
}
}
func TestAddAnnotationNoKey(t *testing.T) {
fakeFS := fs.MakeFakeFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
args := []string{":nokey"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "invalid annotation: :nokey (empty key)" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddAnnotationTooManyColons(t *testing.T) {
fakeFS := fs.MakeFakeFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
args := []string{"key:v1:v2"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "invalid annotation: key:v1:v2 (too many colons)" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddAnnotationNoValue(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
args := []string{"no:,value"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error: %v", err.Error())
}
}
func TestAddAnnotationMultipleArgs(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddAnnotation(fakeFS)
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddAnnotation(fakeFS, v.Validator)
args := []string{"this:annotation", "has:spaces"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error but error is %v", err)
t.Errorf("expected an error")
}
if err != nil && err.Error() != "annotations must be comma-separated, with no spaces. See help text for example" {
if err.Error() != "annotations must be comma-separated, with no spaces" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestRunAddLabel(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
var o addMetadataOptions
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
err := o.RunAddLabel(fakeFS, label)
m := makeKustomization(t)
err := o.addLabels(m)
if err != nil {
t.Errorf("unexpected error: could not write to kustomization file")
}
// adding the same test input should not work
err = o.RunAddLabel(fakeFS, label)
err = o.addLabels(m)
if err == nil {
t.Errorf("expected already in kustomization file error")
}
// adding new labels should work
o.metadata = map[string]string{"new": "label"}
err = o.RunAddLabel(fakeFS, label)
err = o.addLabels(m)
if err != nil {
t.Errorf("unexpected error: could not write to kustomization file")
}
@@ -164,27 +186,88 @@ func TestRunAddLabel(t *testing.T) {
func TestAddLabelNoArgs(t *testing.T) {
fakeFS := fs.MakeFakeFS()
cmd := newCmdAddLabel(fakeFS)
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddLabel(fakeFS, v.Validator)
err := cmd.Execute()
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error but error is: %v", err)
t.Errorf("expected an error")
}
if err != nil && err.Error() != "must specify label" {
if err.Error() != "must specify label" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddLabelInvalidFormat(t *testing.T) {
fakeFS := fs.MakeFakeFS()
v := validators.MakeSadMapValidator(t)
cmd := newCmdAddLabel(fakeFS, v.Validator)
args := []string{"exclamation!:point"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != validators.SAD {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddLabelNoKey(t *testing.T) {
fakeFS := fs.MakeFakeFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddLabel(fakeFS, v.Validator)
args := []string{":nokey"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "invalid label: :nokey (empty key)" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddLabelTooManyColons(t *testing.T) {
fakeFS := fs.MakeFakeFS()
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddLabel(fakeFS, v.Validator)
args := []string{"key:v1:v2"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "invalid label: key:v1:v2 (too many colons)" {
t.Errorf("incorrect error: %v", err.Error())
}
}
func TestAddLabelNoValue(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddLabel(fakeFS, v.Validator)
args := []string{"no,value:"}
err := cmd.RunE(cmd, args)
v.VerifyCall()
if err != nil {
t.Errorf("unexpected error: %v", err.Error())
}
}
func TestAddLabelMultipleArgs(t *testing.T) {
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdAddLabel(fakeFS)
v := validators.MakeHappyMapValidator(t)
cmd := newCmdAddLabel(fakeFS, v.Validator)
args := []string{"this:input", "has:spaces"}
err := cmd.RunE(cmd, args)
v.VerifyNoCall()
if err == nil {
t.Errorf("expected an error but error is: %v", err)
t.Errorf("expected an error")
}
if err != nil && err.Error() != "labels must be comma-separated, with no spaces. See help text for example" {
if err.Error() != "labels must be comma-separated, with no spaces" {
t.Errorf("incorrect error: %v", err.Error())
}
}

View File

@@ -22,8 +22,9 @@ import (
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/patch"
)
type addPatchOptions struct {
@@ -88,12 +89,12 @@ func (o *addPatchOptions) RunAddPatch(fsys fs.FileSystem) error {
return err
}
for _, patch := range patches {
if stringInSlice(patch, m.Patches) {
log.Printf("patch %s already in kustomization file", patch)
for _, p := range patches {
if patch.Exist(m.PatchesStrategicMerge, p) || stringInSlice(p, m.Patches) {
log.Printf("patch %s already in kustomization file", p)
continue
}
m.Patches = append(m.Patches, patch)
m.PatchesStrategicMerge = patch.Append(m.PatchesStrategicMerge, p)
}
return mf.write(m)

View File

@@ -21,8 +21,8 @@ import (
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
const (

View File

@@ -22,8 +22,8 @@ import (
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
type addResourceOptions struct {

View File

@@ -20,8 +20,8 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
const (

View File

@@ -23,10 +23,10 @@ import (
"errors"
"github.com/kubernetes-sigs/kustomize/pkg/app"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/app"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
)
type buildOptions struct {
@@ -44,7 +44,7 @@ The url should follow hashicorp/go-getter URL format described in
https://github.com/hashicorp/go-getter#url-format
url examples:
github.com/kubernetes-sigs/kustomize//examples/multibases?ref=v1.0.6
sigs.k8s.io/kustomize//examples/multibases?ref=v1.0.6
github.com/Liujingfang1/mysql
github.com/Liujingfang1/kustomize//examples/helloWorld?ref=repoUrl2
`

View File

@@ -27,9 +27,9 @@ import (
"github.com/ghodss/yaml"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
type buildTestCase struct {

View File

@@ -19,7 +19,7 @@ package commands
import (
"fmt"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/fs"
)
// cMapFlagsAndArgs encapsulates the options for add configmap commands.

View File

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

View File

@@ -21,8 +21,9 @@ import (
"flag"
"os"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/validators"
)
// NewDefaultCommand returns the default (aka root) command for kustomize command.
@@ -36,7 +37,7 @@ func NewDefaultCommand() *cobra.Command {
Long: `
kustomize manages declarative configuration of Kubernetes.
See https://github.com/kubernetes-sigs/kustomize
See https://sigs.k8s.io/kustomize
`,
}
@@ -109,8 +110,8 @@ func newCmdAdd(fsys fs.FileSystem) *cobra.Command {
newCmdAddPatch(fsys),
newCmdAddConfigMap(fsys),
newCmdAddBase(fsys),
newCmdAddLabel(fsys),
newCmdAddAnnotation(fsys),
newCmdAddLabel(fsys, validators.MakeLabelValidator()),
newCmdAddAnnotation(fsys, validators.MakeAnnotationValidator()),
)
return c
}

View File

@@ -21,11 +21,11 @@ import (
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/configmapandsecret"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
func newCmdAddConfigMap(fSys fs.FileSystem) *cobra.Command {

View File

@@ -19,8 +19,8 @@ package commands
import (
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
)
func TestNewAddConfigMapIsNotNil(t *testing.T) {

View File

@@ -28,10 +28,9 @@ import (
"github.com/ghodss/yaml"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
interror "github.com/kubernetes-sigs/kustomize/pkg/internal/error"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
)
var (
@@ -47,6 +46,8 @@ var (
"CommonLabels",
"CommonAnnotations",
"Patches",
"PatchesStrategicMerge",
"PatchesJson6902",
"ConfigMapGenerator",
"SecretGenerator",
"Vars",
@@ -87,22 +88,17 @@ func newKustomizationFile(mPath string, fsys fs.FileSystem) (*kustomizationFile,
func (mf *kustomizationFile) validate() error {
if !mf.fsys.Exists(mf.path) {
errorMsg := fmt.Sprintf("Missing kustomization file '%s'.\n", mf.path)
merr := interror.KustomizationError{KustomizationPath: mf.path, ErrorMsg: errorMsg}
return merr
return fmt.Errorf("Missing kustomization file '%s'.\n", mf.path)
}
if mf.fsys.IsDir(mf.path) {
mf.path = path.Join(mf.path, constants.KustomizationFileName)
if !mf.fsys.Exists(mf.path) {
errorMsg := fmt.Sprintf("Missing kustomization file '%s'.\n", mf.path)
merr := interror.KustomizationError{KustomizationPath: mf.path, ErrorMsg: errorMsg}
return merr
return fmt.Errorf("Missing kustomization file '%s'.\n", mf.path)
}
} else {
if !strings.HasSuffix(mf.path, constants.KustomizationFileName) {
errorMsg := fmt.Sprintf("Kustomization file path (%s) should have %s suffix\n",
return fmt.Errorf("Kustomization file path (%s) should have %s suffix\n",
mf.path, constants.KustomizationFileSuffix)
return interror.KustomizationError{KustomizationPath: mf.path, ErrorMsg: errorMsg}
}
}
return nil

View File

@@ -21,9 +21,9 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
)
func TestWriteAndRead(t *testing.T) {
@@ -109,7 +109,7 @@ vars:
bases:
- ../namespaces
# some descriptions for the patches
patches:
patchesStrategicMerge:
- service.yaml
- pod.yaml
`)
@@ -165,7 +165,7 @@ BASES:
# some descriptions for the patches
patches:
patchesStrategicMerge:
- service.yaml
- pod.yaml
`)
@@ -200,7 +200,7 @@ bases:
# some descriptions for the patches
patches:
patchesStrategicMerge:
- service.yaml
- pod.yaml
`)

View File

@@ -21,8 +21,8 @@ import (
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
type setNamePrefixOptions struct {

View File

@@ -21,8 +21,8 @@ import (
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
const (

View File

@@ -20,16 +20,17 @@ import (
"errors"
"regexp"
"sort"
"strings"
"github.com/spf13/cobra"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
)
type setImageTagOptions struct {
imageTagMap map[string]string
imageTagMap map[string]types.ImageTag
}
var pattern = regexp.MustCompile("^(.*):([a-zA-Z0-9._-]*)$")
@@ -40,10 +41,10 @@ func newCmdSetImageTag(fsys fs.FileSystem) *cobra.Command {
cmd := &cobra.Command{
Use: "imagetag",
Short: "Sets images and their new tags in the kustomization file",
Short: "Sets images and their new tags or digests in the kustomization file",
Example: `
The command
set imagetag nginx:1.8.0 my-app:latest
set imagetag nginx:1.8.0 my-app:latest alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
will add
imageTags:
@@ -51,9 +52,11 @@ imageTags:
newTag: 1.8.0
- name: my-app
newTag: latest
- name: alpine
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
to the kustomization file if it doesn't exist,
and overwrite the previous newTag if the image name exists.
and overwrite the previous ones if the image tag exists.
`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
@@ -69,15 +72,28 @@ and overwrite the previous newTag if the image name exists.
// Validate validates setImageTag command.
func (o *setImageTagOptions) Validate(args []string) error {
if len(args) == 0 {
return errors.New("no image and newTag specified")
return errors.New("no image specified")
}
o.imageTagMap = make(map[string]string)
o.imageTagMap = make(map[string]types.ImageTag)
for _, arg := range args {
imagetag := pattern.FindStringSubmatch(arg)
if len(imagetag) != 3 {
return errors.New("invalid format of imagetag, must specify it as <image>:<newtag>")
if s := strings.Split(arg, "@"); len(s) > 1 {
o.imageTagMap[s[0]] = types.ImageTag{
Name: s[0],
Digest: s[1],
}
continue
}
s := pattern.FindStringSubmatch(arg)
if len(s) != 3 {
return errors.New("invalid format of imagetag, must specify it as <image>:<newtag> or <image>@<digest>")
}
o.imageTagMap[s[1]] = types.ImageTag{
Name: s[1],
NewTag: s[2],
}
o.imageTagMap[imagetag[1]] = imagetag[2]
}
return nil
}
@@ -92,16 +108,18 @@ func (o *setImageTagOptions) RunSetImageTags(fsys fs.FileSystem) error {
if err != nil {
return err
}
imageTagMap := map[string]string{}
for _, it := range m.ImageTags {
imageTagMap[it.Name] = it.NewTag
}
for key, value := range o.imageTagMap {
imageTagMap[key] = value
if _, ok := o.imageTagMap[it.Name]; ok {
continue
}
o.imageTagMap[it.Name] = it
}
var imageTags []types.ImageTag
for key, value := range imageTagMap {
imageTags = append(imageTags, types.ImageTag{Name: key, NewTag: value})
for _, v := range o.imageTagMap {
imageTags = append(imageTags, v)
}
sort.Slice(imageTags, func(i, j int) bool {
return imageTags[i].Name < imageTags[j].Name

View File

@@ -20,8 +20,8 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
func TestSetImageTagsHappyPath(t *testing.T) {
@@ -29,7 +29,8 @@ func TestSetImageTagsHappyPath(t *testing.T) {
fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent))
cmd := newCmdSetImageTag(fakeFS)
args := []string{"image1:tag1", "image2:tag2", "localhost:5000/operator:1.0.0"}
args := []string{"image1:tag1", "image2:tag2", "localhost:5000/operator:1.0.0",
"foo.bar.baz:5000/one/two@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected cmd error: %v", err)
@@ -40,6 +41,8 @@ func TestSetImageTagsHappyPath(t *testing.T) {
}
expected := []byte(`
imageTags:
- digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
name: foo.bar.baz:5000/one/two
- name: image1
newTag: tag1
- name: image2
@@ -93,7 +96,7 @@ func TestSetImageTagsNoArgs(t *testing.T) {
if err == nil {
t.Errorf("expected error: %v", err)
}
if err.Error() != "no image and newTag specified" {
if err.Error() != "no image specified" {
t.Errorf("incorrect error: %v", err.Error())
}
}

View File

@@ -21,10 +21,10 @@ import (
"fmt"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
type setNamespaceOptions struct {

View File

@@ -21,8 +21,8 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
)
const (

View File

@@ -0,0 +1,4 @@
resources:
- serviceaccount.yaml
- rolebinding.yaml
namePrefix: base-

View File

@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: serviceaccount

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount

View File

@@ -0,0 +1,3 @@
bases:
- ../overlays/a
- ../overlays/b

View File

@@ -0,0 +1,7 @@
bases:
- ../../base/
namePrefix: a-
resources:
- serviceaccount.yaml

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount

View File

@@ -0,0 +1,4 @@
bases:
- ../../base/
namePrefix: b-

View File

@@ -0,0 +1,4 @@
description: multibases with name reference
args: []
filename: testdata/testcase-multibases-conflict/combined
expectedError: detected conflicts when resolving name references serviceaccount

View File

@@ -0,0 +1,4 @@
resources:
- serviceaccount.yaml
- rolebinding.yaml
namePrefix: base-

View File

@@ -0,0 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: serviceaccount

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount

View File

@@ -0,0 +1,3 @@
bases:
- ../overlays/a
- ../overlays/b

View File

@@ -0,0 +1,33 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: a-base-serviceaccount
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: b-base-serviceaccount
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: a-base-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: a-base-serviceaccount
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: b-base-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role
subjects:
- kind: ServiceAccount
name: b-base-serviceaccount

View File

@@ -0,0 +1,4 @@
bases:
- ../../base/
namePrefix: a-

View File

@@ -0,0 +1,4 @@
bases:
- ../../base/
namePrefix: b-

View File

@@ -0,0 +1,4 @@
description: multibases with name reference
args: []
filename: testdata/testcase-multibases-nonconflict/combined
expectedStdout: testdata/testcase-multibases-nonconflict/expected.yaml

View File

@@ -1,7 +1,7 @@
namePrefix: staging-
commonLabels:
env: staging
patches:
patchesStrategicMerge:
- deployment-patch2.yaml
- deployment-patch1.yaml
bases:

View File

@@ -1,7 +1,7 @@
namePrefix: staging-
commonLabels:
env: staging
patches:
patchesStrategicMerge:
- patches/deployment-patch1.yaml
- patches/deployment-patch2.yaml
bases:

View File

@@ -2,7 +2,7 @@ namePrefix: staging-
commonLabels:
env: staging
team: override-foo
patches:
patchesStrategicMerge:
- deployment.yaml
bases:
- ../package/

View File

@@ -78,16 +78,10 @@ metadata:
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app: cockroachdb
name: dev-base-cockroachdb
name: dev-base-cockroachdb-public
spec:
clusterIP: None
ports:
- name: grpc
port: 26257
@@ -101,10 +95,16 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/path: _status/vars
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app: cockroachdb
name: dev-base-cockroachdb-public
name: dev-base-cockroachdb
spec:
clusterIP: None
ports:
- name: grpc
port: 26257

View File

@@ -19,7 +19,7 @@ package commands
import (
"log"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/fs"
)
func globPatterns(fsys fs.FileSystem, patterns []string) ([]string, error) {

View File

@@ -23,16 +23,16 @@ import (
"path"
"strings"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/hash"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/pkg/errors"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/hash"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
// ConfigMapFactory makes ConfigMaps.

View File

@@ -20,12 +20,12 @@ import (
"reflect"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/types"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
func makeEnvConfigMap(name string) *corev1.ConfigMap {

View File

@@ -24,11 +24,11 @@ import (
"strings"
"time"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
)
const (

View File

@@ -23,10 +23,10 @@ import (
"strings"
"github.com/ghodss/yaml"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/transformers"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kube-openapi/pkg/common"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/transformers"
)
type pathConfigs struct {

View File

@@ -21,10 +21,10 @@ import (
"sort"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/internal/loadertest"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/transformers"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/transformers"
)
const (

View File

@@ -7,7 +7,7 @@ commonAnnotations:
note: This is a test annotation
bases:
- ../../package/
patches:
patchesStrategicMerge:
- deployment/deployment.yaml
configMapGenerator:
- name: app-env

View File

@@ -20,7 +20,7 @@ import (
"bytes"
"fmt"
"github.com/kubernetes-sigs/kustomize/pkg/exec"
"sigs.k8s.io/kustomize/pkg/exec"
)
func ExampleNew() {

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestConfigmapError_Error(t *testing.T) {

View File

@@ -21,7 +21,7 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestKustomizationError_Error(t *testing.T) {

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestPatchError_Error(t *testing.T) {

View File

@@ -20,7 +20,7 @@ import (
"strings"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/constants"
)
func TestResourceError_Error(t *testing.T) {

View File

@@ -21,8 +21,8 @@ import (
"fmt"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/pkg/constants"
)
var (

View File

@@ -18,13 +18,10 @@ limitations under the License.
package loadertest
import (
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
)
// CleanupCalled indicates if Cleanup is called.
var CleanupCalled = false
// FakeLoader encapsulates the delegate Loader and the fake file system.
type FakeLoader struct {
fs fs.FileSystem
@@ -73,6 +70,5 @@ func (f FakeLoader) Load(location string) ([]byte, error) {
// Cleanup does nothing
func (f FakeLoader) Cleanup() error {
CleanupCalled = true
return nil
}

View File

@@ -21,7 +21,7 @@ import (
"os"
"path/filepath"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/fs"
)
const currentDir = "."

View File

@@ -21,7 +21,7 @@ import (
"reflect"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/fs"
)
func TestLoader_Root(t *testing.T) {

View File

@@ -24,19 +24,22 @@ import (
"github.com/hashicorp/go-getter"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/fs"
)
// githubLoader loads files from a checkout github repo
type githubLoader struct {
repo string
repo string
// target is the directory which is to be built
targetDir string
// checkoutDir is for the whole repository
checkoutDir string
loader *fileLoader
}
// Root returns the root location for this Loader.
func (l *githubLoader) Root() string {
return l.checkoutDir
return l.targetDir
}
// New delegates to fileLoader.New
@@ -60,15 +63,18 @@ func newGithubLoader(repoUrl string, fs fs.FileSystem) (*githubLoader, error) {
if err != nil {
return nil, err
}
target := filepath.Join(dir, "repo")
err = checkout(repoUrl, target)
repodir := filepath.Join(dir, "repo")
src, subdir := getter.SourceDirSubdir(repoUrl)
err = checkout(src, repodir)
if err != nil {
return nil, err
}
target := filepath.Join(repodir, subdir)
l := newFileLoaderAtRoot(target, fs)
return &githubLoader{
repo: repoUrl,
checkoutDir: dir,
targetDir: target,
checkoutDir: repodir,
loader: l,
}, nil
}
@@ -78,6 +84,9 @@ func isRepoUrl(s string) bool {
if strings.HasPrefix(s, "https://") {
return true
}
if strings.HasPrefix(s, "git::") {
return true
}
host := strings.SplitN(s, "/", 2)[0]
return strings.Contains(host, ".com") || strings.Contains(host, ".org")
}

View File

@@ -46,6 +46,10 @@ func TestIsRepoURL(t *testing.T) {
input: "../relative",
expected: false,
},
{
input: "git::https://gitlab.com/org/repo",
expected: true,
},
}
for _, tc := range testcases {
actual := isRepoUrl(tc.input)

View File

@@ -21,7 +21,7 @@ import (
"fmt"
"path/filepath"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/fs"
)
// Loader interface exposes methods to read bytes.

40
pkg/patch/jsonpatch.go Normal file
View File

@@ -0,0 +1,40 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package patch
// PatchJson6902 represents a json patch for an object
// with format documented https://tools.ietf.org/html/rfc6902.
type PatchJson6902 struct {
// Target refers to a Kubernetes object that the json patch will be
// applied to. It must refer to a Kubernetes resource under the
// purview of this kustomization. Target should use the
// raw name of the object (the name specified in its YAML,
// before addition of a namePrefix).
Target *Target `json:"target" yaml:"target"`
// relative file path for a json patch file inside a kustomization
Path string `json:"path,omitempty" yaml:"path,omitempty"`
}
// Target represents the kubernetes object that the patch is applied to
type Target struct {
Group string `json:"group,omitempty" yaml:"group,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Name string `json:"name" yaml:"name"`
}

View File

@@ -0,0 +1,40 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package patch
// PatchStrategicMerge represents a relative path to a
// stategic merget patch with the format
// https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md
type PatchStrategicMerge string
// Append appends a slice of patch paths to a PatchStategicMerge slice
func Append(patches []PatchStrategicMerge, paths ...string) []PatchStrategicMerge {
for _, p := range paths {
patches = append(patches, PatchStrategicMerge(p))
}
return patches
}
// Exist determines if a patch path exists in a slice of PatchStategicMerge
func Exist(patches []PatchStrategicMerge, path string) bool {
for _, p := range patches {
if p == PatchStrategicMerge(path) {
return true
}
}
return false
}

View File

@@ -0,0 +1,95 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"fmt"
"github.com/evanphx/json-patch"
"github.com/krishicks/yaml-patch"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/patch"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// PatchJson6902Factory makes PatchJson6902 transformers
type PatchJson6902Factory struct {
loader loader.Loader
}
// NewPatchJson6902Factory returns a new PatchJson6902Factory.
func NewPatchJson6902Factory(l loader.Loader) PatchJson6902Factory {
return PatchJson6902Factory{loader: l}
}
// MakePatchJson6902Transformer returns a transformer for applying Json6902 patch
func (f PatchJson6902Factory) MakePatchJson6902Transformer(patches []patch.PatchJson6902) (transformers.Transformer, error) {
var ts []transformers.Transformer
for _, p := range patches {
t, err := f.makeOnePatchJson6902Transformer(p)
if err != nil {
return nil, err
}
if t != nil {
ts = append(ts, t)
}
}
return transformers.NewMultiTransformerWithConflictCheck(ts), nil
}
func (f PatchJson6902Factory) makeOnePatchJson6902Transformer(p patch.PatchJson6902) (transformers.Transformer, error) {
if p.Target == nil {
return nil, fmt.Errorf("must specify the target field in patchesJson6902")
}
if p.Path == "" {
return nil, fmt.Errorf("must specify the path for a json patch file")
}
targetId := resource.NewResIdWithPrefixNamespace(
schema.GroupVersionKind{
Group: p.Target.Group,
Version: p.Target.Version,
Kind: p.Target.Kind,
},
p.Target.Name,
"",
p.Target.Namespace,
)
rawOp, err := f.loader.Load(p.Path)
if err != nil {
return nil, err
}
if isJsonFormat(rawOp) {
decodedPatch, err := jsonpatch.DecodePatch(rawOp)
if err != nil {
return nil, err
}
return newPatchJson6902JSONTransformer(targetId, decodedPatch)
}
decodedPatch, err := yamlpatch.DecodePatch(rawOp)
if err != nil {
return nil, err
}
return newPatchJson6902YAMLTransformer(targetId, decodedPatch)
}
func isJsonFormat(data []byte) bool {
return data[0] == '['
}

View File

@@ -0,0 +1,331 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"reflect"
"strings"
"testing"
"gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/patch"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
func TestNewPatchJson6902FactoryNoTarget(t *testing.T) {
p := patch.PatchJson6902{}
_, err := NewPatchJson6902Factory(nil).makeOnePatchJson6902Transformer(p)
if err == nil {
t.Fatal("expected error")
}
if !strings.Contains(err.Error(), "must specify the target field in patchesJson6902") {
t.Fatalf("incorrect error returned: %v", err)
}
}
func TestNewPatchJson6902FactoryConflict(t *testing.T) {
jsonPatch := []byte(`
target:
name: some-name
kind: Deployment
`)
p := patch.PatchJson6902{}
err := yaml.Unmarshal(jsonPatch, &p)
if err != nil {
t.Fatalf("expected error %v", err)
}
f := NewPatchJson6902Factory(nil)
_, err = f.makeOnePatchJson6902Transformer(p)
if err == nil {
t.Fatal("expected error")
}
if !strings.Contains(err.Error(), "must specify the path for a json patch file") {
t.Fatalf("incorrect error returned %v", err)
}
}
func TestNewPatchJson6902FactoryJSON(t *testing.T) {
ldr := loadertest.NewFakeLoader("/testpath")
operations := []byte(`[
{"op": "replace", "path": "/spec/template/spec/containers/0/name", "value": "my-nginx"},
{"op": "add", "path": "/spec/replica", "value": "3"},
{"op": "add", "path": "/spec/template/spec/containers/0/command", "value": ["arg1", "arg2", "arg3"]}
]`)
err := ldr.AddFile("/testpath/patch.json", operations)
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
jsonPatch := []byte(`
target:
kind: Deployment
name: some-name
path: /testpath/patch.json
`)
p := patch.PatchJson6902{}
err = yaml.Unmarshal(jsonPatch, &p)
if err != nil {
t.Fatal("expected error")
}
tr, err := NewPatchJson6902Factory(ldr).makeOnePatchJson6902Transformer(p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
if tr == nil {
t.Fatal("the returned transformer should not be nil")
}
}
func TestNewPatchJson6902FactoryYAML(t *testing.T) {
ldr := loadertest.NewFakeLoader("/testpath")
operations := []byte(`
- op: replace
path: /spec/template/spec/containers/0/name
value: my-nginx
- op: add
path: /spec/replica
value: 3
- op: add
path: /spec/template/spec/containers/0/command
value: ["arg1", "arg2", "arg3"]
`)
err := ldr.AddFile("/testpath/patch.yaml", operations)
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
jsonPatch := []byte(`
target:
name: some-name
kind: Deployment
path: /testpath/patch.yaml
`)
p := patch.PatchJson6902{}
err = yaml.Unmarshal(jsonPatch, &p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
tr, err := NewPatchJson6902Factory(ldr).makeOnePatchJson6902Transformer(p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
if tr == nil {
t.Fatal("the returned transformer should not be nil")
}
}
func TestNewPatchJson6902FactoryMulti(t *testing.T) {
ldr := loadertest.NewFakeLoader("/testpath")
operations := []byte(`[
{"op": "replace", "path": "/spec/template/spec/containers/0/name", "value": "my-nginx"},
{"op": "add", "path": "/spec/replica", "value": "3"}
]`)
err := ldr.AddFile("/testpath/patch.json", operations)
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
operations = []byte(`
- op: add
path: /spec/template/spec/containers/0/command
value: ["arg1", "arg2", "arg3"]
`)
err = ldr.AddFile("/testpath/patch.yaml", operations)
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
jsonPatches := []byte(`
- target:
kind: foo
name: some-name
path: /testpath/patch.json
- target:
kind: foo
name: some-name
path: /testpath/patch.yaml
`)
var p []patch.PatchJson6902
err = yaml.Unmarshal(jsonPatches, &p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
f := NewPatchJson6902Factory(ldr)
tr, err := f.MakePatchJson6902Transformer(p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
if tr == nil {
t.Fatal("the returned transformer should not be nil")
}
id := resource.NewResId(schema.GroupVersionKind{Kind: "foo"}, "some-name")
base := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"kind": "foo",
"metadata": map[string]interface{}{
"name": "some-name",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "nginx",
},
},
},
},
},
}),
}
expected := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"kind": "foo",
"metadata": map[string]interface{}{
"name": "some-name",
},
"spec": map[string]interface{}{
"replica": "3",
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "my-nginx",
"command": []interface{}{
"arg1",
"arg2",
"arg3",
},
},
},
},
},
},
}),
}
err = tr.Transform(base)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
if !reflect.DeepEqual(base, expected) {
err = expected.ErrorIfNotEqual(base)
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestNewPatchJson6902FactoryMultiConflict(t *testing.T) {
ldr := loadertest.NewFakeLoader("/testpath")
operations := []byte(`[
{"op": "add", "path": "/spec/replica", "value": "3"}
]`)
err := ldr.AddFile("/testpath/patch.json", operations)
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
operations = []byte(`
- op: add
path: /spec/replica
value: 4
`)
err = ldr.AddFile("/testpath/patch.yaml", operations)
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
jsonPatches := []byte(`
- target:
kind: foo
name: some-name
path: /testpath/patch.json
- target:
kind: foo
name: some-name
path: /testpath/patch.yaml
`)
var p []patch.PatchJson6902
err = yaml.Unmarshal(jsonPatches, &p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
f := NewPatchJson6902Factory(ldr)
tr, err := f.MakePatchJson6902Transformer(p)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
if tr == nil {
t.Fatal("the returned transformer should not be nil")
}
id := resource.NewResId(schema.GroupVersionKind{Kind: "foo"}, "some-name")
base := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"kind": "foo",
"metadata": map[string]interface{}{
"name": "somename",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "nginx",
},
},
},
},
},
}),
}
err = tr.Transform(base)
if err == nil {
t.Fatal("expected conflict")
}
if !strings.Contains(err.Error(), "found conflict between different patches") {
t.Fatalf("incorrect error happened %v", err)
}
}

View File

@@ -0,0 +1,61 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"github.com/evanphx/json-patch"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// patchJson6902JSONTransformer applies patches.
type patchJson6902JSONTransformer struct {
target resource.ResId
patch jsonpatch.Patch
}
var _ transformers.Transformer = &patchJson6902JSONTransformer{}
// newPatchJson6902JSONTransformer constructs a PatchJson6902 transformer.
func newPatchJson6902JSONTransformer(t resource.ResId, p jsonpatch.Patch) (transformers.Transformer, error) {
if len(p) == 0 {
return transformers.NewNoOpTransformer(), nil
}
return &patchJson6902JSONTransformer{target: t, patch: p}, nil
}
// Transform apply the json patches on top of the base resources.
func (t *patchJson6902JSONTransformer) Transform(baseResourceMap resmap.ResMap) error {
obj, err := findTargetObj(baseResourceMap, t.target)
if obj == nil {
return err
}
rawObj, err := obj.Unstructured.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := t.patch.Apply(rawObj)
if err != nil {
return err
}
err = obj.UnmarshalJSON(modifiedObj)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,112 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"reflect"
"testing"
"github.com/evanphx/json-patch"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
func TestJsonPatchJSONTransformer_Transform(t *testing.T) {
id := resource.NewResId(deploy, "deploy1")
base := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx",
},
},
},
},
},
}),
}
operations := []byte(`[
{"op": "replace", "path": "/spec/template/spec/containers/0/name", "value": "my-nginx"},
{"op": "add", "path": "/spec/replica", "value": "3"},
{"op": "add", "path": "/spec/template/spec/containers/0/command", "value": ["arg1", "arg2", "arg3"]}
]`)
patch, err := jsonpatch.DecodePatch(operations)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
expected := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"replica": "3",
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "my-nginx",
"command": []interface{}{
"arg1",
"arg2",
"arg3",
},
},
},
},
},
},
}),
}
jpt, err := newPatchJson6902JSONTransformer(id, patch)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
err = jpt.Transform(base)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(base, expected) {
err = expected.ErrorIfNotEqual(base)
t.Fatalf("actual doesn't match expected: %v", err)
}
}

View File

@@ -0,0 +1,62 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"github.com/ghodss/yaml"
"github.com/krishicks/yaml-patch"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// patchJson6902YAMLTransformer applies patches.
type patchJson6902YAMLTransformer struct {
target resource.ResId
patch yamlpatch.Patch
}
var _ transformers.Transformer = &patchJson6902YAMLTransformer{}
// newPatchJson6902YAMLTransformer constructs a PatchJson6902 transformer.
func newPatchJson6902YAMLTransformer(t resource.ResId, p yamlpatch.Patch) (transformers.Transformer, error) {
if len(p) == 0 {
return transformers.NewNoOpTransformer(), nil
}
return &patchJson6902YAMLTransformer{target: t, patch: p}, nil
}
// Transform apply the json patches on top of the base resources.
func (t *patchJson6902YAMLTransformer) Transform(baseResourceMap resmap.ResMap) error {
obj, err := findTargetObj(baseResourceMap, t.target)
if obj == nil {
return err
}
rawObj, err := yaml.Marshal(obj.Unstructured.Object)
if err != nil {
return err
}
modifiedObj, err := t.patch.Apply(rawObj)
if err != nil {
return err
}
err = yaml.Unmarshal(modifiedObj, &obj.Unstructured.Object)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,128 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"reflect"
"testing"
"github.com/krishicks/yaml-patch"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
var deploy = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}
func TestJsonPatchYAMLTransformer_Transform(t *testing.T) {
id := resource.NewResId(deploy, "deploy1")
base := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx",
},
},
},
},
},
}),
}
var image, replica, command interface{}
image = "my-nginx"
replica = "3"
command = []string{"arg1", "arg2", "arg3"}
patch := yamlpatch.Patch{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/name",
Value: yamlpatch.NewNode(&image),
},
{
Op: "add",
Path: "/spec/replica",
Value: yamlpatch.NewNode(&replica),
},
{
Op: "add",
Path: "/spec/template/spec/containers/0/command",
Value: yamlpatch.NewNode(&command),
},
}
expected := resmap.ResMap{
id: resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"replica": "3",
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "my-nginx",
"command": []interface{}{
"arg1",
"arg2",
"arg3",
},
},
},
},
},
},
}),
}
jpt, err := newPatchJson6902YAMLTransformer(id, patch)
if err != nil {
t.Fatalf("unexpected error : %v", err)
}
err = jpt.Transform(base)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(base, expected) {
err = expected.ErrorIfNotEqual(base)
t.Fatalf("actual doesn't match expected: %v", err)
}
}

View File

@@ -0,0 +1,47 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transformer
import (
"fmt"
"log"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
func findTargetObj(m resmap.ResMap, targetId resource.ResId) (*resource.Resource, error) {
matchedIds := m.FindByGVKN(targetId)
if targetId.Namespace() != "" {
var ids []resource.ResId
for _, id := range matchedIds {
if id.Namespace() == targetId.Namespace() {
ids = append(ids, id)
}
}
matchedIds = ids
}
if len(matchedIds) == 0 {
log.Printf("Couldn't find any object to apply the json patch %v, skipping it.", targetId)
return nil, nil
}
if len(matchedIds) > 1 {
return nil, fmt.Errorf("found multiple objects that the patch can apply %v", matchedIds)
}
return m[matchedIds[0]], nil
}

View File

@@ -17,9 +17,9 @@ limitations under the License.
package resmap
import (
"github.com/kubernetes-sigs/kustomize/pkg/configmapandsecret"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
// NewResMapFromConfigMapArgs returns a Resource slice given

View File

@@ -20,12 +20,12 @@ import (
"reflect"
"testing"
"github.com/kubernetes-sigs/kustomize/pkg/configmapandsecret"
"github.com/kubernetes-sigs/kustomize/pkg/fs"
"github.com/kubernetes-sigs/kustomize/pkg/internal/loadertest"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"github.com/kubernetes-sigs/kustomize/pkg/types"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
var cmap = schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"}

View File

@@ -19,8 +19,8 @@ package resmap
import (
"sort"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/pkg/resource"
)
// IdSlice implements the sort interface.
@@ -34,7 +34,7 @@ func (a IdSlice) Less(i, j int) bool {
if a[i].Gvk().String() != a[j].Gvk().String() {
return gvkLess(a[i].Gvk(), a[j].Gvk())
}
return a[i].Name() < a[j].Name()
return a[i].String() < a[j].String()
}
var order = []string{"Namespace", "CustomResourceDefinition", "ServiceAccount",

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