Storage: simplify retrieving the file names from the response frame (#51805)

* add util method for storage list frame

* use go:embed

* remove enum
pull/51865/head
Artur Wierzbicki 3 years ago committed by GitHub
parent 4f931afe29
commit 052132be46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      pkg/services/store/service.go
  2. 6
      pkg/services/store/service_test.go
  3. 73
      pkg/services/store/testdata/example_list_frame.json
  4. 90
      pkg/services/store/testdata/example_root_level_list.json
  5. 26
      pkg/services/store/tree.go
  6. 37
      pkg/services/store/types.go
  7. 47
      pkg/services/store/types_test.go
  8. 6
      pkg/tsdb/grafanads/grafana.go

@ -6,7 +6,6 @@ import (
"fmt"
"strings"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/filestorage"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
@ -34,7 +33,7 @@ type StorageService interface {
registry.BackgroundService
// List folder contents
List(ctx context.Context, user *models.SignedInUser, path string) (*data.Frame, error)
List(ctx context.Context, user *models.SignedInUser, path string) (*StorageListFrame, error)
// Read raw file contents out of the store
Read(ctx context.Context, user *models.SignedInUser, path string) (*filestorage.File, error)
@ -114,7 +113,7 @@ func getOrgId(user *models.SignedInUser) int64 {
return user.OrgId
}
func (s *standardStorageService) List(ctx context.Context, user *models.SignedInUser, path string) (*data.Frame, error) {
func (s *standardStorageService) List(ctx context.Context, user *models.SignedInUser, path string) (*StorageListFrame, error) {
// apply access control here
return s.tree.ListFolder(ctx, getOrgId(user), path)
}

@ -43,15 +43,15 @@ func TestListFiles(t *testing.T) {
frame, err := store.List(context.Background(), dummyUser, "public/testdata")
require.NoError(t, err)
experimental.CheckGoldenJSONFrame(t, "testdata", "public_testdata.golden", frame, true)
experimental.CheckGoldenJSONFrame(t, "testdata", "public_testdata.golden", frame.Frame, true)
file, err := store.Read(context.Background(), dummyUser, "public/testdata/js_libraries.csv")
require.NoError(t, err)
require.NotNil(t, file)
frame, err = testdatasource.LoadCsvContent(bytes.NewReader(file.Contents), file.Name)
testDsFrame, err := testdatasource.LoadCsvContent(bytes.NewReader(file.Contents), file.Name)
require.NoError(t, err)
experimental.CheckGoldenJSONFrame(t, "testdata", "public_testdata_js_libraries.golden", frame, true)
experimental.CheckGoldenJSONFrame(t, "testdata", "public_testdata_js_libraries.golden", testDsFrame, true)
}
func TestUpload(t *testing.T) {

@ -0,0 +1,73 @@
{
"schema": {
"meta": {
"type": "directory-listing",
"custom": {
"HasMore": false
}
},
"fields": [
{
"name": "name",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "mediaType",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "size",
"type": "number",
"typeInfo": {
"frame": "int64"
},
"config": {
"unit": "bytes"
}
}
]
},
"data": {
"values": [
[
"DL_1.jpg",
"Screen Shot 2022-06-23 at 9.05.39 PM.png",
"Screen Shot 2022-06-24 at 11.58.32 AM.png",
"Screen Shot 2022-06-30 at 3.45.03 PM.png",
"Screen Shot 2022-07-05 at 3.24.27 PM.png",
"image.png",
"rocket_1f680.png",
"test-folder",
"topcoder12.png"
],
[
"image/jpeg",
"image/png",
"image/png",
"image/png",
"image/png",
"image/png",
"image/png",
"directory",
"image/png"
],
[
943004,
684257,
256396,
8796,
388290,
182568,
29066,
0,
90563
]
]
}
}

@ -0,0 +1,90 @@
{
"schema": {
"meta": {
"type": "directory-listing"
},
"fields": [
{
"name": "name",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "title",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "description",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "mediaType",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "storageType",
"type": "string",
"typeInfo": {
"frame": "string"
}
},
{
"name": "readOnly",
"type": "boolean",
"typeInfo": {
"frame": "bool"
}
},
{
"name": "builtIn",
"type": "boolean",
"typeInfo": {
"frame": "bool"
}
}
]
},
"data": {
"values": [
[
"public-static",
"resources"
],
[
"Public static files",
"Resources"
],
[
"Access files from the static public files",
"Upload custom resource files"
],
[
"directory",
"directory"
],
[
"disk",
"sql"
],
[
true,
false
],
[
true,
true
]
]
}
}

@ -85,7 +85,7 @@ func (t *nestedTree) GetFile(ctx context.Context, orgId int64, path string) (*fi
return root.Get(ctx, path)
}
func (t *nestedTree) ListFolder(ctx context.Context, orgId int64, path string) (*data.Frame, error) {
func (t *nestedTree) ListFolder(ctx context.Context, orgId int64, path string) (*StorageListFrame, error) {
if path == "" || path == "/" {
t.assureOrgIsInitialized(orgId)
@ -102,13 +102,13 @@ func (t *nestedTree) ListFolder(ctx context.Context, orgId int64, path string) (
readOnly := data.NewFieldFromFieldType(data.FieldTypeBool, count)
builtIn := data.NewFieldFromFieldType(data.FieldTypeBool, count)
mtype := data.NewFieldFromFieldType(data.FieldTypeString, count)
title.Name = "title"
names.Name = "name"
descr.Name = "description"
mtype.Name = "mediaType"
types.Name = "storageType"
readOnly.Name = "readOnly"
builtIn.Name = "builtIn"
title.Name = titleListFrameField
names.Name = nameListFrameField
descr.Name = descriptionListFrameField
mtype.Name = mediaTypeListFrameField
types.Name = storageTypeListFrameField
readOnly.Name = readOnlyListFrameField
builtIn.Name = builtInListFrameField
for _, f := range t.rootsByOrgId[ac.GlobalOrgID] {
meta := f.Meta()
names.Set(idx, meta.Config.Prefix)
@ -138,7 +138,7 @@ func (t *nestedTree) ListFolder(ctx context.Context, orgId int64, path string) (
frame.SetMeta(&data.FrameMeta{
Type: data.FrameTypeDirectoryListing,
})
return frame, nil
return &StorageListFrame{frame}, nil
}
root, path := t.getRoot(orgId, path)
@ -160,9 +160,9 @@ func (t *nestedTree) ListFolder(ctx context.Context, orgId int64, path string) (
names := data.NewFieldFromFieldType(data.FieldTypeString, count)
mtype := data.NewFieldFromFieldType(data.FieldTypeString, count)
fsize := data.NewFieldFromFieldType(data.FieldTypeInt64, count)
names.Name = "name"
mtype.Name = "mediaType"
fsize.Name = "size"
names.Name = nameListFrameField
mtype.Name = mediaTypeListFrameField
fsize.Name = sizeListFrameField
fsize.Config = &data.FieldConfig{
Unit: "bytes",
}
@ -178,5 +178,5 @@ func (t *nestedTree) ListFolder(ctx context.Context, orgId int64, path string) (
"HasMore": listResponse.HasMore,
},
})
return frame, nil
return &StorageListFrame{frame}, nil
}

@ -30,7 +30,7 @@ type WriteValueResponse struct {
type storageTree interface {
GetFile(ctx context.Context, orgId int64, path string) (*filestorage.File, error)
ListFolder(ctx context.Context, orgId int64, path string) (*data.Frame, error)
ListFolder(ctx context.Context, orgId int64, path string) (*StorageListFrame, error)
}
//-------------------------------------------
@ -95,3 +95,38 @@ type RootStorageMeta struct {
Config RootStorageConfig `json:"config"`
}
type StorageListFrame struct {
*data.Frame
}
const (
titleListFrameField = "title"
nameListFrameField = "name"
descriptionListFrameField = "description"
mediaTypeListFrameField = "mediaType"
storageTypeListFrameField = "storageType"
readOnlyListFrameField = "readOnly"
builtInListFrameField = "builtIn"
sizeListFrameField = "size"
)
func (s *StorageListFrame) GetFileNames() []string {
var fileNames []string
if s == nil {
return fileNames
}
field, idx := s.FieldByName(nameListFrameField)
if field.Len() == 0 || idx == -1 {
return fileNames
}
for i := 0; i < field.Len(); i++ {
if stringValue, ok := field.At(i).(string); ok {
fileNames = append(fileNames, stringValue)
}
}
return fileNames
}

@ -0,0 +1,47 @@
package store
import (
_ "embed"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/stretchr/testify/require"
)
var (
//go:embed testdata/example_list_frame.json
exampleListFrameJSON string
//go:embed testdata/example_root_level_list.json
exampleRootLevelListJSON string
)
func TestGetFileNames(t *testing.T) {
frame := &data.Frame{}
err := frame.UnmarshalJSON([]byte(exampleListFrameJSON))
require.NoError(t, err)
listFrame := StorageListFrame{frame}
require.Equal(t, []string{
"DL_1.jpg",
"Screen Shot 2022-06-23 at 9.05.39 PM.png",
"Screen Shot 2022-06-24 at 11.58.32 AM.png",
"Screen Shot 2022-06-30 at 3.45.03 PM.png",
"Screen Shot 2022-07-05 at 3.24.27 PM.png",
"image.png", "rocket_1f680.png",
"test-folder",
"topcoder12.png",
}, listFrame.GetFileNames())
}
func TestGetFileNamesRootLevel(t *testing.T) {
frame := &data.Frame{}
err := frame.UnmarshalJSON([]byte(exampleRootLevelListJSON))
require.NoError(t, err)
listFrame := StorageListFrame{frame}
require.Equal(t, []string{
"public-static",
"resources",
}, listFrame.GetFileNames())
}

@ -109,10 +109,10 @@ func (s *Service) doListQuery(ctx context.Context, query backend.DataQuery) back
}
path := store.RootPublicStatic + "/" + q.Path
frame, err := s.store.List(ctx, nil, path)
listFrame, err := s.store.List(ctx, nil, path)
response.Error = err
if frame != nil {
response.Frames = data.Frames{frame}
if listFrame != nil {
response.Frames = data.Frames{listFrame.Frame}
}
return response
}

Loading…
Cancel
Save