mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
EntityStore: Rename ObjectStore to EntityStore (part 1) (#59613)
This commit is contained in:
parent
b0b74337f1
commit
5dc7b01f9d
@ -288,7 +288,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// Allow HTTP access to the object storage feature (dev only for now)
|
||||
if hs.Features.IsEnabled(featuremgmt.FlagGrpcServer) {
|
||||
apiRoute.Group("/object", hs.httpObjectStore.RegisterHTTPRoutes)
|
||||
apiRoute.Group("/object", hs.httpEntityStore.RegisterHTTPRoutes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/querylibrary"
|
||||
"github.com/grafana/grafana/pkg/services/searchV2"
|
||||
"github.com/grafana/grafana/pkg/services/stats"
|
||||
"github.com/grafana/grafana/pkg/services/store/object/httpobjectstore"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity/httpentitystore"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@ -145,7 +145,7 @@ type HTTPServer struct {
|
||||
ThumbService thumbs.Service
|
||||
ExportService export.ExportService
|
||||
StorageService store.StorageService
|
||||
httpObjectStore httpobjectstore.HTTPObjectStore
|
||||
httpEntityStore httpentitystore.HTTPEntityStore
|
||||
SearchV2HTTPService searchV2.SearchHTTPService
|
||||
QueryLibraryHTTPService querylibrary.HTTPService
|
||||
QueryLibraryService querylibrary.Service
|
||||
@ -234,7 +234,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
pluginsUpdateChecker *updatechecker.PluginsService, searchUsersService searchusers.Service,
|
||||
dataSourcesService datasources.DataSourceService, queryDataService *query.Service,
|
||||
ldapGroups ldap.Groups, teamGuardian teamguardian.TeamGuardian, serviceaccountsService serviceaccounts.Service,
|
||||
authInfoService login.AuthInfoService, storageService store.StorageService, httpObjectStore httpobjectstore.HTTPObjectStore,
|
||||
authInfoService login.AuthInfoService, storageService store.StorageService, httpEntityStore httpentitystore.HTTPEntityStore,
|
||||
notificationService *notifications.NotificationService, dashboardService dashboards.DashboardService,
|
||||
dashboardProvisioningService dashboards.DashboardProvisioningService, folderService folder.Service,
|
||||
datasourcePermissionsService permissions.DatasourcePermissionsService, alertNotificationService *alerting.AlertNotificationService,
|
||||
@ -312,7 +312,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
secretsMigrator: secretsMigrator,
|
||||
secretsPluginMigrator: secretsPluginMigrator,
|
||||
secretsStore: secretsStore,
|
||||
httpObjectStore: httpObjectStore,
|
||||
httpEntityStore: httpEntityStore,
|
||||
DataSourcesService: dataSourcesService,
|
||||
searchUsersService: searchUsersService,
|
||||
ldapGroups: ldapGroups,
|
||||
|
@ -117,7 +117,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/star/starimpl"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
objectdummyserver "github.com/grafana/grafana/pkg/services/store/object/dummy"
|
||||
entitystoredummy "github.com/grafana/grafana/pkg/services/store/entity/dummy"
|
||||
"github.com/grafana/grafana/pkg/services/store/sanitizer"
|
||||
"github.com/grafana/grafana/pkg/services/tag"
|
||||
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
||||
@ -326,7 +326,7 @@ var wireSet = wire.NewSet(
|
||||
teamimpl.ProvideService,
|
||||
ngmetrics.ProvideServiceForTest,
|
||||
notifications.MockNotificationService,
|
||||
objectdummyserver.ProvideFakeObjectServer,
|
||||
entitystoredummy.ProvideFakeEntityServer,
|
||||
wire.Bind(new(notifications.TempUserStore), new(*dbtest.FakeDB)),
|
||||
wire.Bind(new(notifications.Service), new(*notifications.NotificationServiceMock)),
|
||||
wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationServiceMock)),
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
// Grafana resource name. See also:
|
||||
// https://github.com/grafana/grafana/blob/main/pkg/services/store/object/object.proto#L6
|
||||
// https://github.com/grafana/grafana/blob/main/pkg/services/store/entity/entity.proto#L6
|
||||
// NOTE: This structure/format is still under active development and is subject to change
|
||||
type GRN struct {
|
||||
// TenantID contains the ID of the tenant (in hosted grafana) or
|
||||
|
@ -52,17 +52,11 @@ const (
|
||||
// ExternalEntityReferenceRuntime_Transformer is a "type" under runtime
|
||||
// UIDs include: joinByField, organize, seriesToColumns, etc
|
||||
ExternalEntityReferenceRuntime_Transformer = "transformer"
|
||||
|
||||
// ObjectStoreScopeEntity is organized in: {kind}/{uid}
|
||||
ObjectStoreScopeEntity = "entity"
|
||||
|
||||
// ObjectStoreScopeDrive is organized in: {uid/with/slash}.{kind}
|
||||
ObjectStoreScopeDrive = "drive"
|
||||
)
|
||||
|
||||
// ObjectKindInfo describes information needed from the object store
|
||||
// EntityKindInfo describes information needed from the object store
|
||||
// All non-raw types will have a schema that can be used to validate
|
||||
type ObjectKindInfo struct {
|
||||
type EntityKindInfo struct {
|
||||
// Unique short id for this kind
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
@ -82,10 +76,10 @@ type ObjectKindInfo struct {
|
||||
MimeType string `json:"mimeType,omitempty"`
|
||||
}
|
||||
|
||||
// ObjectSummary represents common data derived from a raw object bytes.
|
||||
// EntitySummary represents common data derived from a raw object bytes.
|
||||
// The values should not depend on system state, and are derived from the raw object.
|
||||
// This summary is used for a unified search and object listing
|
||||
type ObjectSummary struct {
|
||||
type EntitySummary struct {
|
||||
UID string `json:"uid,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
@ -99,23 +93,23 @@ type ObjectSummary struct {
|
||||
URL string `json:"URL,omitempty"`
|
||||
|
||||
// When errors exist
|
||||
Error *ObjectErrorInfo `json:"error,omitempty"`
|
||||
Error *EntityErrorInfo `json:"error,omitempty"`
|
||||
|
||||
// Optional field values. The schema will define and document possible values for a given kind
|
||||
Fields map[string]interface{} `json:"fields,omitempty"`
|
||||
|
||||
// eg: panels within dashboard
|
||||
Nested []*ObjectSummary `json:"nested,omitempty"`
|
||||
Nested []*EntitySummary `json:"nested,omitempty"`
|
||||
|
||||
// Optional references to external things
|
||||
References []*ObjectExternalReference `json:"references,omitempty"`
|
||||
References []*EntityExternalReference `json:"references,omitempty"`
|
||||
|
||||
// The summary can not be extended
|
||||
_ interface{}
|
||||
}
|
||||
|
||||
// This will likely get replaced with a more general error framework.
|
||||
type ObjectErrorInfo struct {
|
||||
type EntityErrorInfo struct {
|
||||
// TODO: Match an error code registry?
|
||||
Code int64 `json:"code,omitempty"`
|
||||
|
||||
@ -129,7 +123,7 @@ type ObjectErrorInfo struct {
|
||||
// Reference to another object outside itself
|
||||
// This message is derived from the object body and can be used to search for references.
|
||||
// This does not represent a method to declare a reference to another object.
|
||||
type ObjectExternalReference struct {
|
||||
type EntityExternalReference struct {
|
||||
// datasource (instance), dashboard (instance),
|
||||
Kind string `json:"kind,omitempty"`
|
||||
|
||||
@ -140,6 +134,6 @@ type ObjectExternalReference struct {
|
||||
UID string `json:"UID,omitempty"`
|
||||
}
|
||||
|
||||
// ObjectSummaryBuilder will read an object, validate it, and return a summary, sanitized payload, or an error
|
||||
// EntitySummaryBuilder will read an object, validate it, and return a summary, sanitized payload, or an error
|
||||
// This should not include values that depend on system state, only the raw object
|
||||
type ObjectSummaryBuilder = func(ctx context.Context, uid string, body []byte) (*ObjectSummary, []byte, error)
|
||||
type EntitySummaryBuilder = func(ctx context.Context, uid string, body []byte) (*EntitySummary, []byte, error)
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
samanager "github.com/grafana/grafana/pkg/services/serviceaccounts/manager"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/store/sanitizer"
|
||||
"github.com/grafana/grafana/pkg/services/thumbs"
|
||||
"github.com/grafana/grafana/pkg/services/updatechecker"
|
||||
@ -52,7 +52,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
_ dashboardsnapshots.Service, _ *alerting.AlertNotificationService,
|
||||
_ serviceaccounts.Service, _ *guardian.Provider,
|
||||
_ *plugindashboardsservice.DashboardUpdater, _ *sanitizer.Provider,
|
||||
_ *grpcserver.HealthService, _ object.ObjectStoreServer, _ *grpcserver.ReflectionService,
|
||||
_ *grpcserver.HealthService, _ entity.EntityStoreServer, _ *grpcserver.ReflectionService,
|
||||
) *BackgroundServiceRegistry {
|
||||
return NewBackgroundServiceRegistry(
|
||||
httpServer,
|
||||
|
@ -126,9 +126,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/star/starimpl"
|
||||
"github.com/grafana/grafana/pkg/services/stats/statsimpl"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity/httpentitystore"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity/sqlstash"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind"
|
||||
"github.com/grafana/grafana/pkg/services/store/object/httpobjectstore"
|
||||
"github.com/grafana/grafana/pkg/services/store/object/sqlstash"
|
||||
"github.com/grafana/grafana/pkg/services/store/resolver"
|
||||
"github.com/grafana/grafana/pkg/services/store/sanitizer"
|
||||
"github.com/grafana/grafana/pkg/services/tag"
|
||||
@ -361,9 +361,9 @@ var wireBasicSet = wire.NewSet(
|
||||
grpcserver.ProvideReflectionService,
|
||||
interceptors.ProvideAuthenticator,
|
||||
kind.ProvideService, // The registry of known kinds
|
||||
sqlstash.ProvideSQLObjectServer,
|
||||
resolver.ProvideObjectReferenceResolver,
|
||||
httpobjectstore.ProvideHTTPObjectStore,
|
||||
sqlstash.ProvideSQLEntityServer,
|
||||
resolver.ProvideEntityReferenceResolver,
|
||||
httpentitystore.ProvideHTTPEntityStore,
|
||||
teamimpl.ProvideService,
|
||||
tempuserimpl.ProvideService,
|
||||
loginattemptimpl.ProvideService,
|
||||
|
@ -13,14 +13,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/snapshot"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
var _ Job = new(objectStoreJob)
|
||||
var _ Job = new(entityStoreJob)
|
||||
|
||||
type objectStoreJob struct {
|
||||
type entityStoreJob struct {
|
||||
logger log.Logger
|
||||
|
||||
statusMu sync.Mutex
|
||||
@ -32,19 +32,19 @@ type objectStoreJob struct {
|
||||
|
||||
sess *session.SessionDB
|
||||
playlistService playlist.Service
|
||||
store object.ObjectStoreServer
|
||||
store entity.EntityStoreServer
|
||||
dashboardsnapshots dashboardsnapshots.Service
|
||||
}
|
||||
|
||||
func startObjectStoreJob(ctx context.Context,
|
||||
func startEntityStoreJob(ctx context.Context,
|
||||
cfg ExportConfig,
|
||||
broadcaster statusBroadcaster,
|
||||
db db.DB,
|
||||
playlistService playlist.Service,
|
||||
store object.ObjectStoreServer,
|
||||
store entity.EntityStoreServer,
|
||||
dashboardsnapshots dashboardsnapshots.Service,
|
||||
) (Job, error) {
|
||||
job := &objectStoreJob{
|
||||
job := &entityStoreJob{
|
||||
logger: log.New("export_to_object_store_job"),
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
@ -67,11 +67,11 @@ func startObjectStoreJob(ctx context.Context,
|
||||
return job, nil
|
||||
}
|
||||
|
||||
func (e *objectStoreJob) requestStop() {
|
||||
func (e *entityStoreJob) requestStop() {
|
||||
e.stopRequested = true
|
||||
}
|
||||
|
||||
func (e *objectStoreJob) start(ctx context.Context) {
|
||||
func (e *entityStoreJob) start(ctx context.Context) {
|
||||
defer func() {
|
||||
e.logger.Info("Finished dummy export job")
|
||||
|
||||
@ -123,8 +123,8 @@ func (e *objectStoreJob) start(ctx context.Context) {
|
||||
rowUser.UserID = 0 // avoid Uint64Val issue????
|
||||
}
|
||||
|
||||
_, err = e.store.AdminWrite(ctx, &object.AdminWriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, err = e.store.AdminWrite(ctx, &entity.AdminWriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: dash.UID,
|
||||
Kind: models.StandardKindDashboard,
|
||||
},
|
||||
@ -136,7 +136,7 @@ func (e *objectStoreJob) start(ctx context.Context) {
|
||||
CreatedBy: fmt.Sprintf("user:%d", dash.CreatedBy),
|
||||
Body: dash.Data,
|
||||
Comment: "(exported from SQL)",
|
||||
Origin: &object.ObjectOriginInfo{
|
||||
Origin: &entity.EntityOriginInfo{
|
||||
Source: "export-from-sql",
|
||||
},
|
||||
})
|
||||
@ -174,8 +174,8 @@ func (e *objectStoreJob) start(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = e.store.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, err = e.store.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: playlist.Uid,
|
||||
Kind: models.StandardKindPlaylist,
|
||||
},
|
||||
@ -238,8 +238,8 @@ func (e *objectStoreJob) start(ctx context.Context) {
|
||||
m.Snapshot = b
|
||||
}
|
||||
|
||||
_, err = e.store.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, err = e.store.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: dto.Key,
|
||||
Kind: models.StandardKindSnapshot,
|
||||
},
|
||||
@ -272,7 +272,7 @@ type dashInfo struct {
|
||||
}
|
||||
|
||||
// TODO, paging etc
|
||||
func (e *objectStoreJob) getDashboards(ctx context.Context) ([]dashInfo, error) {
|
||||
func (e *entityStoreJob) getDashboards(ctx context.Context) ([]dashInfo, error) {
|
||||
e.status.Last = "find dashbaords...."
|
||||
e.broadcaster(e.status)
|
||||
|
||||
@ -281,14 +281,14 @@ func (e *objectStoreJob) getDashboards(ctx context.Context) ([]dashInfo, error)
|
||||
return dash, err
|
||||
}
|
||||
|
||||
func (e *objectStoreJob) getStatus() ExportStatus {
|
||||
func (e *entityStoreJob) getStatus() ExportStatus {
|
||||
e.statusMu.Lock()
|
||||
defer e.statusMu.Unlock()
|
||||
|
||||
return e.status
|
||||
}
|
||||
|
||||
func (e *objectStoreJob) getConfig() ExportConfig {
|
||||
func (e *entityStoreJob) getConfig() ExportConfig {
|
||||
e.statusMu.Lock()
|
||||
defer e.statusMu.Unlock()
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/filestorage"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/dashboard"
|
||||
)
|
||||
|
||||
@ -31,7 +30,7 @@ func exportDashboards(helper *commitHelper, job *gitExportJob) error {
|
||||
return err
|
||||
}
|
||||
|
||||
rootDir := path.Join(helper.orgDir, models.ObjectStoreScopeDrive)
|
||||
rootDir := path.Join(helper.orgDir, "drive")
|
||||
folderStructure := commitOptions{
|
||||
when: time.Now(),
|
||||
comment: "Exported folder structure",
|
||||
|
@ -40,7 +40,7 @@ func exportSystemPlaylists(helper *commitHelper, job *gitExportJob) error {
|
||||
gitcmd.body = append(gitcmd.body, commitBody{
|
||||
fpath: filepath.Join(
|
||||
helper.orgDir,
|
||||
models.ObjectStoreScopeEntity,
|
||||
"entity",
|
||||
models.StandardKindPlaylist,
|
||||
fmt.Sprintf("%s.json", playlist.Uid)),
|
||||
body: prettyJSON(playlist),
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@ -159,7 +159,7 @@ type StandardExport struct {
|
||||
playlistService playlist.Service
|
||||
orgService org.Service
|
||||
datasourceService datasources.DataSourceService
|
||||
store object.ObjectStoreServer
|
||||
store entity.EntityStoreServer
|
||||
|
||||
// updated with mutex
|
||||
exportJob Job
|
||||
@ -167,7 +167,7 @@ type StandardExport struct {
|
||||
|
||||
func ProvideService(db db.DB, features featuremgmt.FeatureToggles, gl *live.GrafanaLive, cfg *setting.Cfg,
|
||||
dashboardsnapshotsService dashboardsnapshots.Service, playlistService playlist.Service, orgService org.Service,
|
||||
datasourceService datasources.DataSourceService, store object.ObjectStoreServer) ExportService {
|
||||
datasourceService datasources.DataSourceService, store entity.EntityStoreServer) ExportService {
|
||||
if !features.IsEnabled(featuremgmt.FlagExport) {
|
||||
return &StubExport{}
|
||||
}
|
||||
@ -234,7 +234,7 @@ func (ex *StandardExport) HandleRequestExport(c *models.ReqContext) response.Res
|
||||
case "dummy":
|
||||
job, err = startDummyExportJob(cfg, broadcast)
|
||||
case "objectStore":
|
||||
job, err = startObjectStoreJob(ctx, cfg, broadcast, ex.db, ex.playlistService, ex.store, ex.dashboardsnapshotsService)
|
||||
job, err = startEntityStoreJob(ctx, cfg, broadcast, ex.db, ex.playlistService, ex.store, ex.dashboardsnapshotsService)
|
||||
case "git":
|
||||
dir := filepath.Join(ex.dataDir, "export_git", fmt.Sprintf("git_%d", time.Now().Unix()))
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
||||
objectstore "github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
@ -21,7 +21,7 @@ import (
|
||||
type objectStoreImpl struct {
|
||||
sess *session.SessionDB
|
||||
sqlimpl *Service
|
||||
objectstore object.ObjectStoreServer
|
||||
objectstore entity.EntityStoreServer
|
||||
}
|
||||
|
||||
var _ playlist.Service = &objectStoreImpl{}
|
||||
@ -55,8 +55,8 @@ func (s *objectStoreImpl) sync() {
|
||||
return
|
||||
}
|
||||
body, _ := json.Marshal(dto)
|
||||
_, _ = s.objectstore.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, _ = s.objectstore.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
TenantId: info.OrgID,
|
||||
UID: info.UID,
|
||||
Kind: models.StandardKindPlaylist,
|
||||
@ -73,8 +73,8 @@ func (s *objectStoreImpl) Create(ctx context.Context, cmd *playlist.CreatePlayli
|
||||
if err != nil {
|
||||
return rsp, fmt.Errorf("unable to write playlist to store")
|
||||
}
|
||||
_, err = s.objectstore.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, err = s.objectstore.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
Kind: models.StandardKindPlaylist,
|
||||
UID: rsp.UID,
|
||||
},
|
||||
@ -94,8 +94,8 @@ func (s *objectStoreImpl) Update(ctx context.Context, cmd *playlist.UpdatePlayli
|
||||
if err != nil {
|
||||
return rsp, fmt.Errorf("unable to write playlist to store")
|
||||
}
|
||||
_, err = s.objectstore.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, err = s.objectstore.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: rsp.Uid,
|
||||
Kind: models.StandardKindPlaylist,
|
||||
},
|
||||
@ -111,8 +111,8 @@ func (s *objectStoreImpl) Update(ctx context.Context, cmd *playlist.UpdatePlayli
|
||||
func (s *objectStoreImpl) Delete(ctx context.Context, cmd *playlist.DeletePlaylistCommand) error {
|
||||
err := s.sqlimpl.store.Delete(ctx, cmd)
|
||||
if err == nil {
|
||||
_, err = s.objectstore.Delete(ctx, &object.DeleteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
_, err = s.objectstore.Delete(ctx, &entity.DeleteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: cmd.UID,
|
||||
Kind: models.StandardKindPlaylist,
|
||||
},
|
||||
@ -142,8 +142,8 @@ func (s *objectStoreImpl) GetWithoutItems(ctx context.Context, q *playlist.GetPl
|
||||
}
|
||||
|
||||
func (s *objectStoreImpl) Get(ctx context.Context, q *playlist.GetPlaylistByUidQuery) (*playlist.PlaylistDTO, error) {
|
||||
rsp, err := s.objectstore.Read(ctx, &object.ReadObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
rsp, err := s.objectstore.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: q.UID,
|
||||
Kind: models.StandardKindPlaylist,
|
||||
},
|
||||
@ -152,20 +152,20 @@ func (s *objectStoreImpl) Get(ctx context.Context, q *playlist.GetPlaylistByUidQ
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rsp.Object == nil || rsp.Object.Body == nil {
|
||||
if rsp.Entity == nil || rsp.Entity.Body == nil {
|
||||
return nil, fmt.Errorf("missing object")
|
||||
}
|
||||
|
||||
// Get the object from payload
|
||||
found := &playlist.PlaylistDTO{}
|
||||
err = json.Unmarshal(rsp.Object.Body, found)
|
||||
err = json.Unmarshal(rsp.Entity.Body, found)
|
||||
return found, err
|
||||
}
|
||||
|
||||
func (s *objectStoreImpl) Search(ctx context.Context, q *playlist.GetPlaylistsQuery) (playlist.Playlists, error) {
|
||||
playlists := make(playlist.Playlists, 0)
|
||||
|
||||
rsp, err := s.objectstore.Search(ctx, &object.ObjectSearchRequest{
|
||||
rsp, err := s.objectstore.Search(ctx, &entity.EntitySearchRequest{
|
||||
Kind: []string{models.StandardKindPlaylist},
|
||||
WithBody: true,
|
||||
Limit: 1000,
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
@ -15,7 +15,7 @@ type Service struct {
|
||||
|
||||
var _ playlist.Service = &Service{}
|
||||
|
||||
func ProvideService(db db.DB, toggles featuremgmt.FeatureToggles, objserver object.ObjectStoreServer) playlist.Service {
|
||||
func ProvideService(db db.DB, toggles featuremgmt.FeatureToggles, objserver entity.EntityStoreServer) playlist.Service {
|
||||
var sqlstore store
|
||||
|
||||
// 🐢🐢🐢 pick the store
|
||||
|
@ -54,7 +54,7 @@ type dashboard struct {
|
||||
updated time.Time
|
||||
|
||||
// Use generic structure
|
||||
summary *models.ObjectSummary
|
||||
summary *models.EntitySummary
|
||||
}
|
||||
|
||||
// buildSignal is sent when search index is accessed in organization for which
|
||||
@ -913,7 +913,7 @@ func (l sqlDashboardLoader) LoadDashboards(ctx context.Context, orgID int64, das
|
||||
slug: "",
|
||||
created: time.Now(),
|
||||
updated: time.Now(),
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
//ID: 0,
|
||||
Name: "General",
|
||||
},
|
||||
|
@ -113,14 +113,14 @@ var testDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "boom",
|
||||
},
|
||||
},
|
||||
@ -162,7 +162,7 @@ func TestDashboardIndexUpdates(t *testing.T) {
|
||||
err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{
|
||||
id: 3,
|
||||
uid: "3",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "created",
|
||||
},
|
||||
})
|
||||
@ -181,7 +181,7 @@ func TestDashboardIndexUpdates(t *testing.T) {
|
||||
err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "nginx",
|
||||
},
|
||||
})
|
||||
@ -197,14 +197,14 @@ var testSortDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "a-test",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "z-test",
|
||||
},
|
||||
},
|
||||
@ -288,14 +288,14 @@ var testPrefixDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "Archer Data System",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "Document Sync repo",
|
||||
},
|
||||
},
|
||||
@ -366,7 +366,7 @@ var longPrefixDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "Eyjafjallajökull Eruption data",
|
||||
},
|
||||
},
|
||||
@ -385,14 +385,14 @@ var scatteredTokensDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "Three can keep a secret, if two of them are dead (Benjamin Franklin)",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
uid: "2",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "A secret is powerful when it is empty (Umberto Eco)",
|
||||
},
|
||||
},
|
||||
@ -418,7 +418,7 @@ var dashboardsWithFolders = []dashboard{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
isFolder: true,
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "My folder",
|
||||
},
|
||||
},
|
||||
@ -426,9 +426,9 @@ var dashboardsWithFolders = []dashboard{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
folderID: 1,
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "Dashboard in folder 1",
|
||||
Nested: []*models.ObjectSummary{
|
||||
Nested: []*models.EntitySummary{
|
||||
newNestedPanel(1, "Panel 1"),
|
||||
newNestedPanel(2, "Panel 2"),
|
||||
},
|
||||
@ -438,9 +438,9 @@ var dashboardsWithFolders = []dashboard{
|
||||
id: 3,
|
||||
uid: "3",
|
||||
folderID: 1,
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "Dashboard in folder 2",
|
||||
Nested: []*models.ObjectSummary{
|
||||
Nested: []*models.EntitySummary{
|
||||
newNestedPanel(3, "Panel 3"),
|
||||
},
|
||||
},
|
||||
@ -448,9 +448,9 @@ var dashboardsWithFolders = []dashboard{
|
||||
{
|
||||
id: 4,
|
||||
uid: "4",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "One more dash",
|
||||
Nested: []*models.ObjectSummary{
|
||||
Nested: []*models.EntitySummary{
|
||||
newNestedPanel(4, "Panel 4"),
|
||||
},
|
||||
},
|
||||
@ -505,9 +505,9 @@ var dashboardsWithPanels = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "My Dash",
|
||||
Nested: []*models.ObjectSummary{
|
||||
Nested: []*models.EntitySummary{
|
||||
newNestedPanel(1, "Panel 1"),
|
||||
newNestedPanel(2, "Panel 2"),
|
||||
},
|
||||
@ -515,8 +515,8 @@ var dashboardsWithPanels = []dashboard{
|
||||
},
|
||||
}
|
||||
|
||||
func newNestedPanel(id int64, name string) *models.ObjectSummary {
|
||||
summary := &models.ObjectSummary{
|
||||
func newNestedPanel(id int64, name string) *models.EntitySummary {
|
||||
summary := &models.EntitySummary{
|
||||
Kind: "panel",
|
||||
UID: fmt.Sprintf("???#%d", id),
|
||||
}
|
||||
@ -553,14 +553,14 @@ var punctuationSplitNgramDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "heat-torkel",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "topology heatmap",
|
||||
},
|
||||
},
|
||||
@ -586,7 +586,7 @@ var camelCaseNgramDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: "heatTorkel",
|
||||
},
|
||||
},
|
||||
@ -608,7 +608,7 @@ func dashboardsWithTitles(names ...string) []dashboard {
|
||||
out = append(out, dashboard{
|
||||
id: no,
|
||||
uid: fmt.Sprintf("%d", no),
|
||||
summary: &models.ObjectSummary{
|
||||
summary: &models.EntitySummary{
|
||||
Name: name,
|
||||
},
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
package objectdummyserver
|
||||
package dummy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -14,59 +14,59 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/x/persistentcollection"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type ObjectVersionWithBody struct {
|
||||
*object.ObjectVersionInfo `json:"info,omitempty"`
|
||||
type EntityVersionWithBody struct {
|
||||
*entity.EntityVersionInfo `json:"info,omitempty"`
|
||||
|
||||
Body []byte `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
type RawObjectWithHistory struct {
|
||||
Object *object.RawObject `json:"object,omitempty"`
|
||||
History []*ObjectVersionWithBody `json:"history,omitempty"`
|
||||
type EntityWithHistory struct {
|
||||
Entity *entity.Entity `json:"entity,omitempty"`
|
||||
History []*EntityVersionWithBody `json:"history,omitempty"`
|
||||
}
|
||||
|
||||
var (
|
||||
// increment when RawObject changes
|
||||
rawObjectVersion = 9
|
||||
// increment when Entity changes
|
||||
rawEntityVersion = 10
|
||||
)
|
||||
|
||||
// Make sure we implement both store + admin
|
||||
var _ object.ObjectStoreServer = &dummyObjectServer{}
|
||||
var _ object.ObjectStoreAdminServer = &dummyObjectServer{}
|
||||
var _ entity.EntityStoreServer = &dummyEntityServer{}
|
||||
var _ entity.EntityStoreAdminServer = &dummyEntityServer{}
|
||||
|
||||
func ProvideDummyObjectServer(cfg *setting.Cfg, grpcServerProvider grpcserver.Provider, kinds kind.KindRegistry) object.ObjectStoreServer {
|
||||
objectServer := &dummyObjectServer{
|
||||
collection: persistentcollection.NewLocalFSPersistentCollection[*RawObjectWithHistory]("raw-object", cfg.DataPath, rawObjectVersion),
|
||||
func ProvideDummyEntityServer(cfg *setting.Cfg, grpcServerProvider grpcserver.Provider, kinds kind.KindRegistry) entity.EntityStoreServer {
|
||||
objectServer := &dummyEntityServer{
|
||||
collection: persistentcollection.NewLocalFSPersistentCollection[*EntityWithHistory]("raw-object", cfg.DataPath, rawEntityVersion),
|
||||
log: log.New("in-memory-object-server"),
|
||||
kinds: kinds,
|
||||
}
|
||||
object.RegisterObjectStoreServer(grpcServerProvider.GetServer(), objectServer)
|
||||
entity.RegisterEntityStoreServer(grpcServerProvider.GetServer(), objectServer)
|
||||
return objectServer
|
||||
}
|
||||
|
||||
type dummyObjectServer struct {
|
||||
type dummyEntityServer struct {
|
||||
log log.Logger
|
||||
collection persistentcollection.PersistentCollection[*RawObjectWithHistory]
|
||||
collection persistentcollection.PersistentCollection[*EntityWithHistory]
|
||||
kinds kind.KindRegistry
|
||||
}
|
||||
|
||||
func namespaceFromUID(grn *object.GRN) string {
|
||||
func namespaceFromUID(grn *entity.GRN) string {
|
||||
// TODO
|
||||
return "orgId-1"
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) findObject(ctx context.Context, grn *object.GRN, version string) (*RawObjectWithHistory, *object.RawObject, error) {
|
||||
func (i *dummyEntityServer) findEntity(ctx context.Context, grn *entity.GRN, version string) (*EntityWithHistory, *entity.Entity, error) {
|
||||
if grn == nil {
|
||||
return nil, nil, errors.New("GRN must not be nil")
|
||||
}
|
||||
|
||||
obj, err := i.collection.FindFirst(ctx, namespaceFromUID(grn), func(i *RawObjectWithHistory) (bool, error) {
|
||||
return grn.Equals(i.Object.GRN), nil
|
||||
obj, err := i.collection.FindFirst(ctx, namespaceFromUID(grn), func(i *EntityWithHistory) (bool, error) {
|
||||
return grn.Equals(i.Entity.GRN), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
@ -79,21 +79,21 @@ func (i *dummyObjectServer) findObject(ctx context.Context, grn *object.GRN, ver
|
||||
|
||||
getLatestVersion := version == ""
|
||||
if getLatestVersion {
|
||||
return obj, obj.Object, nil
|
||||
return obj, obj.Entity, nil
|
||||
}
|
||||
|
||||
for _, objVersion := range obj.History {
|
||||
if objVersion.Version == version {
|
||||
copy := &object.RawObject{
|
||||
GRN: obj.Object.GRN,
|
||||
CreatedAt: obj.Object.CreatedAt,
|
||||
CreatedBy: obj.Object.CreatedBy,
|
||||
copy := &entity.Entity{
|
||||
GRN: obj.Entity.GRN,
|
||||
CreatedAt: obj.Entity.CreatedAt,
|
||||
CreatedBy: obj.Entity.CreatedBy,
|
||||
UpdatedAt: objVersion.UpdatedAt,
|
||||
UpdatedBy: objVersion.UpdatedBy,
|
||||
ETag: objVersion.ETag,
|
||||
Version: objVersion.Version,
|
||||
|
||||
// Body is added from the dummy server cache (it does not exist in ObjectVersionInfo)
|
||||
// Body is added from the dummy server cache (it does not exist in EntityVersionInfo)
|
||||
Body: objVersion.Body,
|
||||
}
|
||||
|
||||
@ -104,22 +104,22 @@ func (i *dummyObjectServer) findObject(ctx context.Context, grn *object.GRN, ver
|
||||
return obj, nil, nil
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) Read(ctx context.Context, r *object.ReadObjectRequest) (*object.ReadObjectResponse, error) {
|
||||
func (i *dummyEntityServer) Read(ctx context.Context, r *entity.ReadEntityRequest) (*entity.ReadEntityResponse, error) {
|
||||
grn := getFullGRN(ctx, r.GRN)
|
||||
_, objVersion, err := i.findObject(ctx, grn, r.Version)
|
||||
_, objVersion, err := i.findEntity(ctx, grn, r.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if objVersion == nil {
|
||||
return &object.ReadObjectResponse{
|
||||
Object: nil,
|
||||
return &entity.ReadEntityResponse{
|
||||
Entity: nil,
|
||||
SummaryJson: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
rsp := &object.ReadObjectResponse{
|
||||
Object: objVersion,
|
||||
rsp := &entity.ReadEntityResponse{
|
||||
Entity: objVersion,
|
||||
}
|
||||
if r.WithSummary {
|
||||
// Since we do not store the summary, we can just recreate on demand
|
||||
@ -135,8 +135,8 @@ func (i *dummyObjectServer) Read(ctx context.Context, r *object.ReadObjectReques
|
||||
return rsp, err
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) BatchRead(ctx context.Context, batchR *object.BatchReadObjectRequest) (*object.BatchReadObjectResponse, error) {
|
||||
results := make([]*object.ReadObjectResponse, 0)
|
||||
func (i *dummyEntityServer) BatchRead(ctx context.Context, batchR *entity.BatchReadEntityRequest) (*entity.BatchReadEntityResponse, error) {
|
||||
results := make([]*entity.ReadEntityResponse, 0)
|
||||
for _, r := range batchR.Batch {
|
||||
resp, err := i.Read(ctx, r)
|
||||
if err != nil {
|
||||
@ -145,7 +145,7 @@ func (i *dummyObjectServer) BatchRead(ctx context.Context, batchR *object.BatchR
|
||||
results = append(results, resp)
|
||||
}
|
||||
|
||||
return &object.BatchReadObjectResponse{Results: results}, nil
|
||||
return &entity.BatchReadEntityResponse{Results: results}, nil
|
||||
}
|
||||
|
||||
func createContentsHash(contents []byte) string {
|
||||
@ -153,33 +153,33 @@ func createContentsHash(contents []byte) string {
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) update(ctx context.Context, r *object.AdminWriteObjectRequest, namespace string) (*object.WriteObjectResponse, error) {
|
||||
func (i *dummyEntityServer) update(ctx context.Context, r *entity.AdminWriteEntityRequest, namespace string) (*entity.WriteEntityResponse, error) {
|
||||
builder := i.kinds.GetSummaryBuilder(r.GRN.Kind)
|
||||
if builder == nil {
|
||||
return nil, fmt.Errorf("unsupported kind: " + r.GRN.Kind)
|
||||
}
|
||||
rsp := &object.WriteObjectResponse{}
|
||||
rsp := &entity.WriteEntityResponse{}
|
||||
|
||||
updatedCount, err := i.collection.Update(ctx, namespace, func(i *RawObjectWithHistory) (bool, *RawObjectWithHistory, error) {
|
||||
if !r.GRN.Equals(i.Object.GRN) {
|
||||
updatedCount, err := i.collection.Update(ctx, namespace, func(i *EntityWithHistory) (bool, *EntityWithHistory, error) {
|
||||
if !r.GRN.Equals(i.Entity.GRN) {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
if r.PreviousVersion != "" && i.Object.Version != r.PreviousVersion {
|
||||
return false, nil, fmt.Errorf("expected the previous version to be %s, but was %s", r.PreviousVersion, i.Object.Version)
|
||||
if r.PreviousVersion != "" && i.Entity.Version != r.PreviousVersion {
|
||||
return false, nil, fmt.Errorf("expected the previous version to be %s, but was %s", r.PreviousVersion, i.Entity.Version)
|
||||
}
|
||||
|
||||
prevVersion, err := strconv.Atoi(i.Object.Version)
|
||||
prevVersion, err := strconv.Atoi(i.Entity.Version)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
modifier := store.UserFromContext(ctx)
|
||||
|
||||
updated := &object.RawObject{
|
||||
updated := &entity.Entity{
|
||||
GRN: r.GRN,
|
||||
CreatedAt: i.Object.CreatedAt,
|
||||
CreatedBy: i.Object.CreatedBy,
|
||||
CreatedAt: i.Entity.CreatedAt,
|
||||
CreatedBy: i.Entity.CreatedBy,
|
||||
UpdatedAt: time.Now().UnixMilli(),
|
||||
UpdatedBy: store.GetUserIDString(modifier),
|
||||
Size: int64(len(r.Body)),
|
||||
@ -188,9 +188,9 @@ func (i *dummyObjectServer) update(ctx context.Context, r *object.AdminWriteObje
|
||||
Version: fmt.Sprintf("%d", prevVersion+1),
|
||||
}
|
||||
|
||||
versionInfo := &ObjectVersionWithBody{
|
||||
versionInfo := &EntityVersionWithBody{
|
||||
Body: r.Body,
|
||||
ObjectVersionInfo: &object.ObjectVersionInfo{
|
||||
EntityVersionInfo: &entity.EntityVersionInfo{
|
||||
Version: updated.Version,
|
||||
UpdatedAt: updated.UpdatedAt,
|
||||
UpdatedBy: updated.UpdatedBy,
|
||||
@ -199,18 +199,18 @@ func (i *dummyObjectServer) update(ctx context.Context, r *object.AdminWriteObje
|
||||
Comment: r.Comment,
|
||||
},
|
||||
}
|
||||
rsp.Object = versionInfo.ObjectVersionInfo
|
||||
rsp.Status = object.WriteObjectResponse_UPDATED
|
||||
rsp.Entity = versionInfo.EntityVersionInfo
|
||||
rsp.Status = entity.WriteEntityResponse_UPDATED
|
||||
|
||||
// When saving, it must be different than the head version
|
||||
if i.Object.ETag == updated.ETag {
|
||||
versionInfo.ObjectVersionInfo.Version = i.Object.Version
|
||||
rsp.Status = object.WriteObjectResponse_UNCHANGED
|
||||
if i.Entity.ETag == updated.ETag {
|
||||
versionInfo.EntityVersionInfo.Version = i.Entity.Version
|
||||
rsp.Status = entity.WriteEntityResponse_UNCHANGED
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
return true, &RawObjectWithHistory{
|
||||
Object: updated,
|
||||
return true, &EntityWithHistory{
|
||||
Entity: updated,
|
||||
History: append(i.History, versionInfo),
|
||||
}, nil
|
||||
})
|
||||
@ -219,16 +219,16 @@ func (i *dummyObjectServer) update(ctx context.Context, r *object.AdminWriteObje
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if updatedCount == 0 && rsp.Object == nil {
|
||||
if updatedCount == 0 && rsp.Entity == nil {
|
||||
return nil, fmt.Errorf("could not find object: %v", r.GRN)
|
||||
}
|
||||
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) insert(ctx context.Context, r *object.AdminWriteObjectRequest, namespace string) (*object.WriteObjectResponse, error) {
|
||||
func (i *dummyEntityServer) insert(ctx context.Context, r *entity.AdminWriteEntityRequest, namespace string) (*entity.WriteEntityResponse, error) {
|
||||
modifier := store.GetUserIDString(store.UserFromContext(ctx))
|
||||
rawObj := &object.RawObject{
|
||||
rawObj := &entity.Entity{
|
||||
GRN: r.GRN,
|
||||
UpdatedAt: time.Now().UnixMilli(),
|
||||
CreatedAt: time.Now().UnixMilli(),
|
||||
@ -240,7 +240,7 @@ func (i *dummyObjectServer) insert(ctx context.Context, r *object.AdminWriteObje
|
||||
Version: fmt.Sprintf("%d", 1),
|
||||
}
|
||||
|
||||
info := &object.ObjectVersionInfo{
|
||||
info := &entity.EntityVersionInfo{
|
||||
Version: rawObj.Version,
|
||||
UpdatedAt: rawObj.UpdatedAt,
|
||||
UpdatedBy: rawObj.UpdatedBy,
|
||||
@ -249,10 +249,10 @@ func (i *dummyObjectServer) insert(ctx context.Context, r *object.AdminWriteObje
|
||||
Comment: r.Comment,
|
||||
}
|
||||
|
||||
newObj := &RawObjectWithHistory{
|
||||
Object: rawObj,
|
||||
History: []*ObjectVersionWithBody{{
|
||||
ObjectVersionInfo: info,
|
||||
newObj := &EntityWithHistory{
|
||||
Entity: rawObj,
|
||||
History: []*EntityVersionWithBody{{
|
||||
EntityVersionInfo: info,
|
||||
Body: r.Body,
|
||||
}},
|
||||
}
|
||||
@ -262,30 +262,30 @@ func (i *dummyObjectServer) insert(ctx context.Context, r *object.AdminWriteObje
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &object.WriteObjectResponse{
|
||||
return &entity.WriteEntityResponse{
|
||||
Error: nil,
|
||||
Object: info,
|
||||
Status: object.WriteObjectResponse_CREATED,
|
||||
Entity: info,
|
||||
Status: entity.WriteEntityResponse_CREATED,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) Write(ctx context.Context, r *object.WriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
return i.doWrite(ctx, object.ToAdminWriteObjectRequest(r))
|
||||
func (i *dummyEntityServer) Write(ctx context.Context, r *entity.WriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
return i.doWrite(ctx, entity.ToAdminWriteEntityRequest(r))
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
func (i *dummyEntityServer) AdminWrite(ctx context.Context, r *entity.AdminWriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
// Check permissions?
|
||||
return i.doWrite(ctx, r)
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) doWrite(ctx context.Context, r *object.AdminWriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
func (i *dummyEntityServer) doWrite(ctx context.Context, r *entity.AdminWriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
grn := getFullGRN(ctx, r.GRN)
|
||||
namespace := namespaceFromUID(grn)
|
||||
obj, err := i.collection.FindFirst(ctx, namespace, func(i *RawObjectWithHistory) (bool, error) {
|
||||
obj, err := i.collection.FindFirst(ctx, namespace, func(i *EntityWithHistory) (bool, error) {
|
||||
if i == nil || r == nil {
|
||||
return false, nil
|
||||
}
|
||||
return grn.Equals(i.Object.GRN), nil
|
||||
return grn.Equals(i.Entity.GRN), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -298,12 +298,12 @@ func (i *dummyObjectServer) doWrite(ctx context.Context, r *object.AdminWriteObj
|
||||
return i.update(ctx, r, namespace)
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) Delete(ctx context.Context, r *object.DeleteObjectRequest) (*object.DeleteObjectResponse, error) {
|
||||
func (i *dummyEntityServer) Delete(ctx context.Context, r *entity.DeleteEntityRequest) (*entity.DeleteEntityResponse, error) {
|
||||
grn := getFullGRN(ctx, r.GRN)
|
||||
_, err := i.collection.Delete(ctx, namespaceFromUID(grn), func(i *RawObjectWithHistory) (bool, error) {
|
||||
if grn.Equals(i.Object.GRN) {
|
||||
if r.PreviousVersion != "" && i.Object.Version != r.PreviousVersion {
|
||||
return false, fmt.Errorf("expected the previous version to be %s, but was %s", r.PreviousVersion, i.Object.Version)
|
||||
_, err := i.collection.Delete(ctx, namespaceFromUID(grn), func(i *EntityWithHistory) (bool, error) {
|
||||
if grn.Equals(i.Entity.GRN) {
|
||||
if r.PreviousVersion != "" && i.Entity.Version != r.PreviousVersion {
|
||||
return false, fmt.Errorf("expected the previous version to be %s, but was %s", r.PreviousVersion, i.Entity.Version)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
@ -316,30 +316,30 @@ func (i *dummyObjectServer) Delete(ctx context.Context, r *object.DeleteObjectRe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &object.DeleteObjectResponse{
|
||||
return &entity.DeleteEntityResponse{
|
||||
OK: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) History(ctx context.Context, r *object.ObjectHistoryRequest) (*object.ObjectHistoryResponse, error) {
|
||||
func (i *dummyEntityServer) History(ctx context.Context, r *entity.EntityHistoryRequest) (*entity.EntityHistoryResponse, error) {
|
||||
grn := getFullGRN(ctx, r.GRN)
|
||||
obj, _, err := i.findObject(ctx, grn, "")
|
||||
obj, _, err := i.findEntity(ctx, grn, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rsp := &object.ObjectHistoryResponse{}
|
||||
rsp := &entity.EntityHistoryResponse{}
|
||||
if obj != nil {
|
||||
// Return the most recent versions first
|
||||
// Better? save them in this order?
|
||||
for i := len(obj.History) - 1; i >= 0; i-- {
|
||||
rsp.Versions = append(rsp.Versions, obj.History[i].ObjectVersionInfo)
|
||||
rsp.Versions = append(rsp.Versions, obj.History[i].EntityVersionInfo)
|
||||
}
|
||||
}
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
func (i *dummyObjectServer) Search(ctx context.Context, r *object.ObjectSearchRequest) (*object.ObjectSearchResponse, error) {
|
||||
func (i *dummyEntityServer) Search(ctx context.Context, r *entity.EntitySearchRequest) (*entity.EntitySearchResponse, error) {
|
||||
var kindMap map[string]bool
|
||||
if len(r.Kind) != 0 {
|
||||
kindMap = make(map[string]bool)
|
||||
@ -349,9 +349,9 @@ func (i *dummyObjectServer) Search(ctx context.Context, r *object.ObjectSearchRe
|
||||
}
|
||||
|
||||
// TODO more filters
|
||||
objects, err := i.collection.Find(ctx, namespaceFromUID(&object.GRN{}), func(i *RawObjectWithHistory) (bool, error) {
|
||||
objects, err := i.collection.Find(ctx, namespaceFromUID(&entity.GRN{}), func(i *EntityWithHistory) (bool, error) {
|
||||
if len(r.Kind) != 0 {
|
||||
if _, ok := kindMap[i.Object.GRN.Kind]; !ok {
|
||||
if _, ok := kindMap[i.Entity.GRN.Kind]; !ok {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
@ -361,35 +361,35 @@ func (i *dummyObjectServer) Search(ctx context.Context, r *object.ObjectSearchRe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
searchResults := make([]*object.ObjectSearchResult, 0)
|
||||
searchResults := make([]*entity.EntitySearchResult, 0)
|
||||
for _, o := range objects {
|
||||
builder := i.kinds.GetSummaryBuilder(o.Object.GRN.Kind)
|
||||
builder := i.kinds.GetSummaryBuilder(o.Entity.GRN.Kind)
|
||||
if builder == nil {
|
||||
continue
|
||||
}
|
||||
summary, clean, e2 := builder(ctx, o.Object.GRN.UID, o.Object.Body)
|
||||
summary, clean, e2 := builder(ctx, o.Entity.GRN.UID, o.Entity.Body)
|
||||
if e2 != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
searchResults = append(searchResults, &object.ObjectSearchResult{
|
||||
GRN: o.Object.GRN,
|
||||
Version: o.Object.Version,
|
||||
UpdatedAt: o.Object.UpdatedAt,
|
||||
UpdatedBy: o.Object.UpdatedBy,
|
||||
searchResults = append(searchResults, &entity.EntitySearchResult{
|
||||
GRN: o.Entity.GRN,
|
||||
Version: o.Entity.Version,
|
||||
UpdatedAt: o.Entity.UpdatedAt,
|
||||
UpdatedBy: o.Entity.UpdatedBy,
|
||||
Name: summary.Name,
|
||||
Description: summary.Description,
|
||||
Body: clean,
|
||||
})
|
||||
}
|
||||
|
||||
return &object.ObjectSearchResponse{
|
||||
return &entity.EntitySearchResponse{
|
||||
Results: searchResults,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// This sets the TenantId on the request GRN
|
||||
func getFullGRN(ctx context.Context, grn *object.GRN) *object.GRN {
|
||||
func getFullGRN(ctx context.Context, grn *entity.GRN) *entity.GRN {
|
||||
if grn.TenantId == 0 {
|
||||
modifier := store.UserFromContext(ctx)
|
||||
grn.TenantId = modifier.OrgID
|
@ -1,11 +1,11 @@
|
||||
package objectdummyserver
|
||||
package dummy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -16,8 +16,8 @@ func TestRawEncoders(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
raw := &ObjectVersionWithBody{
|
||||
&object.ObjectVersionInfo{
|
||||
raw := &EntityVersionWithBody{
|
||||
&entity.EntityVersionInfo{
|
||||
Version: "A",
|
||||
},
|
||||
body,
|
||||
@ -30,28 +30,28 @@ func TestRawEncoders(t *testing.T) {
|
||||
fmt.Printf("expect: %s", str)
|
||||
require.JSONEq(t, `{"info":{"version":"A"},"body":"eyJmaWVsZCI6MS4yMywiaGVsbG8iOiJ3b3JsZCJ9"}`, str)
|
||||
|
||||
copy := &ObjectVersionWithBody{}
|
||||
copy := &EntityVersionWithBody{}
|
||||
err = json.Unmarshal(b, copy)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRawObjectWithHistory(t *testing.T) {
|
||||
func TestRawEntityWithHistory(t *testing.T) {
|
||||
body, err := json.Marshal(map[string]interface{}{
|
||||
"hello": "world",
|
||||
"field": 1.23,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
raw := &RawObjectWithHistory{
|
||||
Object: &object.RawObject{
|
||||
GRN: &object.GRN{UID: "x"},
|
||||
raw := &EntityWithHistory{
|
||||
Entity: &entity.Entity{
|
||||
GRN: &entity.GRN{UID: "x"},
|
||||
Version: "A",
|
||||
Body: body,
|
||||
},
|
||||
History: make([]*ObjectVersionWithBody, 0),
|
||||
History: make([]*EntityVersionWithBody, 0),
|
||||
}
|
||||
raw.History = append(raw.History, &ObjectVersionWithBody{
|
||||
&object.ObjectVersionInfo{
|
||||
raw.History = append(raw.History, &EntityVersionWithBody{
|
||||
&entity.EntityVersionInfo{
|
||||
Version: "B",
|
||||
},
|
||||
body,
|
||||
@ -63,7 +63,7 @@ func TestRawObjectWithHistory(t *testing.T) {
|
||||
str := string(b)
|
||||
//fmt.Printf("expect: %s", str)
|
||||
require.JSONEq(t, `{
|
||||
"object": {
|
||||
"entity": {
|
||||
"GRN": {
|
||||
"UID": "x"
|
||||
},
|
||||
@ -83,7 +83,7 @@ func TestRawObjectWithHistory(t *testing.T) {
|
||||
]
|
||||
}`, str)
|
||||
|
||||
copy := &ObjectVersionWithBody{}
|
||||
copy := &EntityVersionWithBody{}
|
||||
err = json.Unmarshal(b, copy)
|
||||
require.NoError(t, err)
|
||||
}
|
46
pkg/services/store/entity/dummy/fake_store.go
Normal file
46
pkg/services/store/entity/dummy/fake_store.go
Normal file
@ -0,0 +1,46 @@
|
||||
package dummy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
)
|
||||
|
||||
// Make sure we implement both store + admin
|
||||
var _ entity.EntityStoreServer = &fakeEntityStore{}
|
||||
var _ entity.EntityStoreAdminServer = &fakeEntityStore{}
|
||||
|
||||
func ProvideFakeEntityServer() entity.EntityStoreServer {
|
||||
return &fakeEntityStore{}
|
||||
}
|
||||
|
||||
type fakeEntityStore struct{}
|
||||
|
||||
func (i fakeEntityStore) AdminWrite(ctx context.Context, r *entity.AdminWriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeEntityStore) Write(ctx context.Context, r *entity.WriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeEntityStore) Read(ctx context.Context, r *entity.ReadEntityRequest) (*entity.ReadEntityResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeEntityStore) BatchRead(ctx context.Context, batchR *entity.BatchReadEntityRequest) (*entity.BatchReadEntityResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeEntityStore) Delete(ctx context.Context, r *entity.DeleteEntityRequest) (*entity.DeleteEntityResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeEntityStore) History(ctx context.Context, r *entity.EntityHistoryRequest) (*entity.EntityHistoryResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeEntityStore) Search(ctx context.Context, r *entity.EntitySearchRequest) (*entity.EntitySearchResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
2251
pkg/services/store/entity/entity.pb.go
Normal file
2251
pkg/services/store/entity/entity.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
||||
syntax = "proto3";
|
||||
package object;
|
||||
package entity;
|
||||
|
||||
option go_package = "./;object";
|
||||
option go_package = "./;entity";
|
||||
|
||||
message GRN {
|
||||
// the tenant/org id
|
||||
int64 tenant_id = 1;
|
||||
|
||||
// Identify the object kind. This kind will be used to apply a schema to the body and
|
||||
// Identify the entity kind. This kind will be used to apply a schema to the body and
|
||||
// will trigger additional indexing behavior.
|
||||
string kind = 3;
|
||||
|
||||
@ -16,21 +16,21 @@ message GRN {
|
||||
string UID = 4;
|
||||
}
|
||||
|
||||
// The canonical object/document data -- this represents the raw bytes and storage level metadata
|
||||
message RawObject {
|
||||
// Object identifier
|
||||
// The canonical entity/document data -- this represents the raw bytes and storage level metadata
|
||||
message Entity {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Time in epoch milliseconds that the object was created
|
||||
// Time in epoch milliseconds that the entity was created
|
||||
int64 created_at = 2;
|
||||
|
||||
// Time in epoch milliseconds that the object was updated
|
||||
// Time in epoch milliseconds that the entity was updated
|
||||
int64 updated_at = 3;
|
||||
|
||||
// Who created the object
|
||||
// Who created the entity
|
||||
string created_by = 4;
|
||||
|
||||
// Who updated the object
|
||||
// Who updated the entity
|
||||
string updated_by = 5;
|
||||
|
||||
// Content Length
|
||||
@ -39,7 +39,7 @@ message RawObject {
|
||||
// MD5 digest of the body
|
||||
string ETag = 7;
|
||||
|
||||
// Raw bytes of the storage object. The kind will determine what is a valid payload
|
||||
// Raw bytes of the storage entity. The kind will determine what is a valid payload
|
||||
bytes body = 8;
|
||||
|
||||
// Folder UID
|
||||
@ -48,29 +48,29 @@ message RawObject {
|
||||
// Unique slug within folder (may be UID)
|
||||
string slug = 10;
|
||||
|
||||
// The version will change when the object is saved. It is not necessarily sortable
|
||||
// The version will change when the entity is saved. It is not necessarily sortable
|
||||
//
|
||||
// NOTE: currently managed by the dashboard+dashboard_version tables
|
||||
string version = 11;
|
||||
|
||||
// External location info
|
||||
ObjectOriginInfo origin = 12;
|
||||
EntityOriginInfo origin = 12;
|
||||
}
|
||||
|
||||
message ObjectOriginInfo {
|
||||
message EntityOriginInfo {
|
||||
// NOTE: currently managed by the dashboard_provisioning table
|
||||
string source = 1;
|
||||
|
||||
// Key in the upstream system
|
||||
string key = 2;
|
||||
|
||||
// Time in epoch milliseconds that the object was last synced with an external system (provisioning/git)
|
||||
// Time in epoch milliseconds that the entity was last synced with an external system (provisioning/git)
|
||||
int64 time = 3;
|
||||
}
|
||||
|
||||
// Report error while working with objects
|
||||
// Report error while working with entitys
|
||||
// NOTE: real systems at scale will contain errors.
|
||||
message ObjectErrorInfo {
|
||||
message EntityErrorInfo {
|
||||
// Match an error code registry?
|
||||
int64 code = 1;
|
||||
|
||||
@ -81,15 +81,15 @@ message ObjectErrorInfo {
|
||||
bytes details_json = 3;
|
||||
}
|
||||
|
||||
// This is a subset of RawObject that does not include body or sync info
|
||||
message ObjectVersionInfo {
|
||||
// The version will change when the object is saved. It is not necessarily sortable
|
||||
// This is a subset of Entity that does not include body or sync info
|
||||
message EntityVersionInfo {
|
||||
// The version will change when the entity is saved. It is not necessarily sortable
|
||||
string version = 1;
|
||||
|
||||
// Time in epoch milliseconds that the object was updated
|
||||
// Time in epoch milliseconds that the entity was updated
|
||||
int64 updated_at = 2;
|
||||
|
||||
// Who updated the object
|
||||
// Who updated the entity
|
||||
string updated_by = 3;
|
||||
|
||||
// Content Length
|
||||
@ -108,8 +108,8 @@ message ObjectVersionInfo {
|
||||
// Get request/response
|
||||
//-----------------------------------------------
|
||||
|
||||
message ReadObjectRequest {
|
||||
// Object identifier
|
||||
message ReadEntityRequest {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Fetch an explicit version
|
||||
@ -122,11 +122,11 @@ message ReadObjectRequest {
|
||||
bool with_summary = 4;
|
||||
}
|
||||
|
||||
message ReadObjectResponse {
|
||||
// Object details with the body removed
|
||||
RawObject object = 1;
|
||||
message ReadEntityResponse {
|
||||
// Entity details with the body removed
|
||||
Entity entity = 1;
|
||||
|
||||
// Object summary as JSON
|
||||
// Entity summary as JSON
|
||||
bytes summary_json = 2;
|
||||
}
|
||||
|
||||
@ -134,29 +134,29 @@ message ReadObjectResponse {
|
||||
// Make many read requests at once (by Kind+ID+version)
|
||||
//------------------------------------------------------
|
||||
|
||||
message BatchReadObjectRequest {
|
||||
repeated ReadObjectRequest batch = 1;
|
||||
message BatchReadEntityRequest {
|
||||
repeated ReadEntityRequest batch = 1;
|
||||
}
|
||||
|
||||
message BatchReadObjectResponse {
|
||||
repeated ReadObjectResponse results = 1;
|
||||
message BatchReadEntityResponse {
|
||||
repeated ReadEntityResponse results = 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// Write request/response
|
||||
//-----------------------------------------------
|
||||
|
||||
message WriteObjectRequest {
|
||||
// Object identifier
|
||||
message WriteEntityRequest {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Where to save the object (empty will leave it unchanged)
|
||||
// Where to save the entity (empty will leave it unchanged)
|
||||
string folder = 2;
|
||||
|
||||
// The raw object body
|
||||
// The raw entity body
|
||||
bytes body = 3;
|
||||
|
||||
// Message that can be seen when exploring object history
|
||||
// Message that can be seen when exploring entity history
|
||||
string comment = 4;
|
||||
|
||||
// Used for optimistic locking. If missing, the previous version will be replaced regardless
|
||||
@ -166,32 +166,32 @@ message WriteObjectRequest {
|
||||
// This operation is useful when syncing a resource from external sources
|
||||
// that have more accurate metadata information (git, or an archive).
|
||||
// This process can bypass the forced checks that
|
||||
message AdminWriteObjectRequest {
|
||||
// Object identifier
|
||||
message AdminWriteEntityRequest {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Where to save the object (empty will leave it unchanged)
|
||||
// Where to save the entity (empty will leave it unchanged)
|
||||
string folder = 2;
|
||||
|
||||
// The raw object body
|
||||
// The raw entity body
|
||||
bytes body = 3;
|
||||
|
||||
// Message that can be seen when exploring object history
|
||||
// Message that can be seen when exploring entity history
|
||||
string comment = 4;
|
||||
|
||||
// Time in epoch milliseconds that the object was created
|
||||
// Time in epoch milliseconds that the entity was created
|
||||
// Optional, if 0 it will use the current time
|
||||
int64 created_at = 5;
|
||||
|
||||
// Time in epoch milliseconds that the object was updated
|
||||
// Time in epoch milliseconds that the entity was updated
|
||||
// Optional, if empty it will use the current user
|
||||
int64 updated_at = 6;
|
||||
|
||||
// Who created the object
|
||||
// Who created the entity
|
||||
// Optional, if 0 it will use the current time
|
||||
string created_by = 7;
|
||||
|
||||
// Who updated the object
|
||||
// Who updated the entity
|
||||
// Optional, if empty it will use the current user
|
||||
string updated_by = 8;
|
||||
|
||||
@ -207,21 +207,21 @@ message AdminWriteObjectRequest {
|
||||
// This will make sense for systems that manage history explicitly externallay
|
||||
bool clear_history = 11;
|
||||
|
||||
// Optionally define where the object came from
|
||||
ObjectOriginInfo origin = 12;
|
||||
// Optionally define where the entity came from
|
||||
EntityOriginInfo origin = 12;
|
||||
}
|
||||
|
||||
message WriteObjectResponse {
|
||||
message WriteEntityResponse {
|
||||
// Error info -- if exists, the save did not happen
|
||||
ObjectErrorInfo error = 1;
|
||||
EntityErrorInfo error = 1;
|
||||
|
||||
// Object identifier
|
||||
// Entity identifier
|
||||
GRN GRN = 2;
|
||||
|
||||
// Object details with the body removed
|
||||
ObjectVersionInfo object = 3;
|
||||
// Entity details with the body removed
|
||||
EntityVersionInfo entity = 3;
|
||||
|
||||
// Object summary as JSON
|
||||
// Entity summary as JSON
|
||||
bytes summary_json = 4;
|
||||
|
||||
// Status code
|
||||
@ -240,15 +240,15 @@ message WriteObjectResponse {
|
||||
// Delete request/response
|
||||
//-----------------------------------------------
|
||||
|
||||
message DeleteObjectRequest {
|
||||
// Object identifier
|
||||
message DeleteEntityRequest {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Used for optimistic locking. If missing, the previous version will be replaced regardless
|
||||
string previous_version = 3;
|
||||
}
|
||||
|
||||
message DeleteObjectResponse {
|
||||
message DeleteEntityResponse {
|
||||
bool OK = 1;
|
||||
}
|
||||
|
||||
@ -256,8 +256,8 @@ message DeleteObjectResponse {
|
||||
// History request/response
|
||||
//-----------------------------------------------
|
||||
|
||||
message ObjectHistoryRequest {
|
||||
// Object identifier
|
||||
message EntityHistoryRequest {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Maximum number of items to return
|
||||
@ -267,12 +267,12 @@ message ObjectHistoryRequest {
|
||||
string next_page_token = 5;
|
||||
}
|
||||
|
||||
message ObjectHistoryResponse {
|
||||
// Object identifier
|
||||
message EntityHistoryResponse {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// Object metadata without the raw bytes
|
||||
repeated ObjectVersionInfo versions = 2;
|
||||
// Entity metadata without the raw bytes
|
||||
repeated EntityVersionInfo versions = 2;
|
||||
|
||||
// More results exist... pass this in the next request
|
||||
string next_page_token = 3;
|
||||
@ -283,7 +283,7 @@ message ObjectHistoryResponse {
|
||||
// List request/response
|
||||
//-----------------------------------------------
|
||||
|
||||
message ObjectSearchRequest {
|
||||
message EntitySearchRequest {
|
||||
// Starting from the requested page (other query parameters must match!)
|
||||
string next_page_token = 1;
|
||||
|
||||
@ -315,24 +315,24 @@ message ObjectSearchRequest {
|
||||
bool with_fields = 10;
|
||||
}
|
||||
|
||||
// Search result metadata for each object
|
||||
message ObjectSearchResult {
|
||||
// Object identifier
|
||||
// Search result metadata for each entity
|
||||
message EntitySearchResult {
|
||||
// Entity identifier
|
||||
GRN GRN = 1;
|
||||
|
||||
// The current veresion of this object
|
||||
// The current veresion of this entity
|
||||
string version = 2;
|
||||
|
||||
// Content Length
|
||||
int64 size = 3;
|
||||
|
||||
// Time in epoch milliseconds that the object was updated
|
||||
// Time in epoch milliseconds that the entity was updated
|
||||
int64 updated_at = 4;
|
||||
|
||||
// Who updated the object
|
||||
// Who updated the entity
|
||||
string updated_by = 5;
|
||||
|
||||
// Optionally include the full object body
|
||||
// Optionally include the full entity body
|
||||
bytes body = 6;
|
||||
|
||||
//----------------------------------------
|
||||
@ -357,12 +357,12 @@ message ObjectSearchResult {
|
||||
// Optionally include extracted JSON
|
||||
bytes fields_json = 12;
|
||||
|
||||
// ObjectErrorInfo in json
|
||||
// EntityErrorInfo in json
|
||||
bytes error_json = 13;
|
||||
}
|
||||
|
||||
message ObjectSearchResponse {
|
||||
repeated ObjectSearchResult results = 1;
|
||||
message EntitySearchResponse {
|
||||
repeated EntitySearchResult results = 1;
|
||||
|
||||
// More results exist... pass this in the next request
|
||||
string next_page_token = 2;
|
||||
@ -373,25 +373,25 @@ message ObjectSearchResponse {
|
||||
// Storage interface
|
||||
//-----------------------------------------------
|
||||
|
||||
// The object store provides a basic CRUD (+watch eventually) interface for generic objects
|
||||
service ObjectStore {
|
||||
rpc Read(ReadObjectRequest) returns (ReadObjectResponse);
|
||||
rpc BatchRead(BatchReadObjectRequest) returns (BatchReadObjectResponse);
|
||||
rpc Write(WriteObjectRequest) returns (WriteObjectResponse);
|
||||
rpc Delete(DeleteObjectRequest) returns (DeleteObjectResponse);
|
||||
rpc History(ObjectHistoryRequest) returns (ObjectHistoryResponse);
|
||||
rpc Search(ObjectSearchRequest) returns (ObjectSearchResponse);
|
||||
// The entity store provides a basic CRUD (+watch eventually) interface for generic entitys
|
||||
service EntityStore {
|
||||
rpc Read(ReadEntityRequest) returns (ReadEntityResponse);
|
||||
rpc BatchRead(BatchReadEntityRequest) returns (BatchReadEntityResponse);
|
||||
rpc Write(WriteEntityRequest) returns (WriteEntityResponse);
|
||||
rpc Delete(DeleteEntityRequest) returns (DeleteEntityResponse);
|
||||
rpc History(EntityHistoryRequest) returns (EntityHistoryResponse);
|
||||
rpc Search(EntitySearchRequest) returns (EntitySearchResponse);
|
||||
|
||||
// Ideally an additional search endpoint with more flexibility to limit what you actually care about
|
||||
// https://github.com/grafana/grafana-plugin-sdk-go/blob/main/proto/backend.proto#L129
|
||||
// rpc SearchEX(ObjectSearchRequest) returns (DataResponse);
|
||||
// rpc SearchEX(EntitySearchRequest) returns (DataResponse);
|
||||
|
||||
// TEMPORARY... while we split this into a new service (see below)
|
||||
rpc AdminWrite(AdminWriteObjectRequest) returns (WriteObjectResponse);
|
||||
rpc AdminWrite(AdminWriteEntityRequest) returns (WriteEntityResponse);
|
||||
}
|
||||
|
||||
// The admin service extends the basic object store interface, but provides
|
||||
// The admin service extends the basic entity store interface, but provides
|
||||
// more explicit control that can support bulk operations like efficient git sync
|
||||
service ObjectStoreAdmin {
|
||||
rpc AdminWrite(AdminWriteObjectRequest) returns (WriteObjectResponse);
|
||||
service EntityStoreAdmin {
|
||||
rpc AdminWrite(AdminWriteEntityRequest) returns (WriteEntityResponse);
|
||||
}
|
405
pkg/services/store/entity/entity_grpc.pb.go
Normal file
405
pkg/services/store/entity/entity_grpc.pb.go
Normal file
@ -0,0 +1,405 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.21.9
|
||||
// source: entity.proto
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// EntityStoreClient is the client API for EntityStore service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type EntityStoreClient interface {
|
||||
Read(ctx context.Context, in *ReadEntityRequest, opts ...grpc.CallOption) (*ReadEntityResponse, error)
|
||||
BatchRead(ctx context.Context, in *BatchReadEntityRequest, opts ...grpc.CallOption) (*BatchReadEntityResponse, error)
|
||||
Write(ctx context.Context, in *WriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteEntityRequest, opts ...grpc.CallOption) (*DeleteEntityResponse, error)
|
||||
History(ctx context.Context, in *EntityHistoryRequest, opts ...grpc.CallOption) (*EntityHistoryResponse, error)
|
||||
Search(ctx context.Context, in *EntitySearchRequest, opts ...grpc.CallOption) (*EntitySearchResponse, error)
|
||||
// TEMPORARY... while we split this into a new service (see below)
|
||||
AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error)
|
||||
}
|
||||
|
||||
type entityStoreClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewEntityStoreClient(cc grpc.ClientConnInterface) EntityStoreClient {
|
||||
return &entityStoreClient{cc}
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) Read(ctx context.Context, in *ReadEntityRequest, opts ...grpc.CallOption) (*ReadEntityResponse, error) {
|
||||
out := new(ReadEntityResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/Read", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) BatchRead(ctx context.Context, in *BatchReadEntityRequest, opts ...grpc.CallOption) (*BatchReadEntityResponse, error) {
|
||||
out := new(BatchReadEntityResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/BatchRead", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) Write(ctx context.Context, in *WriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) {
|
||||
out := new(WriteEntityResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/Write", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) Delete(ctx context.Context, in *DeleteEntityRequest, opts ...grpc.CallOption) (*DeleteEntityResponse, error) {
|
||||
out := new(DeleteEntityResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/Delete", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) History(ctx context.Context, in *EntityHistoryRequest, opts ...grpc.CallOption) (*EntityHistoryResponse, error) {
|
||||
out := new(EntityHistoryResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/History", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) Search(ctx context.Context, in *EntitySearchRequest, opts ...grpc.CallOption) (*EntitySearchResponse, error) {
|
||||
out := new(EntitySearchResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/Search", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *entityStoreClient) AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) {
|
||||
out := new(WriteEntityResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStore/AdminWrite", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// EntityStoreServer is the server API for EntityStore service.
|
||||
// All implementations should embed UnimplementedEntityStoreServer
|
||||
// for forward compatibility
|
||||
type EntityStoreServer interface {
|
||||
Read(context.Context, *ReadEntityRequest) (*ReadEntityResponse, error)
|
||||
BatchRead(context.Context, *BatchReadEntityRequest) (*BatchReadEntityResponse, error)
|
||||
Write(context.Context, *WriteEntityRequest) (*WriteEntityResponse, error)
|
||||
Delete(context.Context, *DeleteEntityRequest) (*DeleteEntityResponse, error)
|
||||
History(context.Context, *EntityHistoryRequest) (*EntityHistoryResponse, error)
|
||||
Search(context.Context, *EntitySearchRequest) (*EntitySearchResponse, error)
|
||||
// TEMPORARY... while we split this into a new service (see below)
|
||||
AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedEntityStoreServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedEntityStoreServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedEntityStoreServer) Read(context.Context, *ReadEntityRequest) (*ReadEntityResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Read not implemented")
|
||||
}
|
||||
func (UnimplementedEntityStoreServer) BatchRead(context.Context, *BatchReadEntityRequest) (*BatchReadEntityResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BatchRead not implemented")
|
||||
}
|
||||
func (UnimplementedEntityStoreServer) Write(context.Context, *WriteEntityRequest) (*WriteEntityResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Write not implemented")
|
||||
}
|
||||
func (UnimplementedEntityStoreServer) Delete(context.Context, *DeleteEntityRequest) (*DeleteEntityResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
||||
}
|
||||
func (UnimplementedEntityStoreServer) History(context.Context, *EntityHistoryRequest) (*EntityHistoryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method History not implemented")
|
||||
}
|
||||
func (UnimplementedEntityStoreServer) Search(context.Context, *EntitySearchRequest) (*EntitySearchResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Search not implemented")
|
||||
}
|
||||
func (UnimplementedEntityStoreServer) AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminWrite not implemented")
|
||||
}
|
||||
|
||||
// UnsafeEntityStoreServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to EntityStoreServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeEntityStoreServer interface {
|
||||
mustEmbedUnimplementedEntityStoreServer()
|
||||
}
|
||||
|
||||
func RegisterEntityStoreServer(s grpc.ServiceRegistrar, srv EntityStoreServer) {
|
||||
s.RegisterService(&EntityStore_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _EntityStore_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReadEntityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).Read(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/Read",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).Read(ctx, req.(*ReadEntityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _EntityStore_BatchRead_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(BatchReadEntityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).BatchRead(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/BatchRead",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).BatchRead(ctx, req.(*BatchReadEntityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _EntityStore_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(WriteEntityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).Write(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/Write",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).Write(ctx, req.(*WriteEntityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _EntityStore_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteEntityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).Delete(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/Delete",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).Delete(ctx, req.(*DeleteEntityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _EntityStore_History_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EntityHistoryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).History(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/History",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).History(ctx, req.(*EntityHistoryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _EntityStore_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EntitySearchRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).Search(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/Search",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).Search(ctx, req.(*EntitySearchRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _EntityStore_AdminWrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminWriteEntityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreServer).AdminWrite(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStore/AdminWrite",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreServer).AdminWrite(ctx, req.(*AdminWriteEntityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// EntityStore_ServiceDesc is the grpc.ServiceDesc for EntityStore service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var EntityStore_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "entity.EntityStore",
|
||||
HandlerType: (*EntityStoreServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Read",
|
||||
Handler: _EntityStore_Read_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "BatchRead",
|
||||
Handler: _EntityStore_BatchRead_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Write",
|
||||
Handler: _EntityStore_Write_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Delete",
|
||||
Handler: _EntityStore_Delete_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "History",
|
||||
Handler: _EntityStore_History_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Search",
|
||||
Handler: _EntityStore_Search_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AdminWrite",
|
||||
Handler: _EntityStore_AdminWrite_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "entity.proto",
|
||||
}
|
||||
|
||||
// EntityStoreAdminClient is the client API for EntityStoreAdmin service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type EntityStoreAdminClient interface {
|
||||
AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error)
|
||||
}
|
||||
|
||||
type entityStoreAdminClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewEntityStoreAdminClient(cc grpc.ClientConnInterface) EntityStoreAdminClient {
|
||||
return &entityStoreAdminClient{cc}
|
||||
}
|
||||
|
||||
func (c *entityStoreAdminClient) AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) {
|
||||
out := new(WriteEntityResponse)
|
||||
err := c.cc.Invoke(ctx, "/entity.EntityStoreAdmin/AdminWrite", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// EntityStoreAdminServer is the server API for EntityStoreAdmin service.
|
||||
// All implementations should embed UnimplementedEntityStoreAdminServer
|
||||
// for forward compatibility
|
||||
type EntityStoreAdminServer interface {
|
||||
AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedEntityStoreAdminServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedEntityStoreAdminServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedEntityStoreAdminServer) AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminWrite not implemented")
|
||||
}
|
||||
|
||||
// UnsafeEntityStoreAdminServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to EntityStoreAdminServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeEntityStoreAdminServer interface {
|
||||
mustEmbedUnimplementedEntityStoreAdminServer()
|
||||
}
|
||||
|
||||
func RegisterEntityStoreAdminServer(s grpc.ServiceRegistrar, srv EntityStoreAdminServer) {
|
||||
s.RegisterService(&EntityStoreAdmin_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _EntityStoreAdmin_AdminWrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminWriteEntityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EntityStoreAdminServer).AdminWrite(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/entity.EntityStoreAdmin/AdminWrite",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EntityStoreAdminServer).AdminWrite(ctx, req.(*AdminWriteEntityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// EntityStoreAdmin_ServiceDesc is the grpc.ServiceDesc for EntityStoreAdmin service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var EntityStoreAdmin_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "entity.EntityStoreAdmin",
|
||||
HandlerType: (*EntityStoreAdminServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "AdminWrite",
|
||||
Handler: _EntityStoreAdmin_AdminWrite_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "entity.proto",
|
||||
}
|
@ -17,5 +17,5 @@ cd "$DIR"
|
||||
protoc -I ./ \
|
||||
--go_out=${DST_DIR} \
|
||||
--go-grpc_out=${DST_DIR} --go-grpc_opt=require_unimplemented_servers=false \
|
||||
object.proto
|
||||
entity.proto
|
||||
|
@ -1,4 +1,4 @@
|
||||
package object
|
||||
package entity
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package httpobjectstore
|
||||
package httpentitystore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
|
||||
@ -20,35 +20,35 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type HTTPObjectStore interface {
|
||||
type HTTPEntityStore interface {
|
||||
// Register HTTP Access to the store
|
||||
RegisterHTTPRoutes(routing.RouteRegister)
|
||||
}
|
||||
|
||||
type httpObjectStore struct {
|
||||
store object.ObjectStoreServer
|
||||
type httpEntityStore struct {
|
||||
store entity.EntityStoreServer
|
||||
log log.Logger
|
||||
kinds kind.KindRegistry
|
||||
}
|
||||
|
||||
func ProvideHTTPObjectStore(store object.ObjectStoreServer, kinds kind.KindRegistry) HTTPObjectStore {
|
||||
return &httpObjectStore{
|
||||
func ProvideHTTPEntityStore(store entity.EntityStoreServer, kinds kind.KindRegistry) HTTPEntityStore {
|
||||
return &httpEntityStore{
|
||||
store: store,
|
||||
log: log.New("http-object-store"),
|
||||
log: log.New("http-entity-store"),
|
||||
kinds: kinds,
|
||||
}
|
||||
}
|
||||
|
||||
// All registered under "api/object"
|
||||
func (s *httpObjectStore) RegisterHTTPRoutes(route routing.RouteRegister) {
|
||||
// All registered under "api/entity"
|
||||
func (s *httpEntityStore) RegisterHTTPRoutes(route routing.RouteRegister) {
|
||||
// For now, require admin for everything
|
||||
reqGrafanaAdmin := middleware.ReqSignedIn //.ReqGrafanaAdmin
|
||||
|
||||
// Every * must parse to a GRN (uid+kind)
|
||||
route.Get("/store/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doGetObject))
|
||||
route.Post("/store/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doWriteObject))
|
||||
route.Delete("/store/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doDeleteObject))
|
||||
route.Get("/raw/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doGetRawObject))
|
||||
route.Get("/store/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doGetEntity))
|
||||
route.Post("/store/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doWriteEntity))
|
||||
route.Delete("/store/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doDeleteEntity))
|
||||
route.Get("/raw/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doGetRawEntity))
|
||||
route.Get("/history/:kind/:uid", reqGrafanaAdmin, routing.Wrap(s.doGetHistory))
|
||||
route.Get("/list/:uid", reqGrafanaAdmin, routing.Wrap(s.doListFolder)) // Simplified version of search -- path is prefix
|
||||
route.Get("/search", reqGrafanaAdmin, routing.Wrap(s.doSearch))
|
||||
@ -60,7 +60,7 @@ func (s *httpObjectStore) RegisterHTTPRoutes(route routing.RouteRegister) {
|
||||
// This function will extract UID+Kind from the requested path "*" in our router
|
||||
// This is far from ideal! but is at least consistent for these endpoints.
|
||||
// This will quickly be revisited as we explore how to encode UID+Kind in a "GRN" format
|
||||
func (s *httpObjectStore) getGRNFromRequest(c *models.ReqContext) (*object.GRN, map[string]string, error) {
|
||||
func (s *httpEntityStore) getGRNFromRequest(c *models.ReqContext) (*entity.GRN, map[string]string, error) {
|
||||
params := web.Params(c.Req)
|
||||
// Read parameters that are encoded in the URL
|
||||
vals := c.Req.URL.Query()
|
||||
@ -69,38 +69,38 @@ func (s *httpObjectStore) getGRNFromRequest(c *models.ReqContext) (*object.GRN,
|
||||
params[k] = v[0]
|
||||
}
|
||||
}
|
||||
return &object.GRN{
|
||||
return &entity.GRN{
|
||||
TenantId: c.OrgID,
|
||||
Kind: params[":kind"],
|
||||
UID: params[":uid"],
|
||||
}, params, nil
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doGetObject(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doGetEntity(c *models.ReqContext) response.Response {
|
||||
grn, params, err := s.getGRNFromRequest(c)
|
||||
if err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
rsp, err := s.store.Read(c.Req.Context(), &object.ReadObjectRequest{
|
||||
rsp, err := s.store.Read(c.Req.Context(), &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
Version: params["version"], // ?version = XYZ
|
||||
WithBody: params["body"] != "false", // default to true
|
||||
WithSummary: params["summary"] == "true", // default to false
|
||||
})
|
||||
if err != nil {
|
||||
return response.Error(500, "error fetching object", err)
|
||||
return response.Error(500, "error fetching entity", err)
|
||||
}
|
||||
if rsp.Object == nil {
|
||||
if rsp.Entity == nil {
|
||||
return response.Error(404, "not found", nil)
|
||||
}
|
||||
|
||||
// Configure etag support
|
||||
currentEtag := rsp.Object.ETag
|
||||
currentEtag := rsp.Entity.ETag
|
||||
previousEtag := c.Req.Header.Get("If-None-Match")
|
||||
if previousEtag == currentEtag {
|
||||
return response.CreateNormalResponse(
|
||||
http.Header{
|
||||
"ETag": []string{rsp.Object.ETag},
|
||||
"ETag": []string{rsp.Entity.ETag},
|
||||
},
|
||||
[]byte{}, // nothing
|
||||
http.StatusNotModified, // 304
|
||||
@ -111,12 +111,12 @@ func (s *httpObjectStore) doGetObject(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, rsp)
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doGetRawObject(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doGetRawEntity(c *models.ReqContext) response.Response {
|
||||
grn, params, err := s.getGRNFromRequest(c)
|
||||
if err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
rsp, err := s.store.Read(c.Req.Context(), &object.ReadObjectRequest{
|
||||
rsp, err := s.store.Read(c.Req.Context(), &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
Version: params["version"], // ?version = XYZ
|
||||
WithBody: true,
|
||||
@ -130,14 +130,14 @@ func (s *httpObjectStore) doGetRawObject(c *models.ReqContext) response.Response
|
||||
return response.Error(400, "Unsupported kind", err)
|
||||
}
|
||||
|
||||
if rsp.Object != nil && rsp.Object.Body != nil {
|
||||
if rsp.Entity != nil && rsp.Entity.Body != nil {
|
||||
// Configure etag support
|
||||
currentEtag := rsp.Object.ETag
|
||||
currentEtag := rsp.Entity.ETag
|
||||
previousEtag := c.Req.Header.Get("If-None-Match")
|
||||
if previousEtag == currentEtag {
|
||||
return response.CreateNormalResponse(
|
||||
http.Header{
|
||||
"ETag": []string{rsp.Object.ETag},
|
||||
"ETag": []string{rsp.Entity.ETag},
|
||||
},
|
||||
[]byte{}, // nothing
|
||||
http.StatusNotModified, // 304
|
||||
@ -152,7 +152,7 @@ func (s *httpObjectStore) doGetRawObject(c *models.ReqContext) response.Response
|
||||
"Content-Type": []string{mime},
|
||||
"ETag": []string{currentEtag},
|
||||
},
|
||||
rsp.Object.Body,
|
||||
rsp.Entity.Body,
|
||||
200,
|
||||
)
|
||||
}
|
||||
@ -161,7 +161,7 @@ func (s *httpObjectStore) doGetRawObject(c *models.ReqContext) response.Response
|
||||
|
||||
const MAX_UPLOAD_SIZE = 5 * 1024 * 1024 // 5MB
|
||||
|
||||
func (s *httpObjectStore) doWriteObject(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doWriteEntity(c *models.ReqContext) response.Response {
|
||||
grn, params, err := s.getGRNFromRequest(c)
|
||||
if err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
@ -174,7 +174,7 @@ func (s *httpObjectStore) doWriteObject(c *models.ReqContext) response.Response
|
||||
return response.Error(400, "error reading body", err)
|
||||
}
|
||||
|
||||
rsp, err := s.store.Write(c.Req.Context(), &object.WriteObjectRequest{
|
||||
rsp, err := s.store.Write(c.Req.Context(), &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: b,
|
||||
Folder: params["folder"],
|
||||
@ -187,12 +187,12 @@ func (s *httpObjectStore) doWriteObject(c *models.ReqContext) response.Response
|
||||
return response.JSON(200, rsp)
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doDeleteObject(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doDeleteEntity(c *models.ReqContext) response.Response {
|
||||
grn, params, err := s.getGRNFromRequest(c)
|
||||
if err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
rsp, err := s.store.Delete(c.Req.Context(), &object.DeleteObjectRequest{
|
||||
rsp, err := s.store.Delete(c.Req.Context(), &entity.DeleteEntityRequest{
|
||||
GRN: grn,
|
||||
PreviousVersion: params["previousVersion"],
|
||||
})
|
||||
@ -202,13 +202,13 @@ func (s *httpObjectStore) doDeleteObject(c *models.ReqContext) response.Response
|
||||
return response.JSON(200, rsp)
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doGetHistory(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doGetHistory(c *models.ReqContext) response.Response {
|
||||
grn, params, err := s.getGRNFromRequest(c)
|
||||
if err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
limit := int64(20) // params
|
||||
rsp, err := s.store.History(c.Req.Context(), &object.ObjectHistoryRequest{
|
||||
rsp, err := s.store.History(c.Req.Context(), &entity.EntityHistoryRequest{
|
||||
GRN: grn,
|
||||
Limit: limit,
|
||||
NextPageToken: params["nextPageToken"],
|
||||
@ -219,7 +219,7 @@ func (s *httpObjectStore) doGetHistory(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, rsp)
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doUpload(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doUpload(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = http.MaxBytesReader(c.Resp, c.Req.Body, MAX_UPLOAD_SIZE)
|
||||
if err := c.Req.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
|
||||
msg := fmt.Sprintf("Please limit file uploaded under %s", util.ByteCountSI(MAX_UPLOAD_SIZE))
|
||||
@ -230,7 +230,7 @@ func (s *httpObjectStore) doUpload(c *models.ReqContext) response.Response {
|
||||
return response.Error(400, "missing files", nil)
|
||||
}
|
||||
|
||||
var rsp []*object.WriteObjectResponse
|
||||
var rsp []*entity.WriteEntityResponse
|
||||
|
||||
message := getMultipartFormValue(c.Req, "message")
|
||||
overwriteExistingFile := getMultipartFormValue(c.Req, "overwriteExistingFile") != "false" // must explicitly overwrite
|
||||
@ -264,14 +264,14 @@ func (s *httpObjectStore) doUpload(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Internal Server Error", err)
|
||||
}
|
||||
|
||||
grn := &object.GRN{
|
||||
grn := &entity.GRN{
|
||||
UID: uid,
|
||||
Kind: kind.ID,
|
||||
TenantId: c.OrgID,
|
||||
}
|
||||
|
||||
if !overwriteExistingFile {
|
||||
result, err := s.store.Read(ctx, &object.ReadObjectRequest{
|
||||
result, err := s.store.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
WithBody: false,
|
||||
WithSummary: false,
|
||||
@ -279,12 +279,12 @@ func (s *httpObjectStore) doUpload(c *models.ReqContext) response.Response {
|
||||
if err != nil {
|
||||
return response.Error(500, "Internal Server Error", err)
|
||||
}
|
||||
if result.Object != nil {
|
||||
if result.Entity != nil {
|
||||
return response.Error(400, "File name already in use", err)
|
||||
}
|
||||
}
|
||||
|
||||
result, err := s.store.Write(ctx, &object.WriteObjectRequest{
|
||||
result, err := s.store.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: data,
|
||||
Comment: message,
|
||||
@ -302,14 +302,14 @@ func (s *httpObjectStore) doUpload(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, rsp)
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doListFolder(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doListFolder(c *models.ReqContext) response.Response {
|
||||
return response.JSON(501, "Not implemented yet")
|
||||
}
|
||||
|
||||
func (s *httpObjectStore) doSearch(c *models.ReqContext) response.Response {
|
||||
func (s *httpEntityStore) doSearch(c *models.ReqContext) response.Response {
|
||||
vals := c.Req.URL.Query()
|
||||
|
||||
req := &object.ObjectSearchRequest{
|
||||
req := &entity.EntitySearchRequest{
|
||||
WithBody: asBoolean("body", vals, false),
|
||||
WithLabels: asBoolean("labels", vals, true),
|
||||
WithFields: asBoolean("fields", vals, true),
|
@ -1,4 +1,4 @@
|
||||
package object
|
||||
package entity
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
@ -10,12 +10,12 @@ import (
|
||||
)
|
||||
|
||||
func init() { //nolint:gochecknoinits
|
||||
jsoniter.RegisterTypeEncoder("object.ObjectSearchResult", &searchResultCodec{})
|
||||
jsoniter.RegisterTypeEncoder("object.WriteObjectResponse", &writeResponseCodec{})
|
||||
jsoniter.RegisterTypeEncoder("object.ReadObjectResponse", &readResponseCodec{})
|
||||
jsoniter.RegisterTypeEncoder("entity.EntitySearchResult", &searchResultCodec{})
|
||||
jsoniter.RegisterTypeEncoder("entity.WriteObjectResponse", &writeResponseCodec{})
|
||||
jsoniter.RegisterTypeEncoder("entity.ReadEntityResponse", &readResponseCodec{})
|
||||
|
||||
jsoniter.RegisterTypeEncoder("object.RawObject", &rawObjectCodec{})
|
||||
jsoniter.RegisterTypeDecoder("object.RawObject", &rawObjectCodec{})
|
||||
jsoniter.RegisterTypeEncoder("entity.Entity", &rawEntityCodec{})
|
||||
jsoniter.RegisterTypeDecoder("entity.Entity", &rawEntityCodec{})
|
||||
}
|
||||
|
||||
func writeRawJson(stream *jsoniter.Stream, val []byte) {
|
||||
@ -27,30 +27,30 @@ func writeRawJson(stream *jsoniter.Stream, val []byte) {
|
||||
}
|
||||
|
||||
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
||||
type rawObjectCodec struct{}
|
||||
type rawEntityCodec struct{}
|
||||
|
||||
func (obj *RawObject) MarshalJSON() ([]byte, error) {
|
||||
func (obj *Entity) MarshalJSON() ([]byte, error) {
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
// UnmarshalJSON will read JSON into a RawObject
|
||||
func (obj *RawObject) UnmarshalJSON(b []byte) error {
|
||||
// UnmarshalJSON will read JSON into a Entity
|
||||
func (obj *Entity) UnmarshalJSON(b []byte) error {
|
||||
if obj == nil {
|
||||
return fmt.Errorf("unexpected nil for raw objcet")
|
||||
}
|
||||
iter := jsoniter.ParseBytes(jsoniter.ConfigDefault, b)
|
||||
readRawObject(iter, obj)
|
||||
readEntity(iter, obj)
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func (codec *rawObjectCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
f := (*RawObject)(ptr)
|
||||
func (codec *rawEntityCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
f := (*Entity)(ptr)
|
||||
return f.GRN == nil && f.Body == nil
|
||||
}
|
||||
|
||||
func (codec *rawObjectCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
obj := (*RawObject)(ptr)
|
||||
func (codec *rawEntityCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
obj := (*Entity)(ptr)
|
||||
stream.WriteObjectStart()
|
||||
stream.WriteObjectField("GRN")
|
||||
stream.WriteVal(obj.GRN)
|
||||
@ -121,13 +121,13 @@ func (codec *rawObjectCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream)
|
||||
stream.WriteObjectEnd()
|
||||
}
|
||||
|
||||
func (codec *rawObjectCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
*(*RawObject)(ptr) = RawObject{}
|
||||
raw := (*RawObject)(ptr)
|
||||
readRawObject(iter, raw)
|
||||
func (codec *rawEntityCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
*(*Entity)(ptr) = Entity{}
|
||||
raw := (*Entity)(ptr)
|
||||
readEntity(iter, raw)
|
||||
}
|
||||
|
||||
func readRawObject(iter *jsoniter.Iterator, raw *RawObject) {
|
||||
func readEntity(iter *jsoniter.Iterator, raw *Entity) {
|
||||
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
|
||||
switch l1Field {
|
||||
case "GRN":
|
||||
@ -152,7 +152,7 @@ func readRawObject(iter *jsoniter.Iterator, raw *RawObject) {
|
||||
case "version":
|
||||
raw.Version = iter.ReadString()
|
||||
case "origin":
|
||||
raw.Origin = &ObjectOriginInfo{}
|
||||
raw.Origin = &EntityOriginInfo{}
|
||||
iter.ReadVal(raw.Origin)
|
||||
|
||||
case "body":
|
||||
@ -160,7 +160,7 @@ func readRawObject(iter *jsoniter.Iterator, raw *RawObject) {
|
||||
iter.ReadVal(&val) // ??? is there a smarter way to just keep the underlying bytes without read+marshal
|
||||
body, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
iter.ReportError("raw object", "error creating json from body")
|
||||
iter.ReportError("raw entity", "error creating json from body")
|
||||
return
|
||||
}
|
||||
raw.Body = body
|
||||
@ -169,7 +169,7 @@ func readRawObject(iter *jsoniter.Iterator, raw *RawObject) {
|
||||
val := iter.ReadString()
|
||||
body, err := base64.StdEncoding.DecodeString(val)
|
||||
if err != nil {
|
||||
iter.ReportError("raw object", "error decoding base64 body")
|
||||
iter.ReportError("raw entity", "error decoding base64 body")
|
||||
return
|
||||
}
|
||||
raw.Body = body
|
||||
@ -184,21 +184,21 @@ func readRawObject(iter *jsoniter.Iterator, raw *RawObject) {
|
||||
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
||||
type readResponseCodec struct{}
|
||||
|
||||
func (obj *ReadObjectResponse) MarshalJSON() ([]byte, error) {
|
||||
func (obj *ReadEntityResponse) MarshalJSON() ([]byte, error) {
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
func (codec *readResponseCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
f := (*ReadObjectResponse)(ptr)
|
||||
f := (*ReadEntityResponse)(ptr)
|
||||
return f == nil
|
||||
}
|
||||
|
||||
func (codec *readResponseCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
obj := (*ReadObjectResponse)(ptr)
|
||||
obj := (*ReadEntityResponse)(ptr)
|
||||
stream.WriteObjectStart()
|
||||
stream.WriteObjectField("object")
|
||||
stream.WriteVal(obj.Object)
|
||||
stream.WriteObjectField("entity")
|
||||
stream.WriteVal(obj.Entity)
|
||||
|
||||
if len(obj.SummaryJson) > 0 {
|
||||
stream.WriteMore()
|
||||
@ -212,18 +212,18 @@ func (codec *readResponseCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stre
|
||||
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
||||
type searchResultCodec struct{}
|
||||
|
||||
func (obj *ObjectSearchResult) MarshalJSON() ([]byte, error) {
|
||||
func (obj *EntitySearchResult) MarshalJSON() ([]byte, error) {
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
func (codec *searchResultCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
f := (*ObjectSearchResult)(ptr)
|
||||
f := (*EntitySearchResult)(ptr)
|
||||
return f.GRN == nil && f.Body == nil
|
||||
}
|
||||
|
||||
func (codec *searchResultCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
obj := (*ObjectSearchResult)(ptr)
|
||||
obj := (*EntitySearchResult)(ptr)
|
||||
stream.WriteObjectStart()
|
||||
stream.WriteObjectField("GRN")
|
||||
stream.WriteVal(obj.GRN)
|
||||
@ -285,18 +285,18 @@ func (codec *searchResultCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stre
|
||||
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
||||
type writeResponseCodec struct{}
|
||||
|
||||
func (obj *WriteObjectResponse) MarshalJSON() ([]byte, error) {
|
||||
func (obj *WriteEntityResponse) MarshalJSON() ([]byte, error) {
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
func (codec *writeResponseCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
f := (*WriteObjectResponse)(ptr)
|
||||
f := (*WriteEntityResponse)(ptr)
|
||||
return f == nil
|
||||
}
|
||||
|
||||
func (codec *writeResponseCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
obj := (*WriteObjectResponse)(ptr)
|
||||
obj := (*WriteEntityResponse)(ptr)
|
||||
stream.WriteObjectStart()
|
||||
stream.WriteObjectField("status")
|
||||
stream.WriteString(obj.Status.String())
|
||||
@ -311,10 +311,10 @@ func (codec *writeResponseCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Str
|
||||
stream.WriteObjectField("GRN")
|
||||
stream.WriteVal(obj.GRN)
|
||||
}
|
||||
if obj.Object != nil {
|
||||
if obj.Entity != nil {
|
||||
stream.WriteMore()
|
||||
stream.WriteObjectField("object")
|
||||
stream.WriteVal(obj.Object)
|
||||
stream.WriteObjectField("entity")
|
||||
stream.WriteVal(obj.Entity)
|
||||
}
|
||||
if len(obj.SummaryJson) > 0 {
|
||||
stream.WriteMore()
|
@ -1,4 +1,4 @@
|
||||
package object
|
||||
package entity
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -14,7 +14,7 @@ func TestRawEncoders(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
raw := &RawObject{
|
||||
raw := &Entity{
|
||||
GRN: &GRN{
|
||||
UID: "a",
|
||||
Kind: "b",
|
||||
@ -42,7 +42,7 @@ func TestRawEncoders(t *testing.T) {
|
||||
"etag": "d"
|
||||
}`, str)
|
||||
|
||||
copy := &RawObject{}
|
||||
copy := &Entity{}
|
||||
err = json.Unmarshal(b, copy)
|
||||
require.NoError(t, err)
|
||||
}
|
@ -15,35 +15,35 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/resolver"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
// Make sure we implement both store + admin
|
||||
var _ object.ObjectStoreServer = &sqlObjectServer{}
|
||||
var _ object.ObjectStoreAdminServer = &sqlObjectServer{}
|
||||
var _ entity.EntityStoreServer = &sqlEntityServer{}
|
||||
var _ entity.EntityStoreAdminServer = &sqlEntityServer{}
|
||||
|
||||
func ProvideSQLObjectServer(db db.DB, cfg *setting.Cfg, grpcServerProvider grpcserver.Provider, kinds kind.KindRegistry, resolver resolver.ObjectReferenceResolver) object.ObjectStoreServer {
|
||||
objectServer := &sqlObjectServer{
|
||||
func ProvideSQLEntityServer(db db.DB, cfg *setting.Cfg, grpcServerProvider grpcserver.Provider, kinds kind.KindRegistry, resolver resolver.EntityReferenceResolver) entity.EntityStoreServer {
|
||||
entityServer := &sqlEntityServer{
|
||||
sess: db.GetSqlxSession(),
|
||||
log: log.New("sql-object-server"),
|
||||
log: log.New("sql-entity-server"),
|
||||
kinds: kinds,
|
||||
resolver: resolver,
|
||||
}
|
||||
object.RegisterObjectStoreServer(grpcServerProvider.GetServer(), objectServer)
|
||||
return objectServer
|
||||
entity.RegisterEntityStoreServer(grpcServerProvider.GetServer(), entityServer)
|
||||
return entityServer
|
||||
}
|
||||
|
||||
type sqlObjectServer struct {
|
||||
type sqlEntityServer struct {
|
||||
log log.Logger
|
||||
sess *session.SessionDB
|
||||
kinds kind.KindRegistry
|
||||
resolver resolver.ObjectReferenceResolver
|
||||
resolver resolver.EntityReferenceResolver
|
||||
}
|
||||
|
||||
func getReadSelect(r *object.ReadObjectRequest) string {
|
||||
func getReadSelect(r *entity.ReadEntityRequest) string {
|
||||
fields := []string{
|
||||
"tenant_id", "kind", "uid", // The PK
|
||||
"version", "slug", "folder",
|
||||
@ -61,10 +61,10 @@ func getReadSelect(r *object.ReadObjectRequest) string {
|
||||
return "SELECT " + strings.Join(fields, ",") + " FROM entity WHERE "
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) rowToReadObjectResponse(ctx context.Context, rows *sql.Rows, r *object.ReadObjectRequest) (*object.ReadObjectResponse, error) {
|
||||
raw := &object.RawObject{
|
||||
GRN: &object.GRN{},
|
||||
Origin: &object.ObjectOriginInfo{},
|
||||
func (s *sqlEntityServer) rowToReadEntityResponse(ctx context.Context, rows *sql.Rows, r *entity.ReadEntityRequest) (*entity.ReadEntityResponse, error) {
|
||||
raw := &entity.Entity{
|
||||
GRN: &entity.GRN{},
|
||||
Origin: &entity.EntityOriginInfo{},
|
||||
}
|
||||
slug := ""
|
||||
|
||||
@ -93,12 +93,12 @@ func (s *sqlObjectServer) rowToReadObjectResponse(ctx context.Context, rows *sql
|
||||
raw.Origin = nil
|
||||
}
|
||||
|
||||
rsp := &object.ReadObjectResponse{
|
||||
Object: raw,
|
||||
rsp := &entity.ReadEntityResponse{
|
||||
Entity: raw,
|
||||
}
|
||||
|
||||
if r.WithSummary || summaryjson.errors != nil {
|
||||
summary, err := summaryjson.toObjectSummary()
|
||||
summary, err := summaryjson.toEntitySummary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -112,7 +112,7 @@ func (s *sqlObjectServer) rowToReadObjectResponse(ctx context.Context, rows *sql
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) validateGRN(ctx context.Context, grn *object.GRN) (*object.GRN, error) {
|
||||
func (s *sqlEntityServer) validateGRN(ctx context.Context, grn *entity.GRN) (*entity.GRN, error) {
|
||||
if grn == nil {
|
||||
return nil, fmt.Errorf("missing GRN")
|
||||
}
|
||||
@ -138,7 +138,7 @@ func (s *sqlObjectServer) validateGRN(ctx context.Context, grn *object.GRN) (*ob
|
||||
return grn, nil
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) Read(ctx context.Context, r *object.ReadObjectRequest) (*object.ReadObjectResponse, error) {
|
||||
func (s *sqlEntityServer) Read(ctx context.Context, r *entity.ReadEntityRequest) (*entity.ReadEntityResponse, error) {
|
||||
if r.Version != "" {
|
||||
return s.readFromHistory(ctx, r)
|
||||
}
|
||||
@ -157,13 +157,13 @@ func (s *sqlObjectServer) Read(ctx context.Context, r *object.ReadObjectRequest)
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
if !rows.Next() {
|
||||
return &object.ReadObjectResponse{}, nil
|
||||
return &entity.ReadEntityResponse{}, nil
|
||||
}
|
||||
|
||||
return s.rowToReadObjectResponse(ctx, rows, r)
|
||||
return s.rowToReadEntityResponse(ctx, rows, r)
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) readFromHistory(ctx context.Context, r *object.ReadObjectRequest) (*object.ReadObjectResponse, error) {
|
||||
func (s *sqlEntityServer) readFromHistory(ctx context.Context, r *entity.ReadEntityRequest) (*entity.ReadEntityResponse, error) {
|
||||
grn, err := s.validateGRN(ctx, r.GRN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -185,14 +185,14 @@ func (s *sqlObjectServer) readFromHistory(ctx context.Context, r *object.ReadObj
|
||||
|
||||
// Version or key not found
|
||||
if !rows.Next() {
|
||||
return &object.ReadObjectResponse{}, nil
|
||||
return &entity.ReadEntityResponse{}, nil
|
||||
}
|
||||
|
||||
raw := &object.RawObject{
|
||||
raw := &entity.Entity{
|
||||
GRN: r.GRN,
|
||||
}
|
||||
rsp := &object.ReadObjectResponse{
|
||||
Object: raw,
|
||||
rsp := &entity.ReadEntityResponse{
|
||||
Entity: raw,
|
||||
}
|
||||
err = rows.Scan(&raw.Body, &raw.Size, &raw.ETag, &raw.UpdatedAt, &raw.UpdatedBy)
|
||||
if err != nil {
|
||||
@ -220,13 +220,13 @@ func (s *sqlObjectServer) readFromHistory(ctx context.Context, r *object.ReadObj
|
||||
|
||||
// Clear the body if not requested
|
||||
if !r.WithBody {
|
||||
rsp.Object.Body = nil
|
||||
rsp.Entity.Body = nil
|
||||
}
|
||||
|
||||
return rsp, err
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) BatchRead(ctx context.Context, b *object.BatchReadObjectRequest) (*object.BatchReadObjectResponse, error) {
|
||||
func (s *sqlEntityServer) BatchRead(ctx context.Context, b *entity.BatchReadEntityRequest) (*entity.BatchReadEntityResponse, error) {
|
||||
if len(b.Batch) < 1 {
|
||||
return nil, fmt.Errorf("missing querires")
|
||||
}
|
||||
@ -262,9 +262,9 @@ func (s *sqlObjectServer) BatchRead(ctx context.Context, b *object.BatchReadObje
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
// TODO? make sure the results are in order?
|
||||
rsp := &object.BatchReadObjectResponse{}
|
||||
rsp := &entity.BatchReadEntityResponse{}
|
||||
for rows.Next() {
|
||||
r, err := s.rowToReadObjectResponse(ctx, rows, req)
|
||||
r, err := s.rowToReadEntityResponse(ctx, rows, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -273,12 +273,12 @@ func (s *sqlObjectServer) BatchRead(ctx context.Context, b *object.BatchReadObje
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) Write(ctx context.Context, r *object.WriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
return s.AdminWrite(ctx, object.ToAdminWriteObjectRequest(r))
|
||||
func (s *sqlEntityServer) Write(ctx context.Context, r *entity.WriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
return s.AdminWrite(ctx, entity.ToAdminWriteEntityRequest(r))
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (s *sqlObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
func (s *sqlEntityServer) AdminWrite(ctx context.Context, r *entity.AdminWriteEntityRequest) (*entity.WriteEntityResponse, error) {
|
||||
grn, err := s.validateGRN(ctx, r.GRN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -313,17 +313,17 @@ func (s *sqlObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteOb
|
||||
|
||||
slug := slugify.Slugify(t)
|
||||
etag := createContentsHash(body)
|
||||
rsp := &object.WriteObjectResponse{
|
||||
rsp := &entity.WriteEntityResponse{
|
||||
GRN: grn,
|
||||
Status: object.WriteObjectResponse_CREATED, // Will be changed if not true
|
||||
Status: entity.WriteEntityResponse_CREATED, // Will be changed if not true
|
||||
}
|
||||
origin := r.Origin
|
||||
if origin == nil {
|
||||
origin = &object.ObjectOriginInfo{}
|
||||
origin = &entity.EntityOriginInfo{}
|
||||
}
|
||||
|
||||
err = s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error {
|
||||
var versionInfo *object.ObjectVersionInfo
|
||||
var versionInfo *entity.EntityVersionInfo
|
||||
isUpdate := false
|
||||
if r.ClearHistory {
|
||||
// Optionally keep the original creation time information
|
||||
@ -337,7 +337,7 @@ func (s *sqlObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteOb
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
versionInfo = &object.ObjectVersionInfo{}
|
||||
versionInfo = &entity.EntityVersionInfo{}
|
||||
} else {
|
||||
versionInfo, err = s.selectForUpdate(ctx, tx, oid)
|
||||
if err != nil {
|
||||
@ -345,10 +345,10 @@ func (s *sqlObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteOb
|
||||
}
|
||||
}
|
||||
|
||||
// Same object
|
||||
// Same entity
|
||||
if versionInfo.ETag == etag {
|
||||
rsp.Object = versionInfo
|
||||
rsp.Status = object.WriteObjectResponse_UNCHANGED
|
||||
rsp.Entity = versionInfo
|
||||
rsp.Status = entity.WriteEntityResponse_UNCHANGED
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -436,10 +436,10 @@ func (s *sqlObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteOb
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Add/update the main `object` table
|
||||
rsp.Object = versionInfo
|
||||
// 5. Add/update the main `entity` table
|
||||
rsp.Entity = versionInfo
|
||||
if isUpdate {
|
||||
rsp.Status = object.WriteObjectResponse_UPDATED
|
||||
rsp.Status = entity.WriteEntityResponse_UPDATED
|
||||
_, err = tx.Exec(ctx, "UPDATE entity SET "+
|
||||
"body=?, size=?, etag=?, version=?, "+
|
||||
"updated_at=?, updated_by=?,"+
|
||||
@ -488,12 +488,12 @@ func (s *sqlObjectServer) AdminWrite(ctx context.Context, r *object.AdminWriteOb
|
||||
})
|
||||
rsp.SummaryJson = summary.marshaled
|
||||
if err != nil {
|
||||
rsp.Status = object.WriteObjectResponse_ERROR
|
||||
rsp.Status = entity.WriteEntityResponse_ERROR
|
||||
}
|
||||
return rsp, err
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) fillCreationInfo(ctx context.Context, tx *session.SessionTx, grn string, createdAt *int64, createdBy *string) error {
|
||||
func (s *sqlEntityServer) fillCreationInfo(ctx context.Context, tx *session.SessionTx, grn string, createdAt *int64, createdBy *string) error {
|
||||
if *createdAt > 1000 {
|
||||
ignore := int64(0)
|
||||
createdAt = &ignore
|
||||
@ -515,7 +515,7 @@ func (s *sqlObjectServer) fillCreationInfo(ctx context.Context, tx *session.Sess
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) selectForUpdate(ctx context.Context, tx *session.SessionTx, grn string) (*object.ObjectVersionInfo, error) {
|
||||
func (s *sqlEntityServer) selectForUpdate(ctx context.Context, tx *session.SessionTx, grn string) (*entity.EntityVersionInfo, error) {
|
||||
q := "SELECT etag,version,updated_at,size FROM entity WHERE grn=?"
|
||||
if false { // TODO, MYSQL/PosgreSQL can lock the row " FOR UPDATE"
|
||||
q += " FOR UPDATE"
|
||||
@ -524,7 +524,7 @@ func (s *sqlObjectServer) selectForUpdate(ctx context.Context, tx *session.Sessi
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current := &object.ObjectVersionInfo{}
|
||||
current := &entity.EntityVersionInfo{}
|
||||
if rows.Next() {
|
||||
err = rows.Scan(¤t.ETag, ¤t.Version, ¤t.UpdatedAt, ¤t.Size)
|
||||
}
|
||||
@ -534,7 +534,7 @@ func (s *sqlObjectServer) selectForUpdate(ctx context.Context, tx *session.Sessi
|
||||
return current, err
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) prepare(ctx context.Context, r *object.AdminWriteObjectRequest) (*summarySupport, []byte, error) {
|
||||
func (s *sqlEntityServer) prepare(ctx context.Context, r *entity.AdminWriteEntityRequest) (*summarySupport, []byte, error) {
|
||||
grn := r.GRN
|
||||
builder := s.kinds.GetSummaryBuilder(grn.Kind)
|
||||
if builder == nil {
|
||||
@ -553,13 +553,13 @@ func (s *sqlObjectServer) prepare(ctx context.Context, r *object.AdminWriteObjec
|
||||
return summaryjson, body, nil
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) Delete(ctx context.Context, r *object.DeleteObjectRequest) (*object.DeleteObjectResponse, error) {
|
||||
func (s *sqlEntityServer) Delete(ctx context.Context, r *entity.DeleteEntityRequest) (*entity.DeleteEntityResponse, error) {
|
||||
grn, err := s.validateGRN(ctx, r.GRN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rsp := &object.DeleteObjectResponse{}
|
||||
rsp := &entity.DeleteEntityResponse{}
|
||||
err = s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error {
|
||||
rsp.OK, err = doDelete(ctx, tx, grn.ToGRNString())
|
||||
return err
|
||||
@ -584,7 +584,7 @@ func doDelete(ctx context.Context, tx *session.SessionTx, grn string) (bool, err
|
||||
return rows > 0, err
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) History(ctx context.Context, r *object.ObjectHistoryRequest) (*object.ObjectHistoryResponse, error) {
|
||||
func (s *sqlEntityServer) History(ctx context.Context, r *entity.EntityHistoryRequest) (*entity.EntityHistoryResponse, error) {
|
||||
grn, err := s.validateGRN(ctx, r.GRN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -609,11 +609,11 @@ func (s *sqlObjectServer) History(ctx context.Context, r *object.ObjectHistoryRe
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
rsp := &object.ObjectHistoryResponse{
|
||||
rsp := &entity.EntityHistoryResponse{
|
||||
GRN: r.GRN,
|
||||
}
|
||||
for rows.Next() {
|
||||
v := &object.ObjectVersionInfo{}
|
||||
v := &entity.EntityVersionInfo{}
|
||||
err := rows.Scan(&v.Version, &v.Size, &v.ETag, &v.UpdatedAt, &v.UpdatedBy, &v.Comment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -623,7 +623,7 @@ func (s *sqlObjectServer) History(ctx context.Context, r *object.ObjectHistoryRe
|
||||
return rsp, err
|
||||
}
|
||||
|
||||
func (s *sqlObjectServer) Search(ctx context.Context, r *object.ObjectSearchRequest) (*object.ObjectSearchResponse, error) {
|
||||
func (s *sqlEntityServer) Search(ctx context.Context, r *entity.EntitySearchRequest) (*entity.EntitySearchResponse, error) {
|
||||
user := store.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, fmt.Errorf("missing user in context")
|
||||
@ -681,10 +681,10 @@ func (s *sqlObjectServer) Search(ctx context.Context, r *object.ObjectSearchRequ
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
oid := ""
|
||||
rsp := &object.ObjectSearchResponse{}
|
||||
rsp := &entity.EntitySearchResponse{}
|
||||
for rows.Next() {
|
||||
result := &object.ObjectSearchResult{
|
||||
GRN: &object.GRN{},
|
||||
result := &entity.EntitySearchResult{
|
||||
GRN: &entity.GRN{},
|
||||
}
|
||||
summaryjson := summarySupport{}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type summarySupport struct {
|
||||
model *models.ObjectSummary
|
||||
model *models.EntitySummary
|
||||
name string
|
||||
description *string // null or empty
|
||||
labels *string
|
||||
@ -16,7 +16,7 @@ type summarySupport struct {
|
||||
marshaled []byte
|
||||
}
|
||||
|
||||
func newSummarySupport(summary *models.ObjectSummary) (*summarySupport, error) {
|
||||
func newSummarySupport(summary *models.EntitySummary) (*summarySupport, error) {
|
||||
var err error
|
||||
var js []byte
|
||||
s := &summarySupport{
|
||||
@ -63,9 +63,9 @@ func newSummarySupport(summary *models.ObjectSummary) (*summarySupport, error) {
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (s summarySupport) toObjectSummary() (*models.ObjectSummary, error) {
|
||||
func (s summarySupport) toEntitySummary() (*models.EntitySummary, error) {
|
||||
var err error
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Name: s.name,
|
||||
}
|
||||
if s.description != nil {
|
@ -1,4 +1,4 @@
|
||||
package object_server_tests
|
||||
package entity_server_tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,7 +11,7 @@ import (
|
||||
saAPI "github.com/grafana/grafana/pkg/services/serviceaccounts/api"
|
||||
saTests "github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/tests/testinfra"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -53,7 +53,7 @@ func createServiceAccountAdminToken(t *testing.T, env *server.TestEnv) (string,
|
||||
|
||||
type testContext struct {
|
||||
authToken string
|
||||
client object.ObjectStoreClient
|
||||
client entity.EntityStoreClient
|
||||
user *user.SignedInUser
|
||||
ctx context.Context
|
||||
}
|
||||
@ -80,7 +80,7 @@ func createTestContext(t *testing.T) testContext {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
client := object.NewObjectStoreClient(conn)
|
||||
client := entity.NewEntityStoreClient(conn)
|
||||
|
||||
return testContext{
|
||||
authToken: authToken,
|
@ -1,4 +1,4 @@
|
||||
package object_server_tests
|
||||
package entity_server_tests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -9,14 +9,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
type rawObjectMatcher struct {
|
||||
grn *object.GRN
|
||||
type rawEntityMatcher struct {
|
||||
grn *entity.GRN
|
||||
createdRange []time.Time
|
||||
updatedRange []time.Time
|
||||
createdBy string
|
||||
@ -39,7 +39,7 @@ func timestampInRange(ts int64, tsRange []time.Time) bool {
|
||||
return ts >= low && ts <= high
|
||||
}
|
||||
|
||||
func requireObjectMatch(t *testing.T, obj *object.RawObject, m rawObjectMatcher) {
|
||||
func requireEntityMatch(t *testing.T, obj *entity.Entity, m rawEntityMatcher) {
|
||||
t.Helper()
|
||||
require.NotNil(t, obj)
|
||||
|
||||
@ -87,7 +87,7 @@ func requireObjectMatch(t *testing.T, obj *object.RawObject, m rawObjectMatcher)
|
||||
require.True(t, len(mismatches) == 0, mismatches)
|
||||
}
|
||||
|
||||
func requireVersionMatch(t *testing.T, obj *object.ObjectVersionInfo, m objectVersionMatcher) {
|
||||
func requireVersionMatch(t *testing.T, obj *entity.EntityVersionInfo, m objectVersionMatcher) {
|
||||
t.Helper()
|
||||
mismatches := ""
|
||||
|
||||
@ -110,7 +110,7 @@ func requireVersionMatch(t *testing.T, obj *object.ObjectVersionInfo, m objectVe
|
||||
require.True(t, len(mismatches) == 0, mismatches)
|
||||
}
|
||||
|
||||
func TestIntegrationObjectServer(t *testing.T) {
|
||||
func TestIntegrationEntityServer(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
@ -121,25 +121,25 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
fakeUser := store.GetUserIDString(testCtx.user)
|
||||
firstVersion := "1"
|
||||
kind := models.StandardKindJSONObj
|
||||
grn := &object.GRN{
|
||||
grn := &entity.GRN{
|
||||
Kind: kind,
|
||||
UID: "my-test-entity",
|
||||
}
|
||||
body := []byte("{\"name\":\"John\"}")
|
||||
|
||||
t.Run("should not retrieve non-existent objects", func(t *testing.T) {
|
||||
resp, err := testCtx.client.Read(ctx, &object.ReadObjectRequest{
|
||||
resp, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, resp)
|
||||
require.Nil(t, resp.Object)
|
||||
require.Nil(t, resp.Entity)
|
||||
})
|
||||
|
||||
t.Run("should be able to read persisted objects", func(t *testing.T) {
|
||||
before := time.Now()
|
||||
writeReq := &object.WriteObjectRequest{
|
||||
writeReq := &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: body,
|
||||
Comment: "first entity!",
|
||||
@ -153,24 +153,24 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
version: &firstVersion,
|
||||
comment: &writeReq.Comment,
|
||||
}
|
||||
requireVersionMatch(t, writeResp.Object, versionMatcher)
|
||||
requireVersionMatch(t, writeResp.Entity, versionMatcher)
|
||||
|
||||
readResp, err := testCtx.client.Read(ctx, &object.ReadObjectRequest{
|
||||
readResp, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
Version: "",
|
||||
WithBody: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, readResp.SummaryJson)
|
||||
require.NotNil(t, readResp.Object)
|
||||
require.NotNil(t, readResp.Entity)
|
||||
|
||||
foundGRN := readResp.Object.GRN
|
||||
foundGRN := readResp.Entity.GRN
|
||||
require.NotNil(t, foundGRN)
|
||||
require.Equal(t, testCtx.user.OrgID, foundGRN.TenantId) // orgId becomes the tenant id when not set
|
||||
require.Equal(t, grn.Kind, foundGRN.Kind)
|
||||
require.Equal(t, grn.UID, foundGRN.UID)
|
||||
|
||||
objectMatcher := rawObjectMatcher{
|
||||
objectMatcher := rawEntityMatcher{
|
||||
grn: grn,
|
||||
createdRange: []time.Time{before, time.Now()},
|
||||
updatedRange: []time.Time{before, time.Now()},
|
||||
@ -179,97 +179,97 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
body: body,
|
||||
version: &firstVersion,
|
||||
}
|
||||
requireObjectMatch(t, readResp.Object, objectMatcher)
|
||||
requireEntityMatch(t, readResp.Entity, objectMatcher)
|
||||
|
||||
deleteResp, err := testCtx.client.Delete(ctx, &object.DeleteObjectRequest{
|
||||
deleteResp, err := testCtx.client.Delete(ctx, &entity.DeleteEntityRequest{
|
||||
GRN: grn,
|
||||
PreviousVersion: writeResp.Object.Version,
|
||||
PreviousVersion: writeResp.Entity.Version,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.True(t, deleteResp.OK)
|
||||
|
||||
readRespAfterDelete, err := testCtx.client.Read(ctx, &object.ReadObjectRequest{
|
||||
readRespAfterDelete, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
Version: "",
|
||||
WithBody: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, readRespAfterDelete.Object)
|
||||
require.Nil(t, readRespAfterDelete.Entity)
|
||||
})
|
||||
|
||||
t.Run("should be able to update an object", func(t *testing.T) {
|
||||
before := time.Now()
|
||||
grn := &object.GRN{
|
||||
grn := &entity.GRN{
|
||||
Kind: kind,
|
||||
UID: util.GenerateShortUID(),
|
||||
}
|
||||
|
||||
writeReq1 := &object.WriteObjectRequest{
|
||||
writeReq1 := &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: body,
|
||||
Comment: "first entity!",
|
||||
}
|
||||
writeResp1, err := testCtx.client.Write(ctx, writeReq1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, object.WriteObjectResponse_CREATED, writeResp1.Status)
|
||||
require.Equal(t, entity.WriteEntityResponse_CREATED, writeResp1.Status)
|
||||
|
||||
body2 := []byte("{\"name\":\"John2\"}")
|
||||
|
||||
writeReq2 := &object.WriteObjectRequest{
|
||||
writeReq2 := &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: body2,
|
||||
Comment: "update1",
|
||||
}
|
||||
writeResp2, err := testCtx.client.Write(ctx, writeReq2)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, writeResp1.Object.Version, writeResp2.Object.Version)
|
||||
require.NotEqual(t, writeResp1.Entity.Version, writeResp2.Entity.Version)
|
||||
|
||||
// Duplicate write (no change)
|
||||
writeDupRsp, err := testCtx.client.Write(ctx, writeReq2)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, writeDupRsp.Error)
|
||||
require.Equal(t, object.WriteObjectResponse_UNCHANGED, writeDupRsp.Status)
|
||||
require.Equal(t, writeResp2.Object.Version, writeDupRsp.Object.Version)
|
||||
require.Equal(t, writeResp2.Object.ETag, writeDupRsp.Object.ETag)
|
||||
require.Equal(t, entity.WriteEntityResponse_UNCHANGED, writeDupRsp.Status)
|
||||
require.Equal(t, writeResp2.Entity.Version, writeDupRsp.Entity.Version)
|
||||
require.Equal(t, writeResp2.Entity.ETag, writeDupRsp.Entity.ETag)
|
||||
|
||||
body3 := []byte("{\"name\":\"John3\"}")
|
||||
writeReq3 := &object.WriteObjectRequest{
|
||||
writeReq3 := &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: body3,
|
||||
Comment: "update3",
|
||||
}
|
||||
writeResp3, err := testCtx.client.Write(ctx, writeReq3)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, writeResp3.Object.Version, writeResp2.Object.Version)
|
||||
require.NotEqual(t, writeResp3.Entity.Version, writeResp2.Entity.Version)
|
||||
|
||||
latestMatcher := rawObjectMatcher{
|
||||
latestMatcher := rawEntityMatcher{
|
||||
grn: grn,
|
||||
createdRange: []time.Time{before, time.Now()},
|
||||
updatedRange: []time.Time{before, time.Now()},
|
||||
createdBy: fakeUser,
|
||||
updatedBy: fakeUser,
|
||||
body: body3,
|
||||
version: &writeResp3.Object.Version,
|
||||
version: &writeResp3.Entity.Version,
|
||||
}
|
||||
readRespLatest, err := testCtx.client.Read(ctx, &object.ReadObjectRequest{
|
||||
readRespLatest, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
Version: "", // latest
|
||||
WithBody: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, readRespLatest.SummaryJson)
|
||||
requireObjectMatch(t, readRespLatest.Object, latestMatcher)
|
||||
requireEntityMatch(t, readRespLatest.Entity, latestMatcher)
|
||||
|
||||
readRespFirstVer, err := testCtx.client.Read(ctx, &object.ReadObjectRequest{
|
||||
readRespFirstVer, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{
|
||||
GRN: grn,
|
||||
Version: writeResp1.Object.Version,
|
||||
Version: writeResp1.Entity.Version,
|
||||
WithBody: true,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, readRespFirstVer.SummaryJson)
|
||||
require.NotNil(t, readRespFirstVer.Object)
|
||||
requireObjectMatch(t, readRespFirstVer.Object, rawObjectMatcher{
|
||||
require.NotNil(t, readRespFirstVer.Entity)
|
||||
requireEntityMatch(t, readRespFirstVer.Entity, rawEntityMatcher{
|
||||
grn: grn,
|
||||
createdRange: []time.Time{before, time.Now()},
|
||||
updatedRange: []time.Time{before, time.Now()},
|
||||
@ -279,19 +279,19 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
version: &firstVersion,
|
||||
})
|
||||
|
||||
history, err := testCtx.client.History(ctx, &object.ObjectHistoryRequest{
|
||||
history, err := testCtx.client.History(ctx, &entity.EntityHistoryRequest{
|
||||
GRN: grn,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []*object.ObjectVersionInfo{
|
||||
writeResp3.Object,
|
||||
writeResp2.Object,
|
||||
writeResp1.Object,
|
||||
require.Equal(t, []*entity.EntityVersionInfo{
|
||||
writeResp3.Entity,
|
||||
writeResp2.Entity,
|
||||
writeResp1.Entity,
|
||||
}, history.Versions)
|
||||
|
||||
deleteResp, err := testCtx.client.Delete(ctx, &object.DeleteObjectRequest{
|
||||
deleteResp, err := testCtx.client.Delete(ctx, &entity.DeleteEntityRequest{
|
||||
GRN: grn,
|
||||
PreviousVersion: writeResp3.Object.Version,
|
||||
PreviousVersion: writeResp3.Entity.Version,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.True(t, deleteResp.OK)
|
||||
@ -302,14 +302,14 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
uid3 := "uid3"
|
||||
uid4 := "uid4"
|
||||
kind2 := models.StandardKindPlaylist
|
||||
w1, err := testCtx.client.Write(ctx, &object.WriteObjectRequest{
|
||||
w1, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: grn,
|
||||
Body: body,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
w2, err := testCtx.client.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
w2, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: uid2,
|
||||
Kind: kind,
|
||||
},
|
||||
@ -317,8 +317,8 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
w3, err := testCtx.client.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
w3, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: uid3,
|
||||
Kind: kind2,
|
||||
},
|
||||
@ -326,8 +326,8 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
w4, err := testCtx.client.Write(ctx, &object.WriteObjectRequest{
|
||||
GRN: &object.GRN{
|
||||
w4, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{
|
||||
GRN: &entity.GRN{
|
||||
UID: uid4,
|
||||
Kind: kind2,
|
||||
},
|
||||
@ -335,7 +335,7 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
search, err := testCtx.client.Search(ctx, &object.ObjectSearchRequest{
|
||||
search, err := testCtx.client.Search(ctx, &entity.EntitySearchRequest{
|
||||
Kind: []string{kind, kind2},
|
||||
WithBody: false,
|
||||
})
|
||||
@ -353,14 +353,14 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
require.Equal(t, []string{"my-test-entity", "uid2", "uid3", "uid4"}, uids)
|
||||
require.Equal(t, []string{"jsonobj", "jsonobj", "playlist", "playlist"}, kinds)
|
||||
require.Equal(t, []string{
|
||||
w1.Object.Version,
|
||||
w2.Object.Version,
|
||||
w3.Object.Version,
|
||||
w4.Object.Version,
|
||||
w1.Entity.Version,
|
||||
w2.Entity.Version,
|
||||
w3.Entity.Version,
|
||||
w4.Entity.Version,
|
||||
}, version)
|
||||
|
||||
// Again with only one kind
|
||||
searchKind1, err := testCtx.client.Search(ctx, &object.ObjectSearchRequest{
|
||||
searchKind1, err := testCtx.client.Search(ctx, &entity.EntitySearchRequest{
|
||||
Kind: []string{kind},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -375,8 +375,8 @@ func TestIntegrationObjectServer(t *testing.T) {
|
||||
require.Equal(t, []string{"my-test-entity", "uid2"}, uids)
|
||||
require.Equal(t, []string{"jsonobj", "jsonobj"}, kinds)
|
||||
require.Equal(t, []string{
|
||||
w1.Object.Version,
|
||||
w2.Object.Version,
|
||||
w1.Entity.Version,
|
||||
w2.Entity.Version,
|
||||
}, version)
|
||||
})
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package object
|
||||
package entity
|
||||
|
||||
// The admin request is a superset of write request features
|
||||
func ToAdminWriteObjectRequest(req *WriteObjectRequest) *AdminWriteObjectRequest {
|
||||
return &AdminWriteObjectRequest{
|
||||
func ToAdminWriteEntityRequest(req *WriteEntityRequest) *AdminWriteEntityRequest {
|
||||
return &AdminWriteEntityRequest{
|
||||
GRN: req.GRN,
|
||||
Body: req.Body,
|
||||
Folder: req.Folder,
|
@ -13,24 +13,24 @@ type ReferenceAccumulator interface {
|
||||
Add(kind string, subtype string, uid string)
|
||||
|
||||
// Returns the set of distinct references in a sorted order
|
||||
Get() []*models.ObjectExternalReference
|
||||
Get() []*models.EntityExternalReference
|
||||
}
|
||||
|
||||
func NewReferenceAccumulator() ReferenceAccumulator {
|
||||
return &referenceAccumulator{
|
||||
refs: make(map[string]*models.ObjectExternalReference),
|
||||
refs: make(map[string]*models.EntityExternalReference),
|
||||
}
|
||||
}
|
||||
|
||||
type referenceAccumulator struct {
|
||||
refs map[string]*models.ObjectExternalReference
|
||||
refs map[string]*models.EntityExternalReference
|
||||
}
|
||||
|
||||
func (x *referenceAccumulator) Add(kind string, sub string, uid string) {
|
||||
key := fmt.Sprintf("%s/%s/%s", kind, sub, uid)
|
||||
_, ok := x.refs[key]
|
||||
if !ok {
|
||||
x.refs[key] = &models.ObjectExternalReference{
|
||||
x.refs[key] = &models.EntityExternalReference{
|
||||
Kind: kind,
|
||||
Type: sub,
|
||||
UID: uid,
|
||||
@ -38,14 +38,14 @@ func (x *referenceAccumulator) Add(kind string, sub string, uid string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (x *referenceAccumulator) Get() []*models.ObjectExternalReference {
|
||||
func (x *referenceAccumulator) Get() []*models.EntityExternalReference {
|
||||
keys := make([]string, 0, len(x.refs))
|
||||
for k := range x.refs {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
refs := make([]*models.ObjectExternalReference, len(keys))
|
||||
refs := make([]*models.EntityExternalReference, len(keys))
|
||||
for i, key := range keys {
|
||||
refs[i] = x.refs[key]
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindDashboard,
|
||||
Name: "Dashboard",
|
||||
Description: "Define a grafana dashboard layout",
|
||||
@ -21,16 +21,16 @@ func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
}
|
||||
|
||||
// This summary does not resolve old name as UID
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
builder := NewStaticDashboardSummaryBuilder(&directLookup{}, true)
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
return builder(ctx, uid, body)
|
||||
}
|
||||
}
|
||||
|
||||
// This implementation moves datasources referenced by internal ID or name to UID
|
||||
func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup, sanitize bool) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup, sanitize bool) models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
var parsed map[string]interface{}
|
||||
|
||||
if sanitize {
|
||||
@ -44,14 +44,14 @@ func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup, sanitize bool) mo
|
||||
// slug? (derived from title)
|
||||
}
|
||||
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Labels: make(map[string]string),
|
||||
Fields: make(map[string]interface{}),
|
||||
}
|
||||
stream := bytes.NewBuffer(body)
|
||||
dash, err := readDashboard(stream, lookup)
|
||||
if err != nil {
|
||||
summary.Error = &models.ObjectErrorInfo{
|
||||
summary.Error = &models.EntityErrorInfo{
|
||||
Message: err.Error(),
|
||||
}
|
||||
return summary, body, err
|
||||
@ -72,7 +72,7 @@ func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup, sanitize bool) mo
|
||||
|
||||
for _, panel := range dash.Panels {
|
||||
panelRefs := NewReferenceAccumulator()
|
||||
p := &models.ObjectSummary{
|
||||
p := &models.EntitySummary{
|
||||
UID: uid + "#" + strconv.FormatInt(panel.ID, 10),
|
||||
Kind: "panel",
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ func TestReadSummaries(t *testing.T) {
|
||||
devdash := "../../../../../devenv/dev-dashboards/panel-graph/"
|
||||
|
||||
ctx := context.Background()
|
||||
reader := GetObjectSummaryBuilder()
|
||||
reader := GetEntitySummaryBuilder()
|
||||
failed := make([]string, 0, 10)
|
||||
|
||||
err := filepath.Walk(devdash,
|
||||
|
@ -9,16 +9,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindDataFrame,
|
||||
Name: "Data frame",
|
||||
Description: "Data frame",
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
df := &data.Frame{}
|
||||
err := json.Unmarshal(body, df)
|
||||
if err != nil {
|
||||
@ -33,7 +33,7 @@ func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Kind: models.StandardKindDataFrame,
|
||||
Name: df.Name,
|
||||
UID: uid,
|
||||
|
@ -23,7 +23,7 @@ func TestDataFrameSummary(t *testing.T) {
|
||||
in, err := data.FrameToJSON(df, data.IncludeAll)
|
||||
require.NoError(t, err)
|
||||
|
||||
summary, out, err := GetObjectSummaryBuilder()(context.Background(), "somthing", in)
|
||||
summary, out, err := GetEntitySummaryBuilder()(context.Background(), "somthing", in)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, in, out) // same json
|
||||
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo(kind string) models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo(kind string) models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: kind,
|
||||
Name: kind,
|
||||
Description: "Dummy kind used for testing.",
|
||||
@ -17,9 +17,9 @@ func GetObjectKindInfo(kind string) models.ObjectKindInfo {
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder(kind string) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
summary := &models.ObjectSummary{
|
||||
func GetEntitySummaryBuilder(kind string) models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
summary := &models.EntitySummary{
|
||||
Name: fmt.Sprintf("Dummy: %s", kind),
|
||||
Kind: kind,
|
||||
Description: fmt.Sprintf("Wrote at %s", time.Now().Local().String()),
|
||||
@ -35,7 +35,7 @@ func GetObjectSummaryBuilder(kind string) models.ObjectSummaryBuilder {
|
||||
},
|
||||
Error: nil, // ignore for now
|
||||
Nested: nil, // ignore for now
|
||||
References: []*models.ObjectExternalReference{
|
||||
References: []*models.EntityExternalReference{
|
||||
{
|
||||
Kind: "ds",
|
||||
Type: "influx",
|
||||
|
@ -13,15 +13,15 @@ type Model struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindFolder,
|
||||
Name: "Folder",
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
obj := &Model{}
|
||||
err := json.Unmarshal(body, obj)
|
||||
if err != nil {
|
||||
@ -32,7 +32,7 @@ func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
obj.Name = store.GuessNameFromUID(uid)
|
||||
}
|
||||
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Kind: models.StandardKindFolder,
|
||||
Name: obj.Name,
|
||||
Description: obj.Description,
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindGeoJSON,
|
||||
Name: "GeoJSON",
|
||||
Description: "JSON formatted spatial data",
|
||||
@ -20,8 +20,8 @@ func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
}
|
||||
|
||||
// Very basic geojson validator
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
var geojson map[string]interface{}
|
||||
err := json.Unmarshal(body, &geojson)
|
||||
if err != nil {
|
||||
@ -38,7 +38,7 @@ func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Kind: models.StandardKindGeoJSON,
|
||||
Name: store.GuessNameFromUID(uid),
|
||||
UID: uid,
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestGeoJSONSummary(t *testing.T) {
|
||||
builder := GetObjectSummaryBuilder()
|
||||
builder := GetEntitySummaryBuilder()
|
||||
geo := []byte(`{"type":"FeatureCo`) // invalid
|
||||
_, _, err := builder(context.Background(), "hello", geo)
|
||||
require.Error(t, err)
|
||||
|
@ -8,16 +8,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindJSONObj,
|
||||
Name: "JSON Object",
|
||||
Description: "JSON Object",
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
v := make(map[string]interface{})
|
||||
err := json.Unmarshal(body, &v)
|
||||
if err != nil {
|
||||
@ -28,7 +28,7 @@ func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &models.ObjectSummary{
|
||||
return &models.EntitySummary{
|
||||
Kind: models.StandardKindJSONObj,
|
||||
Name: store.GuessNameFromUID(uid),
|
||||
UID: uid,
|
||||
|
@ -23,7 +23,7 @@ func TestDataFrameSummary(t *testing.T) {
|
||||
in, err := data.FrameToJSON(df, data.IncludeAll)
|
||||
require.NoError(t, err)
|
||||
|
||||
summary, out, err := GetObjectSummaryBuilder()(context.Background(), "path/to/item", in)
|
||||
summary, out, err := GetEntitySummaryBuilder()(context.Background(), "path/to/item", in)
|
||||
require.NoError(t, err)
|
||||
require.JSONEq(t, string(in), string(out)) // same json
|
||||
|
||||
|
@ -9,19 +9,19 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindPlaylist,
|
||||
Name: "Playlist",
|
||||
Description: "Cycle though a collection of dashboards automatically",
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return summaryBuilder
|
||||
}
|
||||
|
||||
func summaryBuilder(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func summaryBuilder(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
obj := &playlist.Playlist{}
|
||||
err := json.Unmarshal(body, obj)
|
||||
if err != nil {
|
||||
@ -35,7 +35,7 @@ func summaryBuilder(ctx context.Context, uid string, body []byte) (*models.Objec
|
||||
}
|
||||
|
||||
obj.Uid = uid // make sure they are consistent
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
UID: uid,
|
||||
Name: obj.Name,
|
||||
Description: fmt.Sprintf("%d items, refreshed every %s", len(*obj.Items), obj.Interval),
|
||||
@ -44,7 +44,7 @@ func summaryBuilder(ctx context.Context, uid string, body []byte) (*models.Objec
|
||||
for _, item := range *obj.Items {
|
||||
switch item.Type {
|
||||
case playlist.PlaylistItemTypeDashboardByUid:
|
||||
summary.References = append(summary.References, &models.ObjectExternalReference{
|
||||
summary.References = append(summary.References, &models.EntityExternalReference{
|
||||
Kind: "dashboard",
|
||||
UID: item.Value,
|
||||
})
|
||||
@ -57,7 +57,7 @@ func summaryBuilder(ctx context.Context, uid string, body []byte) (*models.Objec
|
||||
|
||||
case playlist.PlaylistItemTypeDashboardById:
|
||||
// obviously insufficient long term... but good to have an example :)
|
||||
summary.Error = &models.ObjectErrorInfo{
|
||||
summary.Error = &models.EntityErrorInfo{
|
||||
Message: "Playlist uses deprecated internal id system",
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestPlaylistSummary(t *testing.T) {
|
||||
builder := GetObjectSummaryBuilder()
|
||||
builder := GetEntitySummaryBuilder()
|
||||
|
||||
// Do not parse invalid input
|
||||
_, _, err := builder(context.Background(), "abc", []byte("{invalid json"))
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindPNG,
|
||||
Name: "PNG",
|
||||
Description: "PNG Image file",
|
||||
@ -21,15 +21,15 @@ func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
}
|
||||
|
||||
// SVG sanitizer based on the rendering service
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
img, err := png.Decode(bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
size := img.Bounds().Size()
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Kind: models.StandardKindSVG,
|
||||
Name: store.GuessNameFromUID(uid),
|
||||
UID: uid,
|
||||
|
@ -14,7 +14,7 @@ func TestPNGSummary(t *testing.T) {
|
||||
img, err := base64.StdEncoding.DecodeString(gopher)
|
||||
require.NoError(t, err)
|
||||
|
||||
summary, out, err := GetObjectSummaryBuilder()(context.Background(), "hello.png", img)
|
||||
summary, out, err := GetEntitySummaryBuilder()(context.Background(), "hello.png", img)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, img, out) // same image
|
||||
|
||||
|
@ -20,46 +20,46 @@ import (
|
||||
)
|
||||
|
||||
type KindRegistry interface {
|
||||
Register(info models.ObjectKindInfo, builder models.ObjectSummaryBuilder) error
|
||||
GetSummaryBuilder(kind string) models.ObjectSummaryBuilder
|
||||
GetInfo(kind string) (models.ObjectKindInfo, error)
|
||||
GetFromExtension(suffix string) (models.ObjectKindInfo, error)
|
||||
GetKinds() []models.ObjectKindInfo
|
||||
Register(info models.EntityKindInfo, builder models.EntitySummaryBuilder) error
|
||||
GetSummaryBuilder(kind string) models.EntitySummaryBuilder
|
||||
GetInfo(kind string) (models.EntityKindInfo, error)
|
||||
GetFromExtension(suffix string) (models.EntityKindInfo, error)
|
||||
GetKinds() []models.EntityKindInfo
|
||||
}
|
||||
|
||||
func NewKindRegistry() KindRegistry {
|
||||
kinds := make(map[string]*kindValues)
|
||||
kinds[models.StandardKindPlaylist] = &kindValues{
|
||||
info: playlist.GetObjectKindInfo(),
|
||||
builder: playlist.GetObjectSummaryBuilder(),
|
||||
info: playlist.GetEntityKindInfo(),
|
||||
builder: playlist.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindDashboard] = &kindValues{
|
||||
info: dashboard.GetObjectKindInfo(),
|
||||
builder: dashboard.GetObjectSummaryBuilder(),
|
||||
info: dashboard.GetEntityKindInfo(),
|
||||
builder: dashboard.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindSnapshot] = &kindValues{
|
||||
info: snapshot.GetObjectKindInfo(),
|
||||
builder: snapshot.GetObjectSummaryBuilder(),
|
||||
info: snapshot.GetEntityKindInfo(),
|
||||
builder: snapshot.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindFolder] = &kindValues{
|
||||
info: folder.GetObjectKindInfo(),
|
||||
builder: folder.GetObjectSummaryBuilder(),
|
||||
info: folder.GetEntityKindInfo(),
|
||||
builder: folder.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindPNG] = &kindValues{
|
||||
info: png.GetObjectKindInfo(),
|
||||
builder: png.GetObjectSummaryBuilder(),
|
||||
info: png.GetEntityKindInfo(),
|
||||
builder: png.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindGeoJSON] = &kindValues{
|
||||
info: geojson.GetObjectKindInfo(),
|
||||
builder: geojson.GetObjectSummaryBuilder(),
|
||||
info: geojson.GetEntityKindInfo(),
|
||||
builder: geojson.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindDataFrame] = &kindValues{
|
||||
info: dataframe.GetObjectKindInfo(),
|
||||
builder: dataframe.GetObjectSummaryBuilder(),
|
||||
info: dataframe.GetEntityKindInfo(),
|
||||
builder: dataframe.GetEntitySummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindJSONObj] = &kindValues{
|
||||
info: jsonobj.GetObjectKindInfo(),
|
||||
builder: jsonobj.GetObjectSummaryBuilder(),
|
||||
info: jsonobj.GetEntityKindInfo(),
|
||||
builder: jsonobj.GetEntitySummaryBuilder(),
|
||||
}
|
||||
|
||||
// create a registry
|
||||
@ -77,29 +77,29 @@ func ProvideService(cfg *setting.Cfg, renderer rendering.Service) KindRegistry {
|
||||
|
||||
// Register SVG support
|
||||
//-----------------------
|
||||
info := svg.GetObjectKindInfo()
|
||||
info := svg.GetEntityKindInfo()
|
||||
allowUnsanitizedSvgUpload := cfg != nil && cfg.Storage.AllowUnsanitizedSvgUpload
|
||||
support := svg.GetObjectSummaryBuilder(allowUnsanitizedSvgUpload, renderer)
|
||||
support := svg.GetEntitySummaryBuilder(allowUnsanitizedSvgUpload, renderer)
|
||||
_ = reg.Register(info, support)
|
||||
|
||||
return reg
|
||||
}
|
||||
|
||||
type kindValues struct {
|
||||
info models.ObjectKindInfo
|
||||
builder models.ObjectSummaryBuilder
|
||||
info models.EntityKindInfo
|
||||
builder models.EntitySummaryBuilder
|
||||
}
|
||||
|
||||
type registry struct {
|
||||
mutex sync.RWMutex
|
||||
kinds map[string]*kindValues
|
||||
info []models.ObjectKindInfo
|
||||
suffix map[string]models.ObjectKindInfo
|
||||
info []models.EntityKindInfo
|
||||
suffix map[string]models.EntityKindInfo
|
||||
}
|
||||
|
||||
func (r *registry) updateInfoArray() {
|
||||
suffix := make(map[string]models.ObjectKindInfo)
|
||||
info := make([]models.ObjectKindInfo, 0, len(r.kinds))
|
||||
suffix := make(map[string]models.EntityKindInfo)
|
||||
info := make([]models.EntityKindInfo, 0, len(r.kinds))
|
||||
for _, v := range r.kinds {
|
||||
info = append(info, v.info)
|
||||
if v.info.FileExtension != "" {
|
||||
@ -113,7 +113,7 @@ func (r *registry) updateInfoArray() {
|
||||
r.suffix = suffix
|
||||
}
|
||||
|
||||
func (r *registry) Register(info models.ObjectKindInfo, builder models.ObjectSummaryBuilder) error {
|
||||
func (r *registry) Register(info models.EntityKindInfo, builder models.EntitySummaryBuilder) error {
|
||||
if info.ID == "" || builder == nil {
|
||||
return fmt.Errorf("invalid kind")
|
||||
}
|
||||
@ -134,7 +134,7 @@ func (r *registry) Register(info models.ObjectKindInfo, builder models.ObjectSum
|
||||
}
|
||||
|
||||
// GetSummaryBuilder returns a builder or nil if not found
|
||||
func (r *registry) GetSummaryBuilder(kind string) models.ObjectSummaryBuilder {
|
||||
func (r *registry) GetSummaryBuilder(kind string) models.EntitySummaryBuilder {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
@ -146,7 +146,7 @@ func (r *registry) GetSummaryBuilder(kind string) models.ObjectSummaryBuilder {
|
||||
}
|
||||
|
||||
// GetInfo returns the registered info
|
||||
func (r *registry) GetInfo(kind string) (models.ObjectKindInfo, error) {
|
||||
func (r *registry) GetInfo(kind string) (models.EntityKindInfo, error) {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
@ -154,11 +154,11 @@ func (r *registry) GetInfo(kind string) (models.ObjectKindInfo, error) {
|
||||
if ok {
|
||||
return v.info, nil
|
||||
}
|
||||
return models.ObjectKindInfo{}, fmt.Errorf("not found")
|
||||
return models.EntityKindInfo{}, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
// GetInfo returns the registered info
|
||||
func (r *registry) GetFromExtension(suffix string) (models.ObjectKindInfo, error) {
|
||||
func (r *registry) GetFromExtension(suffix string) (models.EntityKindInfo, error) {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
@ -166,11 +166,11 @@ func (r *registry) GetFromExtension(suffix string) (models.ObjectKindInfo, error
|
||||
if ok {
|
||||
return v, nil
|
||||
}
|
||||
return models.ObjectKindInfo{}, fmt.Errorf("not found")
|
||||
return models.EntityKindInfo{}, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
// GetSummaryBuilder returns a builder or nil if not found
|
||||
func (r *registry) GetKinds() []models.ObjectKindInfo {
|
||||
func (r *registry) GetKinds() []models.EntityKindInfo {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
func TestKindRegistry(t *testing.T) {
|
||||
registry := NewKindRegistry()
|
||||
err := registry.Register(dummy.GetObjectKindInfo("test"), dummy.GetObjectSummaryBuilder("test"))
|
||||
err := registry.Register(dummy.GetEntityKindInfo("test"), dummy.GetEntitySummaryBuilder("test"))
|
||||
require.NoError(t, err)
|
||||
|
||||
ids := []string{}
|
||||
|
@ -19,15 +19,15 @@ type Model struct {
|
||||
Snapshot json.RawMessage `json:"snapshot,omitempty"`
|
||||
}
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindSnapshot,
|
||||
Name: "Snapshot",
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder() models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
obj := &Model{}
|
||||
err := json.Unmarshal(body, obj)
|
||||
if err != nil {
|
||||
@ -41,7 +41,7 @@ func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return nil, nil, fmt.Errorf("expected delete key")
|
||||
}
|
||||
|
||||
summary := &models.ObjectSummary{
|
||||
summary := &models.EntitySummary{
|
||||
Kind: models.StandardKindFolder,
|
||||
Name: obj.Name,
|
||||
Description: obj.Description,
|
||||
@ -51,7 +51,7 @@ func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
"externalURL": obj.ExternalURL,
|
||||
"expires": obj.Expires,
|
||||
},
|
||||
References: []*models.ObjectExternalReference{
|
||||
References: []*models.EntityExternalReference{
|
||||
{Kind: models.StandardKindDashboard, UID: obj.DashboardUID},
|
||||
},
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
func GetEntityKindInfo() models.EntityKindInfo {
|
||||
return models.EntityKindInfo{
|
||||
ID: models.StandardKindSVG,
|
||||
Name: "SVG",
|
||||
Description: "Scalable Vector Graphics",
|
||||
@ -21,8 +21,8 @@ func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
}
|
||||
|
||||
// SVG sanitizer based on the rendering service
|
||||
func GetObjectSummaryBuilder(allowUnsanitizedSvgUpload bool, renderer rendering.Service) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
func GetEntitySummaryBuilder(allowUnsanitizedSvgUpload bool, renderer rendering.Service) models.EntitySummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.EntitySummary, []byte, error) {
|
||||
if !IsSVG(body) {
|
||||
return nil, nil, fmt.Errorf("invalid svg")
|
||||
}
|
||||
@ -45,7 +45,7 @@ func GetObjectSummaryBuilder(allowUnsanitizedSvgUpload bool, renderer rendering.
|
||||
sanitized = body
|
||||
}
|
||||
|
||||
return &models.ObjectSummary{
|
||||
return &models.EntitySummary{
|
||||
Kind: models.StandardKindSVG,
|
||||
Name: guessNameFromUID(uid),
|
||||
UID: uid,
|
||||
|
@ -1,46 +0,0 @@
|
||||
package objectdummyserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/store/object"
|
||||
)
|
||||
|
||||
// Make sure we implement both store + admin
|
||||
var _ object.ObjectStoreServer = &fakeObjectStore{}
|
||||
var _ object.ObjectStoreAdminServer = &fakeObjectStore{}
|
||||
|
||||
func ProvideFakeObjectServer() object.ObjectStoreServer {
|
||||
return &fakeObjectStore{}
|
||||
}
|
||||
|
||||
type fakeObjectStore struct{}
|
||||
|
||||
func (i fakeObjectStore) AdminWrite(ctx context.Context, r *object.AdminWriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeObjectStore) Write(ctx context.Context, r *object.WriteObjectRequest) (*object.WriteObjectResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeObjectStore) Read(ctx context.Context, r *object.ReadObjectRequest) (*object.ReadObjectResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeObjectStore) BatchRead(ctx context.Context, batchR *object.BatchReadObjectRequest) (*object.BatchReadObjectResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeObjectStore) Delete(ctx context.Context, r *object.DeleteObjectRequest) (*object.DeleteObjectResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeObjectStore) History(ctx context.Context, r *object.ObjectHistoryRequest) (*object.ObjectHistoryResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (i fakeObjectStore) Search(ctx context.Context, r *object.ObjectSearchRequest) (*object.ObjectSearchResponse, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,405 +0,0 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.21.9
|
||||
// source: object.proto
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// ObjectStoreClient is the client API for ObjectStore service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ObjectStoreClient interface {
|
||||
Read(ctx context.Context, in *ReadObjectRequest, opts ...grpc.CallOption) (*ReadObjectResponse, error)
|
||||
BatchRead(ctx context.Context, in *BatchReadObjectRequest, opts ...grpc.CallOption) (*BatchReadObjectResponse, error)
|
||||
Write(ctx context.Context, in *WriteObjectRequest, opts ...grpc.CallOption) (*WriteObjectResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteObjectRequest, opts ...grpc.CallOption) (*DeleteObjectResponse, error)
|
||||
History(ctx context.Context, in *ObjectHistoryRequest, opts ...grpc.CallOption) (*ObjectHistoryResponse, error)
|
||||
Search(ctx context.Context, in *ObjectSearchRequest, opts ...grpc.CallOption) (*ObjectSearchResponse, error)
|
||||
// TEMPORARY... while we split this into a new service (see below)
|
||||
AdminWrite(ctx context.Context, in *AdminWriteObjectRequest, opts ...grpc.CallOption) (*WriteObjectResponse, error)
|
||||
}
|
||||
|
||||
type objectStoreClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewObjectStoreClient(cc grpc.ClientConnInterface) ObjectStoreClient {
|
||||
return &objectStoreClient{cc}
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) Read(ctx context.Context, in *ReadObjectRequest, opts ...grpc.CallOption) (*ReadObjectResponse, error) {
|
||||
out := new(ReadObjectResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/Read", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) BatchRead(ctx context.Context, in *BatchReadObjectRequest, opts ...grpc.CallOption) (*BatchReadObjectResponse, error) {
|
||||
out := new(BatchReadObjectResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/BatchRead", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) Write(ctx context.Context, in *WriteObjectRequest, opts ...grpc.CallOption) (*WriteObjectResponse, error) {
|
||||
out := new(WriteObjectResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/Write", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) Delete(ctx context.Context, in *DeleteObjectRequest, opts ...grpc.CallOption) (*DeleteObjectResponse, error) {
|
||||
out := new(DeleteObjectResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/Delete", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) History(ctx context.Context, in *ObjectHistoryRequest, opts ...grpc.CallOption) (*ObjectHistoryResponse, error) {
|
||||
out := new(ObjectHistoryResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/History", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) Search(ctx context.Context, in *ObjectSearchRequest, opts ...grpc.CallOption) (*ObjectSearchResponse, error) {
|
||||
out := new(ObjectSearchResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/Search", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *objectStoreClient) AdminWrite(ctx context.Context, in *AdminWriteObjectRequest, opts ...grpc.CallOption) (*WriteObjectResponse, error) {
|
||||
out := new(WriteObjectResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStore/AdminWrite", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ObjectStoreServer is the server API for ObjectStore service.
|
||||
// All implementations should embed UnimplementedObjectStoreServer
|
||||
// for forward compatibility
|
||||
type ObjectStoreServer interface {
|
||||
Read(context.Context, *ReadObjectRequest) (*ReadObjectResponse, error)
|
||||
BatchRead(context.Context, *BatchReadObjectRequest) (*BatchReadObjectResponse, error)
|
||||
Write(context.Context, *WriteObjectRequest) (*WriteObjectResponse, error)
|
||||
Delete(context.Context, *DeleteObjectRequest) (*DeleteObjectResponse, error)
|
||||
History(context.Context, *ObjectHistoryRequest) (*ObjectHistoryResponse, error)
|
||||
Search(context.Context, *ObjectSearchRequest) (*ObjectSearchResponse, error)
|
||||
// TEMPORARY... while we split this into a new service (see below)
|
||||
AdminWrite(context.Context, *AdminWriteObjectRequest) (*WriteObjectResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedObjectStoreServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedObjectStoreServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedObjectStoreServer) Read(context.Context, *ReadObjectRequest) (*ReadObjectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Read not implemented")
|
||||
}
|
||||
func (UnimplementedObjectStoreServer) BatchRead(context.Context, *BatchReadObjectRequest) (*BatchReadObjectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BatchRead not implemented")
|
||||
}
|
||||
func (UnimplementedObjectStoreServer) Write(context.Context, *WriteObjectRequest) (*WriteObjectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Write not implemented")
|
||||
}
|
||||
func (UnimplementedObjectStoreServer) Delete(context.Context, *DeleteObjectRequest) (*DeleteObjectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
||||
}
|
||||
func (UnimplementedObjectStoreServer) History(context.Context, *ObjectHistoryRequest) (*ObjectHistoryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method History not implemented")
|
||||
}
|
||||
func (UnimplementedObjectStoreServer) Search(context.Context, *ObjectSearchRequest) (*ObjectSearchResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Search not implemented")
|
||||
}
|
||||
func (UnimplementedObjectStoreServer) AdminWrite(context.Context, *AdminWriteObjectRequest) (*WriteObjectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminWrite not implemented")
|
||||
}
|
||||
|
||||
// UnsafeObjectStoreServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ObjectStoreServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeObjectStoreServer interface {
|
||||
mustEmbedUnimplementedObjectStoreServer()
|
||||
}
|
||||
|
||||
func RegisterObjectStoreServer(s grpc.ServiceRegistrar, srv ObjectStoreServer) {
|
||||
s.RegisterService(&ObjectStore_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ObjectStore_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReadObjectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).Read(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/Read",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).Read(ctx, req.(*ReadObjectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ObjectStore_BatchRead_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(BatchReadObjectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).BatchRead(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/BatchRead",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).BatchRead(ctx, req.(*BatchReadObjectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ObjectStore_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(WriteObjectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).Write(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/Write",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).Write(ctx, req.(*WriteObjectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ObjectStore_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteObjectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).Delete(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/Delete",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).Delete(ctx, req.(*DeleteObjectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ObjectStore_History_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ObjectHistoryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).History(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/History",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).History(ctx, req.(*ObjectHistoryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ObjectStore_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ObjectSearchRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).Search(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/Search",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).Search(ctx, req.(*ObjectSearchRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ObjectStore_AdminWrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminWriteObjectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreServer).AdminWrite(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStore/AdminWrite",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreServer).AdminWrite(ctx, req.(*AdminWriteObjectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ObjectStore_ServiceDesc is the grpc.ServiceDesc for ObjectStore service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ObjectStore_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "object.ObjectStore",
|
||||
HandlerType: (*ObjectStoreServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Read",
|
||||
Handler: _ObjectStore_Read_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "BatchRead",
|
||||
Handler: _ObjectStore_BatchRead_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Write",
|
||||
Handler: _ObjectStore_Write_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Delete",
|
||||
Handler: _ObjectStore_Delete_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "History",
|
||||
Handler: _ObjectStore_History_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Search",
|
||||
Handler: _ObjectStore_Search_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AdminWrite",
|
||||
Handler: _ObjectStore_AdminWrite_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "object.proto",
|
||||
}
|
||||
|
||||
// ObjectStoreAdminClient is the client API for ObjectStoreAdmin service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ObjectStoreAdminClient interface {
|
||||
AdminWrite(ctx context.Context, in *AdminWriteObjectRequest, opts ...grpc.CallOption) (*WriteObjectResponse, error)
|
||||
}
|
||||
|
||||
type objectStoreAdminClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewObjectStoreAdminClient(cc grpc.ClientConnInterface) ObjectStoreAdminClient {
|
||||
return &objectStoreAdminClient{cc}
|
||||
}
|
||||
|
||||
func (c *objectStoreAdminClient) AdminWrite(ctx context.Context, in *AdminWriteObjectRequest, opts ...grpc.CallOption) (*WriteObjectResponse, error) {
|
||||
out := new(WriteObjectResponse)
|
||||
err := c.cc.Invoke(ctx, "/object.ObjectStoreAdmin/AdminWrite", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ObjectStoreAdminServer is the server API for ObjectStoreAdmin service.
|
||||
// All implementations should embed UnimplementedObjectStoreAdminServer
|
||||
// for forward compatibility
|
||||
type ObjectStoreAdminServer interface {
|
||||
AdminWrite(context.Context, *AdminWriteObjectRequest) (*WriteObjectResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedObjectStoreAdminServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedObjectStoreAdminServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedObjectStoreAdminServer) AdminWrite(context.Context, *AdminWriteObjectRequest) (*WriteObjectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminWrite not implemented")
|
||||
}
|
||||
|
||||
// UnsafeObjectStoreAdminServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ObjectStoreAdminServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeObjectStoreAdminServer interface {
|
||||
mustEmbedUnimplementedObjectStoreAdminServer()
|
||||
}
|
||||
|
||||
func RegisterObjectStoreAdminServer(s grpc.ServiceRegistrar, srv ObjectStoreAdminServer) {
|
||||
s.RegisterService(&ObjectStoreAdmin_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ObjectStoreAdmin_AdminWrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminWriteObjectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ObjectStoreAdminServer).AdminWrite(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/object.ObjectStoreAdmin/AdminWrite",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ObjectStoreAdminServer).AdminWrite(ctx, req.(*AdminWriteObjectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ObjectStoreAdmin_ServiceDesc is the grpc.ServiceDesc for ObjectStoreAdmin service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ObjectStoreAdmin_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "object.ObjectStoreAdmin",
|
||||
HandlerType: (*ObjectStoreAdminServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "AdminWrite",
|
||||
Handler: _ObjectStoreAdmin_AdminWrite_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "object.proto",
|
||||
}
|
@ -27,11 +27,11 @@ type ResolutionInfo struct {
|
||||
Timestamp time.Time `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type ObjectReferenceResolver interface {
|
||||
Resolve(ctx context.Context, ref *models.ObjectExternalReference) (ResolutionInfo, error)
|
||||
type EntityReferenceResolver interface {
|
||||
Resolve(ctx context.Context, ref *models.EntityExternalReference) (ResolutionInfo, error)
|
||||
}
|
||||
|
||||
func ProvideObjectReferenceResolver(ds datasources.DataSourceService, pluginStore plugins.Store) ObjectReferenceResolver {
|
||||
func ProvideEntityReferenceResolver(ds datasources.DataSourceService, pluginStore plugins.Store) EntityReferenceResolver {
|
||||
return &standardReferenceResolver{
|
||||
pluginStore: pluginStore,
|
||||
ds: dsCache{
|
||||
@ -46,7 +46,7 @@ type standardReferenceResolver struct {
|
||||
ds dsCache
|
||||
}
|
||||
|
||||
func (r *standardReferenceResolver) Resolve(ctx context.Context, ref *models.ObjectExternalReference) (ResolutionInfo, error) {
|
||||
func (r *standardReferenceResolver) Resolve(ctx context.Context, ref *models.EntityExternalReference) (ResolutionInfo, error) {
|
||||
if ref == nil {
|
||||
return ResolutionInfo{OK: false, Timestamp: getNow()}, fmt.Errorf("ref is nil")
|
||||
}
|
||||
@ -73,7 +73,7 @@ func (r *standardReferenceResolver) Resolve(ctx context.Context, ref *models.Obj
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *standardReferenceResolver) resolveDatasource(ctx context.Context, ref *models.ObjectExternalReference) (ResolutionInfo, error) {
|
||||
func (r *standardReferenceResolver) resolveDatasource(ctx context.Context, ref *models.EntityExternalReference) (ResolutionInfo, error) {
|
||||
ds, err := r.ds.getDS(ctx, ref.UID)
|
||||
if err != nil || ds == nil || ds.UID == "" {
|
||||
return ResolutionInfo{
|
||||
@ -99,7 +99,7 @@ func (r *standardReferenceResolver) resolveDatasource(ctx context.Context, ref *
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *standardReferenceResolver) resolvePlugin(ctx context.Context, ref *models.ObjectExternalReference) (ResolutionInfo, error) {
|
||||
func (r *standardReferenceResolver) resolvePlugin(ctx context.Context, ref *models.EntityExternalReference) (ResolutionInfo, error) {
|
||||
p, ok := r.pluginStore.Plugin(ctx, ref.UID)
|
||||
if !ok {
|
||||
return ResolutionInfo{
|
||||
|
@ -45,18 +45,18 @@ func TestResolver(t *testing.T) {
|
||||
pluginStore := plugins.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{p1, p2, p3},
|
||||
}
|
||||
provider := ProvideObjectReferenceResolver(ds, pluginStore)
|
||||
provider := ProvideEntityReferenceResolver(ds, pluginStore)
|
||||
|
||||
scenarios := []struct {
|
||||
name string
|
||||
given *models.ObjectExternalReference
|
||||
given *models.EntityExternalReference
|
||||
expect ResolutionInfo
|
||||
err string
|
||||
ctx context.Context
|
||||
}{
|
||||
{
|
||||
name: "Missing datasource without type",
|
||||
given: &models.ObjectExternalReference{
|
||||
given: &models.EntityExternalReference{
|
||||
Kind: models.StandardKindDataSource,
|
||||
UID: "xyz",
|
||||
},
|
||||
@ -65,7 +65,7 @@ func TestResolver(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "OK datasource",
|
||||
given: &models.ObjectExternalReference{
|
||||
given: &models.EntityExternalReference{
|
||||
Kind: models.StandardKindDataSource,
|
||||
Type: "influx",
|
||||
UID: "influx-uid",
|
||||
@ -75,7 +75,7 @@ func TestResolver(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Get the default datasource",
|
||||
given: &models.ObjectExternalReference{
|
||||
given: &models.EntityExternalReference{
|
||||
Kind: models.StandardKindDataSource,
|
||||
},
|
||||
expect: ResolutionInfo{
|
||||
@ -87,7 +87,7 @@ func TestResolver(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Get the default datasource (with type)",
|
||||
given: &models.ObjectExternalReference{
|
||||
given: &models.EntityExternalReference{
|
||||
Kind: models.StandardKindDataSource,
|
||||
Type: "influx",
|
||||
},
|
||||
@ -99,7 +99,7 @@ func TestResolver(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Lookup by name",
|
||||
given: &models.ObjectExternalReference{
|
||||
given: &models.EntityExternalReference{
|
||||
Kind: models.StandardKindDataSource,
|
||||
UID: "Influx2",
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user