Allow downgrade from any mode to mode 1 or 2. Allow setting all dual writer combinations (#95968)
* Allow downgrade from any mode to mode 1 or 2 * Allow for all combinations of dual writer setting * Add all cases * Include mode3
This commit is contained in:
@@ -169,6 +169,7 @@ func SetDualWritingMode(
|
||||
"2": Mode2,
|
||||
"3": Mode3,
|
||||
"4": Mode4,
|
||||
"5": Mode5,
|
||||
}
|
||||
errDualWriterSetCurrentMode := errors.New("failed to set current dual writing mode")
|
||||
|
||||
@@ -195,33 +196,14 @@ func SetDualWritingMode(
|
||||
}
|
||||
}
|
||||
|
||||
// Desired mode is 2 and current mode is 1
|
||||
if (desiredMode == Mode2) && (currentMode == Mode1) {
|
||||
// This is where we go through the different gates to allow the instance to migrate from mode 1 to mode 2.
|
||||
// There are none between mode 1 and mode 2
|
||||
currentMode = Mode2
|
||||
|
||||
switch {
|
||||
case desiredMode == Mode2 || desiredMode == Mode1:
|
||||
currentMode = desiredMode
|
||||
err := kvs.Set(ctx, entity, fmt.Sprint(currentMode))
|
||||
if err != nil {
|
||||
return Mode0, errDualWriterSetCurrentMode
|
||||
}
|
||||
}
|
||||
|
||||
if (desiredMode == Mode1) && (currentMode == Mode2) {
|
||||
// This is where we go through the different gates to allow the instance to migrate from mode 2 to mode 1.
|
||||
// There are none between mode 1 and mode 2
|
||||
currentMode = Mode1
|
||||
|
||||
err := kvs.Set(ctx, entity, fmt.Sprint(currentMode))
|
||||
if err != nil {
|
||||
return Mode0, errDualWriterSetCurrentMode
|
||||
}
|
||||
}
|
||||
|
||||
if (desiredMode == Mode3) && (currentMode == Mode2) {
|
||||
// This is where we go through the different gates to allow the instance to migrate from mode 2 to mode 3.
|
||||
|
||||
// gate #1: ensure the data is 100% in sync
|
||||
case desiredMode >= Mode3 && currentMode < Mode3:
|
||||
syncOk, err := runDataSyncer(ctx, currentMode, legacy, storage, entity, reg, serverLockService, requestInfo)
|
||||
if err != nil {
|
||||
klog.Info("data syncer failed for mode:", m)
|
||||
@@ -236,12 +218,16 @@ func SetDualWritingMode(
|
||||
if err != nil {
|
||||
return currentMode, errDualWriterSetCurrentMode
|
||||
}
|
||||
|
||||
return desiredMode, nil
|
||||
case desiredMode >= Mode3 && currentMode >= Mode3:
|
||||
currentMode = desiredMode
|
||||
err := kvs.Set(ctx, entity, fmt.Sprint(currentMode))
|
||||
if err != nil {
|
||||
return currentMode, errDualWriterSetCurrentMode
|
||||
}
|
||||
default:
|
||||
return Mode0, errDualWriterSetCurrentMode
|
||||
}
|
||||
|
||||
// #TODO add support for other combinations of desired and current modes
|
||||
|
||||
return currentMode, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -17,25 +16,42 @@ import (
|
||||
func TestSetDualWritingMode(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
stackID string
|
||||
kvStore *fakeNamespacedKV
|
||||
desiredMode DualWriterMode
|
||||
expectedMode DualWriterMode
|
||||
}
|
||||
tests :=
|
||||
// #TODO add test cases for kv store failures. Requires adding support in kvstore test_utils.go
|
||||
[]testCase{
|
||||
{
|
||||
name: "should return a mode 2 dual writer when mode 2 is set as the desired mode",
|
||||
stackID: "stack-1",
|
||||
kvStore: &fakeNamespacedKV{data: map[string]string{"playlist.grafana.app/playlists": "2"}, namespace: "storage.dualwriting"},
|
||||
desiredMode: Mode2,
|
||||
expectedMode: Mode2,
|
||||
},
|
||||
{
|
||||
name: "should return a mode 1 dual writer when mode 1 is set as the desired mode",
|
||||
stackID: "stack-1",
|
||||
kvStore: &fakeNamespacedKV{data: map[string]string{"playlist.grafana.app/playlists": "2"}, namespace: "storage.dualwriting"},
|
||||
desiredMode: Mode1,
|
||||
expectedMode: Mode1,
|
||||
},
|
||||
{
|
||||
name: "should return mode 3 as desired mode when current mode is > 3",
|
||||
kvStore: &fakeNamespacedKV{data: map[string]string{"playlist.grafana.app/playlists": "5"}, namespace: "storage.dualwriting"},
|
||||
desiredMode: Mode3,
|
||||
expectedMode: Mode3,
|
||||
},
|
||||
{
|
||||
name: "should return mode 3 as desired mode when current mode is 2",
|
||||
kvStore: &fakeNamespacedKV{data: map[string]string{"playlist.grafana.app/playlists": "2"}, namespace: "storage.dualwriting"},
|
||||
desiredMode: Mode3,
|
||||
expectedMode: Mode3,
|
||||
},
|
||||
{
|
||||
name: "should default to mode 0 if there is no desired mode",
|
||||
kvStore: &fakeNamespacedKV{data: map[string]string{}, namespace: "storage.dualwriting"},
|
||||
desiredMode: Mode0,
|
||||
expectedMode: Mode0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -49,17 +65,9 @@ func TestSetDualWritingMode(t *testing.T) {
|
||||
ls := legacyStoreMock{m, l}
|
||||
us := storageMock{m, s}
|
||||
|
||||
kvStore := &fakeNamespacedKV{data: make(map[string]string), namespace: "storage.dualwriting." + tt.stackID}
|
||||
|
||||
dwMode, err := SetDualWritingMode(context.Background(), kvStore, ls, us, "playlist.grafana.app/v0alpha1", tt.desiredMode, p, &fakeServerLock{}, &request.RequestInfo{})
|
||||
dwMode, err := SetDualWritingMode(context.Background(), tt.kvStore, ls, us, "playlist.grafana.app/playlists", tt.desiredMode, p, &fakeServerLock{}, &request.RequestInfo{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expectedMode, dwMode)
|
||||
|
||||
// check kv store
|
||||
val, ok, err := kvStore.Get(context.Background(), "playlist.grafana.app/v0alpha1")
|
||||
assert.True(t, ok)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, val, fmt.Sprint(tt.expectedMode))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +121,7 @@ type fakeNamespacedKV struct {
|
||||
}
|
||||
|
||||
func (f *fakeNamespacedKV) Get(ctx context.Context, key string) (string, bool, error) {
|
||||
val, ok := f.data[f.namespace+key]
|
||||
val, ok := f.data[key]
|
||||
return val, ok, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user