DualWriter: Error when folder+dashboard modes do not match when running mode4+ (#111286)
This commit is contained in:
@@ -77,7 +77,8 @@ func TestRuntime_Create(t *testing.T) {
|
||||
tt.setupStorageFn(us.Mock, tt.input)
|
||||
}
|
||||
|
||||
m := ProvideService(featuremgmt.WithFeatures(featuremgmt.FlagManagedDualWriter), nil, kvstore.NewFakeKVStore(), nil)
|
||||
m, err := ProvideService(featuremgmt.WithFeatures(featuremgmt.FlagManagedDualWriter), kvstore.NewFakeKVStore(), nil)
|
||||
require.NoError(t, err)
|
||||
dw, err := m.NewStorage(kind, ls, us)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -149,7 +150,8 @@ func TestRuntime_Get(t *testing.T) {
|
||||
tt.setupStorageFn(us.Mock, name)
|
||||
}
|
||||
|
||||
m := ProvideService(featuremgmt.WithFeatures(featuremgmt.FlagManagedDualWriter), nil, kvstore.NewFakeKVStore(), nil)
|
||||
m, err := ProvideService(featuremgmt.WithFeatures(featuremgmt.FlagManagedDualWriter), kvstore.NewFakeKVStore(), nil)
|
||||
require.NoError(t, err)
|
||||
dw, err := m.NewStorage(kind, ls, us)
|
||||
require.NoError(t, err)
|
||||
status, err := m.Status(context.Background(), kind)
|
||||
@@ -233,7 +235,8 @@ func TestRuntime_CreateWhileMigrating(t *testing.T) {
|
||||
}
|
||||
|
||||
// Shared provider across all tests
|
||||
dual := ProvideService(featuremgmt.WithFeatures(featuremgmt.FlagManagedDualWriter), nil, kvstore.NewFakeKVStore(), nil)
|
||||
dual, err := ProvideService(featuremgmt.WithFeatures(featuremgmt.FlagManagedDualWriter), kvstore.NewFakeKVStore(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
@@ -24,39 +23,39 @@ func ProvideStaticServiceForTests(cfg *setting.Cfg) Service {
|
||||
|
||||
func ProvideService(
|
||||
features featuremgmt.FeatureToggles,
|
||||
reg prometheus.Registerer,
|
||||
kv kvstore.KVStore,
|
||||
cfg *setting.Cfg,
|
||||
) Service {
|
||||
) (Service, error) {
|
||||
enabled := features.IsEnabledGlobally(featuremgmt.FlagManagedDualWriter) ||
|
||||
features.IsEnabledGlobally(featuremgmt.FlagProvisioning) // required for git provisioning
|
||||
|
||||
if cfg != nil {
|
||||
// Avoid dynamic behavior when things are explicitly configured to mode5
|
||||
allMode5 := true
|
||||
for _, gr := range []string{
|
||||
"dashboards.dashboard.grafana.app",
|
||||
"folders.folder.grafana.app",
|
||||
} {
|
||||
if cfg.UnifiedStorage[gr].DualWriterMode != rest.Mode5 {
|
||||
allMode5 = false
|
||||
break
|
||||
if !enabled {
|
||||
return &staticService{cfg}, nil
|
||||
}
|
||||
|
||||
if cfg != nil {
|
||||
foldersMode := cfg.UnifiedStorage["folders.folder.grafana.app"].DualWriterMode
|
||||
dashboardsMode := cfg.UnifiedStorage["dashboards.dashboard.grafana.app"].DualWriterMode
|
||||
|
||||
// If both are fully on unified (Mode5), the dynamic service is not needed.
|
||||
if foldersMode == rest.Mode5 && dashboardsMode == rest.Mode5 {
|
||||
return &staticService{cfg}, nil
|
||||
}
|
||||
|
||||
if (foldersMode >= rest.Mode4 || dashboardsMode >= rest.Mode4) && foldersMode != dashboardsMode {
|
||||
return nil, fmt.Errorf("dashboards and folders must use the same mode when reading from unified storage")
|
||||
}
|
||||
}
|
||||
if allMode5 || !enabled {
|
||||
return &staticService{cfg} // fallback to using the dual write flags from cfg
|
||||
}
|
||||
}
|
||||
|
||||
db := &keyvalueDB{
|
||||
db: kv,
|
||||
logger: logging.DefaultLogger.With("logger", "dualwrite.kv"),
|
||||
}
|
||||
|
||||
return &service{
|
||||
db: db,
|
||||
db: &keyvalueDB{
|
||||
db: kv,
|
||||
logger: logging.DefaultLogger.With("logger", "dualwrite.kv"),
|
||||
},
|
||||
enabled: enabled,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
type service struct {
|
||||
|
||||
@@ -17,7 +17,8 @@ import (
|
||||
func TestService(t *testing.T) {
|
||||
t.Run("dynamic", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mode := ProvideService(featuremgmt.WithFeatures(), nil, kvstore.NewFakeKVStore(), nil)
|
||||
mode, err := ProvideService(featuremgmt.WithFeatures(), kvstore.NewFakeKVStore(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
gr := schema.GroupResource{Group: "ggg", Resource: "rrr"}
|
||||
status, err := mode.Status(ctx, gr)
|
||||
@@ -69,6 +70,7 @@ func TestService(t *testing.T) {
|
||||
isStatic bool
|
||||
foldersFromUnified bool
|
||||
dashboardsFromUnified bool
|
||||
error string
|
||||
}
|
||||
|
||||
for _, tc := range []testCase{{
|
||||
@@ -93,14 +95,40 @@ func TestService(t *testing.T) {
|
||||
cfg: setting.Cfg{
|
||||
UnifiedStorage: map[string]setting.UnifiedStorageConfig{
|
||||
"dashboards.dashboard.grafana.app": {
|
||||
DualWriterMode: rest.Mode5,
|
||||
DualWriterMode: rest.Mode3,
|
||||
},
|
||||
},
|
||||
}}, {
|
||||
name: "invalid folder mode4",
|
||||
flags: featuremgmt.WithFeatures(featuremgmt.FlagProvisioning),
|
||||
error: "must use the same mode",
|
||||
cfg: setting.Cfg{
|
||||
UnifiedStorage: map[string]setting.UnifiedStorageConfig{
|
||||
"folders.folder.grafana.app": {
|
||||
DualWriterMode: rest.Mode4,
|
||||
},
|
||||
},
|
||||
}}, {
|
||||
name: "invalid dashboards mode4",
|
||||
flags: featuremgmt.WithFeatures(featuremgmt.FlagProvisioning),
|
||||
error: "must use the same mode",
|
||||
cfg: setting.Cfg{
|
||||
UnifiedStorage: map[string]setting.UnifiedStorageConfig{
|
||||
"dashboards.dashboard.grafana.app": {
|
||||
DualWriterMode: rest.Mode4,
|
||||
},
|
||||
},
|
||||
}},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
svc := ProvideService(tc.flags, nil, kvstore.NewFakeKVStore(), &tc.cfg)
|
||||
svc, err := ProvideService(tc.flags, kvstore.NewFakeKVStore(), &tc.cfg)
|
||||
if tc.error != "" {
|
||||
require.ErrorContains(t, err, tc.error)
|
||||
require.Nil(t, svc, "expect a nil service when an error exts")
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
_, isStatic := svc.(*staticService)
|
||||
require.Equal(t, tc.isStatic, isStatic)
|
||||
|
||||
Reference in New Issue
Block a user