Unified Storage: Don't read before create (#102906)

* Unified Storage: Don't read before create

* test: use the existing test infra

* fix: support pq

We use pgx, but it seems to be wrapped in a pq driver shim, causing the errors to be remapped to pq's type. Weird
situation.

* feat: support CDK backend

* revert: there is a postgres_tests block

* fix(CDK): only check existence on ADDED updates

* fix(CDK): use ReadResource to deal with deleted files
This commit is contained in:
Mariell Hoversholm
2025-03-31 15:06:31 +02:00
committed by GitHub
parent 827d86a985
commit f0a6327edc
7 changed files with 93 additions and 18 deletions

View File

@ -3,6 +3,7 @@ package test
import (
"context"
"fmt"
"net/http"
"slices"
"strings"
"testing"
@ -10,8 +11,11 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apiserver/pkg/endpoints/request"
"github.com/grafana/authlib/authn"
"github.com/grafana/authlib/types"
@ -22,12 +26,13 @@ import (
// Test names for the storage backend test suite
const (
TestHappyPath = "happy path"
TestWatchWriteEvents = "watch write events from latest"
TestList = "list"
TestBlobSupport = "blob support"
TestGetResourceStats = "get resource stats"
TestListHistory = "list history"
TestHappyPath = "happy path"
TestWatchWriteEvents = "watch write events from latest"
TestList = "list"
TestBlobSupport = "blob support"
TestGetResourceStats = "get resource stats"
TestListHistory = "list history"
TestCreateNewResource = "create new resource"
)
type NewBackendFunc func(ctx context.Context) resource.StorageBackend
@ -70,6 +75,7 @@ func RunStorageBackendTest(t *testing.T, newBackend NewBackendFunc, opts *TestOp
{TestBlobSupport, runTestIntegrationBlobSupport},
{TestGetResourceStats, runTestIntegrationBackendGetResourceStats},
{TestListHistory, runTestIntegrationBackendListHistory},
{TestCreateNewResource, runTestIntegrationBackendCreateNewResource},
}
for _, tc := range cases {
@ -907,6 +913,42 @@ func runTestIntegrationBlobSupport(t *testing.T, backend resource.StorageBackend
})
}
func runTestIntegrationBackendCreateNewResource(t *testing.T, backend resource.StorageBackend, nsPrefix string) {
ctx := types.WithAuthInfo(t.Context(), authn.NewAccessTokenAuthInfo(authn.Claims[authn.AccessTokenClaims]{
Claims: jwt.Claims{
Subject: "testuser",
},
Rest: authn.AccessTokenClaims{},
}))
server := newServer(t, backend)
ns := nsPrefix + "-create-resource"
ctx = request.WithNamespace(ctx, ns)
request := &resource.CreateRequest{
Key: &resource.ResourceKey{
Namespace: "default",
Group: "test.grafana",
Resource: "Test",
Name: "test",
},
Value: []byte(`{"apiVersion":"test.grafana/v0alpha1","kind":"Test","metadata":{"name":"test","namespace":"default"}}`),
}
response, err := server.Create(ctx, request)
require.NoError(t, err, "create resource")
require.Nil(t, response.Error, "create resource response.Error")
t.Run("gracefully handles resource already exists error", func(t *testing.T) {
response, err := server.Create(ctx, request)
require.NoError(t, err, "create resource")
require.NotNil(t, response.GetError(), "create resource response.Error")
assert.Equal(t, int32(http.StatusConflict), response.GetError().GetCode(), "create resource response.Error.Code")
assert.Equal(t, string(metav1.StatusReasonAlreadyExists), response.GetError().GetReason(), "create resource response.Error.Reason")
t.Logf("Error: %v", response.GetError()) // only prints on failure, so this is fine
})
}
// WriteEventOption is a function that modifies WriteEventOptions
type WriteEventOption func(*WriteEventOptions)