mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 01:50:55 +00:00
Merge pull request #1145 from monopole/invTransformerPlugin
Convert inventory transformer to plugin, reduce k8sdeps.
This commit is contained in:
3
go.mod
3
go.mod
@@ -27,8 +27,7 @@ require (
|
|||||||
github.com/spf13/cobra v0.0.2
|
github.com/spf13/cobra v0.0.2
|
||||||
github.com/spf13/pflag v1.0.1
|
github.com/spf13/pflag v1.0.1
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20190225153610-fe579d43d832 // indirect
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d // indirect
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect
|
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.1
|
gopkg.in/yaml.v2 v2.2.1
|
||||||
k8s.io/api v0.0.0-20180510062335-53d615ae3f44
|
k8s.io/api v0.0.0-20180510062335-53d615ae3f44
|
||||||
|
|||||||
7
go.sum
7
go.sum
@@ -58,16 +58,23 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190225153610-fe579d43d832 h1:2IdId8zoI92l1bUzjAOygcAOkmCe13HY1j0rqPPPzB8=
|
golang.org/x/net v0.0.0-20190225153610-fe579d43d832 h1:2IdId8zoI92l1bUzjAOygcAOkmCe13HY1j0rqPPPzB8=
|
||||||
golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d h1:bt+R27hbE7uVf7PY9S6wpNg9Xo2WRe/XQT0uGq9RQQw=
|
||||||
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
|
|||||||
@@ -5,12 +5,9 @@
|
|||||||
package transformer
|
package transformer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/k8sdeps/transformer/inventory"
|
|
||||||
"sigs.k8s.io/kustomize/k8sdeps/transformer/patch"
|
"sigs.k8s.io/kustomize/k8sdeps/transformer/patch"
|
||||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resource"
|
"sigs.k8s.io/kustomize/pkg/resource"
|
||||||
"sigs.k8s.io/kustomize/pkg/transformers"
|
"sigs.k8s.io/kustomize/pkg/transformers"
|
||||||
"sigs.k8s.io/kustomize/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FactoryImpl makes patch transformer and name hash transformer
|
// FactoryImpl makes patch transformer and name hash transformer
|
||||||
@@ -27,11 +24,3 @@ func (p *FactoryImpl) MakePatchTransformer(
|
|||||||
rf *resource.Factory) (transformers.Transformer, error) {
|
rf *resource.Factory) (transformers.Transformer, error) {
|
||||||
return patch.NewTransformer(slice, rf)
|
return patch.NewTransformer(slice, rf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *FactoryImpl) MakeInventoryTransformer(
|
|
||||||
arg *types.Inventory,
|
|
||||||
ldr ifc.Loader,
|
|
||||||
namespace string,
|
|
||||||
gp types.GarbagePolicy) transformers.Transformer {
|
|
||||||
return inventory.NewTransformer(arg, ldr, namespace, gp)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package inventory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/hasher"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/inventory"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resid"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resource"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/transformers"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// transformer compute the inventory object used in prune
|
|
||||||
type transformer struct {
|
|
||||||
garbagePolicy types.GarbagePolicy
|
|
||||||
ldr ifc.Loader
|
|
||||||
cmName string
|
|
||||||
cmNamespace string
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ transformers.Transformer = &transformer{}
|
|
||||||
|
|
||||||
// NewTransformer makes a new inventory transformer.
|
|
||||||
func NewTransformer(
|
|
||||||
p *types.Inventory,
|
|
||||||
ldr ifc.Loader,
|
|
||||||
namespace string,
|
|
||||||
gp types.GarbagePolicy) transformers.Transformer {
|
|
||||||
if p == nil || p.Type != "ConfigMap" || p.ConfigMap.Namespace != namespace {
|
|
||||||
return transformers.NewNoOpTransformer()
|
|
||||||
}
|
|
||||||
return &transformer{
|
|
||||||
garbagePolicy: gp,
|
|
||||||
ldr: ldr,
|
|
||||||
cmName: p.ConfigMap.Name,
|
|
||||||
cmNamespace: p.ConfigMap.Namespace,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform generates an inventory object based on the input ResMap.
|
|
||||||
// this transformer doesn't change existing resources -
|
|
||||||
// it just visits resources and accumulates information to make a new ConfigMap.
|
|
||||||
// The prune ConfigMap is used to support the pruning command in the client side tool,
|
|
||||||
// which is proposed in https://github.com/kubernetes/enhancements/pull/810
|
|
||||||
// The inventory data is written to annotation since
|
|
||||||
// 1. The key in data field is constrained and couldn't include arbitrary letters
|
|
||||||
// 2. The annotation can be put into any kind of objects
|
|
||||||
func (tf *transformer) Transform(m resmap.ResMap) error {
|
|
||||||
invty := inventory.NewInventory()
|
|
||||||
var keys []string
|
|
||||||
for _, r := range m {
|
|
||||||
ns, _ := r.GetFieldValue("metadata.namespace")
|
|
||||||
item := resid.NewItemId(r.GetGvk(), ns, r.GetName())
|
|
||||||
var refs []resid.ItemId
|
|
||||||
|
|
||||||
for _, refid := range r.GetRefBy() {
|
|
||||||
ref := m[refid]
|
|
||||||
ns, _ := ref.GetFieldValue("metadata.namespace")
|
|
||||||
refs = append(refs, resid.NewItemId(ref.GetGvk(), ns, ref.GetName()))
|
|
||||||
}
|
|
||||||
invty.Current[item] = refs
|
|
||||||
keys = append(keys, item.String())
|
|
||||||
}
|
|
||||||
h, err := hasher.SortArrayAndComputeHash(keys)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
args := &types.ConfigMapArgs{}
|
|
||||||
args.Name = tf.cmName
|
|
||||||
args.Namespace = tf.cmNamespace
|
|
||||||
opts := &types.GeneratorOptions{
|
|
||||||
Annotations: make(map[string]string),
|
|
||||||
}
|
|
||||||
opts.Annotations[inventory.HashAnnotation] = h
|
|
||||||
err = invty.UpdateAnnotations(opts.Annotations)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
kf := kunstruct.NewKunstructuredFactoryImpl()
|
|
||||||
k, err := kf.MakeConfigMap(tf.ldr, opts, args)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if tf.garbagePolicy == types.GarbageCollect {
|
|
||||||
for k := range m {
|
|
||||||
delete(m, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
id := resid.NewResIdWithPrefixNamespace(
|
|
||||||
gvk.Gvk{
|
|
||||||
Version: "v1",
|
|
||||||
Kind: "ConfigMap",
|
|
||||||
},
|
|
||||||
tf.cmName,
|
|
||||||
"", tf.cmNamespace)
|
|
||||||
if _, ok := m[id]; ok {
|
|
||||||
return fmt.Errorf("id %v is already used, please use a different name in the prune field", id)
|
|
||||||
}
|
|
||||||
m[id] = resource.NewFactory(kf).FromKunstructured(k)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package inventory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/fs"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/loader"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resid"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resource"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/types"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/validators"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secret = gvk.Gvk{Version: "v1", Kind: "Secret"}
|
|
||||||
var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"}
|
|
||||||
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
|
|
||||||
|
|
||||||
func makeResMap() resmap.ResMap {
|
|
||||||
rf := resource.NewFactory(
|
|
||||||
kunstruct.NewKunstructuredFactoryImpl())
|
|
||||||
objs := resmap.ResMap{
|
|
||||||
resid.NewResId(cmap, "cm1"): rf.FromMap(
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "ConfigMap",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "cm1",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
resid.NewResId(secret, "secret1"): rf.FromMap(
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "Secret",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "secret1",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
resid.NewResId(deploy, "deploy1"): rf.FromMap(
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deploy1",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"containers": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "nginx",
|
|
||||||
"image": "nginx:1.7.9",
|
|
||||||
"env": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"name": "CM_FOO",
|
|
||||||
"valueFrom": map[string]interface{}{
|
|
||||||
"configMapKeyRef": map[string]interface{}{
|
|
||||||
"name": "cm1",
|
|
||||||
"key": "somekey",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"envFrom": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"configMapRef": map[string]interface{}{
|
|
||||||
"name": "cm1",
|
|
||||||
"key": "somekey",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"secretRef": map[string]interface{}{
|
|
||||||
"name": "secret1",
|
|
||||||
"key": "somekey",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
objs[resid.NewResId(cmap, "cm1")].AppendRefBy(resid.NewResId(deploy, "deploy1"))
|
|
||||||
objs[resid.NewResId(secret, "secret1")].AppendRefBy(resid.NewResId(deploy, "deploy1"))
|
|
||||||
return objs
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInventoryTransformer(t *testing.T) {
|
|
||||||
rf := resource.NewFactory(
|
|
||||||
kunstruct.NewKunstructuredFactoryImpl())
|
|
||||||
ldr := loader.NewFileLoaderAtCwd(validators.MakeFakeValidator(), fs.MakeFakeFS())
|
|
||||||
|
|
||||||
// hash is derived based on all keys in the Inventory
|
|
||||||
// It is added to annotations as
|
|
||||||
// kustomize.config.k8s.io/InventoryHash: hash
|
|
||||||
// When seeing the same annotation, prune binary assumes no
|
|
||||||
// clean up is needed
|
|
||||||
hash := "h44788gt7g"
|
|
||||||
|
|
||||||
// inventory is the derived json string for an Inventory object
|
|
||||||
// It is added to annotations as
|
|
||||||
// kustomize.config.k8s.io/Inventory: inventory
|
|
||||||
inventory := "{\"current\":{\"apps_v1_Deployment|~X|deploy1\":null,\"~G_v1_ConfigMap|~X|cm1\":[{\"group\":\"apps\",\"version\":\"v1\",\"kind\":\"Deployment\",\"name\":\"deploy1\"}],\"~G_v1_Secret|~X|secret1\":[{\"group\":\"apps\",\"version\":\"v1\",\"kind\":\"Deployment\",\"name\":\"deploy1\"}]}}" // nolint
|
|
||||||
|
|
||||||
// This is the root or inventory object which tracks all
|
|
||||||
// the applied resources - this is the thing we expect the transformer to create.
|
|
||||||
pruneMap := rf.FromMap(
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "ConfigMap",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "pruneCM",
|
|
||||||
"namespace": "default",
|
|
||||||
"annotations": map[string]interface{}{
|
|
||||||
"kustomize.config.k8s.io/Inventory": inventory,
|
|
||||||
"kustomize.config.k8s.io/InventoryHash": hash,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expected := resmap.ResMap{
|
|
||||||
resid.NewResIdWithPrefixNamespace(cmap, "pruneCM", "", "default"): pruneMap,
|
|
||||||
}
|
|
||||||
|
|
||||||
p := &types.Inventory{
|
|
||||||
Type: "ConfigMap",
|
|
||||||
ConfigMap: types.NameArgs{
|
|
||||||
Name: "pruneCM",
|
|
||||||
Namespace: "default",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
objs := makeResMap()
|
|
||||||
|
|
||||||
// include the original resmap; only return the ConfigMap for pruning
|
|
||||||
tran := NewTransformer(p, ldr, "default", types.GarbageCollect)
|
|
||||||
tran.Transform(objs)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(objs, expected) {
|
|
||||||
err := expected.ErrorIfNotEqual(objs)
|
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objs = makeResMap()
|
|
||||||
expected = objs.DeepCopy(rf)
|
|
||||||
expected[resid.NewResIdWithPrefixNamespace(cmap, "pruneCM", "", "default")] = pruneMap
|
|
||||||
// append the ConfigMap for pruning to the original resmap
|
|
||||||
tran = NewTransformer(p, ldr, "default", types.GarbageIgnore)
|
|
||||||
tran.Transform(objs)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(objs, expected) {
|
|
||||||
err := expected.ErrorIfNotEqual(objs)
|
|
||||||
t.Fatalf("actual doesn't match expected: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
/*
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
Copyright 2018 The Kubernetes Authors.
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package accumulator
|
package accumulator
|
||||||
|
|
||||||
@@ -29,7 +16,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ResAccumulator accumulates resources and the rules
|
// ResAccumulator accumulates resources and the rules
|
||||||
// used to customize those resources.
|
// used to customize those resources. It's a ResMap
|
||||||
|
// plus stuff needed to modify the ResMap.
|
||||||
type ResAccumulator struct {
|
type ResAccumulator struct {
|
||||||
resMap resmap.ResMap
|
resMap resmap.ResMap
|
||||||
tConfig *config.TransformerConfig
|
tConfig *config.TransformerConfig
|
||||||
|
|||||||
@@ -5,18 +5,13 @@
|
|||||||
package transformer
|
package transformer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
|
||||||
"sigs.k8s.io/kustomize/pkg/resource"
|
"sigs.k8s.io/kustomize/pkg/resource"
|
||||||
"sigs.k8s.io/kustomize/pkg/transformers"
|
"sigs.k8s.io/kustomize/pkg/transformers"
|
||||||
"sigs.k8s.io/kustomize/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Factory makes transformers
|
// Factory makes transformers that require k8sdeps.
|
||||||
type Factory interface {
|
type Factory interface {
|
||||||
MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error)
|
MakePatchTransformer(
|
||||||
MakeInventoryTransformer(
|
slice []*resource.Resource,
|
||||||
p *types.Inventory,
|
rf *resource.Factory) (transformers.Transformer, error)
|
||||||
ldr ifc.Loader,
|
|
||||||
namespace string,
|
|
||||||
gp types.GarbagePolicy) transformers.Transformer
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,14 +127,11 @@ func (kt *KustTarget) makeCustomizedResMap(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// This must be done last, and not as part of
|
|
||||||
|
// The following steps must be done last, not as part of
|
||||||
// the recursion implicit in AccumulateTarget.
|
// the recursion implicit in AccumulateTarget.
|
||||||
p := builtin.NewHashTransformerPlugin()
|
|
||||||
err = kt.configureBuiltinPlugin(p, nil, "hash")
|
err = kt.addHashesToNames(ra)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = ra.Transform(p)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -145,22 +142,60 @@ func (kt *KustTarget) makeCustomizedResMap(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// With all the back references fixed, it's OK to resolve Vars.
|
// With all the back references fixed, it's OK to resolve Vars.
|
||||||
err = ra.ResolveVars()
|
err = ra.ResolveVars()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rm := ra.ResMap()
|
err = kt.computeInventory(ra, garbagePolicy)
|
||||||
pt := kt.tFactory.MakeInventoryTransformer(
|
|
||||||
kt.kustomization.Inventory, kt.ldr,
|
|
||||||
kt.kustomization.Namespace,
|
|
||||||
garbagePolicy)
|
|
||||||
err = pt.Transform(rm)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return rm, nil
|
|
||||||
|
return ra.ResMap(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kt *KustTarget) addHashesToNames(
|
||||||
|
ra *accumulator.ResAccumulator) error {
|
||||||
|
p := builtin.NewHashTransformerPlugin()
|
||||||
|
err := kt.configureBuiltinPlugin(p, nil, "hash")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ra.Transform(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kt *KustTarget) computeInventory(
|
||||||
|
ra *accumulator.ResAccumulator, garbagePolicy types.GarbagePolicy) error {
|
||||||
|
inv := kt.kustomization.Inventory
|
||||||
|
if inv == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if inv.Type != "ConfigMap" {
|
||||||
|
return fmt.Errorf("don't know how to do that")
|
||||||
|
}
|
||||||
|
|
||||||
|
if inv.ConfigMap.Namespace != kt.kustomization.Namespace {
|
||||||
|
return fmt.Errorf("namespace mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := builtin.NewInventoryTransformerPlugin()
|
||||||
|
var c struct {
|
||||||
|
Policy string
|
||||||
|
Name string
|
||||||
|
Namespace string
|
||||||
|
}
|
||||||
|
c.Name = inv.ConfigMap.Name
|
||||||
|
c.Namespace = inv.ConfigMap.Namespace
|
||||||
|
c.Policy = garbagePolicy.String()
|
||||||
|
|
||||||
|
err := kt.configureBuiltinPlugin(p, c, "inventory")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ra.Transform(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) shouldAddHashSuffixesToGeneratedResources() bool {
|
func (kt *KustTarget) shouldAddHashSuffixesToGeneratedResources() bool {
|
||||||
|
|||||||
25
pkg/types/garbagepolicy_string.go
Normal file
25
pkg/types/garbagepolicy_string.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Code generated by "stringer -type=GarbagePolicy"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[GarbageIgnore-1]
|
||||||
|
_ = x[GarbageCollect-2]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _GarbagePolicy_name = "GarbageIgnoreGarbageCollect"
|
||||||
|
|
||||||
|
var _GarbagePolicy_index = [...]uint8{0, 13, 27}
|
||||||
|
|
||||||
|
func (i GarbagePolicy) String() string {
|
||||||
|
i -= 1
|
||||||
|
if i < 0 || i >= GarbagePolicy(len(_GarbagePolicy_index)-1) {
|
||||||
|
return "GarbagePolicy(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||||
|
}
|
||||||
|
return _GarbagePolicy_name[_GarbagePolicy_index[i]:_GarbagePolicy_index[i+1]]
|
||||||
|
}
|
||||||
@@ -146,11 +146,11 @@ type Kustomization struct {
|
|||||||
Inventory *Inventory `json:"inventory,omitempty" yaml:"inventory:omitempty"`
|
Inventory *Inventory `json:"inventory,omitempty" yaml:"inventory:omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:generate stringer -type=GarbagePolicy
|
||||||
type GarbagePolicy int
|
type GarbagePolicy int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
GarbageUnknown GarbagePolicy = iota
|
GarbageIgnore GarbagePolicy = iota + 1
|
||||||
GarbageIgnore
|
|
||||||
GarbageCollect
|
GarbageCollect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package builtin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||||
)
|
)
|
||||||
|
|||||||
136
plugin/builtin/InventoryTransformer.go
Normal file
136
plugin/builtin/InventoryTransformer.go
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
// Code generated by pluginator on InventoryTransformer; DO NOT EDIT.
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/pkg/resource"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/pkg/hasher"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/inventory"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/resid"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InventoryTransformerPlugin struct {
|
||||||
|
ldr ifc.Loader
|
||||||
|
rf *resmap.Factory
|
||||||
|
Policy string `json:"policy,omitempty" yaml:"policy,omitempty"`
|
||||||
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||||
|
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInventoryTransformerPlugin() *InventoryTransformerPlugin {
|
||||||
|
return &InventoryTransformerPlugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *InventoryTransformerPlugin) Config(
|
||||||
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
||||||
|
p.ldr = ldr
|
||||||
|
p.rf = rf
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p.Policy == "" {
|
||||||
|
p.Policy = types.GarbageIgnore.String()
|
||||||
|
}
|
||||||
|
if p.Policy != types.GarbageCollect.String() &&
|
||||||
|
p.Policy != types.GarbageIgnore.String() {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unrecognized garbagePolicy '%s'", p.Policy)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform generates an inventory object from the input ResMap.
|
||||||
|
// This ConfigMap supports the pruning command in
|
||||||
|
// the client side tool proposed here:
|
||||||
|
// https://github.com/kubernetes/enhancements/pull/810
|
||||||
|
//
|
||||||
|
// The inventory data is written to the ConfigMap's
|
||||||
|
// annotations, rather than to the key-value pairs in
|
||||||
|
// the ConfigMap's data field, since
|
||||||
|
// 1. Keys in a ConfigMap's data field are too
|
||||||
|
// constrained for this purpose.
|
||||||
|
// 2. Using annotations allow any object to be used,
|
||||||
|
// not just a ConfigMap, should some other object
|
||||||
|
// (e.g. some App object) become more desirable
|
||||||
|
// for this purpose.
|
||||||
|
func (p *InventoryTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
|
|
||||||
|
inv, h, err := makeInventory(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
args := types.ConfigMapArgs{}
|
||||||
|
args.Name = p.Name
|
||||||
|
args.Namespace = p.Namespace
|
||||||
|
opts := &types.GeneratorOptions{
|
||||||
|
Annotations: make(map[string]string),
|
||||||
|
}
|
||||||
|
opts.Annotations[inventory.HashAnnotation] = h
|
||||||
|
err = inv.UpdateAnnotations(opts.Annotations)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cm, err := p.rf.RF().MakeConfigMap(p.ldr, opts, &args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Policy == types.GarbageCollect.String() {
|
||||||
|
for byeBye := range m {
|
||||||
|
delete(m, byeBye)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id := cm.Id()
|
||||||
|
if _, ok := m[id]; ok {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"id '%v' already used; use a different name", id)
|
||||||
|
}
|
||||||
|
m[id] = cm
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeInventory(m resmap.ResMap) (
|
||||||
|
inv *inventory.Inventory, hash string, err error) {
|
||||||
|
inv = inventory.NewInventory()
|
||||||
|
var keys []string
|
||||||
|
for _, r := range m {
|
||||||
|
ns := getNamespace(r)
|
||||||
|
item := resid.NewItemId(r.GetGvk(), ns, r.GetName())
|
||||||
|
if _, ok := inv.Current[item]; ok {
|
||||||
|
return nil, "", fmt.Errorf(
|
||||||
|
"item '%v' already in inventory", item)
|
||||||
|
}
|
||||||
|
inv.Current[item] = computeRefs(r, m)
|
||||||
|
keys = append(keys, item.String())
|
||||||
|
}
|
||||||
|
h, err := hasher.SortArrayAndComputeHash(keys)
|
||||||
|
return inv, h, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNamespace(r *resource.Resource) string {
|
||||||
|
ns, err := r.GetFieldValue("metadata.namespace")
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "no field named") {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeRefs(r *resource.Resource, m resmap.ResMap) (refs []resid.ItemId) {
|
||||||
|
for _, refid := range r.GetRefBy() {
|
||||||
|
ref := m[refid]
|
||||||
|
ns := getNamespace(ref)
|
||||||
|
refs = append(refs, resid.NewItemId(ref.GetGvk(), ns, ref.GetName()))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
137
plugin/builtin/inventorytransformer/InventoryTransformer.go
Normal file
137
plugin/builtin/inventorytransformer/InventoryTransformer.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
//go:generate go run sigs.k8s.io/kustomize/plugin/pluginator
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/pkg/resource"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/pkg/hasher"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/inventory"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/resid"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/pkg/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type plugin struct {
|
||||||
|
ldr ifc.Loader
|
||||||
|
rf *resmap.Factory
|
||||||
|
Policy string `json:"policy,omitempty" yaml:"policy,omitempty"`
|
||||||
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||||
|
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var KustomizePlugin plugin
|
||||||
|
|
||||||
|
func (p *plugin) Config(
|
||||||
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
|
||||||
|
p.ldr = ldr
|
||||||
|
p.rf = rf
|
||||||
|
err = yaml.Unmarshal(c, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p.Policy == "" {
|
||||||
|
p.Policy = types.GarbageIgnore.String()
|
||||||
|
}
|
||||||
|
if p.Policy != types.GarbageCollect.String() &&
|
||||||
|
p.Policy != types.GarbageIgnore.String() {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unrecognized garbagePolicy '%s'", p.Policy)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform generates an inventory object from the input ResMap.
|
||||||
|
// This ConfigMap supports the pruning command in
|
||||||
|
// the client side tool proposed here:
|
||||||
|
// https://github.com/kubernetes/enhancements/pull/810
|
||||||
|
//
|
||||||
|
// The inventory data is written to the ConfigMap's
|
||||||
|
// annotations, rather than to the key-value pairs in
|
||||||
|
// the ConfigMap's data field, since
|
||||||
|
// 1. Keys in a ConfigMap's data field are too
|
||||||
|
// constrained for this purpose.
|
||||||
|
// 2. Using annotations allow any object to be used,
|
||||||
|
// not just a ConfigMap, should some other object
|
||||||
|
// (e.g. some App object) become more desirable
|
||||||
|
// for this purpose.
|
||||||
|
func (p *plugin) Transform(m resmap.ResMap) error {
|
||||||
|
|
||||||
|
inv, h, err := makeInventory(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
args := types.ConfigMapArgs{}
|
||||||
|
args.Name = p.Name
|
||||||
|
args.Namespace = p.Namespace
|
||||||
|
opts := &types.GeneratorOptions{
|
||||||
|
Annotations: make(map[string]string),
|
||||||
|
}
|
||||||
|
opts.Annotations[inventory.HashAnnotation] = h
|
||||||
|
err = inv.UpdateAnnotations(opts.Annotations)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cm, err := p.rf.RF().MakeConfigMap(p.ldr, opts, &args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Policy == types.GarbageCollect.String() {
|
||||||
|
for byeBye := range m {
|
||||||
|
delete(m, byeBye)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id := cm.Id()
|
||||||
|
if _, ok := m[id]; ok {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"id '%v' already used; use a different name", id)
|
||||||
|
}
|
||||||
|
m[id] = cm
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeInventory(m resmap.ResMap) (
|
||||||
|
inv *inventory.Inventory, hash string, err error) {
|
||||||
|
inv = inventory.NewInventory()
|
||||||
|
var keys []string
|
||||||
|
for _, r := range m {
|
||||||
|
ns := getNamespace(r)
|
||||||
|
item := resid.NewItemId(r.GetGvk(), ns, r.GetName())
|
||||||
|
if _, ok := inv.Current[item]; ok {
|
||||||
|
return nil, "", fmt.Errorf(
|
||||||
|
"item '%v' already in inventory", item)
|
||||||
|
}
|
||||||
|
inv.Current[item] = computeRefs(r, m)
|
||||||
|
keys = append(keys, item.String())
|
||||||
|
}
|
||||||
|
h, err := hasher.SortArrayAndComputeHash(keys)
|
||||||
|
return inv, h, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNamespace(r *resource.Resource) string {
|
||||||
|
ns, err := r.GetFieldValue("metadata.namespace")
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "no field named") {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeRefs(r *resource.Resource, m resmap.ResMap) (refs []resid.ItemId) {
|
||||||
|
for _, refid := range r.GetRefBy() {
|
||||||
|
ref := m[refid]
|
||||||
|
ns := getNamespace(ref)
|
||||||
|
refs = append(refs, resid.NewItemId(ref.GetGvk(), ns, ref.GetName()))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
125
plugin/builtin/inventorytransformer/InventoryTransformer_test.go
Normal file
125
plugin/builtin/inventorytransformer/InventoryTransformer_test.go
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/pkg/kusttest"
|
||||||
|
"sigs.k8s.io/kustomize/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
content = `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: secret1
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deploy1
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
name: CM_FOO
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: someKey
|
||||||
|
name: cm1
|
||||||
|
envFrom:
|
||||||
|
configMapRef:
|
||||||
|
key: someKey
|
||||||
|
name: cm1
|
||||||
|
secretRef:
|
||||||
|
key: someKey
|
||||||
|
name: secret1
|
||||||
|
image: nginx:1.7.9
|
||||||
|
name: nginx
|
||||||
|
`
|
||||||
|
inv = `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
kustomize.config.k8s.io/Inventory: '{"current":{"apps_v1_Deployment|~X|deploy1":null,"~G_v1_ConfigMap|~X|cm1":null,"~G_v1_Secret|~X|secret1":null}}'
|
||||||
|
kustomize.config.k8s.io/InventoryHash: h44788gt7g
|
||||||
|
name: pruneCM
|
||||||
|
namespace: default
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInventoryTransformerCollect(t *testing.T) {
|
||||||
|
tc := plugin.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "InventoryTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: InventoryTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
policy: GarbageCollect
|
||||||
|
name: pruneCM
|
||||||
|
namespace: default
|
||||||
|
`, content)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, inv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInventoryTransformerIgnore(t *testing.T) {
|
||||||
|
tc := plugin.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "InventoryTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: InventoryTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
policy: GarbageIgnore
|
||||||
|
name: pruneCM
|
||||||
|
namespace: default
|
||||||
|
`, content)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, inv+"---"+content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInventoryTransformerDefaultPolicy(t *testing.T) {
|
||||||
|
tc := plugin.NewEnvForTest(t).Set()
|
||||||
|
defer tc.Reset()
|
||||||
|
|
||||||
|
tc.BuildGoPlugin(
|
||||||
|
"builtin", "", "InventoryTransformer")
|
||||||
|
|
||||||
|
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||||
|
|
||||||
|
rm := th.LoadAndRunTransformer(`
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: InventoryTransformer
|
||||||
|
metadata:
|
||||||
|
name: notImportantHere
|
||||||
|
name: pruneCM
|
||||||
|
namespace: default
|
||||||
|
`, content)
|
||||||
|
|
||||||
|
th.AssertActualEqualsExpected(rm, inv+"---"+content)
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user