-
Notifications
You must be signed in to change notification settings - Fork 292
/
hash.go
80 lines (67 loc) · 1.84 KB
/
hash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package kubernetesapply
import (
"crypto"
"encoding/base64"
"fmt"
"hash"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
)
var defaultJSONIterator = createDefaultJSONIterator()
func createDefaultJSONIterator() jsoniter.API {
return jsoniter.Config{
EscapeHTML: true,
SortMapKeys: true,
ValidateJsonRawMessage: true,
CaseSensitive: true,
}.Froze()
}
// Compute the hash of all the inputs we fed into this apply.
func ComputeInputHash(spec v1alpha1.KubernetesApplySpec, imageMaps map[types.NamespacedName]*v1alpha1.ImageMap) (string, error) {
w := newHashWriter()
err := w.append(spec)
if err != nil {
return "", err
}
for _, imageMapName := range spec.ImageMaps {
imageMap, ok := imageMaps[types.NamespacedName{Name: imageMapName}]
if !ok {
return "", fmt.Errorf("missing image map: %v", err)
}
err = w.append(imageMap.Spec)
if err != nil {
return "", fmt.Errorf("hashing %s spec: %v", imageMapName, err)
}
// Don't hash in the BuildStartedTime, because
// this changes even when the image does not change.
status := imageMap.Status
status.BuildStartTime = nil
err = w.append(status)
if err != nil {
return "", fmt.Errorf("hashing %s status: %v", imageMapName, err)
}
}
return w.done(), nil
}
type hashWriter struct {
h hash.Hash
}
func newHashWriter() *hashWriter {
return &hashWriter{h: crypto.SHA1.New()}
}
func (w hashWriter) append(o interface{}) error {
data, err := defaultJSONIterator.Marshal(o)
if err != nil {
return errors.Wrap(err, "serializing object for hash")
}
_, err = w.h.Write(data)
if err != nil {
return errors.Wrap(err, "computing hash")
}
return nil
}
func (w hashWriter) done() string {
return base64.URLEncoding.EncodeToString(w.h.Sum(nil))
}