diff --git a/cmd/lakefs/cmd/run.go b/cmd/lakefs/cmd/run.go index 0d27a3534e4..0b2d1e25b57 100644 --- a/cmd/lakefs/cmd/run.go +++ b/cmd/lakefs/cmd/run.go @@ -139,12 +139,6 @@ var runCmd = &cobra.Command{ logger.WithError(err).Fatal("failed to create login token provider") } - blockstoreType := baseCfg.Blockstore.Type - if blockstoreType == "mem" { - printLocalWarning(os.Stderr, fmt.Sprintf("blockstore type %s", blockstoreType)) - logger.WithField("adapter_type", blockstoreType).Warn("Block adapter NOT SUPPORTED for production use") - } - metadata := initStatsMetadata(ctx, logger, authMetadataManager, cfg) bufferedCollector := stats.NewBufferedCollector(metadata.InstallationID, stats.Config(baseCfg.Stats), stats.WithLogger(logger.WithField("service", "stats_collector"))) @@ -155,6 +149,16 @@ var runCmd = &cobra.Command{ logger.WithError(err).Fatal("Failed to create block adapter") } + blockstoreMetadata, err := blockStore.BlockstoreMetadata(ctx) + if err != nil { + logger.WithError(err).Fatal("Failed to get block adapter metadata") + } + if !blockstoreMetadata.IsProductionSafe { + blockstoreType := blockStore.BlockstoreType() + printLocalWarning(os.Stderr, fmt.Sprintf("blockstore type %s", blockstoreType)) + logger.WithField("adapter_type", blockstoreType).Warn("Block adapter NOT SUPPORTED for production use") + } + bufferedCollector.SetRuntimeCollector(blockStore.RuntimeStats) // send metadata bufferedCollector.CollectMetadata(metadata) diff --git a/pkg/block/adapter.go b/pkg/block/adapter.go index d62ab936e98..b65412d734b 100644 --- a/pkg/block/adapter.go +++ b/pkg/block/adapter.go @@ -166,7 +166,8 @@ type Properties struct { } type BlockstoreMetadata struct { - Region *string + IsProductionSafe bool + Region *string } type PutResponse struct { diff --git a/pkg/block/azure/adapter.go b/pkg/block/azure/adapter.go index 470e0bd0426..120f6536b52 100644 --- a/pkg/block/azure/adapter.go +++ b/pkg/block/azure/adapter.go @@ -616,7 +616,9 @@ func (a *Adapter) BlockstoreType() string { } func (a *Adapter) BlockstoreMetadata(_ context.Context) (*block.BlockstoreMetadata, error) { - return nil, block.ErrOperationNotSupported + return &block.BlockstoreMetadata{ + IsProductionSafe: true, + }, nil } func (a *Adapter) CompleteMultiPartUpload(ctx context.Context, obj block.ObjectPointer, _ string, multipartList *block.MultipartUploadCompletion) (*block.CompleteMultiPartUploadResponse, error) { diff --git a/pkg/block/gs/adapter.go b/pkg/block/gs/adapter.go index eaa6816f1d0..60440b551fe 100644 --- a/pkg/block/gs/adapter.go +++ b/pkg/block/gs/adapter.go @@ -681,7 +681,9 @@ func (a *Adapter) BlockstoreType() string { } func (a *Adapter) BlockstoreMetadata(_ context.Context) (*block.BlockstoreMetadata, error) { - return nil, block.ErrOperationNotSupported + return &block.BlockstoreMetadata{ + IsProductionSafe: true, + }, nil } func (a *Adapter) GetStorageNamespaceInfo(string) *block.StorageNamespaceInfo { diff --git a/pkg/block/local/adapter.go b/pkg/block/local/adapter.go index bf352e8bde9..83eba2e57eb 100644 --- a/pkg/block/local/adapter.go +++ b/pkg/block/local/adapter.go @@ -533,7 +533,9 @@ func (l *Adapter) BlockstoreType() string { } func (l *Adapter) BlockstoreMetadata(_ context.Context) (*block.BlockstoreMetadata, error) { - return nil, block.ErrOperationNotSupported + return &block.BlockstoreMetadata{ + IsProductionSafe: true, + }, nil } func (l *Adapter) GetStorageNamespaceInfo(string) *block.StorageNamespaceInfo { diff --git a/pkg/block/mem/adapter.go b/pkg/block/mem/adapter.go index 0e9f6c213b1..23c9f419b33 100644 --- a/pkg/block/mem/adapter.go +++ b/pkg/block/mem/adapter.go @@ -434,7 +434,9 @@ func (a *Adapter) BlockstoreType() string { } func (a *Adapter) BlockstoreMetadata(_ context.Context) (*block.BlockstoreMetadata, error) { - return nil, fmt.Errorf("blockstore metadata: %w", block.ErrOperationNotSupported) + return &block.BlockstoreMetadata{ + IsProductionSafe: false, + }, nil } func (a *Adapter) GetStorageNamespaceInfo(string) *block.StorageNamespaceInfo { diff --git a/pkg/block/s3/adapter.go b/pkg/block/s3/adapter.go index af14f2ca47c..c5285be92b2 100644 --- a/pkg/block/s3/adapter.go +++ b/pkg/block/s3/adapter.go @@ -895,7 +895,10 @@ func (a *Adapter) BlockstoreMetadata(ctx context.Context) (*block.BlockstoreMeta if err != nil { return nil, err } - return &block.BlockstoreMetadata{Region: ®ion}, nil + return &block.BlockstoreMetadata{ + IsProductionSafe: true, + Region: ®ion, + }, nil } func (a *Adapter) GetStorageNamespaceInfo(string) *block.StorageNamespaceInfo { diff --git a/pkg/block/transient/adapter.go b/pkg/block/transient/adapter.go index f518b5c51e1..7b350f7259f 100644 --- a/pkg/block/transient/adapter.go +++ b/pkg/block/transient/adapter.go @@ -143,7 +143,9 @@ func (a *Adapter) BlockstoreType() string { } func (a *Adapter) BlockstoreMetadata(_ context.Context) (*block.BlockstoreMetadata, error) { - return nil, block.ErrOperationNotSupported + return &block.BlockstoreMetadata{ + IsProductionSafe: false, + }, nil } func (a *Adapter) GetStorageNamespaceInfo(string) *block.StorageNamespaceInfo { diff --git a/pkg/block/validations.go b/pkg/block/validations.go index 84f26c2d6a3..db1ee6e9d1b 100644 --- a/pkg/block/validations.go +++ b/pkg/block/validations.go @@ -2,17 +2,17 @@ package block import ( "context" - "errors" "fmt" ) func ValidateInterRegionStorage(ctx context.Context, adapter Adapter, storageID, storageNamespace string) error { blockstoreMetadata, err := adapter.BlockstoreMetadata(ctx) - if errors.Is(err, ErrOperationNotSupported) { + if err != nil { + return err + } + if blockstoreMetadata.Region == nil { // region detection not supported for the server's blockstore, skip validation return nil - } else if err != nil { - return fmt.Errorf("failed to get blockstore region: %w", err) } bucketRegion, err := adapter.GetRegion(ctx, storageID, storageNamespace) diff --git a/pkg/block/validations_test.go b/pkg/block/validations_test.go index 07d23efb856..328bcdf6027 100644 --- a/pkg/block/validations_test.go +++ b/pkg/block/validations_test.go @@ -15,7 +15,7 @@ func TestController_ValidateInterRegionStorage(t *testing.T) { t.Run("namespace with the same region as the storage", func(t *testing.T) { opts := []testutil.MockAdapterOption{ - testutil.WithBlockstoreMetadata(&block.BlockstoreMetadata{Region: swag.String("us-west-2")}), + testutil.WithBlockstoreMetadata(block.BlockstoreMetadata{Region: swag.String("us-west-2")}), testutil.WithNamespaceRegion("us-west-2"), } adapter := testutil.NewMockAdapter(opts...) @@ -26,7 +26,7 @@ func TestController_ValidateInterRegionStorage(t *testing.T) { t.Run("namespace region different from storage region", func(t *testing.T) { opts := []testutil.MockAdapterOption{ - testutil.WithBlockstoreMetadata(&block.BlockstoreMetadata{Region: swag.String("us-east-1")}), + testutil.WithBlockstoreMetadata(block.BlockstoreMetadata{Region: swag.String("us-east-1")}), testutil.WithNamespaceRegion("us-west-2"), } adapter := testutil.NewMockAdapter(opts...) diff --git a/pkg/testutil/adapter.go b/pkg/testutil/adapter.go index 5ae7ece16ba..d83807d1fff 100644 --- a/pkg/testutil/adapter.go +++ b/pkg/testutil/adapter.go @@ -16,7 +16,7 @@ type MockAdapter struct { LastStorageNamespace string LastStorageClass *string - blockstoreMetadata *block.BlockstoreMetadata + blockstoreMetadata block.BlockstoreMetadata namespaceRegion *string } @@ -39,7 +39,7 @@ func NewMockAdapter(opts ...MockAdapterOption) *MockAdapter { return adapter } -func WithBlockstoreMetadata(bm *block.BlockstoreMetadata) func(a *MockAdapter) { +func WithBlockstoreMetadata(bm block.BlockstoreMetadata) func(a *MockAdapter) { return func(a *MockAdapter) { a.blockstoreMetadata = bm } @@ -132,11 +132,7 @@ func (a *MockAdapter) BlockstoreType() string { } func (a *MockAdapter) BlockstoreMetadata(_ context.Context) (*block.BlockstoreMetadata, error) { - if a.blockstoreMetadata != nil { - return a.blockstoreMetadata, nil - } else { - return nil, block.ErrOperationNotSupported - } + return &a.blockstoreMetadata, nil } func (a *MockAdapter) GetStorageNamespaceInfo(string) *block.StorageNamespaceInfo { diff --git a/webui/test/e2e/poms/repositoryPage.ts b/webui/test/e2e/poms/repositoryPage.ts index 2acdc8d1475..4efe774274b 100644 --- a/webui/test/e2e/poms/repositoryPage.ts +++ b/webui/test/e2e/poms/repositoryPage.ts @@ -134,7 +134,7 @@ export class RepositoryPage { } async uploadObject(filePath: string): Promise { - await this.page.getByRole("button", { name: "Upload" }).click(); + await this.page.getByRole("button", { name: "Upload", exact: true }).click(); await this.page.getByText("Drag & drop files or folders here").click(); const fileInput = await this.page.locator('input[type="file"]'); await fileInput.setInputFiles(filePath);