mirror of
https://github.com/grafana/grafana.git
synced 2025-01-02 04:07:15 -06:00
22c937340e
This reverts commit 5e4fd94413
.
112 lines
3.2 KiB
Go
112 lines
3.2 KiB
Go
package models
|
|
|
|
import (
|
|
// nolint:gosec
|
|
"crypto/sha1"
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
|
)
|
|
|
|
// InstanceLabels is an extension to data.Labels with methods
|
|
// for database serialization.
|
|
type InstanceLabels data.Labels
|
|
|
|
// FromDB loads labels stored in the database as json tuples into InstanceLabels.
|
|
// FromDB is part of the xorm Conversion interface.
|
|
func (il *InstanceLabels) FromDB(b []byte) error {
|
|
tl := &tupleLabels{}
|
|
err := json.Unmarshal(b, tl)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
labels, err := tupleLablesToLabels(*tl)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*il = labels
|
|
return nil
|
|
}
|
|
|
|
// ToDB is not implemented as serialization is handled with manual SQL queries).
|
|
// ToDB is part of the xorm Conversion interface.
|
|
func (il *InstanceLabels) ToDB() ([]byte, error) {
|
|
// Currently handled manually in sql command, needed to fulfill the xorm
|
|
// converter interface it seems
|
|
return []byte{}, fmt.Errorf("database serialization of alerting ng Instance labels is not implemented")
|
|
}
|
|
|
|
func (il *InstanceLabels) StringKey() (string, error) {
|
|
tl := labelsToTupleLabels(*il)
|
|
b, err := json.Marshal(tl)
|
|
if err != nil {
|
|
return "", fmt.Errorf("can not gereate key due to failure to encode labels: %w", err)
|
|
}
|
|
return string(b), nil
|
|
}
|
|
|
|
// StringAndHash returns a the json representation of the labels as tuples
|
|
// sorted by key. It also returns the a hash of that representation.
|
|
func (il *InstanceLabels) StringAndHash() (string, string, error) {
|
|
tl := labelsToTupleLabels(*il)
|
|
|
|
b, err := json.Marshal(tl)
|
|
if err != nil {
|
|
return "", "", fmt.Errorf("can not gereate key for alert instance due to failure to encode labels: %w", err)
|
|
}
|
|
|
|
h := sha1.New()
|
|
if _, err := h.Write(b); err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
return string(b), fmt.Sprintf("%x", h.Sum(nil)), nil
|
|
}
|
|
|
|
// The following is based on SDK code, copied for now
|
|
|
|
// tupleLables is an alternative representation of Labels (map[string]string) that can be sorted
|
|
// and then marshalled into a consistent string that can be used a map key. All tupleLabel objects
|
|
// in tupleLabels should have unique first elements (keys).
|
|
type tupleLabels []tupleLabel
|
|
|
|
// tupleLabel is an element of tupleLabels and should be in the form of [2]{"key", "value"}.
|
|
type tupleLabel [2]string
|
|
|
|
// Sort tupleLabels by each elements first property (key).
|
|
func (t *tupleLabels) sortBtKey() {
|
|
if t == nil {
|
|
return
|
|
}
|
|
sort.Slice((*t)[:], func(i, j int) bool {
|
|
return (*t)[i][0] < (*t)[j][0]
|
|
})
|
|
}
|
|
|
|
// labelsToTupleLabels converts Labels (map[string]string) to tupleLabels.
|
|
func labelsToTupleLabels(l InstanceLabels) tupleLabels {
|
|
t := make(tupleLabels, 0, len(l))
|
|
for k, v := range l {
|
|
t = append(t, tupleLabel{k, v})
|
|
}
|
|
t.sortBtKey()
|
|
return t
|
|
}
|
|
|
|
// tupleLabelsToLabels converts tupleLabels to Labels (map[string]string), erroring if there are duplicate keys.
|
|
func tupleLablesToLabels(tuples tupleLabels) (InstanceLabels, error) {
|
|
if tuples == nil {
|
|
return InstanceLabels{}, nil
|
|
}
|
|
labels := make(map[string]string)
|
|
for _, tuple := range tuples {
|
|
if key, ok := labels[tuple[0]]; ok {
|
|
return nil, fmt.Errorf("duplicate key '%v' in lables: %v", key, tuples)
|
|
}
|
|
labels[tuple[0]] = tuple[1]
|
|
}
|
|
return labels, nil
|
|
}
|