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