@@ -2,10 +2,15 @@ package rest
2
2
3
3
import (
4
4
"context"
5
+ "errors"
6
+ "fmt"
5
7
8
+ "github.com/grafana/grafana/pkg/infra/kvstore"
9
+ "github.com/grafana/grafana/pkg/services/featuremgmt"
6
10
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7
11
"k8s.io/apimachinery/pkg/runtime"
8
12
"k8s.io/apiserver/pkg/registry/rest"
13
+ "k8s.io/klog/v2"
9
14
)
10
15
11
16
var (
@@ -69,12 +74,13 @@ type LegacyStorage interface {
69
74
type DualWriter interface {
70
75
Storage
71
76
LegacyStorage
77
+ Mode () DualWriterMode
72
78
}
73
79
74
80
type DualWriterMode int
75
81
76
82
const (
77
- Mode1 DualWriterMode = iota
83
+ Mode1 DualWriterMode = iota + 1
78
84
Mode2
79
85
Mode3
80
86
Mode4
@@ -117,3 +123,70 @@ func (u *updateWrapper) Preconditions() *metav1.Preconditions {
117
123
func (u * updateWrapper ) UpdatedObject (ctx context.Context , oldObj runtime.Object ) (newObj runtime.Object , err error ) {
118
124
return u .updated , nil
119
125
}
126
+
127
+ func SetDualWritingMode (
128
+ ctx context.Context ,
129
+ kvs * kvstore.NamespacedKVStore ,
130
+ features featuremgmt.FeatureToggles ,
131
+ entity string ,
132
+ legacy LegacyStorage ,
133
+ storage Storage ,
134
+ ) (DualWriter , error ) {
135
+ toMode := map [string ]DualWriterMode {
136
+ "1" : Mode1 ,
137
+ "2" : Mode2 ,
138
+ "3" : Mode3 ,
139
+ "4" : Mode4 ,
140
+ }
141
+ errDualWriterSetCurrentMode := errors .New ("failed to set current dual writing mode" )
142
+
143
+ // Use entity name as key
144
+ m , ok , err := kvs .Get (ctx , entity )
145
+ if err != nil {
146
+ return nil , errors .New ("failed to fetch current dual writing mode" )
147
+ }
148
+
149
+ currentMode , valid := toMode [m ]
150
+
151
+ if ! valid && ok {
152
+ // Only log if "ok" because initially all instances will have mode unset for playlists.
153
+ klog .Info ("invalid dual writing mode for playlists mode:" , m )
154
+ }
155
+
156
+ if ! valid || ! ok {
157
+ // Default to mode 1
158
+ currentMode = Mode1
159
+
160
+ err := kvs .Set (ctx , entity , fmt .Sprint (currentMode ))
161
+ if err != nil {
162
+ return nil , errDualWriterSetCurrentMode
163
+ }
164
+ }
165
+
166
+ // Desired mode is 2 and current mode is 1
167
+ if features .IsEnabledGlobally (featuremgmt .FlagDualWritePlaylistsMode2 ) && (currentMode == Mode1 ) {
168
+ // This is where we go through the different gates to allow the instance to migrate from mode 1 to mode 2.
169
+ // There are none between mode 1 and mode 2
170
+ currentMode = Mode2
171
+
172
+ err := kvs .Set (ctx , entity , fmt .Sprint (currentMode ))
173
+ if err != nil {
174
+ return nil , errDualWriterSetCurrentMode
175
+ }
176
+ }
177
+ // #TODO enable this check when we have a flag/config for setting mode 1 as the desired mode
178
+ // if features.IsEnabledGlobally(featuremgmt.FlagDualWritePlaylistsMode1) && (currentMode == Mode2) {
179
+ // // This is where we go through the different gates to allow the instance to migrate from mode 2 to mode 1.
180
+ // // There are none between mode 1 and mode 2
181
+ // currentMode = Mode1
182
+
183
+ // err := kvs.Set(ctx, entity, fmt.Sprint(currentMode))
184
+ // if err != nil {
185
+ // return nil, errDualWriterSetCurrentMode
186
+ // }
187
+ // }
188
+
189
+ // #TODO add support for other combinations of desired and current modes
190
+
191
+ return NewDualWriter (currentMode , legacy , storage ), nil
192
+ }
0 commit comments