mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-30 09:51:23 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bff2e8883 | ||
|
|
483188ba89 | ||
|
|
672bda0c9c | ||
|
|
49b32473ca | ||
|
|
08400d77a6 | ||
|
|
c912baeb3a | ||
|
|
433733eb0e | ||
|
|
f996ac82c7 | ||
|
|
efcb7cc5a5 | ||
|
|
bf7b57537b | ||
|
|
6b597f8711 | ||
|
|
088739900f | ||
|
|
3bf13f83d3 | ||
|
|
c64a72f1f9 | ||
|
|
8b60b456ac |
@@ -1,5 +1,7 @@
|
|||||||
# kustomize
|
# kustomize
|
||||||
|
|
||||||
|
_[v3.0.0](https://github.com/kubernetes-sigs/kustomize/releases/tag/v3.0.0) is the latest release._
|
||||||
|
|
||||||
`kustomize` lets you customize raw, template-free YAML
|
`kustomize` lets you customize raw, template-free YAML
|
||||||
files for multiple purposes, leaving the original YAML
|
files for multiple purposes, leaving the original YAML
|
||||||
untouched and usable as is.
|
untouched and usable as is.
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
# Go Plugin Guided Example for Linux
|
# Go Plugin Guided Example for Linux
|
||||||
|
|
||||||
This is a (no reading allowed!) 60 second copy/paste guided
|
|
||||||
example. Full plugin docs [here](README.md).
|
|
||||||
|
|
||||||
[SopsEncodedSecrets repository]: https://github.com/monopole/sopsencodedsecrets
|
[SopsEncodedSecrets repository]: https://github.com/monopole/sopsencodedsecrets
|
||||||
[Go plugin]: https://golang.org/pkg/plugin
|
[Go plugin]: https://golang.org/pkg/plugin
|
||||||
|
[Go plugin caveats]: goPluginCaveats.md
|
||||||
|
|
||||||
|
This is a (no reading allowed!) 60 second copy/paste guided
|
||||||
|
example.
|
||||||
|
|
||||||
|
Full plugin docs [here](README.md).
|
||||||
|
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].
|
||||||
@@ -25,15 +30,18 @@ current setup.
|
|||||||
## Make a place to work
|
## Make a place to work
|
||||||
|
|
||||||
```
|
```
|
||||||
|
# Keeping these separate to avoid cluttering the DEMO dir.
|
||||||
DEMO=$(mktemp -d)
|
DEMO=$(mktemp -d)
|
||||||
|
tmpGoPath=$(mktemp -d)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install kustomize
|
## Install kustomize
|
||||||
|
|
||||||
Need v3.0.0 for what follows:
|
Need v3.0.0 for what follows, and you must _compile_
|
||||||
|
it (not download the binary from the release page):
|
||||||
|
|
||||||
```
|
```
|
||||||
GOBIN=$DEMO/bin go get sigs.k8s.io/kustomize/v3/cmd/kustomize@v3.0.0-pre
|
GOPATH=$tmpGoPath go install sigs.k8s.io/kustomize/v3/cmd/kustomize
|
||||||
```
|
```
|
||||||
|
|
||||||
## Make a home for plugins
|
## Make a home for plugins
|
||||||
@@ -147,7 +155,7 @@ Build the object code for use by kustomize:
|
|||||||
|
|
||||||
```
|
```
|
||||||
cd $MY_PLUGIN_DIR
|
cd $MY_PLUGIN_DIR
|
||||||
go build -buildmode plugin -o ${kind}.so ${kind}.go
|
GOPATH=$tmpGoPath go build -buildmode plugin -o ${kind}.so ${kind}.go
|
||||||
```
|
```
|
||||||
|
|
||||||
This step may succeed, but kustomize might
|
This step may succeed, but kustomize might
|
||||||
@@ -199,7 +207,8 @@ cat <<EOF >$MYAPP/secGenerator.yaml
|
|||||||
apiVersion: ${apiVersion}
|
apiVersion: ${apiVersion}
|
||||||
kind: ${kind}
|
kind: ${kind}
|
||||||
metadata:
|
metadata:
|
||||||
name: forbiddenValues
|
name: mySecretGenerator
|
||||||
|
name: forbiddenValues
|
||||||
namespace: production
|
namespace: production
|
||||||
file: myEncryptedData.yaml
|
file: myEncryptedData.yaml
|
||||||
keys:
|
keys:
|
||||||
@@ -257,7 +266,7 @@ echo $keyLocation
|
|||||||
### Install `sops`
|
### Install `sops`
|
||||||
|
|
||||||
```
|
```
|
||||||
GOBIN=$DEMO/bin 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 Google Cloud key
|
||||||
@@ -270,13 +279,12 @@ ROCKET: saturn-v
|
|||||||
FRUIT: apple
|
FRUIT: apple
|
||||||
CAR: dymaxion
|
CAR: dymaxion
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Encrypt the data into file the plugin wants to read:
|
Encrypt the data into file the plugin wants to read:
|
||||||
|
|
||||||
```
|
```
|
||||||
$DEMO/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
|
||||||
```
|
```
|
||||||
@@ -287,11 +295,32 @@ Review the files
|
|||||||
tree $DEMO
|
tree $DEMO
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This should look something like:
|
||||||
|
|
||||||
|
> ```
|
||||||
|
> /tmp/tmp.0kIE9VclPt
|
||||||
|
> ├── kustomize
|
||||||
|
> │ └── plugin
|
||||||
|
> │ └── mygenerators
|
||||||
|
> │ └── sopsencodedsecrets
|
||||||
|
> │ ├── go.mod
|
||||||
|
> │ ├── go.sum
|
||||||
|
> │ ├── LICENSE
|
||||||
|
> │ ├── README.md
|
||||||
|
> │ ├── SopsEncodedSecrets.go
|
||||||
|
> │ ├── SopsEncodedSecrets.so
|
||||||
|
> │ └── SopsEncodedSecrets_test.go
|
||||||
|
> └── myapp
|
||||||
|
> ├── kustomization.yaml
|
||||||
|
> ├── myClearData.yaml
|
||||||
|
> ├── myEncryptedData.yaml
|
||||||
|
> └── secGenerator.yaml
|
||||||
|
> ```
|
||||||
|
|
||||||
## Build your app, using the plugin:
|
## Build your app, using the plugin:
|
||||||
|
|
||||||
```
|
```
|
||||||
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
|
XDG_CONFIG_HOME=$DEMO $tmpGoPath/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||||||
```
|
```
|
||||||
|
|
||||||
This should emit a kubernetes secret, with
|
This should emit a kubernetes secret, with
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
# kustomize 3.0.0
|
# kustomize 3.0.0
|
||||||
|
|
||||||
This release is basically [v2.1.0](v2.1.0.md),
|
This release is basically [v2.1.0](v2.1.0.md),
|
||||||
with some post-v2.1.0 bugs fixed and a `v3` in Go
|
with many post-v2.1.0 bugs fixed (in about 150
|
||||||
package paths.
|
commits) and a `v3` in Go package paths.
|
||||||
|
|
||||||
[plugin]: https://github.com/kubernetes-sigs/kustomize/tree/master/docs/plugins
|
[plugin]: https://github.com/kubernetes-sigs/kustomize/tree/master/docs/plugins
|
||||||
|
|
||||||
The major version increment to `v3` puts a new
|
The major version increment to `v3` puts a new
|
||||||
floor on a stable API for [plugin] developers
|
floor on a stable API for [plugin] developers
|
||||||
(both _Go_ plugin developers and _exec_ plugin
|
(both _Go_ plugin developers and _exec_ plugin
|
||||||
developers who happen to use Go), to carry them
|
developers who happen to use Go).
|
||||||
through the coming series of minor releases and
|
|
||||||
patches.
|
|
||||||
|
|
||||||
|
|
||||||
### Why so soon after v2.1.0?
|
### Why so soon after v2.1.0?
|
||||||
|
|
||||||
|
|||||||
1
go.sum
1
go.sum
@@ -149,6 +149,7 @@ k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c=
|
|||||||
k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208 h1:5sW+fEHvlJI3Ngolx30CmubFulwH28DhKjGf70Xmtco=
|
k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208 h1:5sW+fEHvlJI3Ngolx30CmubFulwH28DhKjGf70Xmtco=
|
||||||
k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
|
k8s.io/kube-openapi v0.0.0-20190603182131-db7b694dc208/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
|
||||||
|
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ type Kunstructured interface {
|
|||||||
GetKind() string
|
GetKind() string
|
||||||
GetName() string
|
GetName() string
|
||||||
SetName(string)
|
SetName(string)
|
||||||
|
SetNamespace(string)
|
||||||
GetLabels() map[string]string
|
GetLabels() map[string]string
|
||||||
SetLabels(map[string]string)
|
SetLabels(map[string]string)
|
||||||
GetAnnotations() map[string]string
|
GetAnnotations() map[string]string
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ func (r *Resource) Replace(other *Resource) {
|
|||||||
r.SetAnnotations(
|
r.SetAnnotations(
|
||||||
mergeStringMaps(other.GetAnnotations(), r.GetAnnotations()))
|
mergeStringMaps(other.GetAnnotations(), r.GetAnnotations()))
|
||||||
r.SetName(other.GetName())
|
r.SetName(other.GetName())
|
||||||
|
r.SetNamespace(other.GetNamespace())
|
||||||
r.copyOtherFields(other)
|
r.copyOtherFields(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,3 +87,43 @@ metadata:
|
|||||||
type: Opaque
|
type: Opaque
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNamespacedGeneratorWithOverlays(t *testing.T) {
|
||||||
|
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
|
||||||
|
th.WriteK("/app/base", `
|
||||||
|
namespace: base
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: testCase
|
||||||
|
literals:
|
||||||
|
- base=true
|
||||||
|
`)
|
||||||
|
th.WriteK("/app/overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
|
||||||
|
namespace: overlay
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: testCase
|
||||||
|
behavior: merge
|
||||||
|
literals:
|
||||||
|
- overlay=true
|
||||||
|
`)
|
||||||
|
m, err := th.MakeKustTarget().MakeCustomizedResMap()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Err: %v", err)
|
||||||
|
}
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
base: "true"
|
||||||
|
overlay: "true"
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
annotations: {}
|
||||||
|
labels: {}
|
||||||
|
name: testCase-4g75kbk6gm
|
||||||
|
namespace: overlay
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.updateClusterRoleBinding(m)
|
p.updateClusterRoleBinding(m)
|
||||||
|
p.updateServiceReference(m)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,3 +126,40 @@ func (p *NamespaceTransformerPlugin) updateClusterRoleBinding(m resmap.ResMap) {
|
|||||||
objMap["subjects"] = subjects
|
objMap["subjects"] = subjects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *NamespaceTransformerPlugin) updateServiceReference(m resmap.ResMap) {
|
||||||
|
svc := gvk.Gvk{Version: "v1", Kind: "Service"}
|
||||||
|
svcMap := map[string]bool{}
|
||||||
|
for _, id := range m.AllIds() {
|
||||||
|
if id.Gvk.Equals(svc) {
|
||||||
|
svcMap[id.Name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, res := range m.Resources() {
|
||||||
|
if res.OrgId().Kind != "ValidatingWebhookConfiguration" &&
|
||||||
|
res.OrgId().Kind != "MutatingWebhookConfiguration" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
objMap := res.Map()
|
||||||
|
webhooks, ok := objMap["webhooks"].([]interface{})
|
||||||
|
if webhooks == nil || !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i := range webhooks {
|
||||||
|
webhook := webhooks[i].(map[string]interface{})
|
||||||
|
transformers.MutateField(
|
||||||
|
webhook, []string{"clientConfig", "service"},
|
||||||
|
false, func(obj interface{}) (interface{}, error) {
|
||||||
|
svc := obj.(map[string]interface{})
|
||||||
|
svcName, foundN := svc["name"]
|
||||||
|
if foundN && svcMap[svcName.(string)] {
|
||||||
|
svc["namespace"] = p.Namespace
|
||||||
|
}
|
||||||
|
return svc, nil
|
||||||
|
})
|
||||||
|
webhooks[i] = webhook
|
||||||
|
}
|
||||||
|
objMap["webhooks"] = webhooks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ func (p *plugin) Transform(m resmap.ResMap) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.updateClusterRoleBinding(m)
|
p.updateClusterRoleBinding(m)
|
||||||
|
p.updateServiceReference(m)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,3 +127,40 @@ func (p *plugin) updateClusterRoleBinding(m resmap.ResMap) {
|
|||||||
objMap["subjects"] = subjects
|
objMap["subjects"] = subjects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *plugin) updateServiceReference(m resmap.ResMap) {
|
||||||
|
svc := gvk.Gvk{Version: "v1", Kind: "Service"}
|
||||||
|
svcMap := map[string]bool{}
|
||||||
|
for _, id := range m.AllIds() {
|
||||||
|
if id.Gvk.Equals(svc) {
|
||||||
|
svcMap[id.Name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, res := range m.Resources() {
|
||||||
|
if res.OrgId().Kind != "ValidatingWebhookConfiguration" &&
|
||||||
|
res.OrgId().Kind != "MutatingWebhookConfiguration" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
objMap := res.Map()
|
||||||
|
webhooks, ok := objMap["webhooks"].([]interface{})
|
||||||
|
if webhooks == nil || !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i := range webhooks {
|
||||||
|
webhook := webhooks[i].(map[string]interface{})
|
||||||
|
transformers.MutateField(
|
||||||
|
webhook, []string{"clientConfig", "service"},
|
||||||
|
false, func(obj interface{}) (interface{}, error) {
|
||||||
|
svc := obj.(map[string]interface{})
|
||||||
|
svcName, foundN := svc["name"]
|
||||||
|
if foundN && svcMap[svcName.(string)] {
|
||||||
|
svc["namespace"] = p.Namespace
|
||||||
|
}
|
||||||
|
return svc, nil
|
||||||
|
})
|
||||||
|
webhooks[i] = webhook
|
||||||
|
}
|
||||||
|
objMap["webhooks"] = webhooks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ metadata:
|
|||||||
namespace: foo
|
namespace: foo
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: svc1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: ns1
|
name: ns1
|
||||||
@@ -72,6 +77,22 @@ subjects:
|
|||||||
name: another
|
name: another
|
||||||
namespace: random
|
namespace: random
|
||||||
---
|
---
|
||||||
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
|
kind: ValidatingWebhookConfiguration
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
webhooks:
|
||||||
|
- name: example1
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc1
|
||||||
|
namespace: system
|
||||||
|
- name: example2
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc2
|
||||||
|
namespace: system
|
||||||
|
---
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
@@ -92,6 +113,12 @@ metadata:
|
|||||||
namespace: test
|
namespace: test
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: svc1
|
||||||
|
namespace: test
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: ns1
|
name: ns1
|
||||||
@@ -123,6 +150,22 @@ subjects:
|
|||||||
name: another
|
name: another
|
||||||
namespace: random
|
namespace: random
|
||||||
---
|
---
|
||||||
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
|
kind: ValidatingWebhookConfiguration
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
webhooks:
|
||||||
|
- clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc1
|
||||||
|
namespace: test
|
||||||
|
name: example1
|
||||||
|
- clientConfig:
|
||||||
|
service:
|
||||||
|
name: svc2
|
||||||
|
namespace: system
|
||||||
|
name: example2
|
||||||
|
---
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -75,14 +75,14 @@ git tag -a $version -m "Release $version"
|
|||||||
```
|
```
|
||||||
|
|
||||||
### trigger the cloud build
|
### trigger the cloud build
|
||||||
|
Push the tag:
|
||||||
Pushing the tag will trigger a job in [Google Cloud
|
|
||||||
Build] to put a new release on the [releases page].
|
|
||||||
|
|
||||||
```
|
```
|
||||||
git push upstream $version
|
git push upstream $version
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This triggers a job in [Google Cloud Build] to
|
||||||
|
put a new release on the [release page].
|
||||||
|
|
||||||
### Update release notes
|
### Update release notes
|
||||||
|
|
||||||
Visit the [release page] and edit the release notes as desired.
|
Visit the [release page] and edit the release notes as desired.
|
||||||
|
|||||||
Reference in New Issue
Block a user