mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 17:52:30 +08:00
EntityStore: Rename ObjectStore to EntityStore (part 2) (#59616)
This commit is contained in:
@ -105,7 +105,7 @@ The following toggles require explicitly setting Grafana's [app mode]({{< relref
|
|||||||
| `export` | Export grafana instance (to git, etc) |
|
| `export` | Export grafana instance (to git, etc) |
|
||||||
| `azureMonitorResourcePickerForMetrics` | New UI for Azure Monitor Metrics Query |
|
| `azureMonitorResourcePickerForMetrics` | New UI for Azure Monitor Metrics Query |
|
||||||
| `grpcServer` | Run GRPC server |
|
| `grpcServer` | Run GRPC server |
|
||||||
| `objectStore` | SQL-based object store |
|
| `entityStore` | SQL-based entity store (requires storage flag also) |
|
||||||
| `queryLibrary` | Reusable query library |
|
| `queryLibrary` | Reusable query library |
|
||||||
| `accessControlOnCall` | Access control primitives for OnCall |
|
| `accessControlOnCall` | Access control primitives for OnCall |
|
||||||
| `nestedFolders` | Enable folder nesting |
|
| `nestedFolders` | Enable folder nesting |
|
||||||
|
2
go.mod
2
go.mod
@ -203,7 +203,7 @@ require (
|
|||||||
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect
|
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect
|
||||||
github.com/oklog/run v1.1.0 // indirect
|
github.com/oklog/run v1.1.0 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect
|
github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect
|
||||||
github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect
|
github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
@ -65,7 +65,7 @@ export interface FeatureToggles {
|
|||||||
internationalization?: boolean;
|
internationalization?: boolean;
|
||||||
topnav?: boolean;
|
topnav?: boolean;
|
||||||
grpcServer?: boolean;
|
grpcServer?: boolean;
|
||||||
objectStore?: boolean;
|
entityStore?: boolean;
|
||||||
traceqlEditor?: boolean;
|
traceqlEditor?: boolean;
|
||||||
flameGraph?: boolean;
|
flameGraph?: boolean;
|
||||||
cloudWatchCrossAccountQuerying?: boolean;
|
cloudWatchCrossAccountQuerying?: boolean;
|
||||||
|
@ -285,11 +285,11 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
if hs.Features.IsEnabled(featuremgmt.FlagStorage) {
|
if hs.Features.IsEnabled(featuremgmt.FlagStorage) {
|
||||||
// Will eventually be replaced with the 'object' route
|
// Will eventually be replaced with the 'object' route
|
||||||
apiRoute.Group("/storage", hs.StorageService.RegisterHTTPRoutes)
|
apiRoute.Group("/storage", hs.StorageService.RegisterHTTPRoutes)
|
||||||
|
}
|
||||||
|
|
||||||
// Allow HTTP access to the object storage feature (dev only for now)
|
// Allow HTTP access to the entity storage feature (dev only for now)
|
||||||
if hs.Features.IsEnabled(featuremgmt.FlagGrpcServer) {
|
if hs.Features.IsEnabled(featuremgmt.FlagEntityStore) {
|
||||||
apiRoute.Group("/object", hs.httpEntityStore.RegisterHTTPRoutes)
|
apiRoute.Group("/entity", hs.httpEntityStore.RegisterHTTPRoutes)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if hs.Features.IsEnabled(featuremgmt.FlagPanelTitleSearch) {
|
if hs.Features.IsEnabled(featuremgmt.FlagPanelTitleSearch) {
|
||||||
|
@ -233,7 +233,7 @@ func (ex *StandardExport) HandleRequestExport(c *models.ReqContext) response.Res
|
|||||||
switch cfg.Format {
|
switch cfg.Format {
|
||||||
case "dummy":
|
case "dummy":
|
||||||
job, err = startDummyExportJob(cfg, broadcast)
|
job, err = startDummyExportJob(cfg, broadcast)
|
||||||
case "objectStore":
|
case "entityStore":
|
||||||
job, err = startEntityStoreJob(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()))
|
||||||
|
@ -281,8 +281,8 @@ var (
|
|||||||
RequiresDevMode: true,
|
RequiresDevMode: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "objectStore",
|
Name: "entityStore",
|
||||||
Description: "SQL-based object store",
|
Description: "SQL-based entity store (requires storage flag also)",
|
||||||
State: FeatureStateAlpha,
|
State: FeatureStateAlpha,
|
||||||
RequiresDevMode: true,
|
RequiresDevMode: true,
|
||||||
},
|
},
|
||||||
|
@ -203,9 +203,9 @@ const (
|
|||||||
// Run GRPC server
|
// Run GRPC server
|
||||||
FlagGrpcServer = "grpcServer"
|
FlagGrpcServer = "grpcServer"
|
||||||
|
|
||||||
// FlagObjectStore
|
// FlagEntityStore
|
||||||
// SQL-based object store
|
// SQL-based entity store (requires storage flag also)
|
||||||
FlagObjectStore = "objectStore"
|
FlagEntityStore = "entityStore"
|
||||||
|
|
||||||
// FlagTraceqlEditor
|
// FlagTraceqlEditor
|
||||||
// Show the TraceQL editor in the explore page
|
// Show the TraceQL editor in the explore page
|
||||||
|
@ -18,15 +18,15 @@ import (
|
|||||||
// 2. CREATE/UPDATE/DELETE same items to the object store
|
// 2. CREATE/UPDATE/DELETE same items to the object store
|
||||||
// 3. Use the object store for all read operations
|
// 3. Use the object store for all read operations
|
||||||
// This givs us a safe test bed to work with the store but still roll back without any lost work
|
// This givs us a safe test bed to work with the store but still roll back without any lost work
|
||||||
type objectStoreImpl struct {
|
type entityStoreImpl struct {
|
||||||
sess *session.SessionDB
|
sess *session.SessionDB
|
||||||
sqlimpl *Service
|
sqlimpl *Service
|
||||||
objectstore entity.EntityStoreServer
|
store entity.EntityStoreServer
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ playlist.Service = &objectStoreImpl{}
|
var _ playlist.Service = &entityStoreImpl{}
|
||||||
|
|
||||||
func (s *objectStoreImpl) sync() {
|
func (s *entityStoreImpl) sync() {
|
||||||
type Info struct {
|
type Info struct {
|
||||||
OrgID int64 `db:"org_id"`
|
OrgID int64 `db:"org_id"`
|
||||||
UID string `db:"uid"`
|
UID string `db:"uid"`
|
||||||
@ -55,7 +55,7 @@ func (s *objectStoreImpl) sync() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
body, _ := json.Marshal(dto)
|
body, _ := json.Marshal(dto)
|
||||||
_, _ = s.objectstore.Write(ctx, &entity.WriteEntityRequest{
|
_, _ = s.store.Write(ctx, &entity.WriteEntityRequest{
|
||||||
GRN: &entity.GRN{
|
GRN: &entity.GRN{
|
||||||
TenantId: info.OrgID,
|
TenantId: info.OrgID,
|
||||||
UID: info.UID,
|
UID: info.UID,
|
||||||
@ -66,14 +66,14 @@ func (s *objectStoreImpl) sync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectStoreImpl) Create(ctx context.Context, cmd *playlist.CreatePlaylistCommand) (*playlist.Playlist, error) {
|
func (s *entityStoreImpl) Create(ctx context.Context, cmd *playlist.CreatePlaylistCommand) (*playlist.Playlist, error) {
|
||||||
rsp, err := s.sqlimpl.store.Insert(ctx, cmd)
|
rsp, err := s.sqlimpl.store.Insert(ctx, cmd)
|
||||||
if err == nil && rsp != nil {
|
if err == nil && rsp != nil {
|
||||||
body, err := json.Marshal(cmd)
|
body, err := json.Marshal(cmd)
|
||||||
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, &entity.WriteEntityRequest{
|
_, err = s.store.Write(ctx, &entity.WriteEntityRequest{
|
||||||
GRN: &entity.GRN{
|
GRN: &entity.GRN{
|
||||||
Kind: models.StandardKindPlaylist,
|
Kind: models.StandardKindPlaylist,
|
||||||
UID: rsp.UID,
|
UID: rsp.UID,
|
||||||
@ -87,14 +87,14 @@ func (s *objectStoreImpl) Create(ctx context.Context, cmd *playlist.CreatePlayli
|
|||||||
return rsp, err
|
return rsp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectStoreImpl) Update(ctx context.Context, cmd *playlist.UpdatePlaylistCommand) (*playlist.PlaylistDTO, error) {
|
func (s *entityStoreImpl) Update(ctx context.Context, cmd *playlist.UpdatePlaylistCommand) (*playlist.PlaylistDTO, error) {
|
||||||
rsp, err := s.sqlimpl.store.Update(ctx, cmd)
|
rsp, err := s.sqlimpl.store.Update(ctx, cmd)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
body, err := json.Marshal(cmd)
|
body, err := json.Marshal(cmd)
|
||||||
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, &entity.WriteEntityRequest{
|
_, err = s.store.Write(ctx, &entity.WriteEntityRequest{
|
||||||
GRN: &entity.GRN{
|
GRN: &entity.GRN{
|
||||||
UID: rsp.Uid,
|
UID: rsp.Uid,
|
||||||
Kind: models.StandardKindPlaylist,
|
Kind: models.StandardKindPlaylist,
|
||||||
@ -108,10 +108,10 @@ func (s *objectStoreImpl) Update(ctx context.Context, cmd *playlist.UpdatePlayli
|
|||||||
return rsp, err
|
return rsp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectStoreImpl) Delete(ctx context.Context, cmd *playlist.DeletePlaylistCommand) error {
|
func (s *entityStoreImpl) 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, &entity.DeleteEntityRequest{
|
_, err = s.store.Delete(ctx, &entity.DeleteEntityRequest{
|
||||||
GRN: &entity.GRN{
|
GRN: &entity.GRN{
|
||||||
UID: cmd.UID,
|
UID: cmd.UID,
|
||||||
Kind: models.StandardKindPlaylist,
|
Kind: models.StandardKindPlaylist,
|
||||||
@ -128,7 +128,7 @@ func (s *objectStoreImpl) Delete(ctx context.Context, cmd *playlist.DeletePlayli
|
|||||||
// Read access is managed entirely by the object store
|
// Read access is managed entirely by the object store
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
func (s *objectStoreImpl) GetWithoutItems(ctx context.Context, q *playlist.GetPlaylistByUidQuery) (*playlist.Playlist, error) {
|
func (s *entityStoreImpl) GetWithoutItems(ctx context.Context, q *playlist.GetPlaylistByUidQuery) (*playlist.Playlist, error) {
|
||||||
p, err := s.Get(ctx, q) // OrgID is actually picked from the user!
|
p, err := s.Get(ctx, q) // OrgID is actually picked from the user!
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -141,8 +141,8 @@ func (s *objectStoreImpl) GetWithoutItems(ctx context.Context, q *playlist.GetPl
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectStoreImpl) Get(ctx context.Context, q *playlist.GetPlaylistByUidQuery) (*playlist.PlaylistDTO, error) {
|
func (s *entityStoreImpl) Get(ctx context.Context, q *playlist.GetPlaylistByUidQuery) (*playlist.PlaylistDTO, error) {
|
||||||
rsp, err := s.objectstore.Read(ctx, &entity.ReadEntityRequest{
|
rsp, err := s.store.Read(ctx, &entity.ReadEntityRequest{
|
||||||
GRN: &entity.GRN{
|
GRN: &entity.GRN{
|
||||||
UID: q.UID,
|
UID: q.UID,
|
||||||
Kind: models.StandardKindPlaylist,
|
Kind: models.StandardKindPlaylist,
|
||||||
@ -162,10 +162,10 @@ func (s *objectStoreImpl) Get(ctx context.Context, q *playlist.GetPlaylistByUidQ
|
|||||||
return found, err
|
return found, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectStoreImpl) Search(ctx context.Context, q *playlist.GetPlaylistsQuery) (playlist.Playlists, error) {
|
func (s *entityStoreImpl) 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, &entity.EntitySearchRequest{
|
rsp, err := s.store.Search(ctx, &entity.EntitySearchRequest{
|
||||||
Kind: []string{models.StandardKindPlaylist},
|
Kind: []string{models.StandardKindPlaylist},
|
||||||
WithBody: true,
|
WithBody: true,
|
||||||
Limit: 1000,
|
Limit: 1000,
|
@ -31,11 +31,11 @@ func ProvideService(db db.DB, toggles featuremgmt.FeatureToggles, objserver enti
|
|||||||
svc := &Service{store: sqlstore}
|
svc := &Service{store: sqlstore}
|
||||||
|
|
||||||
// FlagObjectStore is only supported in development mode
|
// FlagObjectStore is only supported in development mode
|
||||||
if toggles.IsEnabled(featuremgmt.FlagObjectStore) {
|
if toggles.IsEnabled(featuremgmt.FlagEntityStore) {
|
||||||
impl := &objectStoreImpl{
|
impl := &entityStoreImpl{
|
||||||
sqlimpl: svc,
|
sqlimpl: svc,
|
||||||
objectstore: objserver,
|
store: objserver,
|
||||||
sess: db.GetSqlxSession(),
|
sess: db.GetSqlxSession(),
|
||||||
}
|
}
|
||||||
impl.sync() // load everythign from the existing SQL setup into the new object store
|
impl.sync() // load everythign from the existing SQL setup into the new object store
|
||||||
return impl
|
return impl
|
||||||
|
@ -18,7 +18,7 @@ func getLatinPathColumn(name string) *migrator.Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addObjectStorageMigrations(mg *migrator.Migrator) {
|
func addEntityStoreMigrations(mg *migrator.Migrator) {
|
||||||
grnLength := 256 // len(tenant)~8 + len(kind)!16 + len(kind)~128 = 256
|
grnLength := 256 // len(tenant)~8 + len(kind)!16 + len(kind)~128 = 256
|
||||||
tables := []migrator.Table{}
|
tables := []migrator.Table{}
|
||||||
tables = append(tables, migrator.Table{
|
tables = append(tables, migrator.Table{
|
@ -83,8 +83,8 @@ func (*OSSMigrations) AddMigration(mg *Migrator) {
|
|||||||
addCommentMigrations(mg)
|
addCommentMigrations(mg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if mg.Cfg.IsFeatureToggleEnabled(featuremgmt.FlagObjectStore) {
|
if mg.Cfg.IsFeatureToggleEnabled(featuremgmt.FlagEntityStore) {
|
||||||
addObjectStorageMigrations(mg)
|
addEntityStoreMigrations(mg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +489,7 @@ var featuresEnabledDuringTests = []string{
|
|||||||
featuremgmt.FlagDashboardPreviews,
|
featuremgmt.FlagDashboardPreviews,
|
||||||
featuremgmt.FlagDashboardComments,
|
featuremgmt.FlagDashboardComments,
|
||||||
featuremgmt.FlagPanelTitleSearch,
|
featuremgmt.FlagPanelTitleSearch,
|
||||||
featuremgmt.FlagObjectStore,
|
featuremgmt.FlagEntityStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitTestDBWithMigration initializes the test DB given custom migrations.
|
// InitTestDBWithMigration initializes the test DB given custom migrations.
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func init() { //nolint:gochecknoinits
|
func init() { //nolint:gochecknoinits
|
||||||
jsoniter.RegisterTypeEncoder("entity.EntitySearchResult", &searchResultCodec{})
|
jsoniter.RegisterTypeEncoder("entity.EntitySearchResult", &searchResultCodec{})
|
||||||
jsoniter.RegisterTypeEncoder("entity.WriteObjectResponse", &writeResponseCodec{})
|
jsoniter.RegisterTypeEncoder("entity.WriteEntityResponse", &writeResponseCodec{})
|
||||||
jsoniter.RegisterTypeEncoder("entity.ReadEntityResponse", &readResponseCodec{})
|
jsoniter.RegisterTypeEncoder("entity.ReadEntityResponse", &readResponseCodec{})
|
||||||
|
|
||||||
jsoniter.RegisterTypeEncoder("entity.Entity", &rawEntityCodec{})
|
jsoniter.RegisterTypeEncoder("entity.Entity", &rawEntityCodec{})
|
||||||
|
@ -64,7 +64,7 @@ func createTestContext(t *testing.T) testContext {
|
|||||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||||
EnableFeatureToggles: []string{
|
EnableFeatureToggles: []string{
|
||||||
featuremgmt.FlagGrpcServer,
|
featuremgmt.FlagGrpcServer,
|
||||||
featuremgmt.FlagObjectStore,
|
featuremgmt.FlagEntityStore,
|
||||||
},
|
},
|
||||||
AppModeProduction: false, // required for migrations to run
|
AppModeProduction: false, // required for migrations to run
|
||||||
GRPCServerAddress: "127.0.0.1:0", // :0 for choosing the port automatically
|
GRPCServerAddress: "127.0.0.1:0", // :0 for choosing the port automatically
|
||||||
|
@ -61,7 +61,7 @@ interface ExporterInfo {
|
|||||||
|
|
||||||
const formats: Array<SelectableValue<string>> = [
|
const formats: Array<SelectableValue<string>> = [
|
||||||
{ label: 'GIT', value: 'git', description: 'Exports a fresh git repository' },
|
{ label: 'GIT', value: 'git', description: 'Exports a fresh git repository' },
|
||||||
{ label: 'Object store', value: 'objectStore', description: 'Export to the SQL based object store' },
|
{ label: 'Entity store', value: 'entityStore', description: 'Export to the SQL based entity store' },
|
||||||
];
|
];
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -173,9 +173,9 @@ export const ExportView = ({ onPathChange }: Props) => {
|
|||||||
onChange={(v) => setBody({ ...body!, format: v.value! })}
|
onChange={(v) => setBody({ ...body!, format: v.value! })}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
{body?.format === 'objectStore' && !config.featureToggles.objectStore && (
|
{body?.format === 'entityStore' && !config.featureToggles.entityStore && (
|
||||||
<div>
|
<div>
|
||||||
<Alert title="Missing feature flag">Enable the `objectStore` feature flag</Alert>
|
<Alert title="Missing feature flag">Enable the `entityStore` feature flag</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{body?.format === 'git' && (
|
{body?.format === 'git' && (
|
||||||
|
Reference in New Issue
Block a user