Unistore/dualwriter: delegate SetDefaultPermissions to Unified on Mode3 (#109308)

* Unistore/dualwriter: delegate SetDefaultPermissions to Unified on Mode3

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>

---------

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>
This commit is contained in:
maicon
2025-08-07 18:41:41 -03:00
committed by GitHub
parent e6c24e0709
commit a5abc6727f
2 changed files with 29 additions and 39 deletions
+28 -10
View File
@@ -39,16 +39,7 @@ type dualWriter struct {
func (d *dualWriter) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
// If we read from unified, we can just do that and return.
if d.readUnified {
unifiedGet, unifiedErr := d.unified.Get(ctx, name, options)
if apierrors.IsNotFound(unifiedErr) {
// If resource is not found in unified storage, fallback to legacy.
// This fixes cases in where records (stored in multiple tables, including permissions)
// are inserted first in legacy and then on Unified.
log := logging.FromContext(ctx).With("method", "Get")
log.Error("resource not found in Unified Storage, trying to GET from legacy", "err", unifiedErr)
return d.legacy.Get(ctx, name, options)
}
return unifiedGet, unifiedErr
return d.unified.Get(ctx, name, options)
}
// If legacy is still our main store, lets first read from it.
legacyGet, err := d.legacy.Get(ctx, name, options)
@@ -196,6 +187,22 @@ func (d *dualWriter) Create(ctx context.Context, in runtime.Object, createValida
return nil, fmt.Errorf("name or generatename have to be set")
}
readFromUnifiedWriteToBothStorages := d.readUnified && d.legacy != nil && d.unified != nil
permissions := ""
if readFromUnifiedWriteToBothStorages {
objIn, err := utils.MetaAccessor(in)
if err != nil {
return nil, err
}
// keep permissions, we will set it back after the object is created
permissions = objIn.GetAnnotation(utils.AnnoKeyGrantPermissions)
if permissions != "" {
objIn.SetAnnotation(utils.AnnoKeyGrantPermissions, "") // remove the annotation for now
}
}
// create in legacy first, and then unistore. if unistore fails, but legacy succeeds,
// will try to cleanup the object in legacy.
createdFromLegacy, err := d.legacy.Create(ctx, in, createValidation, options)
@@ -212,6 +219,17 @@ func (d *dualWriter) Create(ctx context.Context, in runtime.Object, createValida
accCreated.SetResourceVersion("")
accCreated.SetUID("")
if readFromUnifiedWriteToBothStorages {
objCopy, err := utils.MetaAccessor(createdCopy)
if err != nil {
return nil, err
}
// restore the permissions annotation, as we removed it before creating in legacy
if permissions != "" {
objCopy.SetAnnotation(utils.AnnoKeyGrantPermissions, permissions)
}
}
// If unified storage is the primary storage, let's just create it in the foreground and return it.
if d.readUnified {
storageObj, errObjectSt := d.unified.Create(ctx, createdCopy, createValidation, options)
@@ -109,40 +109,12 @@ func TestMode3_Get(t *testing.T) {
},
},
{
name: "should return an error when getting an object in the unified store fails",
name: "should return an error when getting an object in the unified store fails, and should not go to legacy",
setupStorageFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error"))
},
wantErr: true,
},
{
name: "should return an error when getting an object in the unified store fails with not found error, and legacy fails as well",
setupLegacyFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error"))
},
setupStorageFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(nil, apierrors.NewNotFound(schema.GroupResource{Group: "dashboards.dashboard.grafana.app", Resource: "dashboard"}, "uid"))
},
wantErr: true,
},
{
name: "should succeed when getting an object in the UnifiedStorage fails with NotFound, but Legacy succeeds",
setupLegacyFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil)
},
setupStorageFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(nil, apierrors.NewNotFound(schema.GroupResource{Group: "dashboards.dashboard.grafana.app", Resource: "dashboard"}, "uid"))
},
},
{
name: "should succeed when getting an object in the LegacyStorage fails",
setupLegacyFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error"))
},
setupStorageFn: func(m *mock.Mock, name string) {
m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil)
},
},
}
name := "foo"