mirror of
https://github.com/luxfi/kms.git
synced 2026-07-27 03:38:31 +00:00
ghcr.io/luxfi/kms-operator has had no new image since v1.12.3. The Build KMS
Operator workflow failed on every tag since (v1.12.4 … v1.12.7) while its
sibling Build KMS succeeded on the same tag, so the tags looked published.
Dockerfile.operator:27 builds with -mod=vendor, and vendor/ had drifted from
go.mod in both directions:
- go.opentelemetry.io/otel/{metric,trace}: in vendor/modules.txt, not in go.mod
- github.com/luxfi/{crypto,geth,ids,keys,zap,address,age,cache,constants,
container,formatting,math,go-bip32,go-bip39}: in go.mod, not marked explicit
`go mod vendor` alone could not fix it — it aborted first on go.sum entries
missing for the k8s packages cmd/kms-operator imports (k8s.io/api/core/v1,
k8s.io/apimachinery/..., k8s.io/client-go/{dynamic,kubernetes,rest}). So:
go mod tidy (adds them, drops now-unused indirects) then go mod vendor.
Verified by stash control:
operator, -mod=vendor: rc=1 -> rc=0 ("inconsistent vendoring" 1 -> 0)
server, -mod=vendor: rc=1 -> rc=1 (unchanged)
The server's vendor build was already broken and stays broken, for an unrelated
reason: blst.h has never been vendored (confirmed absent from HEAD's tree, so it
could not have worked before either) — go mod vendor does not copy cgo headers
that live outside the package dir. It is not a regression and does not affect
CI: the server's Dockerfile builds with GOFLAGS=-mod=mod after `rm -f go.sum &&
go mod download`, i.e. from the module cache, never from vendor/. The operator
is the only -mod=vendor consumer, which is exactly why it was the only failure.
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
131 lines
3.8 KiB
Go
131 lines
3.8 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package attribute // import "go.opentelemetry.io/otel/attribute"
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"go.opentelemetry.io/otel/attribute/internal/xxhash"
|
|
)
|
|
|
|
// Type identifiers. These identifiers are hashed before the value of the
|
|
// corresponding type. This is done to distinguish values that are hashed with
|
|
// the same value representation (e.g. `int64(1)` and `true`, []int64{0} and
|
|
// int64(0)).
|
|
//
|
|
// These are all 8 byte length strings converted to a uint64 representation. A
|
|
// uint64 is used instead of the string directly as an optimization, it avoids
|
|
// the for loop in [xxhash] which adds minor overhead.
|
|
const (
|
|
boolID uint64 = 7953749933313450591 // "_boolean" (little endian)
|
|
int64ID uint64 = 7592915492740740150 // "64_bit_i" (little endian)
|
|
float64ID uint64 = 7376742710626956342 // "64_bit_f" (little endian)
|
|
stringID uint64 = 6874584755375207263 // "_string_" (little endian)
|
|
boolSliceID uint64 = 6875993255270243167 // "_[]bool_" (little endian)
|
|
int64SliceID uint64 = 3762322556277578591 // "_[]int64" (little endian)
|
|
float64SliceID uint64 = 7308324551835016539 // "[]double" (little endian)
|
|
stringSliceID uint64 = 7453010373645655387 // "[]string" (little endian)
|
|
byteSliceID uint64 = 6874028470941080415 // "_[]byte_" (little endian)
|
|
sliceID uint64 = 7883494272577650031 // "__slice_" (little endian)
|
|
emptyID uint64 = 7305809155345288421 // "__empty_" (little endian)
|
|
)
|
|
|
|
// hashKVs returns a new xxHash64 hash of kvs.
|
|
func hashKVs(kvs []KeyValue) uint64 {
|
|
h := xxhash.New()
|
|
for _, kv := range kvs {
|
|
h = hashKV(h, kv)
|
|
}
|
|
return h.Sum64()
|
|
}
|
|
|
|
// hashKV returns the xxHash64 hash of kv with h as the base.
|
|
func hashKV(h xxhash.Hash, kv KeyValue) xxhash.Hash {
|
|
h = h.String(string(kv.Key))
|
|
return hashValue(h, kv.Value)
|
|
}
|
|
|
|
func hashValue(h xxhash.Hash, v Value) xxhash.Hash {
|
|
switch v.Type() {
|
|
case BOOL:
|
|
h = h.Uint64(boolID)
|
|
h = h.Uint64(v.numeric)
|
|
case INT64:
|
|
h = h.Uint64(int64ID)
|
|
h = h.Uint64(v.numeric)
|
|
case FLOAT64:
|
|
h = h.Uint64(float64ID)
|
|
// Assumes numeric stored with math.Float64bits.
|
|
h = h.Uint64(v.numeric)
|
|
case STRING:
|
|
h = h.Uint64(stringID)
|
|
h = h.String(v.stringly)
|
|
case BOOLSLICE:
|
|
h = h.Uint64(boolSliceID)
|
|
rv := reflect.ValueOf(v.slice)
|
|
for i := 0; i < rv.Len(); i++ {
|
|
h = h.Bool(rv.Index(i).Bool())
|
|
}
|
|
case INT64SLICE:
|
|
h = h.Uint64(int64SliceID)
|
|
rv := reflect.ValueOf(v.slice)
|
|
for i := 0; i < rv.Len(); i++ {
|
|
h = h.Int64(rv.Index(i).Int())
|
|
}
|
|
case FLOAT64SLICE:
|
|
h = h.Uint64(float64SliceID)
|
|
rv := reflect.ValueOf(v.slice)
|
|
for i := 0; i < rv.Len(); i++ {
|
|
h = h.Float64(rv.Index(i).Float())
|
|
}
|
|
case STRINGSLICE:
|
|
h = h.Uint64(stringSliceID)
|
|
rv := reflect.ValueOf(v.slice)
|
|
for i := 0; i < rv.Len(); i++ {
|
|
h = h.String(rv.Index(i).String())
|
|
}
|
|
case BYTESLICE:
|
|
h = h.Uint64(byteSliceID)
|
|
h = h.String(v.stringly)
|
|
case SLICE:
|
|
h = h.Uint64(sliceID)
|
|
switch vals := v.slice.(type) {
|
|
case [0]Value:
|
|
// No values to hash, but the type identifier is still hashed above.
|
|
case [1]Value:
|
|
h = hashValueSlice(h, vals[:])
|
|
case [2]Value:
|
|
h = hashValueSlice(h, vals[:])
|
|
case [3]Value:
|
|
h = hashValueSlice(h, vals[:])
|
|
case [4]Value:
|
|
h = hashValueSlice(h, vals[:])
|
|
case [5]Value:
|
|
h = hashValueSlice(h, vals[:])
|
|
default:
|
|
rv := reflect.ValueOf(v.slice)
|
|
for i := 0; i < rv.Len(); i++ {
|
|
h = hashValue(h, rv.Index(i).Interface().(Value))
|
|
}
|
|
}
|
|
case EMPTY:
|
|
h = h.Uint64(emptyID)
|
|
default:
|
|
// Logging is an alternative, but using the internal logger here
|
|
// causes an import cycle so it is not done.
|
|
val := v.AsInterface()
|
|
msg := fmt.Sprintf("unknown value type: %[1]v (%[1]T)", val)
|
|
panic(msg)
|
|
}
|
|
return h
|
|
}
|
|
|
|
func hashValueSlice(h xxhash.Hash, vals []Value) xxhash.Hash {
|
|
for _, v := range vals {
|
|
h = hashValue(h, v)
|
|
}
|
|
return h
|
|
}
|