support generic response
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/apistore"
|
||||
"github.com/grafana/grafana/pkg/tsdb/grafana-testdata-datasource/kinds"
|
||||
)
|
||||
|
||||
@@ -89,10 +90,6 @@ func RegisterAPIService(
|
||||
return nil, fmt.Errorf("plugin client is not a PluginClient: %T", pluginClient)
|
||||
}
|
||||
|
||||
if pluginJSON.ID != "grafana-testdata-datasource" {
|
||||
continue // FOR TESTING! codec currently picks the first registered apiVersion :cry:
|
||||
}
|
||||
|
||||
builder, err = NewDataSourceAPIBuilder(
|
||||
pluginJSON,
|
||||
client,
|
||||
@@ -223,6 +220,12 @@ func (b *DataSourceAPIBuilder) AllowedV0Alpha1Resources() []string {
|
||||
}
|
||||
|
||||
func (b *DataSourceAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.APIGroupInfo, opts builder.APIGroupOptions) error {
|
||||
opts.StorageOptsRegister(b.datasourceResourceInfo.GroupResource(), apistore.StorageOptions{
|
||||
EnableFolderSupport: false,
|
||||
|
||||
Scheme: opts.Scheme, // allows for generic Type applied to multiple groups
|
||||
})
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
|
||||
// Register the raw datasource connection
|
||||
|
||||
@@ -3,8 +3,10 @@ package apistore
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
@@ -138,8 +140,7 @@ func (s *Storage) prepareObjectForStorage(ctx context.Context, newObject runtime
|
||||
return v, err
|
||||
}
|
||||
|
||||
err = s.codec.Encode(newObject, &v.raw)
|
||||
if err == nil {
|
||||
if err = s.encode(newObject, &v.raw); err == nil {
|
||||
err = s.handleLargeResources(ctx, obj, &v.raw)
|
||||
}
|
||||
return v, err
|
||||
@@ -233,8 +234,7 @@ func (s *Storage) prepareObjectForUpdate(ctx context.Context, updateObject runti
|
||||
obj.SetAnnotation(utils.AnnoKeyUpdatedTimestamp, previous.GetAnnotation(utils.AnnoKeyUpdatedTimestamp))
|
||||
}
|
||||
|
||||
err = s.codec.Encode(updateObject, &v.raw)
|
||||
if err == nil {
|
||||
if s.encode(updateObject, &v.raw); err == nil {
|
||||
err = s.handleLargeResources(ctx, obj, &v.raw)
|
||||
}
|
||||
return v, err
|
||||
@@ -268,7 +268,38 @@ func (s *Storage) handleLargeResources(ctx context.Context, obj utils.GrafanaMet
|
||||
}
|
||||
|
||||
// Now encode the smaller version
|
||||
return s.codec.Encode(orig, buf)
|
||||
return s.encode(orig, buf)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Storage) encode(obj runtime.Object, w io.Writer) error {
|
||||
// The standard encoder is fine when only one type maps to a group
|
||||
if s.opts.Scheme == nil {
|
||||
return s.codec.Encode(obj, w)
|
||||
}
|
||||
|
||||
// Ensure group+version+kind are configured
|
||||
info := obj.GetObjectKind()
|
||||
gvk := info.GroupVersionKind()
|
||||
if gvk.Group == "" || gvk.Kind == "" || gvk.Version == "" {
|
||||
gvks, _, err := s.opts.Scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to encode object %w", err)
|
||||
}
|
||||
for _, v := range gvks {
|
||||
if v.Group != s.gr.Group {
|
||||
continue // skip values not in this group
|
||||
}
|
||||
gvk.Group = v.Group
|
||||
gvk.Kind = v.Kind
|
||||
if gvk.Version == "" {
|
||||
gvk.Version = v.Version
|
||||
}
|
||||
info.SetGroupVersionKind(gvk)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return json.NewEncoder(w).Encode(obj)
|
||||
}
|
||||
|
||||
@@ -33,9 +33,11 @@ func TestPrepareObjectForStorage(t *testing.T) {
|
||||
node, err := snowflake.NewNode(rand.Int64N(1024))
|
||||
require.NoError(t, err)
|
||||
s := &Storage{
|
||||
gr: dashv1.DashboardResourceInfo.GroupResource(),
|
||||
codec: apitesting.TestCodec(rtcodecs, dashv1.DashboardResourceInfo.GroupVersion()),
|
||||
snowflake: node,
|
||||
opts: StorageOptions{
|
||||
Scheme: rtscheme,
|
||||
EnableFolderSupport: true,
|
||||
LargeObjectSupport: nil,
|
||||
MaximumNameLength: 100,
|
||||
|
||||
@@ -57,6 +57,8 @@ type DefaultPermissionSetter = func(ctx context.Context, key *resourcepb.Resourc
|
||||
|
||||
// Optional settings that apply to a single resource
|
||||
type StorageOptions struct {
|
||||
Scheme *runtime.Scheme
|
||||
|
||||
// ????: should we constrain this to only dashboards for now?
|
||||
// Not yet clear if this is a good general solution, or just a stop-gap
|
||||
LargeObjectSupport LargeObjectSupport
|
||||
|
||||
@@ -37,7 +37,7 @@ func TestIntegrationTestDatasource(t *testing.T) {
|
||||
grafanarest.Mode0, // Legacy only
|
||||
// grafanarest.Mode2, // write both, read legacy
|
||||
// grafanarest.Mode3, // write both, read unified
|
||||
// grafanarest.Mode5, // Unified only
|
||||
grafanarest.Mode5, // Unified only
|
||||
} {
|
||||
t.Run(fmt.Sprintf("testdata (mode:%d)", mode), func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
Reference in New Issue
Block a user