From 8345af928cca93e25a050bc145f3ab2cffba04b1 Mon Sep 17 00:00:00 2001 From: Leonor Oliveira <9090754+leonorfmartins@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:57:44 +0100 Subject: [PATCH] [Dual writer] Read kind value passed as dualwriter's argument (#91113) * Include kind on the dualwriter to be used on metrics * Use kind as argument * Skip dual writer in mode4 --- pkg/apiserver/rest/dualwriter.go | 12 ++-- pkg/apiserver/rest/dualwriter_mode1.go | 61 ++++++---------- pkg/apiserver/rest/dualwriter_mode1_test.go | 13 ++-- pkg/apiserver/rest/dualwriter_mode2.go | 78 +++++++-------------- pkg/apiserver/rest/dualwriter_mode2_test.go | 12 ++-- pkg/apiserver/rest/dualwriter_mode3.go | 59 +++++----------- pkg/apiserver/rest/dualwriter_mode3_test.go | 12 ++-- pkg/apiserver/rest/dualwriter_mode4.go | 46 ++++-------- pkg/apiserver/rest/dualwriter_mode4_test.go | 12 ++-- pkg/services/apiserver/builder/helper.go | 8 ++- 10 files changed, 116 insertions(+), 197 deletions(-) diff --git a/pkg/apiserver/rest/dualwriter.go b/pkg/apiserver/rest/dualwriter.go index 94b3ae1f595..5cae1cf6f22 100644 --- a/pkg/apiserver/rest/dualwriter.go +++ b/pkg/apiserver/rest/dualwriter.go @@ -102,7 +102,7 @@ const ( // TODO: make this function private as there should only be one public way of setting the dual writing mode // NewDualWriter returns a new DualWriter. -func NewDualWriter(mode DualWriterMode, legacy LegacyStorage, storage Storage, reg prometheus.Registerer) DualWriter { +func NewDualWriter(mode DualWriterMode, legacy LegacyStorage, storage Storage, reg prometheus.Registerer, kind string) DualWriter { metrics := &dualWriterMetrics{} metrics.init(reg) switch mode { @@ -110,18 +110,18 @@ func NewDualWriter(mode DualWriterMode, legacy LegacyStorage, storage Storage, r // writing to legacy storage without `unifiedStorage` enabled. case Mode1: // read and write only from legacy storage - return newDualWriterMode1(legacy, storage, metrics) + return newDualWriterMode1(legacy, storage, metrics, kind) case Mode2: // write to both, read from storage but use legacy as backup - return newDualWriterMode2(legacy, storage, metrics) + return newDualWriterMode2(legacy, storage, metrics, kind) case Mode3: // write to both, read from storage only - return newDualWriterMode3(legacy, storage, metrics) + return newDualWriterMode3(legacy, storage, metrics, kind) case Mode4: // read and write only from storage - return newDualWriterMode4(legacy, storage, metrics) + return newDualWriterMode4(legacy, storage, metrics, kind) default: - return newDualWriterMode1(legacy, storage, metrics) + return newDualWriterMode1(legacy, storage, metrics, kind) } } diff --git a/pkg/apiserver/rest/dualwriter_mode1.go b/pkg/apiserver/rest/dualwriter_mode1.go index f09f589a56d..45d6288b4d1 100644 --- a/pkg/apiserver/rest/dualwriter_mode1.go +++ b/pkg/apiserver/rest/dualwriter_mode1.go @@ -18,15 +18,16 @@ type DualWriterMode1 struct { Legacy LegacyStorage Storage Storage *dualWriterMetrics - Log klog.Logger + kind string + Log klog.Logger } 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) *DualWriterMode1 { - return &DualWriterMode1{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode1").WithValues("mode", mode1Str), dualWriterMetrics: dwm} +func newDualWriterMode1(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, kind string) *DualWriterMode1 { + return &DualWriterMode1{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode1").WithValues("mode", mode1Str, "kind", kind), dualWriterMetrics: dwm} } // Mode returns the mode of the dual writer. @@ -37,18 +38,17 @@ func (d *DualWriterMode1) Mode() DualWriterMode { // Create overrides the behavior of the generic DualWriter and writes only to LegacyStorage. func (d *DualWriterMode1) Create(ctx context.Context, original runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { var method = "create" - var kind = original.GetObjectKind().GroupVersionKind().Kind - log := d.Log.WithValues("method", method, "kind", kind) + log := d.Log.WithValues("method", method) ctx = klog.NewContext(ctx, log) startLegacy := time.Now() created, err := d.Legacy.Create(ctx, original, createValidation, options) if err != nil { log.Error(err, "unable to create object in legacy storage") - d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode1Str, d.kind, method, startLegacy) return created, err } - d.recordLegacyDuration(false, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode1Str, d.kind, method, startLegacy) createdCopy := created.DeepCopyObject() @@ -62,7 +62,7 @@ func (d *DualWriterMode1) Create(ctx context.Context, original runtime.Object, c startStorage := time.Now() storageObj, errObjectSt := d.Storage.Create(ctx, createdCopy, createValidation, options) - d.recordStorageDuration(errObjectSt != nil, mode1Str, kind, method, startStorage) + d.recordStorageDuration(errObjectSt != nil, mode1Str, d.kind, method, startStorage) if err != nil { cancel() } @@ -87,19 +87,14 @@ func (d *DualWriterMode1) Get(ctx context.Context, name string, options *metav1. if errLegacy != nil { log.Error(errLegacy, "unable to get object in legacy storage") } - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - - d.recordLegacyDuration(errLegacy != nil, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(errLegacy != nil, mode1Str, d.kind, method, startLegacy) go func(res runtime.Object) { startStorage := time.Now() ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage get timeout")) defer cancel() storageObj, err := d.Storage.Get(ctx, name, options) - d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode1Str, d.kind, method, startStorage) if err != nil { log.Error(err, "unable to get object in storage") cancel() @@ -126,18 +121,14 @@ func (d *DualWriterMode1) List(ctx context.Context, options *metainternalversion if errLegacy != nil { log.Error(errLegacy, "unable to list object in legacy storage") } - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordLegacyDuration(errLegacy != nil, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(errLegacy != nil, mode1Str, d.kind, method, startLegacy) go func(res runtime.Object) { startStorage := time.Now() ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage list timeout")) defer cancel() storageObj, err := d.Storage.List(ctx, options) - d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode1Str, d.kind, method, startStorage) if err != nil { cancel() } @@ -158,13 +149,9 @@ func (d *DualWriterMode1) Delete(ctx context.Context, name string, deleteValidat startLegacy := time.Now() res, async, err := d.Legacy.Delete(ctx, name, deleteValidation, options) - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to delete object in legacy storage") - d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode1Str, d.kind, method, startLegacy) return res, async, err } d.recordLegacyDuration(false, mode1Str, name, method, startLegacy) @@ -174,7 +161,7 @@ func (d *DualWriterMode1) Delete(ctx context.Context, name string, deleteValidat ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage delete timeout")) defer cancel() storageObj, _, err := d.Storage.Delete(ctx, name, deleteValidation, options) - d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode1Str, d.kind, method, startStorage) if err != nil { cancel() } @@ -194,25 +181,21 @@ func (d *DualWriterMode1) DeleteCollection(ctx context.Context, deleteValidation log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startLegacy := time.Now() res, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions) - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to delete collection in legacy storage") - d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode1Str, d.kind, method, startLegacy) return res, err } - d.recordLegacyDuration(false, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode1Str, d.kind, method, startLegacy) go func(res runtime.Object) { startStorage := time.Now() ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage deletecollection timeout")) defer cancel() storageObj, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, listOptions) - d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode1Str, d.kind, method, startStorage) if err != nil { cancel() } @@ -230,19 +213,15 @@ func (d *DualWriterMode1) Update(ctx context.Context, name string, objInfo rest. var method = "update" log := d.Log.WithValues("name", name, "method", method, "name", name) ctx = klog.NewContext(ctx, log) - var kind string startLegacy := time.Now() res, async, err := d.Legacy.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to update in legacy storage") - d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode1Str, d.kind, method, startLegacy) return res, async, err } - d.recordLegacyDuration(false, mode1Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode1Str, d.kind, method, startLegacy) go func(res runtime.Object) { ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage update timeout")) @@ -278,7 +257,7 @@ func (d *DualWriterMode1) Update(ctx context.Context, name string, objInfo rest. startStorage := time.Now() defer cancel() storageObj, _, errObjectSt := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) - d.recordStorageDuration(errObjectSt != nil, mode1Str, kind, method, startStorage) + d.recordStorageDuration(errObjectSt != nil, mode1Str, d.kind, method, startStorage) if err != nil { cancel() } diff --git a/pkg/apiserver/rest/dualwriter_mode1_test.go b/pkg/apiserver/rest/dualwriter_mode1_test.go index 9e1fdff5ad9..ba2742af515 100644 --- a/pkg/apiserver/rest/dualwriter_mode1_test.go +++ b/pkg/apiserver/rest/dualwriter_mode1_test.go @@ -25,6 +25,7 @@ var exampleList = &example.PodList{TypeMeta: metav1.TypeMeta{Kind: "foo"}, ListM var anotherList = &example.PodList{Items: []example.Pod{*anotherObj}} var p = prometheus.NewRegistry() +var kind = "foo" func TestMode1_Create(t *testing.T) { type testCase struct { @@ -72,7 +73,7 @@ func TestMode1_Create(t *testing.T) { tt.setupStorageFn(m) } - dw := NewDualWriter(Mode1, ls, us, p) + dw := NewDualWriter(Mode1, ls, us, p, kind) obj, err := dw.Create(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.CreateOptions{}) @@ -135,7 +136,7 @@ func TestMode1_Get(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode1, ls, us, p) + dw := NewDualWriter(Mode1, ls, us, p, kind) obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) @@ -186,7 +187,7 @@ func TestMode1_List(t *testing.T) { tt.setupStorageFn(m) } - dw := NewDualWriter(Mode1, ls, us, p) + dw := NewDualWriter(Mode1, ls, us, p, kind) _, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) @@ -241,7 +242,7 @@ func TestMode1_Delete(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode1, ls, us, p) + dw := NewDualWriter(Mode1, ls, us, p, kind) obj, _, err := dw.Delete(context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) @@ -300,7 +301,7 @@ func TestMode1_DeleteCollection(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode1, ls, us, p) + dw := NewDualWriter(Mode1, ls, us, p, kind) obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{}) @@ -376,7 +377,7 @@ func TestMode1_Update(t *testing.T) { tt.setupGetFn(m, tt.input) } - dw := NewDualWriter(Mode1, ls, us, p) + dw := NewDualWriter(Mode1, ls, us, p, kind) obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) diff --git a/pkg/apiserver/rest/dualwriter_mode2.go b/pkg/apiserver/rest/dualwriter_mode2.go index 55768a80943..3b611f6e1ed 100644 --- a/pkg/apiserver/rest/dualwriter_mode2.go +++ b/pkg/apiserver/rest/dualwriter_mode2.go @@ -21,15 +21,16 @@ type DualWriterMode2 struct { Storage Storage Legacy LegacyStorage *dualWriterMetrics - Log klog.Logger + kind string + Log klog.Logger } const mode2Str = "2" // NewDualWriterMode2 returns a new DualWriter in mode 2. // Mode 2 represents writing to LegacyStorage and Storage and reading from LegacyStorage. -func newDualWriterMode2(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics) *DualWriterMode2 { - return &DualWriterMode2{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode2").WithValues("mode", mode2Str), dualWriterMetrics: dwm} +func newDualWriterMode2(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, kind string) *DualWriterMode2 { + return &DualWriterMode2{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode2").WithValues("mode", mode2Str, "kind", kind), dualWriterMetrics: dwm} } // Mode returns the mode of the dual writer. @@ -40,18 +41,17 @@ func (d *DualWriterMode2) Mode() DualWriterMode { // Create overrides the behavior of the generic DualWriter and writes to LegacyStorage and Storage. func (d *DualWriterMode2) Create(ctx context.Context, original runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { var method = "create" - var kind = original.GetObjectKind().GroupVersionKind().Kind - log := d.Log.WithValues("method", method, "kind", kind) + log := d.Log.WithValues("method", method) ctx = klog.NewContext(ctx, log) startLegacy := time.Now() created, err := d.Legacy.Create(ctx, original, createValidation, options) if err != nil { log.Error(err, "unable to create object in legacy storage") - d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode2Str, d.kind, method, startLegacy) return created, err } - d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode2Str, d.kind, method, startLegacy) if err := enrichLegacyObject(original, created); err != nil { return created, err @@ -61,10 +61,10 @@ func (d *DualWriterMode2) Create(ctx context.Context, original runtime.Object, c rsp, err := d.Storage.Create(ctx, created, createValidation, options) if err != nil { log.WithValues("name").Error(err, "unable to create object in storage") - d.recordStorageDuration(true, mode2Str, kind, method, startStorage) + d.recordStorageDuration(true, mode2Str, d.kind, method, startStorage) return rsp, err } - d.recordStorageDuration(false, mode2Str, kind, method, startStorage) + d.recordStorageDuration(false, mode2Str, d.kind, method, startStorage) areEqual := Compare(rsp, created) d.recordOutcome(mode2Str, getName(rsp), areEqual, method) @@ -82,12 +82,7 @@ func (d *DualWriterMode2) Get(ctx context.Context, name string, options *metav1. startStorage := time.Now() objStorage, err := d.Storage.Get(ctx, name, options) - var kind string - if objStorage != nil { - kind = objStorage.GetObjectKind().GroupVersionKind().Kind - } - - d.recordStorageDuration(err != nil, mode2Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode2Str, d.kind, method, startStorage) if err != nil { // if it errors because it's not found, we try to fetch it from the legacy storage if !apierrors.IsNotFound(err) { @@ -101,10 +96,10 @@ func (d *DualWriterMode2) Get(ctx context.Context, name string, options *metav1. objLegacy, err := d.Legacy.Get(ctx, name, options) if err != nil { log.Error(err, "unable to fetch object from legacy") - d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode2Str, d.kind, method, startLegacy) return objLegacy, err } - d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode2Str, d.kind, method, startLegacy) areEqual := Compare(objStorage, objLegacy) d.recordOutcome(mode2Str, name, areEqual, method) @@ -128,16 +123,12 @@ func (d *DualWriterMode2) List(ctx context.Context, options *metainternalversion startLegacy := time.Now() ll, err := d.Legacy.List(ctx, options) - var kind string - if ll != nil { - kind = ll.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to list objects from legacy storage") - d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode2Str, d.kind, method, startLegacy) return ll, err } - d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode2Str, d.kind, method, startLegacy) legacyList, err := meta.ExtractList(ll) if err != nil { @@ -160,10 +151,10 @@ func (d *DualWriterMode2) List(ctx context.Context, options *metainternalversion sl, err := d.Storage.List(ctx, &optionsStorage) if err != nil { log.Error(err, "unable to list objects from storage") - d.recordStorageDuration(true, mode2Str, kind, method, startStorage) + d.recordStorageDuration(true, mode2Str, d.kind, method, startStorage) return sl, err } - d.recordStorageDuration(false, mode2Str, kind, method, startStorage) + d.recordStorageDuration(false, mode2Str, d.kind, method, startStorage) storageList, err := meta.ExtractList(sl) if err != nil { @@ -205,18 +196,14 @@ func (d *DualWriterMode2) DeleteCollection(ctx context.Context, deleteValidation log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startLegacy := time.Now() deleted, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions) - if deleted != nil { - kind = deleted.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.WithValues("deleted", deleted).Error(err, "failed to delete collection successfully from legacy storage") - d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode2Str, d.kind, method, startLegacy) return deleted, err } - d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode2Str, d.kind, method, startLegacy) legacyList, err := meta.ExtractList(deleted) if err != nil { @@ -237,10 +224,10 @@ func (d *DualWriterMode2) DeleteCollection(ctx context.Context, deleteValidation res, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, &optionsStorage) if err != nil { log.WithValues("deleted", res).Error(err, "failed to delete collection successfully from Storage") - d.recordStorageDuration(true, mode2Str, kind, method, startStorage) + d.recordStorageDuration(true, mode2Str, d.kind, method, startStorage) return res, err } - d.recordStorageDuration(false, mode2Str, kind, method, startStorage) + d.recordStorageDuration(false, mode2Str, d.kind, method, startStorage) areEqual := Compare(res, deleted) d.recordOutcome(mode2Str, getName(res), areEqual, method) @@ -255,33 +242,29 @@ func (d *DualWriterMode2) Delete(ctx context.Context, name string, deleteValidat var method = "delete" log := d.Log.WithValues("name", name, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startLegacy := time.Now() deletedLS, async, err := d.Legacy.Delete(ctx, name, deleteValidation, options) - if deletedLS != nil { - kind = deletedLS.GetObjectKind().GroupVersionKind().Kind - } if err != nil { if !apierrors.IsNotFound(err) { log.WithValues("objectList", deletedLS).Error(err, "could not delete from legacy store") - d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(true, mode2Str, d.kind, method, startLegacy) return deletedLS, async, err } } - d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy) + d.recordLegacyDuration(false, mode2Str, d.kind, method, startLegacy) startStorage := time.Now() deletedS, _, err := d.Storage.Delete(ctx, name, deleteValidation, options) if err != nil { if !apierrors.IsNotFound(err) { log.WithValues("objectList", deletedS).Error(err, "could not delete from duplicate storage") - d.recordStorageDuration(true, mode2Str, kind, method, startStorage) + d.recordStorageDuration(true, mode2Str, d.kind, method, startStorage) } return deletedS, async, err } - d.recordStorageDuration(false, mode2Str, kind, method, startStorage) + d.recordStorageDuration(false, mode2Str, d.kind, method, startStorage) areEqual := Compare(deletedS, deletedLS) d.recordOutcome(mode2Str, name, areEqual, method) @@ -297,13 +280,9 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest. var method = "update" log := d.Log.WithValues("name", name, "method", method) ctx = klog.NewContext(ctx, log) - var kind string // get foundObj and (updated) object so they can be stored in legacy store foundObj, err := d.Storage.Get(ctx, name, &metav1.GetOptions{}) - if foundObj != nil { - kind = foundObj.GetObjectKind().GroupVersionKind().Kind - } if err != nil { if !apierrors.IsNotFound(err) { log.WithValues("object", foundObj).Error(err, "could not get object to update") @@ -314,9 +293,6 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest. // obj can be populated in case it's found or empty in case it's not found updated, err := objInfo.UpdatedObject(ctx, foundObj) - if updated != nil { - kind = updated.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.WithValues("object", updated).Error(err, "could not update or create object") return nil, false, err @@ -326,10 +302,10 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest. obj, created, err := d.Legacy.Update(ctx, name, &updateWrapper{upstream: objInfo, updated: updated}, createValidation, updateValidation, forceAllowCreate, options) if err != nil { log.WithValues("object", obj).Error(err, "could not update in legacy storage") - d.recordLegacyDuration(true, mode2Str, kind, "update", startLegacy) + d.recordLegacyDuration(true, mode2Str, d.kind, "update", startLegacy) return obj, created, err } - d.recordLegacyDuration(false, mode2Str, kind, "update", startLegacy) + d.recordLegacyDuration(false, mode2Str, d.kind, "update", startLegacy) // if the object is found, create a new updateWrapper with the object found if foundObj != nil { @@ -348,7 +324,7 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest. res, created, err := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) if err != nil { log.WithValues("object", res).Error(err, "could not update in storage") - d.recordStorageDuration(true, mode2Str, kind, "update", startStorage) + d.recordStorageDuration(true, mode2Str, d.kind, "update", startStorage) return res, created, err } diff --git a/pkg/apiserver/rest/dualwriter_mode2_test.go b/pkg/apiserver/rest/dualwriter_mode2_test.go index f0c89b6ad75..fd7e168b84a 100644 --- a/pkg/apiserver/rest/dualwriter_mode2_test.go +++ b/pkg/apiserver/rest/dualwriter_mode2_test.go @@ -67,7 +67,7 @@ func TestMode2_Create(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode2, ls, us, p) + dw := NewDualWriter(Mode2, ls, us, p, kind) obj, err := dw.Create(context.Background(), tt.input, createFn, &metav1.CreateOptions{}) @@ -143,7 +143,7 @@ func TestMode2_Get(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode2, ls, us, p) + dw := NewDualWriter(Mode2, ls, us, p, kind) obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) @@ -196,7 +196,7 @@ func TestMode2_List(t *testing.T) { tt.setupStorageFn(m) } - dw := NewDualWriter(Mode2, ls, us, p) + dw := NewDualWriter(Mode2, ls, us, p, kind) obj, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) @@ -289,7 +289,7 @@ func TestMode2_Delete(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode2, ls, us, p) + dw := NewDualWriter(Mode2, ls, us, p, kind) obj, _, err := dw.Delete(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{}) @@ -361,7 +361,7 @@ func TestMode2_DeleteCollection(t *testing.T) { tt.setupStorageFn(m) } - dw := NewDualWriter(Mode2, ls, us, p) + dw := NewDualWriter(Mode2, ls, us, p, kind) obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: tt.input}}, &metainternalversion.ListOptions{}) @@ -469,7 +469,7 @@ func TestMode2_Update(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode2, ls, us, p) + dw := NewDualWriter(Mode2, ls, us, p, kind) obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) diff --git a/pkg/apiserver/rest/dualwriter_mode3.go b/pkg/apiserver/rest/dualwriter_mode3.go index 17e9560b0c3..76dd8adb127 100644 --- a/pkg/apiserver/rest/dualwriter_mode3.go +++ b/pkg/apiserver/rest/dualwriter_mode3.go @@ -16,13 +16,14 @@ type DualWriterMode3 struct { Legacy LegacyStorage Storage Storage *dualWriterMetrics - Log klog.Logger + kind string + Log klog.Logger } // 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) *DualWriterMode3 { - return &DualWriterMode3{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode3").WithValues("mode", mode3Str), dualWriterMetrics: dwm} +func newDualWriterMode3(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, kind string) *DualWriterMode3 { + return &DualWriterMode3{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode3").WithValues("mode", mode3Str, "kind", kind), dualWriterMetrics: dwm} } // Mode returns the mode of the dual writer. @@ -35,18 +36,17 @@ const mode3Str = "3" // Create overrides the behavior of the generic DualWriter and writes to LegacyStorage and Storage. func (d *DualWriterMode3) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { var method = "create" - var kind = obj.GetObjectKind().GroupVersionKind().Kind - log := d.Log.WithValues("kind", kind, "method", method) + log := d.Log.WithValues("method", method) ctx = klog.NewContext(ctx, log) startStorage := time.Now() created, err := d.Storage.Create(ctx, obj, createValidation, options) if err != nil { log.Error(err, "unable to create object in storage") - d.recordLegacyDuration(true, mode3Str, kind, method, startStorage) + d.recordLegacyDuration(true, mode3Str, d.kind, method, startStorage) return created, err } - d.recordStorageDuration(false, mode3Str, kind, method, startStorage) + d.recordStorageDuration(false, mode3Str, d.kind, method, startStorage) go func() { ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy create timeout")) @@ -54,7 +54,7 @@ func (d *DualWriterMode3) Create(ctx context.Context, obj runtime.Object, create startLegacy := time.Now() _, errObjectSt := d.Legacy.Create(ctx, obj, createValidation, options) - d.recordLegacyDuration(errObjectSt != nil, mode3Str, kind, method, startLegacy) + d.recordLegacyDuration(errObjectSt != nil, mode3Str, d.kind, method, startLegacy) }() return created, err @@ -71,12 +71,7 @@ func (d *DualWriterMode3) Get(ctx context.Context, name string, options *metav1. if err != nil { log.Error(err, "unable to get object in storage") } - - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode3Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode3Str, d.kind, method, startStorage) return res, err } @@ -92,11 +87,7 @@ func (d *DualWriterMode3) List(ctx context.Context, options *metainternalversion if err != nil { log.Error(err, "unable to list object in storage") } - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode3Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode3Str, d.kind, method, startStorage) return res, err } @@ -106,15 +97,11 @@ func (d *DualWriterMode3) Delete(ctx context.Context, name string, deleteValidat log := d.Log.WithValues("name", name, "method", method) ctx = klog.NewContext(ctx, d.Log) - var kind string startStorage := time.Now() res, async, err := d.Storage.Delete(ctx, name, deleteValidation, options) - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to delete object in storage") - d.recordStorageDuration(true, mode3Str, kind, method, startStorage) + d.recordStorageDuration(true, mode3Str, d.kind, method, startStorage) return res, async, err } d.recordStorageDuration(false, mode3Str, name, method, startStorage) @@ -124,7 +111,7 @@ func (d *DualWriterMode3) Delete(ctx context.Context, name string, deleteValidat ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy delete timeout")) defer cancel() _, _, err := d.Legacy.Delete(ctx, name, deleteValidation, options) - d.recordLegacyDuration(err != nil, mode3Str, kind, method, startLegacy) + d.recordLegacyDuration(err != nil, mode3Str, d.kind, method, startLegacy) }() return res, async, err @@ -135,19 +122,15 @@ func (d *DualWriterMode3) Update(ctx context.Context, name string, objInfo rest. var method = "update" log := d.Log.WithValues("name", name, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startStorage := time.Now() res, async, err := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to update in storage") - d.recordLegacyDuration(true, mode3Str, kind, method, startStorage) + d.recordLegacyDuration(true, mode3Str, d.kind, method, startStorage) return res, async, err } - d.recordStorageDuration(false, mode3Str, kind, method, startStorage) + d.recordStorageDuration(false, mode3Str, d.kind, method, startStorage) go func() { ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy update timeout")) @@ -155,7 +138,7 @@ func (d *DualWriterMode3) Update(ctx context.Context, name string, objInfo rest. startLegacy := time.Now() defer cancel() _, _, errObjectSt := d.Legacy.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) - d.recordLegacyDuration(errObjectSt != nil, mode3Str, kind, method, startLegacy) + d.recordLegacyDuration(errObjectSt != nil, mode3Str, d.kind, method, startLegacy) }() return res, async, err @@ -166,26 +149,22 @@ func (d *DualWriterMode3) DeleteCollection(ctx context.Context, deleteValidation var method = "delete-collection" log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startStorage := time.Now() res, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, listOptions) - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } if err != nil { log.Error(err, "unable to delete collection in storage") - d.recordStorageDuration(true, mode3Str, kind, method, startStorage) + d.recordStorageDuration(true, mode3Str, d.kind, method, startStorage) return res, err } - d.recordStorageDuration(false, mode3Str, kind, method, startStorage) + d.recordStorageDuration(false, mode3Str, d.kind, method, startStorage) go func() { startLegacy := time.Now() ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy deletecollection timeout")) defer cancel() _, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions) - d.recordStorageDuration(err != nil, mode3Str, kind, method, startLegacy) + d.recordStorageDuration(err != nil, mode3Str, d.kind, method, startLegacy) }() return res, err @@ -194,7 +173,7 @@ func (d *DualWriterMode3) DeleteCollection(ctx context.Context, deleteValidation //TODO: uncomment when storage watch is implemented // func (d *DualWriterMode3) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { // var method = "watch" -// d.Log.WithValues("kind", options.Kind, "method", method, "mode", mode3Str).Info("starting to watch") +// d.Log.WithValues("kind", d.kind, "method", method, "mode", mode3Str).Info("starting to watch") // return d.Storage.Watch(ctx, options) // } diff --git a/pkg/apiserver/rest/dualwriter_mode3_test.go b/pkg/apiserver/rest/dualwriter_mode3_test.go index b32e6fe3daa..ecbd2724c83 100644 --- a/pkg/apiserver/rest/dualwriter_mode3_test.go +++ b/pkg/apiserver/rest/dualwriter_mode3_test.go @@ -60,7 +60,7 @@ func TestMode3_Create(t *testing.T) { tt.setupStorageFn(m) } - dw := NewDualWriter(Mode3, ls, us, p) + dw := NewDualWriter(Mode3, ls, us, p, kind) obj, err := dw.Create(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.CreateOptions{}) @@ -117,7 +117,7 @@ func TestMode3_Get(t *testing.T) { } p := prometheus.NewRegistry() - dw := NewDualWriter(Mode3, ls, us, p) + dw := NewDualWriter(Mode3, ls, us, p, kind) obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) @@ -171,7 +171,7 @@ func TestMode3_List(t *testing.T) { tt.setupStorageFn(m, tt.options) } - dw := NewDualWriter(Mode3, ls, us, p) + dw := NewDualWriter(Mode3, ls, us, p, kind) res, err := dw.List(context.Background(), tt.options) @@ -225,7 +225,7 @@ func TestMode3_Delete(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode3, ls, us, p) + dw := NewDualWriter(Mode3, ls, us, p, kind) obj, _, err := dw.Delete(context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) @@ -279,7 +279,7 @@ func TestMode3_DeleteCollection(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode3, ls, us, p) + dw := NewDualWriter(Mode3, ls, us, p, kind) obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{}) @@ -340,7 +340,7 @@ func TestMode3_Update(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode3, ls, us, p) + dw := NewDualWriter(Mode3, ls, us, p, kind) obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) diff --git a/pkg/apiserver/rest/dualwriter_mode4.go b/pkg/apiserver/rest/dualwriter_mode4.go index 94df3cea591..f0491e567a0 100644 --- a/pkg/apiserver/rest/dualwriter_mode4.go +++ b/pkg/apiserver/rest/dualwriter_mode4.go @@ -15,15 +15,16 @@ type DualWriterMode4 struct { Legacy LegacyStorage Storage Storage *dualWriterMetrics - Log klog.Logger + kind string + Log klog.Logger } const mode4Str = "4" // newDualWriterMode4 returns a new DualWriter in mode 4. // Mode 4 represents writing and reading from Storage. -func newDualWriterMode4(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics) *DualWriterMode4 { - return &DualWriterMode4{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode4").WithValues("mode", mode4Str), dualWriterMetrics: dwm} +func newDualWriterMode4(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, kind string) *DualWriterMode4 { + return &DualWriterMode4{Legacy: legacy, Storage: storage, Log: klog.NewKlogr().WithName("DualWriterMode4").WithValues("mode", mode4Str, "kind", kind), dualWriterMetrics: dwm} } // Mode returns the mode of the dual writer. @@ -36,8 +37,7 @@ func (d *DualWriterMode4) Mode() DualWriterMode { // Create overrides the behavior of the generic DualWriter and writes only to Storage. func (d *DualWriterMode4) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { var method = "create" - var kind = obj.GetObjectKind().GroupVersionKind().Kind - log := d.Log.WithValues("method", method, "kind", kind) + log := d.Log.WithValues("method", method) ctx = klog.NewContext(ctx, log) startStorage := time.Now() @@ -45,7 +45,7 @@ func (d *DualWriterMode4) Create(ctx context.Context, obj runtime.Object, create if err != nil { log.Error(err, "unable to create object in storage") } - d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode4Str, d.kind, method, startStorage) return res, err } @@ -60,11 +60,7 @@ func (d *DualWriterMode4) Get(ctx context.Context, name string, options *metav1. if err != nil { log.Error(err, "unable to create object in storage") } - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode4Str, d.kind, method, startStorage) return res, err } @@ -73,16 +69,12 @@ func (d *DualWriterMode4) Delete(ctx context.Context, name string, deleteValidat log := d.Log.WithValues("name", name, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startStorage := time.Now() res, async, err := d.Storage.Delete(ctx, name, deleteValidation, options) if err != nil { log.Error(err, "unable to delete object in storage") } - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode4Str, d.kind, method, startStorage) return res, async, err } @@ -91,36 +83,28 @@ func (d *DualWriterMode4) DeleteCollection(ctx context.Context, deleteValidation var method = "delete-collection" log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method, "mode", mode4Str) ctx = klog.NewContext(ctx, log) - var kind string startStorage := time.Now() res, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, listOptions) if err != nil { log.Error(err, "unable to delete collection in storage") } - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode4Str, d.kind, method, startStorage) return res, err } // Update overrides the generic behavior of the Storage and writes only to US. func (d *DualWriterMode4) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { var method = "update" - log := d.Log.WithValues("name", name, "method", method) + log := d.Log.WithValues("name", name, "kind", d.kind, "method", method) ctx = klog.NewContext(ctx, log) - var kind string startStorage := time.Now() res, async, err := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) if err != nil { log.Error(err, "unable to update object in storage") } - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode4Str, d.kind, method, startStorage) return res, async, err } @@ -134,18 +118,14 @@ func (d *DualWriterMode4) List(ctx context.Context, options *metainternalversion if err != nil { log.Error(err, "unable to list objects in storage") } - var kind string - if res != nil { - kind = res.GetObjectKind().GroupVersionKind().Kind - } - d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage) + d.recordStorageDuration(err != nil, mode4Str, d.kind, method, startStorage) return res, err } //TODO: uncomment when storage watch is implemented // func (d *DualWriterMode4) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { // var method = "watch" -// d.Log.WithValues("kind", kind, "method", method, "mode", mode4Str).Info("starting to watch") +// d.Log.WithValues("kind", d.kind, "method", method, "mode", mode4Str).Info("starting to watch") // return d.Storage.Watch(ctx, options) // } diff --git a/pkg/apiserver/rest/dualwriter_mode4_test.go b/pkg/apiserver/rest/dualwriter_mode4_test.go index bddaf4a7995..eda09e0790b 100644 --- a/pkg/apiserver/rest/dualwriter_mode4_test.go +++ b/pkg/apiserver/rest/dualwriter_mode4_test.go @@ -53,7 +53,7 @@ func TestMode4_Create(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode4, ls, us, p) + dw := NewDualWriter(Mode4, ls, us, p, kind) obj, err := dw.Create(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.CreateOptions{}) @@ -110,7 +110,7 @@ func TestMode4_Get(t *testing.T) { } p := prometheus.NewRegistry() - dw := NewDualWriter(Mode4, ls, us, p) + dw := NewDualWriter(Mode4, ls, us, p, kind) obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) @@ -166,7 +166,7 @@ func TestMode4_List(t *testing.T) { tt.setupStorageFn(m, tt.options) } - dw := NewDualWriter(Mode4, ls, us, p) + dw := NewDualWriter(Mode4, ls, us, p, kind) res, err := dw.List(context.Background(), tt.options) @@ -220,7 +220,7 @@ func TestMode4_Delete(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode4, ls, us, p) + dw := NewDualWriter(Mode4, ls, us, p, kind) obj, _, err := dw.Delete(context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) @@ -275,7 +275,7 @@ func TestMode4_DeleteCollection(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode4, ls, us, p) + dw := NewDualWriter(Mode4, ls, us, p, kind) obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{}) @@ -330,7 +330,7 @@ func TestMode4_Update(t *testing.T) { tt.setupStorageFn(m, tt.input) } - dw := NewDualWriter(Mode4, ls, us, p) + dw := NewDualWriter(Mode4, ls, us, p, kind) obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) diff --git a/pkg/services/apiserver/builder/helper.go b/pkg/services/apiserver/builder/helper.go index d0cc628fbcf..28cef15a8c8 100644 --- a/pkg/services/apiserver/builder/helper.go +++ b/pkg/services/apiserver/builder/helper.go @@ -174,10 +174,14 @@ func InstallAPIs( if err != nil { return nil, err } - if currentMode == grafanarest.Mode0 { + switch currentMode { + case grafanarest.Mode0: return legacy, nil + case grafanarest.Mode4: + return storage, nil + default: } - return grafanarest.NewDualWriter(currentMode, legacy, storage, reg), nil + return grafanarest.NewDualWriter(currentMode, legacy, storage, reg, key), nil } }