history in resource package

This commit is contained in:
Ryan McKinley 2024-06-27 10:09:59 +03:00
parent 37c6b56e4e
commit b71329a8c3
5 changed files with 120 additions and 132 deletions

View File

@ -113,10 +113,9 @@ func (a *dashboardSqlAccess) GetDashboard(ctx context.Context, orgId int64, uid
defer func() { _ = rows.Close() }()
row, err := rows.Next()
if err != nil {
if err != nil || row == nil {
return nil, 0, err
}
return row.Dash, row.Version, nil
}

View File

@ -29,6 +29,7 @@ import (
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/provisioning"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/storage/unified/apistore"
)
var _ builder.APIGroupBuilder = (*DashboardsAPIBuilder)(nil)
@ -154,9 +155,10 @@ func (b *DashboardsAPIBuilder) GetAPIGroupInfo(
storage[dash.StoragePath("dto")] = &DTOConnector{
builder: b,
}
storage[dash.StoragePath("versions")] = &VersionsREST{
search: b.store.server, // resource.NewLocalResourceSearchClient(b.store.server),
}
storage[dash.StoragePath("history")] = apistore.NewHistoryConnector(
b.store.server, // as client???
dashboard.DashboardResourceInfo.GroupResource(),
)
// // Dual writes if a RESTOptionsGetter is provided
// if desiredMode != grafanarest.Mode0 && optsGetter != nil {

View File

@ -1,125 +0,0 @@
package dashboard
import (
"context"
"encoding/json"
"net/http"
"strconv"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
"github.com/grafana/grafana/pkg/apimachinery/utils"
dashboard "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/storage/unified/resource"
)
type VersionsREST struct {
search resource.ResourceSearchServer // should be a client!
}
var _ = rest.Connecter(&VersionsREST{})
var _ = rest.StorageMetadata(&VersionsREST{})
func (r *VersionsREST) New() runtime.Object {
return &metav1.PartialObjectMetadataList{}
}
func (r *VersionsREST) Destroy() {
}
func (r *VersionsREST) ConnectMethods() []string {
return []string{"GET"}
}
func (r *VersionsREST) ProducesMIMETypes(verb string) []string {
return nil
}
func (r *VersionsREST) ProducesObject(verb string) interface{} {
return &metav1.PartialObjectMetadataList{}
}
func (r *VersionsREST) NewConnectOptions() (runtime.Object, bool, string) {
return nil, true, ""
}
func (r *VersionsREST) Connect(ctx context.Context, uid string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
info, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
}
key := &resource.ResourceKey{
Namespace: info.Value,
Group: dashboard.GROUP,
Resource: dashboard.DashboardResourceInfo.GroupResource().Resource,
Name: uid,
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
path := req.URL.Path
idx := strings.LastIndex(path, "/versions/")
if idx > 0 {
vkey := path[strings.LastIndex(path, "/")+1:]
version, err := strconv.ParseInt(vkey, 10, 64)
if err != nil {
responder.Error(err)
return
}
dashbytes, err := r.search.Read(ctx, &resource.ReadRequest{
Key: key,
ResourceVersion: version,
})
if err != nil {
responder.Error(err)
return
}
// Convert the version to a regular dashboard
dash := &dashboard.Dashboard{}
json.Unmarshal(dashbytes.Value, dash)
meta, err := utils.MetaAccessor(dash)
if err != nil {
responder.Error(err)
return
}
meta.SetResourceVersionInt64(dashbytes.ResourceVersion)
responder.Object(100, dash)
return
}
rsp, err := r.search.History(ctx, &resource.HistoryRequest{
NextPageToken: "", // TODO!
Limit: 100,
Key: key,
})
if err != nil {
responder.Error(err)
return
}
list := &metav1.PartialObjectMetadataList{
ListMeta: metav1.ListMeta{
Continue: rsp.NextPageToken,
},
}
if rsp.ResourceVersion > 0 {
list.ResourceVersion = strconv.FormatInt(rsp.ResourceVersion, 10)
}
for _, v := range rsp.Items {
partial := metav1.PartialObjectMetadata{}
err = json.Unmarshal(v.PartialObjectMeta, &partial)
if err != nil {
responder.Error(err)
return
}
list.Items = append(list.Items, partial)
}
responder.Object(http.StatusOK, list)
}), nil
}

View File

@ -0,0 +1,103 @@
package apistore
import (
"context"
"encoding/json"
"net/http"
"strconv"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/registry/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/storage/unified/resource"
)
type HistoryConnector interface {
rest.Storage
rest.Connecter
rest.StorageMetadata
}
func NewHistoryConnector(search resource.ResourceSearchServer, gr schema.GroupResource) HistoryConnector {
return &historyREST{
search: search,
gr: gr,
}
}
type historyREST struct {
search resource.ResourceSearchServer // should be a client!
gr schema.GroupResource
}
func (r *historyREST) New() runtime.Object {
return &metav1.PartialObjectMetadataList{}
}
func (r *historyREST) Destroy() {
}
func (r *historyREST) ConnectMethods() []string {
return []string{"GET"}
}
func (r *historyREST) ProducesMIMETypes(verb string) []string {
return nil
}
func (r *historyREST) ProducesObject(verb string) interface{} {
return &metav1.PartialObjectMetadataList{}
}
func (r *historyREST) NewConnectOptions() (runtime.Object, bool, string) {
return nil, false, ""
}
func (r *historyREST) Connect(ctx context.Context, uid string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
info, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
}
key := &resource.ResourceKey{
Namespace: info.Value,
Group: r.gr.Group,
Resource: r.gr.Resource,
Name: uid,
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
query := req.URL.Query()
rsp, err := r.search.History(ctx, &resource.HistoryRequest{
NextPageToken: query.Get("token"),
Limit: 100, // TODO, from query
Key: key,
})
if err != nil {
responder.Error(err)
return
}
list := &metav1.PartialObjectMetadataList{
ListMeta: metav1.ListMeta{
Continue: rsp.NextPageToken,
},
}
if rsp.ResourceVersion > 0 {
list.ResourceVersion = strconv.FormatInt(rsp.ResourceVersion, 10)
}
for _, v := range rsp.Items {
partial := metav1.PartialObjectMetadata{}
err = json.Unmarshal(v.PartialObjectMeta, &partial)
if err != nil {
responder.Error(err)
return
}
list.Items = append(list.Items, partial)
}
responder.Object(http.StatusOK, list)
}), nil
}

View File

@ -248,12 +248,21 @@ func (s *Storage) Watch(ctx context.Context, _ string, opts storage.ListOptions)
// The returned contents may be delayed, but it is guaranteed that they will
// match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'.
func (s *Storage) Get(ctx context.Context, _ string, opts storage.GetOptions, objPtr runtime.Object) error {
key, err := getKey(ctx)
var err error
req := &resource.ReadRequest{}
req.Key, err = getKey(ctx)
if err != nil {
return err
}
rsp, err := s.store.Read(ctx, &resource.ReadRequest{Key: key})
if opts.ResourceVersion != "" {
req.ResourceVersion, err = strconv.ParseInt(opts.ResourceVersion, 10, 64)
if err != nil {
return err
}
}
rsp, err := s.store.Read(ctx, req)
if err != nil {
return err
}