Alerting: time interval service to support addressing intervals by Base64 encoded name (#90563)

* rename to getMuteTimingByName

* add UID to api model of MuteTiming

* update GetMuteTiming to search by UID

* update UpdateMuteTiming to support search by UID

* update DeleteMuteTiming to support uid

* make sure UID is populated

* update usages

* use base64 url-safe, no padding encoding for UID
This commit is contained in:
Yuri Tseretyan
2024-07-26 16:43:40 -04:00
committed by GitHub
parent 2ab746ae76
commit 6b0d20c96a
6 changed files with 221 additions and 46 deletions
@@ -2,8 +2,6 @@ package timeinterval
import (
"encoding/json"
"fmt"
"hash/fnv"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
@@ -14,12 +12,6 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
)
func getIntervalUID(t definitions.MuteTimeInterval) string {
sum := fnv.New64()
_, _ = sum.Write([]byte(t.Name))
return fmt.Sprintf("%016x", sum.Sum64())
}
func convertToK8sResources(orgID int64, intervals []definitions.MuteTimeInterval, namespacer request.NamespaceMapper, selector fields.Selector) (*model.TimeIntervalList, error) {
data, err := json.Marshal(intervals)
if err != nil {
@@ -59,12 +51,11 @@ func convertToK8sResource(orgID int64, interval definitions.MuteTimeInterval, na
}
func buildTimeInterval(orgID int64, interval definitions.MuteTimeInterval, spec model.TimeIntervalSpec, namespacer request.NamespaceMapper) model.TimeInterval {
uid := getIntervalUID(interval) // TODO replace to stable UID when we switch to normal storage
i := model.TimeInterval{
TypeMeta: resourceInfo.TypeMeta(),
ObjectMeta: metav1.ObjectMeta{
UID: types.UID(uid), // TODO This is needed to make PATCH work
Name: uid, // TODO replace to stable UID when we switch to normal storage
UID: types.UID(interval.UID), // TODO This is needed to make PATCH work
Name: interval.UID, // TODO replace to stable UID when we switch to normal storage
Namespace: namespacer(orgID),
ResourceVersion: interval.Version,
},
@@ -85,6 +76,7 @@ func convertToDomainModel(interval *model.TimeInterval) (definitions.MuteTimeInt
return definitions.MuteTimeInterval{}, err
}
result.Version = interval.ResourceVersion
result.UID = interval.ObjectMeta.Name
err = result.Validate()
if err != nil {
return definitions.MuteTimeInterval{}, err
@@ -25,10 +25,9 @@ var resourceInfo = notifications.TimeIntervalResourceInfo
type TimeIntervalService interface {
GetMuteTimings(ctx context.Context, orgID int64) ([]definitions.MuteTimeInterval, error)
GetMuteTiming(ctx context.Context, name string, orgID int64) (definitions.MuteTimeInterval, error)
CreateMuteTiming(ctx context.Context, mt definitions.MuteTimeInterval, orgID int64) (definitions.MuteTimeInterval, error)
UpdateMuteTiming(ctx context.Context, mt definitions.MuteTimeInterval, orgID int64) (definitions.MuteTimeInterval, error)
DeleteMuteTiming(ctx context.Context, name string, orgID int64, provenance definitions.Provenance, version string) error
DeleteMuteTiming(ctx context.Context, nameOrUid string, orgID int64, provenance definitions.Provenance, version string) error
}
type legacyStorage struct {
@@ -85,7 +84,7 @@ func (s *legacyStorage) Get(ctx context.Context, uid string, _ *metav1.GetOption
}
for _, mt := range timings {
if getIntervalUID(mt) == uid {
if mt.UID == uid {
return convertToK8sResource(info.OrgID, mt, s.namespacer)
}
}
@@ -159,7 +158,7 @@ func (s *legacyStorage) Update(ctx context.Context,
return old, false, err
}
if p.ObjectMeta.Name != getIntervalUID(interval) {
if p.ObjectMeta.Name != interval.UID {
return nil, false, errors.NewBadRequest("title of cannot be changed. Consider creating a new resource.")
}
@@ -196,8 +195,8 @@ func (s *legacyStorage) Delete(ctx context.Context, uid string, deleteValidation
return nil, false, fmt.Errorf("expected time-interval but got %s", old.GetObjectKind().GroupVersionKind())
}
err = s.service.DeleteMuteTiming(ctx, p.Spec.Name, info.OrgID, definitions.Provenance(models.ProvenanceNone), version) // TODO add support for dry-run option
return old, false, err // false - will be deleted async
err = s.service.DeleteMuteTiming(ctx, p.ObjectMeta.Name, info.OrgID, definitions.Provenance(models.ProvenanceNone), version) // TODO add support for dry-run option
return old, false, err // false - will be deleted async
}
func (s *legacyStorage) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *internalversion.ListOptions) (runtime.Object, error) {