mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
171 lines
4.8 KiB
Go
171 lines
4.8 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apiserver/pkg/registry/rest"
|
|
|
|
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
|
"github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
|
"github.com/grafana/grafana/pkg/registry/apis/dashboard/access"
|
|
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
|
"github.com/grafana/grafana/pkg/services/apiserver/storage/entity"
|
|
)
|
|
|
|
var (
|
|
_ rest.Storage = (*dashboardStorage)(nil)
|
|
_ rest.Scoper = (*dashboardStorage)(nil)
|
|
_ rest.SingularNameProvider = (*dashboardStorage)(nil)
|
|
_ rest.Getter = (*dashboardStorage)(nil)
|
|
_ rest.Lister = (*dashboardStorage)(nil)
|
|
_ rest.Creater = (*dashboardStorage)(nil)
|
|
_ rest.Updater = (*dashboardStorage)(nil)
|
|
_ rest.GracefulDeleter = (*dashboardStorage)(nil)
|
|
)
|
|
|
|
type dashboardStorage struct {
|
|
resource common.ResourceInfo
|
|
access access.DashboardAccess
|
|
tableConverter rest.TableConvertor
|
|
}
|
|
|
|
func (s *dashboardStorage) New() runtime.Object {
|
|
return s.resource.NewFunc()
|
|
}
|
|
|
|
func (s *dashboardStorage) Destroy() {}
|
|
|
|
func (s *dashboardStorage) NamespaceScoped() bool {
|
|
return true
|
|
}
|
|
|
|
func (s *dashboardStorage) GetSingularName() string {
|
|
return s.resource.GetSingularName()
|
|
}
|
|
|
|
func (s *dashboardStorage) NewList() runtime.Object {
|
|
return s.resource.NewListFunc()
|
|
}
|
|
|
|
func (s *dashboardStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
|
|
return s.tableConverter.ConvertToTable(ctx, object, tableOptions)
|
|
}
|
|
|
|
func (s *dashboardStorage) Create(ctx context.Context,
|
|
obj runtime.Object,
|
|
createValidation rest.ValidateObjectFunc,
|
|
options *metav1.CreateOptions,
|
|
) (runtime.Object, error) {
|
|
info, err := request.NamespaceInfoFrom(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
p, ok := obj.(*v0alpha1.Dashboard)
|
|
if !ok {
|
|
return nil, fmt.Errorf("expected dashboard?")
|
|
}
|
|
|
|
// HACK to simplify unique name testing from kubectl
|
|
t := p.Spec.GetNestedString("title")
|
|
if strings.Contains(t, "${NOW}") {
|
|
t = strings.ReplaceAll(t, "${NOW}", fmt.Sprintf("%d", time.Now().Unix()))
|
|
p.Spec.Set("title", t)
|
|
}
|
|
|
|
dash, _, err := s.access.SaveDashboard(ctx, info.OrgID, p)
|
|
return dash, err
|
|
}
|
|
|
|
func (s *dashboardStorage) Update(ctx context.Context,
|
|
name string,
|
|
objInfo rest.UpdatedObjectInfo,
|
|
createValidation rest.ValidateObjectFunc,
|
|
updateValidation rest.ValidateObjectUpdateFunc,
|
|
forceAllowCreate bool,
|
|
options *metav1.UpdateOptions,
|
|
) (runtime.Object, bool, error) {
|
|
info, err := request.NamespaceInfoFrom(ctx, true)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
created := false
|
|
old, err := s.Get(ctx, name, nil)
|
|
if err != nil {
|
|
return old, created, err
|
|
}
|
|
|
|
obj, err := objInfo.UpdatedObject(ctx, old)
|
|
if err != nil {
|
|
return old, created, err
|
|
}
|
|
p, ok := obj.(*v0alpha1.Dashboard)
|
|
if !ok {
|
|
return nil, created, fmt.Errorf("expected dashboard after update")
|
|
}
|
|
|
|
_, created, err = s.access.SaveDashboard(ctx, info.OrgID, p)
|
|
if err == nil {
|
|
r, err := s.Get(ctx, name, nil)
|
|
return r, created, err
|
|
}
|
|
return nil, created, err
|
|
}
|
|
|
|
// GracefulDeleter
|
|
func (s *dashboardStorage) 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
|
|
}
|
|
|
|
return s.access.DeleteDashboard(ctx, info.OrgID, name)
|
|
}
|
|
|
|
func (s *dashboardStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
|
|
orgId, err := request.OrgIDForList(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// fmt.Printf("LIST: %s\n", options.Continue)
|
|
|
|
// translate grafana.app/* label selectors into field requirements
|
|
requirements, newSelector, err := entity.ReadLabelSelectors(options.LabelSelector)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
query := &access.DashboardQuery{
|
|
OrgID: orgId,
|
|
Limit: int(options.Limit),
|
|
MaxBytes: 2 * 1024 * 1024, // 2MB,
|
|
ContinueToken: options.Continue,
|
|
Requirements: requirements,
|
|
Labels: newSelector,
|
|
}
|
|
|
|
return s.access.GetDashboards(ctx, query)
|
|
}
|
|
|
|
func (s *dashboardStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
|
info, err := request.NamespaceInfoFrom(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.access.GetDashboard(ctx, info.OrgID, name)
|
|
}
|
|
|
|
// GracefulDeleter
|
|
func (s *dashboardStorage) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *internalversion.ListOptions) (runtime.Object, error) {
|
|
return nil, fmt.Errorf("DeleteCollection for dashboards not implemented")
|
|
}
|