K8s/DualWriter: Remove legacy interface (#101395)

This commit is contained in:
Ryan McKinley
2025-02-27 13:27:28 +03:00
committed by GitHub
parent b16904651f
commit 58457d41d3
26 changed files with 108 additions and 299 deletions
+18 -23
View File
@@ -26,8 +26,18 @@ var (
_ rest.SingularNameProvider = (DualWriter)(nil)
)
type dualWriteContextKey struct{}
func IsDualWriteUpdate(ctx context.Context) bool {
return ctx.Value(dualWriteContextKey{}) == true
}
func WithDualWriteUpdate(ctx context.Context) context.Context {
return context.WithValue(ctx, dualWriteContextKey{}, true)
}
// Function that will create a dual writer
type DualWriteBuilder func(gr schema.GroupResource, legacy LegacyStorage, storage Storage) (Storage, error)
type DualWriteBuilder func(gr schema.GroupResource, legacy Storage, unified Storage) (Storage, error)
// Storage is a storage implementation that satisfies the same interfaces as genericregistry.Store.
type Storage interface {
@@ -36,26 +46,12 @@ type Storage interface {
rest.TableConvertor
rest.SingularNameProvider
rest.Getter
// TODO: when watch is implemented, we can replace all the below with rest.StandardStorage
rest.Lister
rest.CreaterUpdater
rest.GracefulDeleter
rest.CollectionDeleter
}
// LegacyStorage is a storage implementation that writes to the Grafana SQL database.
type LegacyStorage interface {
rest.Storage
rest.Scoper
rest.SingularNameProvider
rest.CreaterUpdater
rest.Lister
rest.GracefulDeleter
rest.CollectionDeleter
rest.TableConvertor
rest.Getter
}
// DualWriter is a storage implementation that writes first to LegacyStorage and then to Storage.
// If writing to LegacyStorage fails, the write to Storage is skipped and the error is returned.
// Storage is used for all read operations. This is useful as a migration step from SQL based
@@ -79,7 +75,6 @@ type LegacyStorage interface {
type DualWriter interface {
Storage
LegacyStorage
Mode() DualWriterMode
}
@@ -110,8 +105,8 @@ const (
// NewDualWriter returns a new DualWriter.
func NewDualWriter(
mode DualWriterMode,
legacy LegacyStorage,
storage Storage,
legacy Storage,
unified Storage,
reg prometheus.Registerer,
resource string,
) Storage {
@@ -122,17 +117,17 @@ func NewDualWriter(
return legacy
case Mode1:
// read and write only from legacy storage
return newDualWriterMode1(legacy, storage, metrics, resource)
return newDualWriterMode1(legacy, unified, metrics, resource)
case Mode2:
// write to both, read from storage but use legacy as backup
return newDualWriterMode2(legacy, storage, metrics, resource)
return newDualWriterMode2(legacy, unified, metrics, resource)
case Mode3:
// write to both, read from storage only
return newDualWriterMode3(legacy, storage, metrics, resource)
return newDualWriterMode3(legacy, unified, metrics, resource)
case Mode4, Mode5:
return storage
return unified
default:
return newDualWriterMode1(legacy, storage, metrics, resource)
return newDualWriterMode1(legacy, unified, metrics, resource)
}
}
+2 -2
View File
@@ -15,7 +15,7 @@ import (
)
type DualWriterMode1 struct {
Legacy LegacyStorage
Legacy Storage
Storage Storage
*dualWriterMetrics
resource string
@@ -26,7 +26,7 @@ const mode1Str = "1"
// NewDualWriterMode1 returns a new DualWriter in mode 1.
// Mode 1 represents writing to and reading from LegacyStorage.
func newDualWriterMode1(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode1 {
func newDualWriterMode1(legacy Storage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode1 {
return &DualWriterMode1{
Legacy: legacy,
Storage: storage,
+24 -24
View File
@@ -60,10 +60,10 @@ func TestMode1_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -122,10 +122,10 @@ func TestMode1_CreateOnUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -190,10 +190,10 @@ func TestMode1_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -251,10 +251,10 @@ func TestMode1_GetFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -308,10 +308,10 @@ func TestMode1_List(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -365,10 +365,10 @@ func TestMode1_ListFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -434,10 +434,10 @@ func TestMode1_Delete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -494,10 +494,10 @@ func TestMode1_DeleteFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -565,10 +565,10 @@ func TestMode1_DeleteCollection(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -626,10 +626,10 @@ func TestMode1_DeleteCollectionFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -695,10 +695,10 @@ func TestMode1_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -761,10 +761,10 @@ func TestMode1_UpdateOnUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+2 -8
View File
@@ -16,15 +16,9 @@ import (
"github.com/grafana/grafana/pkg/apimachinery/utils"
)
type dualWriteContextKey struct{}
func IsDualWriteUpdate(ctx context.Context) bool {
return ctx.Value(dualWriteContextKey{}) == true
}
type DualWriterMode2 struct {
Storage Storage
Legacy LegacyStorage
Legacy Storage
*dualWriterMetrics
resource string
Log klog.Logger
@@ -35,7 +29,7 @@ const mode2Str = "2"
// newDualWriterMode2 returns a new DualWriter in mode 2.
// Mode 2 represents writing to LegacyStorage first, then to Storage.
// When reading, values from LegacyStorage will be returned.
func newDualWriterMode2(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode2 {
func newDualWriterMode2(legacy Storage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode2 {
return &DualWriterMode2{
Legacy: legacy,
Storage: storage,
+12 -12
View File
@@ -54,10 +54,10 @@ func TestMode2_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -138,10 +138,10 @@ func TestMode2_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -212,10 +212,10 @@ func TestMode2_List(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -313,10 +313,10 @@ func TestMode2_Delete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -382,10 +382,10 @@ func TestMode2_DeleteCollection(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -451,10 +451,10 @@ func TestMode2_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+2 -2
View File
@@ -17,7 +17,7 @@ import (
)
type DualWriterMode3 struct {
Legacy LegacyStorage
Legacy Storage
Storage Storage
watchImp rest.Watcher // watch is only available in mode 3 and 4
*dualWriterMetrics
@@ -27,7 +27,7 @@ type DualWriterMode3 struct {
// newDualWriterMode3 returns a new DualWriter in mode 3.
// Mode 3 represents writing to LegacyStorage and Storage and reading from Storage.
func newDualWriterMode3(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode3 {
func newDualWriterMode3(legacy Storage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode3 {
return &DualWriterMode3{
Legacy: legacy,
Storage: storage,
+14 -14
View File
@@ -61,10 +61,10 @@ func TestMode3_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -128,10 +128,10 @@ func TestMode3_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -187,10 +187,10 @@ func TestMode1_GetFromLegacyStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -234,10 +234,10 @@ func TestMode3_List(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupStorageFn != nil {
@@ -311,10 +311,10 @@ func TestMode3_Delete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -380,10 +380,10 @@ func TestMode3_DeleteCollection(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -449,10 +449,10 @@ func TestMode3_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+1 -1
View File
@@ -33,7 +33,7 @@ type SyncerConfig struct {
RequestInfo *request.RequestInfo
Mode DualWriterMode
LegacyStorage LegacyStorage
LegacyStorage Storage
Storage Storage
ServerLockService ServerLockService
+4 -4
View File
@@ -181,12 +181,12 @@ func TestLegacyToUnifiedStorage_DataSyncer(t *testing.T) {
// mode 1
for _, tt := range tests {
t.Run("Mode-1-"+tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
lm := &mock.Mock{}
um := &mock.Mock{}
ls := legacyStoreMock{lm, l}
ls := storageMock{lm, l}
us := storageMock{um, s}
if tt.setupLegacyFn != nil {
@@ -221,12 +221,12 @@ func TestLegacyToUnifiedStorage_DataSyncer(t *testing.T) {
// mode 2
for _, tt := range tests {
t.Run("Mode-2-"+tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
lm := &mock.Mock{}
um := &mock.Mock{}
ls := legacyStoreMock{lm, l}
ls := storageMock{lm, l}
us := storageMock{um, s}
if tt.setupLegacyFn != nil {
+2 -2
View File
@@ -64,7 +64,7 @@ func TestSetDualWritingMode(t *testing.T) {
}
for _, tt := range tests {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
sm := &mock.Mock{}
@@ -75,7 +75,7 @@ func TestSetDualWritingMode(t *testing.T) {
lm := &mock.Mock{}
lm.On("List", mock.Anything, mock.Anything).Return(exampleList, nil)
ls := legacyStoreMock{lm, l}
ls := storageMock{lm, l}
serverLockSvc := &fakeServerLock{
err: tt.serverLockError,
-91
View File
@@ -11,102 +11,11 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
)
type legacyStoreMock struct {
*mock.Mock
LegacyStorage
}
type storageMock struct {
*mock.Mock
Storage
}
func (m legacyStoreMock) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, obj, createValidation, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) NewList() runtime.Object {
return nil
}
func (m legacyStoreMock) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
select {
case <-ctx.Done():
return nil, false, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if err := args.Get(2); err != nil {
return nil, false, err.(error)
}
return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2)
}
func (m legacyStoreMock) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
select {
case <-ctx.Done():
return nil, false, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, deleteValidation, options)
if err := args.Get(2); err != nil {
return nil, false, err.(error)
}
return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2)
}
func (m legacyStoreMock) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, deleteValidation, options, listOptions)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
// Unified Store
func (m storageMock) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
select {
@@ -13,7 +13,7 @@ import (
model "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/resource/receiver/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
grafanaRest "github.com/grafana/grafana/pkg/apiserver/rest"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
alertingac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
@@ -22,7 +22,7 @@ import (
)
var (
_ grafanaRest.LegacyStorage = (*legacyStorage)(nil)
_ grafanarest.Storage = (*legacyStorage)(nil)
)
type ReceiverService interface {
@@ -11,14 +11,14 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
model "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/resource/routingtree/v0alpha1"
grafanaRest "github.com/grafana/grafana/pkg/apiserver/rest"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
alerting_models "github.com/grafana/grafana/pkg/services/ngalert/models"
)
var (
_ grafanaRest.LegacyStorage = (*legacyStorage)(nil)
_ grafanarest.Storage = (*legacyStorage)(nil)
)
type RouteService interface {
@@ -4,13 +4,14 @@ import (
"context"
"fmt"
"github.com/grafana/alerting/templates"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
"github.com/grafana/alerting/templates"
model "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/resource/templategroup/v0alpha1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
@@ -19,7 +20,7 @@ import (
)
var (
_ grafanarest.LegacyStorage = (*legacyStorage)(nil)
_ grafanarest.Storage = (*legacyStorage)(nil)
)
type TemplateService interface {
@@ -11,14 +11,14 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
model "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/resource/timeinterval/v0alpha1"
grafanaRest "github.com/grafana/grafana/pkg/apiserver/rest"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
)
var (
_ grafanaRest.LegacyStorage = (*legacyStorage)(nil)
_ grafanarest.Storage = (*legacyStorage)(nil)
)
type TimeIntervalService interface {
@@ -28,7 +28,7 @@ type DashboardStorage struct {
Features featuremgmt.FeatureToggles
}
func (s *DashboardStorage) NewStore(scheme *runtime.Scheme, defaultOptsGetter generic.RESTOptionsGetter, reg prometheus.Registerer) (grafanarest.LegacyStorage, error) {
func (s *DashboardStorage) NewStore(scheme *runtime.Scheme, defaultOptsGetter generic.RESTOptionsGetter, reg prometheus.Registerer) (grafanarest.Storage, error) {
server, err := resource.NewResourceServer(resource.ResourceServerOptions{
Backend: s.Access,
Reg: reg,
+3 -2
View File
@@ -17,6 +17,8 @@ import (
"k8s.io/kube-openapi/pkg/spec3"
"k8s.io/kube-openapi/pkg/validation/spec"
"github.com/prometheus/client_golang/prometheus"
claims "github.com/grafana/authlib/types"
"github.com/grafana/grafana/pkg/apimachinery/utils"
dashboardinternal "github.com/grafana/grafana/pkg/apis/dashboard"
@@ -42,7 +44,6 @@ import (
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"
"github.com/grafana/grafana/pkg/storage/unified/apistore"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/prometheus/client_golang/prometheus"
)
var (
@@ -247,7 +248,7 @@ func (b *DashboardsAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver
func (b *DashboardsAPIBuilder) storageForVersion(
opts builder.APIGroupOptions,
legacyStore grafanarest.LegacyStorage,
legacyStore grafanarest.Storage,
largeObjects apistore.LargeObjectSupport,
newDTOFunc func() runtime.Object,
) (map[string]rest.Storage, error) {
+1 -1
View File
@@ -48,7 +48,7 @@ func RegisterApp(
return provider
}
func (p *PlaylistAppProvider) legacyStorageGetter(requested schema.GroupVersionResource) grafanarest.LegacyStorage {
func (p *PlaylistAppProvider) legacyStorageGetter(requested schema.GroupVersionResource) grafanarest.Storage {
gvr := schema.GroupVersionResource{
Group: playlistv0alpha1.PlaylistKind().Group(),
Version: playlistv0alpha1.PlaylistKind().Version(),
+1 -1
View File
@@ -286,7 +286,7 @@ func InstallAPIs(
// nolint:staticcheck
if storageOpts.StorageType != options.StorageTypeLegacy {
dualWrite = func(gr schema.GroupResource, legacy grafanarest.LegacyStorage, storage grafanarest.Storage) (grafanarest.Storage, error) {
dualWrite = func(gr schema.GroupResource, legacy grafanarest.Storage, storage grafanarest.Storage) (grafanarest.Storage, error) {
// Dashboards + Folders may be managed (depends on feature toggles and database state)
if dualWriteService != nil && dualWriteService.ShouldManage(gr) {
return dualWriteService.NewStorage(gr, legacy, storage) // eventually this can replace this whole function
@@ -18,7 +18,7 @@ import (
var _ AppBuilder = (*appBuilder)(nil)
type LegacyStorageGetter func(schema.GroupVersionResource) grafanarest.LegacyStorage
type LegacyStorageGetter func(schema.GroupVersionResource) grafanarest.Storage
type AppBuilderConfig struct {
Authorizer authorizer.Authorizer
+1 -1
View File
@@ -26,7 +26,7 @@ type mockService struct {
}
// NewStorage implements Service.
func (m *mockService) NewStorage(gr schema.GroupResource, legacy rest.LegacyStorage, storage rest.Storage) (rest.Storage, error) {
func (m *mockService) NewStorage(gr schema.GroupResource, legacy rest.Storage, storage rest.Storage) (rest.Storage, error) {
return nil, fmt.Errorf("not implemented")
}
+2 -2
View File
@@ -15,7 +15,7 @@ import (
)
func (m *service) NewStorage(gr schema.GroupResource,
legacy grafanarest.LegacyStorage,
legacy grafanarest.Storage,
storage grafanarest.Storage,
) (grafanarest.Storage, error) {
status, err := m.Status(context.Background(), gr)
@@ -53,7 +53,7 @@ func (m *service) NewStorage(gr schema.GroupResource,
// When a resource is marked as "migrating", all write requests will be 503 unavailable
type runtimeDualWriter struct {
service Service
legacy grafanarest.LegacyStorage
legacy grafanarest.Storage
unified grafanarest.Storage
dualwrite grafanarest.Storage
gr schema.GroupResource
@@ -76,10 +76,10 @@ func TestManagedMode3_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (rest.LegacyStorage)(nil)
l := (rest.Storage)(nil)
s := (rest.Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -148,10 +148,10 @@ func TestManagedMode3_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (rest.LegacyStorage)(nil)
l := (rest.Storage)(nil)
s := (rest.Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -249,10 +249,10 @@ func TestManagedMode3_CreateWhileMigrating(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (rest.LegacyStorage)(nil)
l := (rest.Storage)(nil)
s := (rest.Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+1 -1
View File
@@ -14,7 +14,7 @@ type staticService struct {
cfg *setting.Cfg
}
func (m *staticService) NewStorage(gr schema.GroupResource, legacy rest.LegacyStorage, storage rest.Storage) (rest.Storage, error) {
func (m *staticService) NewStorage(gr schema.GroupResource, legacy rest.Storage, storage rest.Storage) (rest.Storage, error) {
return nil, fmt.Errorf("not implemented")
}
@@ -13,102 +13,11 @@ import (
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
)
type legacyStoreMock struct {
*mock.Mock
grafanarest.LegacyStorage
}
type storageMock struct {
*mock.Mock
grafanarest.Storage
}
func (m legacyStoreMock) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, obj, createValidation, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) NewList() runtime.Object {
return nil
}
func (m legacyStoreMock) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
select {
case <-ctx.Done():
return nil, false, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if err := args.Get(2); err != nil {
return nil, false, err.(error)
}
return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2)
}
func (m legacyStoreMock) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
select {
case <-ctx.Done():
return nil, false, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, deleteValidation, options)
if err := args.Get(2); err != nil {
return nil, false, err.(error)
}
return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2)
}
func (m legacyStoreMock) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, deleteValidation, options, listOptions)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
// Unified Store
func (m storageMock) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
select {
+1 -1
View File
@@ -36,7 +36,7 @@ type Service interface {
ShouldManage(gr schema.GroupResource) bool
// Create a managed k8s storage instance
NewStorage(gr schema.GroupResource, legacy grafanarest.LegacyStorage, storage grafanarest.Storage) (grafanarest.Storage, error)
NewStorage(gr schema.GroupResource, legacy grafanarest.Storage, storage grafanarest.Storage) (grafanarest.Storage, error)
// Check if the dual writes is reading from unified storage (mode3++)
ReadFromUnified(ctx context.Context, gr schema.GroupResource) (bool, error)