Skip to content

Commit

Permalink
Merge pull request #32 from ecordell/nohasherror
Browse files Browse the repository at this point in the history
hash: remove errors from api (breaking api change)
  • Loading branch information
ecordell authored Jan 26, 2023
2 parents 3b0fa4d + 8d358d6 commit 45ed61d
Show file tree
Hide file tree
Showing 7 changed files with 546 additions and 31 deletions.
4 changes: 0 additions & 4 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ linters:
enable:
- "bidichk"
- "bodyclose"
- "deadcode"
- "errcheck"
- "errname"
- "errorlint"
Expand All @@ -17,7 +16,6 @@ linters:
- "gosec"
- "gosimple"
- "govet"
- "ifshort"
- "importas"
- "ineffassign"
- "makezero"
Expand All @@ -27,12 +25,10 @@ linters:
- "revive"
- "rowserrcheck"
- "staticcheck"
- "structcheck"
- "stylecheck"
- "tenv"
- "typecheck"
- "unconvert"
- "unused"
- "varcheck"
- "wastedassign"
- "whitespace"
8 changes: 2 additions & 6 deletions component/ensure_component.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,7 @@ func (e *EnsureComponentByHash[K, A]) Handle(ctx context.Context) {
ownedObjs := e.List(ctx, e.nn.MustValue(ctx))

newObj := e.newObj(ctx)
hash, err := e.Hash(newObj)
if err != nil {
e.ctrls.RequeueErr(ctx, err)
return
}
hash := e.Hash(newObj)
newObj = newObj.WithAnnotations(map[string]string{e.HashAnnotationKey: hash})

matchingObjs := make([]K, 0)
Expand All @@ -78,7 +74,7 @@ func (e *EnsureComponentByHash[K, A]) Handle(ctx context.Context) {

if len(matchingObjs) == 0 {
// apply if no matching KubeObject in cluster
_, err = e.applyObject(ctx, newObj)
_, err := e.applyObject(ctx, newObj)
if err != nil {
e.ctrls.RequeueErr(ctx, err)
return
Expand Down
37 changes: 18 additions & 19 deletions hash/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import (
)

type (
ObjectHashFunc func(obj any) (string, error)
ObjectHashFunc func(obj any) string
EqualFunc func(a, b string) bool
)

// ObjectHasher hashes and object and can compare hashes for equality
type ObjectHasher interface {
Hash(obj any) (string, error)
Hash(obj any) string
Equal(a, b string) bool
}

Expand All @@ -28,7 +28,7 @@ type hasher struct {
EqualFunc
}

func (h *hasher) Hash(obj interface{}) (string, error) {
func (h *hasher) Hash(obj interface{}) string {
return h.ObjectHashFunc(obj)
}

Expand All @@ -54,25 +54,24 @@ func NewObjectHash() ObjectHasher {

// SecureObject canonicalizes the object before hashing with sha512 and then
// with xxhash
func SecureObject(obj interface{}) (string, error) {
func SecureObject(obj interface{}) string {
hasher := sha512.New512_256()
printer := spew.ConfigState{
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
}
_, err := printer.Fprintf(hasher, "%#v", obj)
if err != nil {
return "", err
}
// sha512's hasher.Write never returns an error, and Fprintf just passes up
// the underlying Write call's error, so we can safely ignore the error here
_, _ = printer.Fprintf(hasher, "%#v", obj)
// xxhash the sha512 hash to get a shorter value
xxhasher := xxhash.New()
_, err = xxhasher.Write(hasher.Sum(nil))
if err != nil {
return "", err
}
return rand.SafeEncodeString(fmt.Sprint(xxhasher.Sum(nil))), nil

// xxhash's hasher.Write never returns an error, so we can safely ignore
// the error here tpp
_, _ = xxhasher.Write(hasher.Sum(nil))
return rand.SafeEncodeString(fmt.Sprint(xxhasher.Sum(nil)))
}

// SecureEqual compares hashes safely
Expand All @@ -81,19 +80,19 @@ func SecureEqual(a, b string) bool {
}

// Object canonicalizes the object before hashing with xxhash
func Object(obj interface{}) (string, error) {
func Object(obj interface{}) string {
hasher := xxhash.New()
printer := spew.ConfigState{
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
}
_, err := printer.Fprintf(hasher, "%#v", obj)
if err != nil {
return "", err
}
return rand.SafeEncodeString(fmt.Sprint(hasher.Sum(nil))), nil

// xxhash's hasher.Write never returns an error, and Fprintf just passes up
// the underlying Write call's error, so we can safely ignore the error here
_, _ = printer.Fprintf(hasher, "%#v", obj)
return rand.SafeEncodeString(fmt.Sprint(hasher.Sum(nil)))
}

// Equal compares hashes safely
Expand Down
4 changes: 2 additions & 2 deletions hash/hash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func ExampleObject() {
"some": "data",
},
}
hash, _ := Object(configmap)
hash := Object(configmap)
fmt.Println(Equal(hash, "n688h54h56ch64bh677h55fh648hddq"))
// Output: true
}
Expand All @@ -23,7 +23,7 @@ func ExampleSecureObject() {
"some": "data",
},
}
hash, _ := SecureObject(secret)
hash := SecureObject(secret)
fmt.Println(SecureEqual(hash, "n665hb8h667h68hfbhffh669h54dq"))
// Output: true
}
107 changes: 107 additions & 0 deletions hash/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package hash

// Set is a set that stores objects based on their Object hash
type Set[T any] map[string]T

// NewSet creates a set from a list of objects
func NewSet[T any](objects ...T) Set[T] {
set := make(map[string]T, len(objects))
for _, o := range objects {
set[Object(o)] = o
}
return set
}

// Has returns true if all objects are already in the set
func (s Set[T]) Has(objects ...T) bool {
for _, o := range objects {
_, ok := s[Object(o)]
if !ok {
return false
}
}
return true
}

// Insert adds all objects to the set
func (s Set[T]) Insert(objects ...T) Set[T] {
for _, o := range objects {
s[Object(o)] = o
}
return s
}

// Delete removes all objects from the set
func (s Set[T]) Delete(objects ...T) Set[T] {
for _, o := range objects {
delete(s, Object(o))
}
return s
}

// Len returns the number of objects in the set
func (s Set[T]) Len() int {
return len(s)
}

// Intersect returns a new set containing all the elements common to both.
// The new set will contain the object values from the receiver, not from the
// argument.
func (s Set[T]) Intersect(other Set[T]) Set[T] {
out := NewSet[T]()
for h, o := range s {
if _, ok := other[h]; ok {
out[h] = o
}
}
return out
}

// SetDifference returns the set of objects in s that are not in other.
func (s Set[T]) SetDifference(other Set[T]) Set[T] {
result := NewSet[T]()
for h, o := range s {
if _, ok := other[h]; !ok {
result[h] = o
}
}
return result
}

// Union returns the set of objects common to both sets.
func (s Set[T]) Union(other Set[T]) Set[T] {
result := NewSet[T]()
for h, o := range other {
result[h] = o
}
for h, o := range s {
result[h] = o
}
return result
}

// Contains returns true if all elements of other can be found in s.
func (s Set[T]) Contains(other Set[T]) bool {
for h := range other {
if _, ok := s[h]; !ok {
return false
}
}
return true
}

// EqualElements returns true if both sets have equal elements.
func (s Set[T]) EqualElements(other Set[T]) bool {
return s.Len() == other.Len() && s.Contains(other)
}

// Pop removes and returns a single element from the set, and a bool indicating
// whether an element was found to pop.
func (s Set[T]) Pop() (T, bool) {
for h, o := range s {
delete(s, h)
return o, true
}
var zero T
return zero, false
}
Loading

0 comments on commit 45ed61d

Please sign in to comment.