update hash util

This commit is contained in:
Mengqi Yu 2018-04-11 15:20:49 -07:00
parent d94a69e883
commit 3ae6eefc2d
2 changed files with 28 additions and 8 deletions

View File

@ -25,7 +25,7 @@ import (
) )
// ConfigMapHash returns a hash of the ConfigMap. // ConfigMapHash returns a hash of the ConfigMap.
// The data, Kind, and Name are taken into account. // The Data, Kind, and Name are taken into account.
func ConfigMapHash(cm *v1.ConfigMap) (string, error) { func ConfigMapHash(cm *v1.ConfigMap) (string, error) {
encoded, err := encodeConfigMap(cm) encoded, err := encodeConfigMap(cm)
if err != nil { if err != nil {
@ -39,7 +39,7 @@ func ConfigMapHash(cm *v1.ConfigMap) (string, error) {
} }
// SecretHash returns a hash of the Secret. // SecretHash returns a hash of the Secret.
// The data, Kind, Name, and Type are taken into account. // The Data, Kind, Name, and Type are taken into account.
func SecretHash(sec *v1.Secret) (string, error) { func SecretHash(sec *v1.Secret) (string, error) {
encoded, err := encodeSecret(sec) encoded, err := encodeSecret(sec)
if err != nil { if err != nil {
@ -53,10 +53,14 @@ func SecretHash(sec *v1.Secret) (string, error) {
} }
// encodeConfigMap encodes a ConfigMap. // encodeConfigMap encodes a ConfigMap.
// data, Kind, and Name are taken into account. // Data, Kind, and Name are taken into account.
func encodeConfigMap(cm *v1.ConfigMap) (string, error) { func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
// json.Marshal sorts the keys in a stable order in the encoding // json.Marshal sorts the keys in a stable order in the encoding
data, err := json.Marshal(map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data}) m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data}
if len(cm.BinaryData) > 0 {
m["binaryData"] = cm.BinaryData
}
data, err := json.Marshal(m)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -64,7 +68,7 @@ func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
} }
// encodeSecret encodes a Secret. // encodeSecret encodes a Secret.
// data, Kind, Name, and Type are taken into account. // Data, Kind, Name, and Type are taken into account.
func encodeSecret(sec *v1.Secret) (string, error) { func encodeSecret(sec *v1.Secret) (string, error) {
// json.Marshal sorts the keys in a stable order in the encoding // json.Marshal sorts the keys in a stable order in the encoding
data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data}) data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data})

View File

@ -32,11 +32,19 @@ func TestConfigMapHash(t *testing.T) {
err string err string
}{ }{
// empty map // empty map
{"empty data", &v1.ConfigMap{Data: map[string]string{}}, "42745tchd9", ""}, {"empty data", &v1.ConfigMap{Data: map[string]string{}, BinaryData: map[string][]byte{}}, "42745tchd9", ""},
// one key // one key
{"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, "9g67k2htb6", ""}, {"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, "9g67k2htb6", ""},
// three keys (tests sorting order) // three keys (tests sorting order)
{"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, "f5h7t85m9b", ""}, {"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, "f5h7t85m9b", ""},
// empty binary data map
{"empty binary data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, "dk855m5d49", ""},
// one key with binary data
{"one key with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, "mk79584b8c", ""},
// three keys with binary data (tests sorting order)
{"three keys with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "t458mc6db2", ""},
// two keys, one with string and another with binary data
{"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, "698h7c7t9m", ""},
} }
for _, c := range cases { for _, c := range cases {
@ -89,6 +97,14 @@ func TestEncodeConfigMap(t *testing.T) {
{"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""}, {"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
// three keys (tests sorting order) // three keys (tests sorting order)
{"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, `{"data":{"one":"","three":"3","two":"2"},"kind":"ConfigMap","name":""}`, ""}, {"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, `{"data":{"one":"","three":"3","two":"2"},"kind":"ConfigMap","name":""}`, ""},
// empty binary map
{"empty data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, `{"data":null,"kind":"ConfigMap","name":""}`, ""},
// one key with binary data
{"one key", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, `{"binaryData":{"one":""},"data":null,"kind":"ConfigMap","name":""}`, ""},
// three keys with binary data (tests sorting order)
{"three keys", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, `{"binaryData":{"one":"","three":"Mw==","two":"Mg=="},"data":null,"kind":"ConfigMap","name":""}`, ""},
// two keys, one string and one binary values
{"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, `{"binaryData":{"two":""},"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
} }
for _, c := range cases { for _, c := range cases {
s, err := encodeConfigMap(c.cm) s, err := encodeConfigMap(c.cm)
@ -141,14 +157,14 @@ func TestTypeStability(t *testing.T) {
errfmt := `case %q, expected %d fields but got %d errfmt := `case %q, expected %d fields but got %d
Depending on the field(s) you added, you may need to modify the hash function for this type. Depending on the field(s) you added, you may need to modify the hash function for this type.
To guide you: the hash function targets fields that comprise the contents of objects, To guide you: the hash function targets fields that comprise the contents of objects,
not their metadata (e.g. the data of a ConfigMap, but nothing in ObjectMeta). not their metadata (e.g. the Data of a ConfigMap, but nothing in ObjectMeta).
` `
cases := []struct { cases := []struct {
typeName string typeName string
obj interface{} obj interface{}
expect int expect int
}{ }{
{"ConfigMap", v1.ConfigMap{}, 3}, {"ConfigMap", v1.ConfigMap{}, 4},
{"Secret", v1.Secret{}, 5}, {"Secret", v1.Secret{}, 5},
} }
for _, c := range cases { for _, c := range cases {