mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
Move hashing transformer out of k8sdeps.
This commit is contained in:
@@ -18,13 +18,20 @@ import (
|
||||
|
||||
// KunstructuredFactoryImpl hides construction using apimachinery types.
|
||||
type KunstructuredFactoryImpl struct {
|
||||
hasher *kustHash
|
||||
}
|
||||
|
||||
var _ ifc.KunstructuredFactory = &KunstructuredFactoryImpl{}
|
||||
|
||||
// NewKunstructuredFactoryImpl returns a factory.
|
||||
func NewKunstructuredFactoryImpl() ifc.KunstructuredFactory {
|
||||
return &KunstructuredFactoryImpl{}
|
||||
return &KunstructuredFactoryImpl{hasher: NewKustHash()}
|
||||
}
|
||||
|
||||
// Hasher returns a kunstructured hasher
|
||||
// input: kunstructured; output: string hash.
|
||||
func (kf *KunstructuredFactoryImpl) Hasher() ifc.KunstructuredHasher {
|
||||
return kf.hasher
|
||||
}
|
||||
|
||||
// SliceFromBytes returns a slice of Kunstructured.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package hash
|
||||
package kunstruct
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/kustomize/pkg/hasher"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
)
|
||||
|
||||
// kustHash computes a hash of an unstructured object.
|
||||
@@ -21,9 +22,9 @@ func NewKustHash() *kustHash {
|
||||
}
|
||||
|
||||
// Hash returns a hash of either a ConfigMap or a Secret
|
||||
func (h *kustHash) Hash(m map[string]interface{}) (string, error) {
|
||||
func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
|
||||
u := unstructured.Unstructured{
|
||||
Object: m,
|
||||
Object: m.Map(),
|
||||
}
|
||||
kind := u.GetKind()
|
||||
switch kind {
|
||||
@@ -42,7 +43,8 @@ func (h *kustHash) Hash(m map[string]interface{}) (string, error) {
|
||||
return secretHash(sec)
|
||||
default:
|
||||
return "", fmt.Errorf(
|
||||
"type %s is not supported for hashing in %v", kind, m)
|
||||
"type %s is not supported for hashing in %v",
|
||||
kind, m.Map())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package hash
|
||||
package kunstruct
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@@ -5,7 +5,6 @@
|
||||
package transformer
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/k8sdeps/transformer/hash"
|
||||
"sigs.k8s.io/kustomize/k8sdeps/transformer/inventory"
|
||||
"sigs.k8s.io/kustomize/k8sdeps/transformer/patch"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
@@ -29,11 +28,6 @@ func (p *FactoryImpl) MakePatchTransformer(
|
||||
return patch.NewTransformer(slice, rf)
|
||||
}
|
||||
|
||||
// MakeHashTransformer makes a new name hash transformer
|
||||
func (p *FactoryImpl) MakeHashTransformer() transformers.Transformer {
|
||||
return hash.NewTransformer()
|
||||
}
|
||||
|
||||
func (p *FactoryImpl) MakeInventoryTransformer(
|
||||
arg *types.Inventory,
|
||||
ldr ifc.Loader,
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package hash
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||
"sigs.k8s.io/kustomize/pkg/transformers"
|
||||
)
|
||||
|
||||
type transformer struct{}
|
||||
|
||||
var _ transformers.Transformer = &transformer{}
|
||||
|
||||
// NewTransformer make a hash transformer.
|
||||
func NewTransformer() transformers.Transformer {
|
||||
return &transformer{}
|
||||
}
|
||||
|
||||
// Transform appends hash to generated resources.
|
||||
func (tf *transformer) Transform(m resmap.ResMap) error {
|
||||
for _, res := range m {
|
||||
if res.NeedHashSuffix() {
|
||||
h, err := NewKustHash().Hash(res.Map())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package hash
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
|
||||
"sigs.k8s.io/kustomize/pkg/resid"
|
||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||
"sigs.k8s.io/kustomize/pkg/resource"
|
||||
"sigs.k8s.io/kustomize/pkg/types"
|
||||
)
|
||||
|
||||
func TestNameHashTransformer(t *testing.T) {
|
||||
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(deploy, "deploy1"): rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"group": "apps",
|
||||
"apiVersion": "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:1.7.9",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
resid.NewResId(service, "svc1"): rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Service",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "svc1",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"ports": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "port1",
|
||||
"port": "12345",
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
resid.NewResId(secret, "secret1"): rf.FromMapAndOption(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Secret",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "secret1",
|
||||
},
|
||||
}, &types.GeneratorArgs{Behavior: "create"}, &types.GeneratorOptions{DisableNameSuffixHash: false}),
|
||||
}
|
||||
|
||||
expected := resmap.ResMap{
|
||||
resid.NewResId(cmap, "cm1"): rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "cm1",
|
||||
},
|
||||
}),
|
||||
resid.NewResId(deploy, "deploy1"): rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"group": "apps",
|
||||
"apiVersion": "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:1.7.9",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
resid.NewResId(service, "svc1"): rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Service",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "svc1",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"ports": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "port1",
|
||||
"port": "12345",
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
resid.NewResId(secret, "secret1"): rf.FromMapAndOption(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Secret",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "secret1-7kc45hd5f7",
|
||||
},
|
||||
}, &types.GeneratorArgs{Behavior: "create"}, &types.GeneratorOptions{DisableNameSuffixHash: false}),
|
||||
}
|
||||
|
||||
tran := NewTransformer()
|
||||
tran.Transform(objs)
|
||||
|
||||
if !reflect.DeepEqual(objs, expected) {
|
||||
err := expected.ErrorIfNotEqual(objs)
|
||||
t.Fatalf("actual doesn't match expected: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ type Kunstructured interface {
|
||||
type KunstructuredFactory interface {
|
||||
SliceFromBytes([]byte) ([]Kunstructured, error)
|
||||
FromMap(m map[string]interface{}) Kunstructured
|
||||
Hasher() KunstructuredHasher
|
||||
MakeConfigMap(
|
||||
ldr Loader,
|
||||
options *types.GeneratorOptions,
|
||||
@@ -68,5 +69,11 @@ type KunstructuredFactory interface {
|
||||
args *types.SecretArgs) (Kunstructured, error)
|
||||
}
|
||||
|
||||
// KunstructuredHasher returns a hash of the argument
|
||||
// or an error.
|
||||
type KunstructuredHasher interface {
|
||||
Hash(Kunstructured) (string, error)
|
||||
}
|
||||
|
||||
// See core.v1.SecretTypeOpaque
|
||||
const SecretTypeOpaque = "Opaque"
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
// Factory makes transformers
|
||||
type Factory interface {
|
||||
MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error)
|
||||
MakeHashTransformer() transformers.Transformer
|
||||
MakeInventoryTransformer(
|
||||
p *types.Inventory,
|
||||
ldr ifc.Loader,
|
||||
|
||||
@@ -37,6 +37,10 @@ func NewFactory(kf ifc.KunstructuredFactory) *Factory {
|
||||
return &Factory{kf: kf}
|
||||
}
|
||||
|
||||
func (rf *Factory) Hasher() ifc.KunstructuredHasher {
|
||||
return rf.kf.Hasher()
|
||||
}
|
||||
|
||||
// FromMap returns a new instance of Resource.
|
||||
func (rf *Factory) FromMap(m map[string]interface{}) *Resource {
|
||||
return &Resource{
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"sigs.k8s.io/kustomize/pkg/transformers"
|
||||
"sigs.k8s.io/kustomize/pkg/transformers/config"
|
||||
"sigs.k8s.io/kustomize/pkg/types"
|
||||
"sigs.k8s.io/kustomize/plugin/builtin"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
@@ -126,10 +127,18 @@ func (kt *KustTarget) makeCustomizedResMap(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = ra.Transform(kt.tFactory.MakeHashTransformer())
|
||||
// This must be done last, and not as part of
|
||||
// the recursion implicit in AccumulateTarget.
|
||||
p := builtin.NewHashTransformerPlugin()
|
||||
err = kt.configureBuiltinPlugin(p, nil, "hash")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = ra.Transform(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Given that names have changed (prefixs/suffixes added),
|
||||
// fix all the back references to those names.
|
||||
err = ra.FixBackReferences()
|
||||
|
||||
@@ -234,10 +234,14 @@ func (kt *KustTarget) configureBuiltinImageTagTransformer(
|
||||
}
|
||||
|
||||
func (kt *KustTarget) configureBuiltinPlugin(
|
||||
p plugins.Configurable, c interface{}, id string) error {
|
||||
y, err := yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "builtin %s marshal", id)
|
||||
p plugins.Configurable, c interface{}, id string) (err error) {
|
||||
var y []byte
|
||||
if c != nil {
|
||||
y, err = yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(
|
||||
err, "builtin %s marshal", id)
|
||||
}
|
||||
}
|
||||
err = p.Config(kt.ldr, kt.rFactory, y)
|
||||
if err != nil {
|
||||
|
||||
36
plugin/builtin/HashTransformer.go
Normal file
36
plugin/builtin/HashTransformer.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Code generated by pluginator on HashTransformer; DO NOT EDIT.
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||
)
|
||||
|
||||
type HashTransformerPlugin struct {
|
||||
hasher ifc.KunstructuredHasher
|
||||
}
|
||||
|
||||
func NewHashTransformerPlugin() *HashTransformerPlugin {
|
||||
return &HashTransformerPlugin{}
|
||||
}
|
||||
|
||||
func (p *HashTransformerPlugin) Config(
|
||||
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
|
||||
p.hasher = rf.RF().Hasher()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Transform appends hash to generated resources.
|
||||
func (p *HashTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||
for _, res := range m {
|
||||
if res.NeedHashSuffix() {
|
||||
h, err := p.hasher.Hash(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
38
plugin/builtin/hashtransformer/HashTransformer.go
Normal file
38
plugin/builtin/hashtransformer/HashTransformer.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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"
|
||||
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
"sigs.k8s.io/kustomize/pkg/resmap"
|
||||
)
|
||||
|
||||
type plugin struct {
|
||||
hasher ifc.KunstructuredHasher
|
||||
}
|
||||
|
||||
var KustomizePlugin plugin
|
||||
|
||||
func (p *plugin) Config(
|
||||
ldr ifc.Loader, rf *resmap.Factory, config []byte) (err error) {
|
||||
p.hasher = rf.RF().Hasher()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Transform appends hash to generated resources.
|
||||
func (p *plugin) Transform(m resmap.ResMap) error {
|
||||
for _, res := range m {
|
||||
if res.NeedHashSuffix() {
|
||||
h, err := p.hasher.Hash(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
87
plugin/builtin/hashtransformer/HashTransformer_test.go
Normal file
87
plugin/builtin/hashtransformer/HashTransformer_test.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
func TestHashTransformer(t *testing.T) {
|
||||
tc := plugin.NewEnvForTest(t).Set()
|
||||
defer tc.Reset()
|
||||
|
||||
tc.BuildGoPlugin(
|
||||
"builtin", "", "HashTransformer")
|
||||
|
||||
th := kusttest_test.NewKustTestPluginHarness(t, "/app")
|
||||
|
||||
rm := th.LoadAndRunTransformer(`
|
||||
apiVersion: builtin
|
||||
kind: HashTransformer
|
||||
metadata:
|
||||
name: myMapGen
|
||||
name: myMap
|
||||
envs:
|
||||
- devops.env
|
||||
- uxteam.env
|
||||
literals:
|
||||
- FRUIT=apple
|
||||
- VEGETABLE=carrot
|
||||
`, `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm1
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret1
|
||||
---
|
||||
apiVersion: v1
|
||||
group: apps
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
old-lab: old-val
|
||||
spec:
|
||||
containers:
|
||||
- name: ngnix
|
||||
image: nginx:1.7.9
|
||||
`)
|
||||
|
||||
th.AssertActualEqualsExpected(rm, `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm1
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret1
|
||||
---
|
||||
apiVersion: v1
|
||||
group: apps
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
old-lab: old-val
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.7.9
|
||||
name: ngnix
|
||||
`)
|
||||
}
|
||||
Reference in New Issue
Block a user