Backend
This commit is contained in:
@@ -16,13 +16,28 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/legacy_storage"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func ConvertToK8sResource(orgID int64, r definitions.Route, version string, namespacer request.NamespaceMapper) (*model.RoutingTree, error) {
|
||||
func ConvertToK8sResources(orgID int64, routes legacy_storage.ManagedRoutes, namespacer request.NamespaceMapper) (*model.RoutingTreeList, error) {
|
||||
result := &model.RoutingTreeList{
|
||||
Items: make([]model.RoutingTree, 0, len(routes)),
|
||||
}
|
||||
for _, r := range routes {
|
||||
k8sResource, err := ConvertToK8sResource(orgID, r, namespacer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert route %q to k8s resource: %w", r.Name, err)
|
||||
}
|
||||
result.Items = append(result.Items, *k8sResource)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func ConvertToK8sResource(orgID int64, r *legacy_storage.ManagedRoute, namespacer request.NamespaceMapper) (*model.RoutingTree, error) {
|
||||
spec := model.RoutingTreeSpec{
|
||||
Defaults: model.RoutingTreeRouteDefaults{
|
||||
GroupBy: r.GroupByStr,
|
||||
GroupBy: r.GroupBy,
|
||||
GroupWait: optionalPrometheusDurationToString(r.GroupWait),
|
||||
GroupInterval: optionalPrometheusDurationToString(r.GroupInterval),
|
||||
RepeatInterval: optionalPrometheusDurationToString(r.RepeatInterval),
|
||||
@@ -39,9 +54,9 @@ func ConvertToK8sResource(orgID int64, r definitions.Route, version string, name
|
||||
|
||||
var result = &model.RoutingTree{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: model.UserDefinedRoutingTreeName,
|
||||
Name: r.Name,
|
||||
Namespace: namespacer(orgID),
|
||||
ResourceVersion: version,
|
||||
ResourceVersion: r.Version,
|
||||
},
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
alerting_models "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/legacy_storage"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -22,9 +23,11 @@ var (
|
||||
)
|
||||
|
||||
type RouteService interface {
|
||||
GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, string, error)
|
||||
UpdatePolicyTree(ctx context.Context, orgID int64, tree definitions.Route, p alerting_models.Provenance, version string) (definitions.Route, string, error)
|
||||
ResetPolicyTree(ctx context.Context, orgID int64, p alerting_models.Provenance) (definitions.Route, error)
|
||||
GetManagedRoutes(ctx context.Context, orgID int64) (legacy_storage.ManagedRoutes, error)
|
||||
GetManagedRoute(ctx context.Context, orgID int64, name string) (legacy_storage.ManagedRoute, error)
|
||||
DeleteManagedRoute(ctx context.Context, orgID int64, name string, p alerting_models.Provenance, version string) error
|
||||
CreateManagedRoute(ctx context.Context, orgID int64, name string, subtree definitions.Route, p alerting_models.Provenance) (*legacy_storage.ManagedRoute, error)
|
||||
UpdateManagedRoute(ctx context.Context, orgID int64, name string, subtree definitions.Route, p alerting_models.Provenance, version string) (*legacy_storage.ManagedRoute, error)
|
||||
}
|
||||
|
||||
type legacyStorage struct {
|
||||
@@ -55,56 +58,76 @@ func (s *legacyStorage) ConvertToTable(ctx context.Context, object runtime.Objec
|
||||
return s.tableConverter.ConvertToTable(ctx, object, tableOptions)
|
||||
}
|
||||
|
||||
func (s *legacyStorage) getUserDefinedRoutingTree(ctx context.Context) (*model.RoutingTree, error) {
|
||||
func (s *legacyStorage) List(ctx context.Context, _ *internalversion.ListOptions) (runtime.Object, error) {
|
||||
orgId, err := request.OrgIDForList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, version, err := s.service.GetPolicyTree(ctx, orgId)
|
||||
managedRoutes, err := s.service.GetManagedRoutes(ctx, orgId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ConvertToK8sResource(orgId, res, version, s.namespacer)
|
||||
}
|
||||
|
||||
func (s *legacyStorage) List(ctx context.Context, _ *internalversion.ListOptions) (runtime.Object, error) {
|
||||
user, err := s.getUserDefinedRoutingTree(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &model.RoutingTreeList{
|
||||
Items: []model.RoutingTree{
|
||||
*user,
|
||||
},
|
||||
}, nil
|
||||
return ConvertToK8sResources(orgId, managedRoutes, s.namespacer)
|
||||
}
|
||||
|
||||
func (s *legacyStorage) Get(ctx context.Context, name string, _ *metav1.GetOptions) (runtime.Object, error) {
|
||||
if name != model.UserDefinedRoutingTreeName {
|
||||
return nil, errors.NewNotFound(ResourceInfo.GroupResource(), name)
|
||||
info, err := request.NamespaceInfoFrom(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.getUserDefinedRoutingTree(ctx)
|
||||
managedRoute, err := s.service.GetManagedRoute(ctx, info.OrgID, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ConvertToK8sResource(info.OrgID, &managedRoute, s.namespacer)
|
||||
}
|
||||
|
||||
func (s *legacyStorage) Create(_ context.Context,
|
||||
_ runtime.Object,
|
||||
_ rest.ValidateObjectFunc,
|
||||
func (s *legacyStorage) Create(ctx context.Context,
|
||||
obj runtime.Object,
|
||||
createValidation rest.ValidateObjectFunc,
|
||||
_ *metav1.CreateOptions,
|
||||
) (runtime.Object, error) {
|
||||
return nil, errors.NewMethodNotSupported(ResourceInfo.GroupResource(), "create")
|
||||
info, err := request.NamespaceInfoFrom(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if createValidation != nil {
|
||||
if err := createValidation(ctx, obj.DeepCopyObject()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
p, ok := obj.(*model.RoutingTree)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected %s but got %s", ResourceInfo.GroupVersionKind(), obj.GetObjectKind().GroupVersionKind())
|
||||
}
|
||||
domainModel, _, err := convertToDomainModel(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
created, err := s.service.CreateManagedRoute(ctx, info.OrgID, p.Name, domainModel, alerting_models.ProvenanceNone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ConvertToK8sResource(info.OrgID, created, s.namespacer)
|
||||
}
|
||||
|
||||
func (s *legacyStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, _ rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, _ bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
|
||||
if name != model.UserDefinedRoutingTreeName {
|
||||
return nil, false, errors.NewNotFound(ResourceInfo.GroupResource(), name)
|
||||
}
|
||||
func (s *legacyStorage) Update(
|
||||
ctx context.Context,
|
||||
name string,
|
||||
objInfo rest.UpdatedObjectInfo,
|
||||
_ rest.ValidateObjectFunc,
|
||||
updateValidation rest.ValidateObjectUpdateFunc,
|
||||
_ bool,
|
||||
_ *metav1.UpdateOptions,
|
||||
) (runtime.Object, bool, error) {
|
||||
info, err := request.NamespaceInfoFrom(ctx, true)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
old, err := s.Get(ctx, model.UserDefinedRoutingTreeName, nil)
|
||||
old, err := s.Get(ctx, name, nil)
|
||||
if err != nil {
|
||||
return old, false, err
|
||||
}
|
||||
@@ -122,24 +145,26 @@ func (s *legacyStorage) Update(ctx context.Context, name string, objInfo rest.Up
|
||||
return nil, false, fmt.Errorf("expected %s but got %s", ResourceInfo.GroupVersionKind(), obj.GetObjectKind().GroupVersionKind())
|
||||
}
|
||||
|
||||
model, version, err := convertToDomainModel(p)
|
||||
domainModel, version, err := convertToDomainModel(p)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
updated, updatedVersion, err := s.service.UpdatePolicyTree(ctx, info.OrgID, model, alerting_models.ProvenanceNone, version)
|
||||
updated, err := s.service.UpdateManagedRoute(ctx, info.OrgID, p.Name, domainModel, alerting_models.ProvenanceNone, version)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
obj, err = ConvertToK8sResource(info.OrgID, updated, updatedVersion, s.namespacer)
|
||||
obj, err = ConvertToK8sResource(info.OrgID, updated, s.namespacer)
|
||||
return obj, false, err
|
||||
}
|
||||
|
||||
// Delete implements rest.GracefulDeleter. It is needed for API server to not crash when it registers DeleteCollection method
|
||||
func (s *legacyStorage) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, opts *metav1.DeleteOptions) (runtime.Object, bool, error) {
|
||||
if name != model.UserDefinedRoutingTreeName {
|
||||
return nil, false, errors.NewNotFound(ResourceInfo.GroupResource(), name)
|
||||
}
|
||||
func (s *legacyStorage) Delete(
|
||||
ctx context.Context,
|
||||
name string,
|
||||
deleteValidation rest.ValidateObjectFunc,
|
||||
options *metav1.DeleteOptions,
|
||||
) (runtime.Object, bool, error) {
|
||||
info, err := request.NamespaceInfoFrom(ctx, true)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
@@ -155,10 +180,14 @@ func (s *legacyStorage) Delete(ctx context.Context, name string, deleteValidatio
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
_, err = s.service.ResetPolicyTree(ctx, info.OrgID, alerting_models.ProvenanceNone) // TODO add support for dry-run option
|
||||
version := ""
|
||||
if options.Preconditions != nil && options.Preconditions.ResourceVersion != nil {
|
||||
version = *options.Preconditions.ResourceVersion
|
||||
}
|
||||
err = s.service.DeleteManagedRoute(ctx, info.OrgID, name, alerting_models.ProvenanceNone, version) // TODO add support for dry-run option
|
||||
return old, false, err
|
||||
}
|
||||
|
||||
func (s *legacyStorage) DeleteCollection(_ context.Context, _ rest.ValidateObjectFunc, _ *metav1.DeleteOptions, _ *internalversion.ListOptions) (runtime.Object, error) {
|
||||
return nil, errors.NewMethodNotSupported(ResourceInfo.GroupResource(), "delete")
|
||||
return nil, errors.NewMethodNotSupported(ResourceInfo.GroupResource(), "deleteCollection")
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package routingtree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
model "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1"
|
||||
@@ -14,5 +16,18 @@ var ResourceInfo = utils.NewResourceInfo(kind.Group(), kind.Version(),
|
||||
kind.GroupVersionResource().Resource, strings.ToLower(kind.Kind()), kind.Kind(),
|
||||
func() runtime.Object { return kind.ZeroValue() },
|
||||
func() runtime.Object { return kind.ZeroListValue() },
|
||||
utils.TableColumns{},
|
||||
utils.TableColumns{
|
||||
Definition: []metav1.TableColumnDefinition{
|
||||
{Name: "Name", Type: "string", Format: "name"},
|
||||
},
|
||||
Reader: func(obj any) ([]interface{}, error) {
|
||||
r, ok := obj.(*model.RoutingTree)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected resource or info")
|
||||
}
|
||||
return []interface{}{
|
||||
r.Name,
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user