mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
Allow hash suffixing of arbitrary types
This commit is contained in:
@@ -5,7 +5,6 @@ package kunstruct
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -21,7 +20,7 @@ func NewKustHash() *kustHash {
|
||||
return &kustHash{}
|
||||
}
|
||||
|
||||
// Hash returns a hash of either a ConfigMap or a Secret
|
||||
// Hash returns a hash of the given object
|
||||
func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
|
||||
u := unstructured.Unstructured{
|
||||
Object: m.Map(),
|
||||
@@ -36,15 +35,12 @@ func (h *kustHash) Hash(m ifc.Kunstructured) (string, error) {
|
||||
return configMapHash(cm)
|
||||
case "Secret":
|
||||
sec, err := unstructuredToSecret(u)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return secretHash(sec)
|
||||
default:
|
||||
return "", fmt.Errorf(
|
||||
"type %s is not supported for hashing in %v",
|
||||
kind, m.Map())
|
||||
return unstructuredHash(&u)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +72,21 @@ func secretHash(sec *corev1.Secret) (string, error) {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// unstructuredHash creates a hash for an arbitrary type.
|
||||
// All fields of the object are taken into account when generating the hash.
|
||||
// This is a fallback for when a specalised hash for the type is unavailable.
|
||||
func unstructuredHash(u *unstructured.Unstructured) (string, error) {
|
||||
encoded, err := json.Marshal(u.Object)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
h, err := hasher.Encode(hasher.Hash(string(encoded)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// encodeConfigMap encodes a ConfigMap.
|
||||
// Data, Kind, and Name are taken into account.
|
||||
// BinaryData is included if it's not empty to avoid useless key in output.
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func TestConfigMapHash(t *testing.T) {
|
||||
@@ -75,6 +76,39 @@ func TestSecretHash(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnstructuredHash(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
unstructured *unstructured.Unstructured
|
||||
hash string
|
||||
err string
|
||||
}{
|
||||
{"minimal", &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "test/v1",
|
||||
"kind": "TestResource",
|
||||
"metadata": map[string]string{"name": "my-resource"}},
|
||||
}, "2tt46d7f79", ""},
|
||||
{"with spec", &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "test/v1",
|
||||
"kind": "TestResource",
|
||||
"metadata": map[string]string{"name": "my-resource"},
|
||||
"spec": map[string]interface{}{"foo": 1, "bar": "abc"}},
|
||||
}, "6gc62g4m6k", ""},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
h, err := unstructuredHash(c.unstructured)
|
||||
if SkipRest(t, c.desc, err, c.err) {
|
||||
continue
|
||||
}
|
||||
if c.hash != h {
|
||||
t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeConfigMap(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
|
||||
@@ -255,7 +255,11 @@ A generator exec plugin can adjust the generator options for the resources it em
|
||||
|
||||
Resources can be marked as needing to be processed by the internal hash transformer by including the `needs-hash` annotation. When set valid values for the annotation are `"true"` and `"false"` which respectively enable or disable hash suffixing for the resource. Omitting the annotation is equivalent to setting the value `"false"`.
|
||||
|
||||
If this annotation is set on a resource not supported by the hash transformer the build will fail.
|
||||
Hashes are determined as follows:
|
||||
|
||||
* For `ConfigMap` resources, hashes are based on the values of the `name`, `data`, and `binaryData` fields.
|
||||
* For `Secret` resources, hashes are based on the values of the `name`, `type`, `data`, and `stringData` fields.
|
||||
* For any other object type, hashes are based on the entire object content (i.e. all fields).
|
||||
|
||||
Example:
|
||||
```yaml
|
||||
|
||||
Reference in New Issue
Block a user