This is an automated email from the ASF dual-hosted git repository.
miroslav pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new 117fc0559d OAK-11506 Update oak-segment-azure tools to use azure sdk
v12 implementation (#2160)
117fc0559d is described below
commit 117fc0559db3965de8ffe98e97207dffc84bd063
Author: Ieran Bogdan <[email protected]>
AuthorDate: Wed Mar 19 10:57:50 2025 +0200
OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation (#2160)
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - refactor AzurePersistenceManager
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - fix unit tests
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - fix unit tests
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - remove AZURE_STORAGE_ACCOUNT_NAME
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - remove AZURE_STORAGE_ACCOUNT_NAME
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - PR review change
* OAK-11506 Update oak-segment-azure tools to use azure sdk v12
implementation - PR review change
---
.../oak/run/cli/SegmentTarFixtureProvider.java | 5 +-
.../explorer/AzureSegmentStoreExplorerBackend.java | 6 +-
.../jackrabbit/oak/run/FileStoreDiffCommand.java | 31 ++---
.../jackrabbit/oak/run/DataStoreCommandTest.java | 9 +-
.../oak/segment/azure/AzurePersistence.java | 4 +
.../oak/segment/azure/AzurePersistenceManager.java | 77 +++++++++--
.../oak/segment/azure/AzureUtilities.java | 4 +-
.../oak/segment/azure/tool/AzureCheck.java | 45 ++++---
.../oak/segment/azure/tool/AzureCompact.java | 120 ++++++++++-------
.../oak/segment/azure/tool/SegmentCopy.java | 13 +-
.../segment/azure/tool/SegmentStoreMigrator.java | 19 ++-
.../oak/segment/azure/tool/ToolUtils.java | 73 +++++------
.../azure/util/AzureConfigurationParserUtils.java | 5 +-
.../segment/azure/AzurePersistenceManagerTest.java | 142 +++++++++++++++++++++
.../SegmentCopyAzureServicePrincipalToTarTest.java | 20 +--
.../segment/azure/tool/SegmentCopyTestBase.java | 2 +-
.../oak/segment/azure/tool/ToolUtilsTest.java | 96 ++++----------
...entAzureServicePrincipalNodeStoreContainer.java | 34 ++---
.../upgrade/cli/node/SegmentAzureFactoryTest.java | 16 +--
19 files changed, 426 insertions(+), 295 deletions(-)
diff --git
a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/cli/SegmentTarFixtureProvider.java
b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/cli/SegmentTarFixtureProvider.java
index 6918658f99..0d70319717 100644
---
a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/cli/SegmentTarFixtureProvider.java
+++
b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/cli/SegmentTarFixtureProvider.java
@@ -30,7 +30,6 @@ import java.nio.file.Files;
import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.oak.commons.pio.Closer;
import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.file.FileStore;
import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
@@ -53,12 +52,10 @@ class SegmentTarFixtureProvider {
FileStoreBuilder builder;
if (segmentStoreType == ToolUtils.SegmentStoreType.AZURE) {
- final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8 = new AzureStorageCredentialManagerV8();
SegmentNodeStorePersistence segmentNodeStorePersistence =
- ToolUtils.newSegmentNodeStorePersistence(segmentStoreType,
pathOrUri, azureStorageCredentialManagerV8);
+ ToolUtils.newSegmentNodeStorePersistence(segmentStoreType,
pathOrUri);
File tempDir =
Files.createTempDirectory("azure-segment-store").toFile();
closer.register(() -> FileUtils.deleteQuietly(tempDir));
- closer.register(azureStorageCredentialManagerV8);
builder =
fileStoreBuilder(tempDir).withCustomPersistence(segmentNodeStorePersistence);
} else {
builder = fileStoreBuilder(new
File(pathOrUri)).withMaxFileSize(256);
diff --git
a/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/AzureSegmentStoreExplorerBackend.java
b/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/AzureSegmentStoreExplorerBackend.java
index 742576a066..a3a116ecb5 100644
---
a/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/AzureSegmentStoreExplorerBackend.java
+++
b/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/AzureSegmentStoreExplorerBackend.java
@@ -18,7 +18,6 @@
*/
package org.apache.jackrabbit.oak.explorer;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
import org.apache.jackrabbit.oak.segment.spi.persistence.JournalFile;
@@ -39,16 +38,14 @@ import static
org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreB
public class AzureSegmentStoreExplorerBackend extends
AbstractSegmentTarExplorerBackend {
private final String path;
private SegmentNodeStorePersistence persistence;
- private final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8;
public AzureSegmentStoreExplorerBackend(String path) {
this.path = path;
- this.azureStorageCredentialManagerV8 = new
AzureStorageCredentialManagerV8();
}
@Override
public void open() throws IOException {
- this.persistence =
newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE, path,
azureStorageCredentialManagerV8);
+ this.persistence =
newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE, path);
try {
this.store =
fileStoreBuilder(Files.createTempDirectory(getClass().getSimpleName() +
"-").toFile())
@@ -63,7 +60,6 @@ public class AzureSegmentStoreExplorerBackend extends
AbstractSegmentTarExplorer
@Override
public void close() {
super.close();
- azureStorageCredentialManagerV8.close();
}
@Override
diff --git
a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
index cf01abbf43..dd49502329 100644
---
a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
+++
b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
@@ -27,7 +27,6 @@ import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.apache.jackrabbit.oak.run.commons.Command;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore;
import
org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence;
@@ -86,22 +85,20 @@ class FileStoreDiffCommand implements Command {
}
} else {
if (pathOrURI.startsWith("az:")) {
- try (AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8 = new AzureStorageCredentialManagerV8()) {
- SegmentNodeStorePersistence azurePersistence =
ToolUtils.newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE,
pathOrURI, azureStorageCredentialManagerV8);
- ReadOnlyFileStore store =
fileStoreBuilder(Files.createTempDirectory(getClass().getSimpleName() +
"-").toFile())
-
.withCustomPersistence(azurePersistence).withBlobStore(newBasicReadOnlyBlobStore()).buildReadOnly();
- statusCode = Diff.builder()
- .withPath(pathOrURI)
- .withReadOnlyFileStore(store)
- .withOutput(out)
- .withInterval(interval)
- .withIncremental(incremental)
- .withFilter(path)
- .withIgnoreMissingSegments(ignoreSNFEs)
- .withRevisionsProcessor(ToolUtils::readRevisions)
- .build()
- .run();
- }
+ SegmentNodeStorePersistence azurePersistence =
ToolUtils.newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE,
pathOrURI);
+ ReadOnlyFileStore store =
fileStoreBuilder(Files.createTempDirectory(getClass().getSimpleName() +
"-").toFile())
+
.withCustomPersistence(azurePersistence).withBlobStore(newBasicReadOnlyBlobStore()).buildReadOnly();
+ statusCode = Diff.builder()
+ .withPath(pathOrURI)
+ .withReadOnlyFileStore(store)
+ .withOutput(out)
+ .withInterval(interval)
+ .withIncremental(incremental)
+ .withFilter(path)
+ .withIgnoreMissingSegments(ignoreSNFEs)
+ .withRevisionsProcessor(ToolUtils::readRevisions)
+ .build()
+ .run();
} else {
ReadOnlyFileStore store = fileStoreBuilder(new
File(pathOrURI)).withBlobStore(newBasicReadOnlyBlobStore()).buildReadOnly();
statusCode = Diff.builder()
diff --git
a/oak-run/src/test/java/org/apache/jackrabbit/oak/run/DataStoreCommandTest.java
b/oak-run/src/test/java/org/apache/jackrabbit/oak/run/DataStoreCommandTest.java
index 7bf9c2a274..cc17485b2c 100644
---
a/oak-run/src/test/java/org/apache/jackrabbit/oak/run/DataStoreCommandTest.java
+++
b/oak-run/src/test/java/org/apache/jackrabbit/oak/run/DataStoreCommandTest.java
@@ -71,8 +71,7 @@ import
org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakDirectory;
import org.apache.jackrabbit.oak.run.cli.BlobStoreOptions.Type;
import org.apache.jackrabbit.oak.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistenceManager;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
import org.apache.jackrabbit.oak.segment.file.FileStore;
@@ -1128,7 +1127,6 @@ public class DataStoreCommandTest {
class AzureSegmentStoreFixture extends SegmentStoreFixture {
private static final String AZURE_DIR = "repository";
private String container;
- private final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8 = new AzureStorageCredentialManagerV8();
@Override public NodeStore init(DataStoreBlobStore blobStore, File
storeFile) throws Exception {
Properties props = AzureDataStoreUtils.getAzureConfig();
@@ -1138,14 +1136,14 @@ public class DataStoreCommandTest {
container = container + System.currentTimeMillis();
// Create the azure segment container
String connectionString = getAzureConnectionString(accessKey,
secretKey, container, AZURE_DIR);
- AzureUtilitiesV8.cloudBlobDirectoryFrom(connectionString,
container, AZURE_DIR);
+
AzurePersistenceManager.createAzurePersistence(connectionString, null,
accessKey, container, AZURE_DIR, false, true);
// get the azure uri expected by the command
storePath = getAzureUri(accessKey, container, AZURE_DIR);
// initialize azure segment for test setup
SegmentNodeStorePersistence segmentNodeStorePersistence =
-
ToolUtils.newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE,
storePath, azureStorageCredentialManagerV8);
+
ToolUtils.newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE,
storePath);
fileStore =
fileStoreBuilder(storeFile).withBlobStore(blobStore)
.withCustomPersistence(segmentNodeStorePersistence).build();
@@ -1177,7 +1175,6 @@ public class DataStoreCommandTest {
public void after() {
try {
AzureDataStoreUtils.deleteContainer(container);
- azureStorageCredentialManagerV8.close();
} catch(Exception e) {
log.error("Error in cleaning the container {}", container,
e);
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
index a0f0ddded5..9a6f75595c 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
@@ -53,6 +53,10 @@ public class AzurePersistence implements
SegmentNodeStorePersistence {
protected WriteAccessController writeAccessController = new
WriteAccessController();
+ public AzurePersistence(BlobContainerClient blobContainerClient, String
rootPrefix) {
+ this(blobContainerClient, blobContainerClient, blobContainerClient,
rootPrefix);
+ }
+
public AzurePersistence(BlobContainerClient readBlobContainerClient,
BlobContainerClient writeBlobContainerClient, BlobContainerClient
noRetryBlobContainerClient, String rootPrefix) {
this(readBlobContainerClient, writeBlobContainerClient,
noRetryBlobContainerClient, rootPrefix, null);
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManager.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManager.java
index 12fee4c31c..e16179741e 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManager.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManager.java
@@ -41,14 +41,18 @@ public class AzurePersistenceManager {
private AzurePersistenceManager() {
}
- public static AzurePersistence createAzurePersistenceFrom(@NotNull String
accountName, @NotNull String containerName, @NotNull String rootPrefix,
@NotNull Environment environment) throws IOException {
+ public static AzurePersistence createAzurePersistenceFrom(String
accountName, String containerName, String rootPrefix, String sasToken) throws
IOException {
+ return createAzurePersistence(null, sasToken, accountName,
containerName, rootPrefix, false, false);
+ }
+
+ public static AzurePersistence createAzurePersistenceFrom(String
accountName, String containerName, String rootPrefix, Environment environment)
throws IOException {
final String clientId = environment.getVariable(AZURE_CLIENT_ID);
final String clientSecret =
environment.getVariable(AZURE_CLIENT_SECRET);
final String tenantId = environment.getVariable(AZURE_TENANT_ID);
if (StringUtils.isNoneBlank(clientId, clientSecret, tenantId)) {
try {
- return
createPersistenceFromServicePrincipalCredentials(accountName, containerName,
rootPrefix, clientId, clientSecret, tenantId, false, false);
+ return
createPersistenceFromServicePrincipalCredentials(accountName, containerName,
rootPrefix, clientId, clientSecret, tenantId, false, true);
} catch (IllegalArgumentException |
StringIndexOutOfBoundsException e) {
log.error("Error occurred while connecting to Azure Storage
using service principals: ", e);
throw new IllegalArgumentException(
@@ -86,6 +90,7 @@ public class AzurePersistenceManager {
}
private static AzurePersistence createPersistenceFromAccessKey(String
accountName, String containerName, String accessKey, String blobEndpoint,
String rootPrefix, boolean enableSecondaryLocation, boolean createContainer)
throws IOException {
+ checkIfEmpty(accessKey, "accessKey");
StringBuilder connectionString = new StringBuilder();
connectionString.append("DefaultEndpointsProtocol=https;");
connectionString.append("AccountName=").append(accountName).append(';');
@@ -93,7 +98,7 @@ public class AzurePersistenceManager {
if (!StringUtils.isBlank(blobEndpoint)) {
connectionString.append("BlobEndpoint=").append(blobEndpoint).append(';');
}
- return createAzurePersistence(connectionString.toString(),
accountName, containerName, rootPrefix, enableSecondaryLocation,
createContainer);
+ return createAzurePersistence(connectionString.toString(), null,
accountName, containerName, rootPrefix, enableSecondaryLocation,
createContainer);
}
@NotNull
@@ -114,11 +119,12 @@ public class AzurePersistenceManager {
@NotNull
- private static AzurePersistence
createPersistenceFromServicePrincipalCredentials(Configuration configuration)
throws IOException {
+ private static AzurePersistence
createPersistenceFromServicePrincipalCredentials(Configuration configuration) {
return
createPersistenceFromServicePrincipalCredentials(configuration.accountName(),
configuration.containerName(), configuration.rootPath(),
configuration.clientId(), configuration.clientSecret(),
configuration.tenantId(), configuration.enableSecondaryLocation(), true);
}
- private static AzurePersistence
createPersistenceFromServicePrincipalCredentials(String accountName, String
containerName, String rootPrefix, String clientId, String clientSecret, String
tenantId, boolean enableSecondaryLocation, boolean createContainer) throws
IOException {
+ public static AzurePersistence
createPersistenceFromServicePrincipalCredentials(String accountName, String
containerName, String rootPrefix, String clientId, String clientSecret, String
tenantId, boolean enableSecondaryLocation, boolean createContainer) {
+ checkArguments(accountName, containerName, rootPrefix);
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy = new
AzureHttpRequestLoggingPolicy();
ClientSecretCredential clientSecretCredential = new
ClientSecretCredentialBuilder()
@@ -146,21 +152,41 @@ public class AzurePersistenceManager {
@NotNull
private static AzurePersistence createAzurePersistence(String
connectionString, Configuration configuration, boolean createContainer) throws
IOException {
- return createAzurePersistence(connectionString,
configuration.accountName(), configuration.containerName(),
configuration.rootPath(), configuration.enableSecondaryLocation(),
createContainer);
+ return createAzurePersistence(connectionString, null,
configuration.accountName(), configuration.containerName(),
configuration.rootPath(), configuration.enableSecondaryLocation(),
createContainer);
}
@NotNull
- private static AzurePersistence createAzurePersistence(String
connectionString, String accountName, String containerName, String rootPrefix,
boolean enableSecondaryLocation, boolean createContainer) throws IOException {
+ public static AzurePersistence createAzurePersistence(String
connectionString, String sasToken, String accountName, String containerName,
String rootPrefix, boolean enableSecondaryLocation, boolean createContainer)
throws IOException {
+ if (StringUtils.isBlank(connectionString) &&
StringUtils.isBlank(sasToken)) {
+ throw new IllegalArgumentException("Both connectionString and
sasToken are not configured. Please configure one of them.");
+ }
+ checkArguments(accountName, containerName, rootPrefix);
+
try {
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy = new
AzureHttpRequestLoggingPolicy();
RequestRetryOptions retryOptions =
readRequestRetryOptions(enableSecondaryLocation, accountName);
- BlobContainerClient blobContainerClient =
getBlobContainerClient(accountName, containerName, retryOptions,
azureHttpRequestLoggingPolicy, connectionString);
+ BlobContainerClient blobContainerClient;
+ if (sasToken != null) {
+ blobContainerClient =
getBlobContainerClientWithSas(accountName, containerName, retryOptions,
azureHttpRequestLoggingPolicy, sasToken);
+ } else {
+ blobContainerClient = getBlobContainerClient(accountName,
containerName, retryOptions, azureHttpRequestLoggingPolicy, connectionString);
+ }
RequestRetryOptions writeRetryOptions =
AzureRequestOptions.getRetryOperationsOptimiseForWriteOperations();
- BlobContainerClient writeBlobContainerClient =
getBlobContainerClient(accountName, containerName, writeRetryOptions,
azureHttpRequestLoggingPolicy, connectionString);
+ BlobContainerClient writeBlobContainerClient;
+ if (sasToken != null) {
+ writeBlobContainerClient =
getBlobContainerClientWithSas(accountName, containerName, writeRetryOptions,
azureHttpRequestLoggingPolicy, sasToken);
+ } else {
+ writeBlobContainerClient = getBlobContainerClient(accountName,
containerName, writeRetryOptions, azureHttpRequestLoggingPolicy,
connectionString);
+ }
- BlobContainerClient noRetryBlobContainerClient =
getBlobContainerClient(accountName, containerName, null,
azureHttpRequestLoggingPolicy, connectionString);
+ BlobContainerClient noRetryBlobContainerClient;
+ if (sasToken != null) {
+ noRetryBlobContainerClient =
getBlobContainerClientWithSas(accountName, containerName, null,
azureHttpRequestLoggingPolicy, sasToken);
+ } else {
+ noRetryBlobContainerClient =
getBlobContainerClient(accountName, containerName, null,
azureHttpRequestLoggingPolicy, connectionString);
+ }
if (createContainer) {
blobContainerClient.createIfNotExists();
@@ -174,8 +200,15 @@ public class AzurePersistenceManager {
}
}
+ private static BlobContainerClient getBlobContainerClientWithSas(String
accountName, String containerName, RequestRetryOptions requestRetryOptions,
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy, String sasToken) {
+ BlobServiceClient blobServiceClient =
blobServiceClientBuilder(accountName, requestRetryOptions,
azureHttpRequestLoggingPolicy, sasToken)
+ .buildClient();
+
+ return blobServiceClient.getBlobContainerClient(containerName);
+ }
+
private static BlobContainerClient getBlobContainerClient(String
accountName, String containerName, RequestRetryOptions requestRetryOptions,
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy, String
connectionString) {
- BlobServiceClient blobServiceClient =
blobServiceClientBuilder(accountName, requestRetryOptions,
azureHttpRequestLoggingPolicy)
+ BlobServiceClient blobServiceClient =
blobServiceClientBuilder(accountName, requestRetryOptions,
azureHttpRequestLoggingPolicy, null)
.connectionString(connectionString)
.buildClient();
@@ -183,15 +216,20 @@ public class AzurePersistenceManager {
}
private static BlobContainerClient getBlobContainerClient(String
accountName, String containerName, RequestRetryOptions requestRetryOptions,
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy,
ClientSecretCredential clientSecretCredential) {
- BlobServiceClient blobServiceClient =
blobServiceClientBuilder(accountName, requestRetryOptions,
azureHttpRequestLoggingPolicy)
+ BlobServiceClient blobServiceClient =
blobServiceClientBuilder(accountName, requestRetryOptions,
azureHttpRequestLoggingPolicy, null)
.credential(clientSecretCredential)
.buildClient();
return blobServiceClient.getBlobContainerClient(containerName);
}
- private static BlobServiceClientBuilder blobServiceClientBuilder(String
accountName, RequestRetryOptions requestRetryOptions,
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy) {
- String endpoint = String.format("https://%s.blob.core.windows.net",
accountName);
+ private static BlobServiceClientBuilder blobServiceClientBuilder(String
accountName, RequestRetryOptions requestRetryOptions,
AzureHttpRequestLoggingPolicy azureHttpRequestLoggingPolicy, String sasToken) {
+ if (sasToken == null) {
+ sasToken = "";
+ } else {
+ sasToken = "?" + sasToken;
+ }
+ String endpoint = String.format("https://%s.blob.core.windows.net%s",
accountName, sasToken);
BlobServiceClientBuilder builder = new BlobServiceClientBuilder()
.endpoint(endpoint)
@@ -221,4 +259,15 @@ public class AzurePersistenceManager {
return rootPath;
}
+ private static void checkArguments(String accountName, String
containerName, String rootPrefix){
+ checkIfEmpty(accountName, "Account name");
+ checkIfEmpty(containerName, "Container name");
+ checkIfEmpty(rootPrefix, "Root prefix");
+ }
+
+ private static void checkIfEmpty(String argument, String argumentName) {
+ if (StringUtils.isEmpty(argument)) {
+ throw new IllegalArgumentException(String.format("%s must not be
empty argument", argumentName));
+ }
+ }
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureUtilities.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureUtilities.java
index f6743edafc..c3a7349a0e 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureUtilities.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureUtilities.java
@@ -60,7 +60,9 @@ public final class AzureUtilities {
public static List<BlobItem> getBlobs(BlobContainerClient
blobContainerClient, ListBlobsOptions listOptions) {
- listOptions.setDetails(new
BlobListDetails().setRetrieveMetadata(true));
+ if (listOptions != null) {
+ listOptions.setDetails(new
BlobListDetails().setRetrieveMetadata(true));
+ }
return blobContainerClient.listBlobs(listOptions,
null).stream().collect(Collectors.toList());
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCheck.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCheck.java
index 486fb5b132..b6479a6607 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCheck.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCheck.java
@@ -16,9 +16,8 @@
*/
package org.apache.jackrabbit.oak.segment.azure.tool;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzurePersistenceV8;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
+import com.azure.storage.blob.BlobContainerClient;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
import org.apache.jackrabbit.oak.segment.file.JournalReader;
import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore;
@@ -57,6 +56,8 @@ public class AzureCheck {
private String path;
+ private String rootPrefix;
+
private String journal;
private long debugInterval = Long.MAX_VALUE;
@@ -85,7 +86,7 @@ public class AzureCheck {
private Integer persistentCacheSizeGb;
- private CloudBlobDirectory cloudBlobDirectory;
+ private BlobContainerClient blobContainerClient;
private Builder() {
// Prevent external instantiation.
@@ -102,6 +103,17 @@ public class AzureCheck {
return this;
}
+ /**
+ * The root prefix to an existing segment store. This parameter is
required.
+ *
+ * @param rootPrefix
+ * @return this builder.
+ */
+ public Builder withRootPrefix(String rootPrefix) {
+ this.rootPrefix = rootPrefix;
+ return this;
+ }
+
/**
* The path to the journal of the segment store. This parameter is
* optional. If not provided, the journal in the default location is
@@ -278,12 +290,12 @@ public class AzureCheck {
/**
* The Azure blob directory to connect to.
- * @param cloudBlobDirectory
+ * @param blobContainerClient
* the Azure blob directory.
* @return this builder
*/
- public Builder withCloudBlobDirectory(CloudBlobDirectory
cloudBlobDirectory) {
- this.cloudBlobDirectory = requireNonNull(cloudBlobDirectory);
+ public Builder withBlobContainerClient(BlobContainerClient
blobContainerClient) {
+ this.blobContainerClient = requireNonNull(blobContainerClient);
return this;
}
@@ -293,7 +305,7 @@ public class AzureCheck {
* @return an instance of {@link Runnable}.
*/
public AzureCheck build() {
- if (cloudBlobDirectory == null) {
+ if (blobContainerClient == null) {
requireNonNull(path);
}
return new AzureCheck(this);
@@ -320,6 +332,8 @@ public class AzureCheck {
private final String path;
+ private final String rootPrefix;
+
private final String journal;
private final long debugInterval;
@@ -348,11 +362,11 @@ public class AzureCheck {
private final Integer persistentCacheSizeGb;
- private final CloudBlobDirectory cloudBlobDirectory;
- private final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8;
+ private final BlobContainerClient blobContainerClient;
private AzureCheck(Builder builder) {
this.path = builder.path;
+ this.rootPrefix = builder.rootPrefix;
this.debugInterval = builder.debugInterval;
this.checkHead = builder.checkHead;
this.checkBinaries = builder.checkBinaries;
@@ -367,8 +381,7 @@ public class AzureCheck {
this.failFast = builder.failFast;
this.persistentCachePath = builder.persistentCachePath;
this.persistentCacheSizeGb = builder.persistentCacheSizeGb;
- this.cloudBlobDirectory = builder.cloudBlobDirectory;
- this.azureStorageCredentialManagerV8 = new
AzureStorageCredentialManagerV8();
+ this.blobContainerClient = builder.blobContainerClient;
}
private static Integer revisionsToCheckCount(Integer revisionsCount) {
@@ -379,10 +392,10 @@ public class AzureCheck {
StatisticsIOMonitor ioMonitor = new StatisticsIOMonitor();
SegmentNodeStorePersistence persistence;
- if (cloudBlobDirectory != null) {
- persistence = new AzurePersistenceV8(cloudBlobDirectory);
+ if (blobContainerClient != null) {
+ persistence = new AzurePersistence(blobContainerClient,
rootPrefix);
} else {
- persistence =
ToolUtils.newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE,
path, azureStorageCredentialManagerV8);
+ persistence =
ToolUtils.newSegmentNodeStorePersistence(ToolUtils.SegmentStoreType.AZURE,
path);
}
if (persistentCachePath != null) {
@@ -434,8 +447,6 @@ public class AzureCheck {
} catch (Exception e) {
e.printStackTrace(err);
return 1;
- } finally {
- azureStorageCredentialManagerV8.close();
}
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCompact.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCompact.java
index d150be0936..1a61d9fcb6 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCompact.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/AzureCompact.java
@@ -19,24 +19,19 @@ package org.apache.jackrabbit.oak.segment.azure.tool;
import static
org.apache.jackrabbit.oak.commons.conditions.Validate.checkArgument;
import static java.util.Objects.requireNonNull;
import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.createArchiveManager;
-import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.createCloudBlobDirectory;
+import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.createAzurePersistence;
import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.decorateWithCache;
import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.newFileStore;
-import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.newSegmentNodeStorePersistence;
import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.printableStopwatch;
+import com.azure.storage.blob.BlobContainerClient;
+import com.azure.storage.blob.models.BlobItem;
+import com.azure.storage.blob.models.BlobListDetails;
+import com.azure.storage.blob.models.ListBlobsOptions;
import org.apache.jackrabbit.guava.common.base.Stopwatch;
-import com.microsoft.azure.storage.StorageException;
-import com.microsoft.azure.storage.blob.BlobListingDetails;
-import com.microsoft.azure.storage.blob.CloudBlob;
-import com.microsoft.azure.storage.blob.CloudBlobContainer;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
-import com.microsoft.azure.storage.blob.ListBlobItem;
import org.apache.jackrabbit.oak.segment.SegmentCache;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzurePersistenceV8;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.SegmentStoreType;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.GCType;
import
org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.CompactorType;
import org.apache.jackrabbit.oak.segment.file.FileStore;
@@ -53,7 +48,6 @@ import java.io.PrintStream;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.Collections;
-import java.util.EnumSet;
import java.util.List;
/**
@@ -79,6 +73,10 @@ public class AzureCompact {
private String targetPath;
+ private String rootPrefix;
+
+ private String targetRootPrefix;
+
private boolean force;
private long gcLogInterval = 150000;
@@ -99,9 +97,9 @@ public class AzureCompact {
private int garbageThresholdPercentage;
- private CloudBlobDirectory sourceCloudBlobDirectory;
+ private BlobContainerClient sourceBlobContainerClient;
- private CloudBlobDirectory destinationCloudBlobDirectory;
+ private BlobContainerClient destinationBlobContainerClient;
private Builder() {
// Prevent external instantiation.
@@ -131,6 +129,30 @@ public class AzureCompact {
return this;
}
+ /**
+ * The root directory to an existing segment store.
+ *
+ * @param rootPrefix
+ * the directory to an existing segment store.
+ * @return the builder
+ */
+ public Builder withRootPrefix(String rootPrefix) {
+ this.rootPrefix = rootPrefix;
+ return this;
+ }
+
+ /**
+ * The root directory to the target segment store.
+ *
+ * @param targetRootPrefix
+ * the root directory to the target segmen store.
+ * @return this builder
+ */
+ public Builder withTargetRootPrefix(String targetRootPrefix) {
+ this.targetRootPrefix = targetRootPrefix;
+ return this;
+ }
+
/**
* Whether to fail if run on an older version of the store of force
upgrading
* its format.
@@ -253,13 +275,13 @@ public class AzureCompact {
return this;
}
- public Builder withSourceCloudBlobDirectory(CloudBlobDirectory
sourceCloudBlobDirectory) {
- this.sourceCloudBlobDirectory =
requireNonNull(sourceCloudBlobDirectory);
+ public Builder withSourceBlobContainerClient(BlobContainerClient
sourceBlobContainerClient) {
+ this.sourceBlobContainerClient =
requireNonNull(sourceBlobContainerClient);
return this;
}
- public Builder withDestinationCloudBlobDirectory(CloudBlobDirectory
destinationCloudBlobDirectory) {
- this.destinationCloudBlobDirectory =
requireNonNull(destinationCloudBlobDirectory);
+ public Builder withDestinationBlobContainerClient(BlobContainerClient
destinationBlobContainerClient) {
+ this.destinationBlobContainerClient =
requireNonNull(destinationBlobContainerClient);
return this;
}
@@ -269,7 +291,7 @@ public class AzureCompact {
* @return an instance of {@link Runnable}.
*/
public AzureCompact build() {
- if (sourceCloudBlobDirectory == null ||
destinationCloudBlobDirectory == null) {
+ if (sourceBlobContainerClient == null ||
destinationBlobContainerClient == null) {
requireNonNull(path);
requireNonNull(targetPath);
}
@@ -283,6 +305,10 @@ public class AzureCompact {
private final String targetPath;
+ private final String rootPrefix;
+
+ private final String targetRootPrefix;
+
private final int segmentCacheSize;
private final boolean strictVersionCheck;
@@ -303,14 +329,15 @@ public class AzureCompact {
private final int garbageThresholdPercentage;
- private final CloudBlobDirectory sourceCloudBlobDirectory;
+ private final BlobContainerClient sourceBlobContainerClient;
- private final CloudBlobDirectory destinationCloudBlobDirectory;
- private final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8;
+ private final BlobContainerClient destinationBlobContainerClient;
private AzureCompact(Builder builder) {
this.path = builder.path;
this.targetPath = builder.targetPath;
+ this.rootPrefix = builder.rootPrefix;
+ this.targetRootPrefix = builder.targetRootPrefix;
this.segmentCacheSize = builder.segmentCacheSize;
this.strictVersionCheck = !builder.force;
this.gcLogInterval = builder.gcLogInterval;
@@ -321,22 +348,26 @@ public class AzureCompact {
this.persistentCacheSizeGb = builder.persistentCacheSizeGb;
this.garbageThresholdGb = builder.garbageThresholdGb;
this.garbageThresholdPercentage = builder.garbageThresholdPercentage;
- this.sourceCloudBlobDirectory = builder.sourceCloudBlobDirectory;
- this.destinationCloudBlobDirectory =
builder.destinationCloudBlobDirectory;
- this.azureStorageCredentialManagerV8 = new
AzureStorageCredentialManagerV8();
+ this.sourceBlobContainerClient = builder.sourceBlobContainerClient;
+ this.destinationBlobContainerClient =
builder.destinationBlobContainerClient;
}
- public int run() throws IOException, StorageException, URISyntaxException {
+ public int run() throws IOException, URISyntaxException {
Stopwatch watch = Stopwatch.createStarted();
SegmentNodeStorePersistence roPersistence;
SegmentNodeStorePersistence rwPersistence;
- if (sourceCloudBlobDirectory != null && destinationCloudBlobDirectory
!= null) {
- roPersistence = new AzurePersistenceV8(sourceCloudBlobDirectory);
- rwPersistence = new
AzurePersistenceV8(destinationCloudBlobDirectory);
+ BlobContainerClient targetContainer;
+ if (sourceBlobContainerClient != null &&
destinationBlobContainerClient != null) {
+ roPersistence = new AzurePersistence(sourceBlobContainerClient,
rootPrefix);
+ rwPersistence = new
AzurePersistence(destinationBlobContainerClient, targetRootPrefix);
+ targetContainer = destinationBlobContainerClient;
} else {
- roPersistence =
newSegmentNodeStorePersistence(SegmentStoreType.AZURE, path,
azureStorageCredentialManagerV8);
- rwPersistence =
newSegmentNodeStorePersistence(SegmentStoreType.AZURE, targetPath,
azureStorageCredentialManagerV8);
+ roPersistence = createAzurePersistence(path);
+
+ AzurePersistence rwAzurePersistence =
createAzurePersistence(targetPath);
+ targetContainer = rwAzurePersistence.getReadBlobContainerClient();
+ rwPersistence = rwAzurePersistence;
}
if (persistentCachePath != null) {
@@ -348,8 +379,8 @@ public class AzureCompact {
SegmentArchiveManager roArchiveManager =
createArchiveManager(roPersistence);
SegmentArchiveManager rwArchiveManager =
createArchiveManager(rwPersistence);
- System.out.printf("Compacting %s\n", path != null ? path :
sourceCloudBlobDirectory.getUri().toString());
- System.out.printf(" to %s\n", targetPath != null ? targetPath :
destinationCloudBlobDirectory.getUri().toString());
+ System.out.printf("Compacting %s\n", path != null ? path :
sourceBlobContainerClient.getBlobContainerUrl());
+ System.out.printf(" to %s\n", targetPath != null ? targetPath :
destinationBlobContainerClient.getBlobContainerUrl());
System.out.printf(" before\n");
List<String> beforeArchives = Collections.emptyList();
try {
@@ -360,14 +391,6 @@ public class AzureCompact {
printArchives(System.out, beforeArchives);
- CloudBlobContainer targetContainer = null;
- if (targetPath != null) {
- CloudBlobDirectory targetDirectory =
createCloudBlobDirectory(targetPath.substring(3),
azureStorageCredentialManagerV8);
- targetContainer = targetDirectory.getContainer();
- } else {
- targetContainer = destinationCloudBlobDirectory.getContainer();
- }
-
GCGeneration gcGeneration = null;
String root = null;
@@ -424,8 +447,6 @@ public class AzureCompact {
long newSize = printTargetRepoSizeInfo(targetContainer);
persistGCJournal(rwPersistence, newSize, gcGeneration, root);
- // close azure storage credential manager
- azureStorageCredentialManagerV8.close();
return 0;
}
@@ -456,13 +477,14 @@ public class AzureCompact {
return true;
}
- private long printTargetRepoSizeInfo(CloudBlobContainer container) {
- System.out.printf("Calculating the size of container %s\n",
container.getName());
+ private long printTargetRepoSizeInfo(BlobContainerClient
blobContainerClient) {
+ System.out.printf("Calculating the size of container %s\n",
blobContainerClient.getBlobContainerName());
long size = 0;
- for (ListBlobItem i : container.listBlobs(null, true,
EnumSet.of(BlobListingDetails.METADATA), null, null)) {
- if (i instanceof CloudBlob) {
- size += ((CloudBlob) i).getProperties().getLength();
- }
+ ListBlobsOptions listBlobsOptions = new ListBlobsOptions();
+ listBlobsOptions.setDetails(new
BlobListDetails().setRetrieveMetadata(true));
+
+ for (BlobItem blobItem :
blobContainerClient.listBlobs(listBlobsOptions, null)) {
+ size += blobItem.getProperties().getContentLength();
}
System.out.printf("The size is: %d MB \n", size / 1024 / 1024);
return size;
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopy.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopy.java
index 706f64885a..cfed41d3cf 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopy.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopy.java
@@ -43,7 +43,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.jackrabbit.oak.commons.Buffer;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
import
org.apache.jackrabbit.oak.segment.azure.tool.SegmentStoreMigrator.Segment;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.SegmentStoreType;
import org.apache.jackrabbit.oak.segment.azure.util.Retrier;
@@ -260,7 +259,6 @@ public class SegmentCopy {
private SegmentNodeStorePersistence destPersistence;
private ExecutorService executor =
Executors.newFixedThreadPool(READ_THREADS + 1);
- private final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8;
public SegmentCopy(Builder builder) {
this.source = builder.source;
@@ -273,7 +271,6 @@ public class SegmentCopy {
this.maxSizeGb = builder.maxSizeGb;
this.outWriter = builder.outWriter;
this.errWriter = builder.errWriter;
- this.azureStorageCredentialManagerV8 = new
AzureStorageCredentialManagerV8();
}
public int run() {
@@ -288,7 +285,7 @@ public class SegmentCopy {
if (flat && destType == SegmentStoreType.TAR) {
try {
if (srcPersistence == null) {
- srcPersistence = newSegmentNodeStorePersistence(srcType,
source, azureStorageCredentialManagerV8);
+ srcPersistence = newSegmentNodeStorePersistence(srcType,
source);
}
SegmentArchiveManager sourceManager =
srcPersistence.createArchiveManager(false, false,
@@ -366,14 +363,12 @@ public class SegmentCopy {
destination);
e.printStackTrace(errWriter);
return 1;
- } finally {
- azureStorageCredentialManagerV8.close();
}
} else {
try {
if (srcPersistence == null || destPersistence == null) {
- srcPersistence = newSegmentNodeStorePersistence(srcType,
source, azureStorageCredentialManagerV8);
- destPersistence = newSegmentNodeStorePersistence(destType,
destination, azureStorageCredentialManagerV8);
+ srcPersistence = newSegmentNodeStorePersistence(srcType,
source);
+ destPersistence = newSegmentNodeStorePersistence(destType,
destination);
}
printMessage(outWriter, "Started segment-copy transfer!");
@@ -397,8 +392,6 @@ public class SegmentCopy {
destination);
e.printStackTrace(errWriter);
return 1;
- } finally {
- azureStorageCredentialManagerV8.close();
}
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
index 6bba400c16..404be35419 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
@@ -19,11 +19,9 @@ package org.apache.jackrabbit.oak.segment.azure.tool;
import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.fetchByteArray;
import static
org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.storeDescription;
-import com.microsoft.azure.storage.StorageException;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
-
+import com.azure.storage.blob.BlobContainerClient;
import org.apache.jackrabbit.oak.commons.Buffer;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzurePersistenceV8;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.SegmentStoreType;
import org.apache.jackrabbit.oak.segment.azure.util.Retrier;
import org.apache.jackrabbit.oak.segment.file.tar.TarPersistence;
@@ -45,7 +43,6 @@ import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
-import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -289,9 +286,9 @@ public class SegmentStoreMigrator implements Closeable {
return this;
}
- public Builder withSource(CloudBlobDirectory dir) throws
URISyntaxException, StorageException {
- this.source = new AzurePersistenceV8(dir);
- this.sourceName = storeDescription(SegmentStoreType.AZURE,
dir.getContainer().getName() + "/" + dir.getPrefix());
+ public Builder withSource(BlobContainerClient blobContainerClient,
String rootPrefix) {
+ this.source = new AzurePersistence(blobContainerClient,
rootPrefix);
+ this.sourceName = storeDescription(SegmentStoreType.AZURE,
blobContainerClient.getBlobContainerName() + "/" + rootPrefix);
return this;
}
@@ -313,9 +310,9 @@ public class SegmentStoreMigrator implements Closeable {
return this;
}
- public Builder withTarget(CloudBlobDirectory dir) throws
URISyntaxException, StorageException {
- this.target = new AzurePersistenceV8(dir);
- this.targetName = storeDescription(SegmentStoreType.AZURE,
dir.getContainer().getName() + "/" + dir.getPrefix());
+ public Builder withTarget(BlobContainerClient blobContainerClient,
String rootPrefix) {
+ this.target = new AzurePersistence(blobContainerClient,
rootPrefix);
+ this.targetName = storeDescription(SegmentStoreType.AZURE,
blobContainerClient.getBlobContainerUrl() + "/" + rootPrefix);
return this;
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtils.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtils.java
index 3eab847215..e41e6f5350 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtils.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtils.java
@@ -21,27 +21,24 @@ package org.apache.jackrabbit.oak.segment.azure.tool;
import static
org.apache.jackrabbit.oak.segment.azure.util.AzureConfigurationParserUtils.KEY_ACCOUNT_NAME;
import static
org.apache.jackrabbit.oak.segment.azure.util.AzureConfigurationParserUtils.KEY_DIR;
import static
org.apache.jackrabbit.oak.segment.azure.util.AzureConfigurationParserUtils.KEY_SHARED_ACCESS_SIGNATURE;
-import static
org.apache.jackrabbit.oak.segment.azure.util.AzureConfigurationParserUtils.KEY_STORAGE_URI;
+import static
org.apache.jackrabbit.oak.segment.azure.util.AzureConfigurationParserUtils.KEY_CONTAINER_NAME;
import static
org.apache.jackrabbit.oak.segment.azure.util.AzureConfigurationParserUtils.parseAzureConfigurationFromUri;
import static
org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.defaultGCOptions;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
-import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.apache.jackrabbit.oak.commons.Buffer;
import org.apache.jackrabbit.oak.commons.collections.ListUtils;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzurePersistenceV8;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistenceManager;
import org.apache.jackrabbit.oak.segment.azure.util.Environment;
import
org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.CompactorType;
import org.apache.jackrabbit.oak.segment.file.*;
@@ -60,12 +57,8 @@ import
org.apache.jackrabbit.oak.segment.spi.persistence.persistentcache.Persist
import org.apache.jackrabbit.guava.common.base.Stopwatch;
import org.apache.jackrabbit.guava.common.collect.Iterators;
-import com.microsoft.azure.storage.StorageCredentials;
-import com.microsoft.azure.storage.StorageCredentialsSharedAccessSignature;
-import com.microsoft.azure.storage.StorageException;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
+
import org.apache.jackrabbit.oak.stats.StatisticsProvider;
-import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -130,15 +123,12 @@ public class ToolUtils {
}
public static SegmentNodeStorePersistence
newSegmentNodeStorePersistence(SegmentStoreType storeType,
-
String pathOrUri,
-
@Nullable AzureStorageCredentialManagerV8 azureStorageCredentialManagerV8) {
+
String pathOrUri) {
SegmentNodeStorePersistence persistence = null;
switch (storeType) {
case AZURE:
- Objects.requireNonNull(azureStorageCredentialManagerV8, "azure
storage credentials manager instance cannot be null");
- CloudBlobDirectory cloudBlobDirectory =
createCloudBlobDirectory(pathOrUri.substring(3),
azureStorageCredentialManagerV8);
- persistence = new AzurePersistenceV8(cloudBlobDirectory);
+ persistence = createAzurePersistence(pathOrUri.substring(3));
break;
default:
persistence = new TarPersistence(new File(pathOrUri));
@@ -160,48 +150,43 @@ public class ToolUtils {
return archiveManager;
}
- public static CloudBlobDirectory createCloudBlobDirectory(String path,
AzureStorageCredentialManagerV8 azureStorageCredentialManagerV8) {
- return createCloudBlobDirectory(path, ENVIRONMENT,
azureStorageCredentialManagerV8);
+ public static AzurePersistence createAzurePersistence(String path) {
+ return createAzurePersistence(path, ENVIRONMENT);
}
- public static CloudBlobDirectory createCloudBlobDirectory(String path,
- Environment
environment,
-
AzureStorageCredentialManagerV8 azureStorageCredentialManagerV8) {
+ public static AzurePersistence createAzurePersistence(String path,
+ Environment
environment) {
Map<String, String> config = parseAzureConfigurationFromUri(path);
String accountName = config.get(KEY_ACCOUNT_NAME);
-
- StorageCredentials credentials;
- if (config.containsKey(KEY_SHARED_ACCESS_SIGNATURE)) {
- credentials = new
StorageCredentialsSharedAccessSignature(config.get(KEY_SHARED_ACCESS_SIGNATURE));
- } else {
- credentials =
azureStorageCredentialManagerV8.getStorageCredentialsFromEnvironment(accountName,
environment);
- }
-
- String uri = config.get(KEY_STORAGE_URI);
+ String containerName = config.get(KEY_CONTAINER_NAME);
String dir = config.get(KEY_DIR);
+ AzurePersistence azurePersistence;
try {
- return AzureUtilitiesV8.cloudBlobDirectoryFrom(credentials, uri,
dir);
- } catch (URISyntaxException | StorageException e) {
+ if (config.containsKey(KEY_SHARED_ACCESS_SIGNATURE)) {
+ azurePersistence =
AzurePersistenceManager.createAzurePersistenceFrom(accountName, containerName,
dir, config.get(KEY_SHARED_ACCESS_SIGNATURE));
+ } else {
+ azurePersistence =
AzurePersistenceManager.createAzurePersistenceFrom(accountName, containerName,
dir, environment);
+ }
+ } catch (IOException e) {
throw new IllegalArgumentException(
"Could not connect to the Azure Storage. Please verify the
path provided!");
}
+ return azurePersistence;
}
public static List<String> readRevisions(String uri) {
- try (AzureStorageCredentialManagerV8 azureStorageCredentialManagerV8 =
new AzureStorageCredentialManagerV8()) {
- SegmentNodeStorePersistence persistence =
newSegmentNodeStorePersistence(SegmentStoreType.AZURE, uri,
azureStorageCredentialManagerV8);
- JournalFile journal = persistence.getJournalFile();
- if (journal.exists()) {
- try (JournalReader journalReader = new JournalReader(journal))
{
- Iterator<String> revisionIterator =
Iterators.transform(journalReader,
- entry -> entry.getRevision());
- return ListUtils.toList(revisionIterator);
- } catch (Exception e) {
- log.error("Error while reading from journal file");
- e.printStackTrace();
- }
+ SegmentNodeStorePersistence persistence =
newSegmentNodeStorePersistence(SegmentStoreType.AZURE, uri);
+ JournalFile journal = persistence.getJournalFile();
+ if (journal.exists()) {
+ try (JournalReader journalReader = new JournalReader(journal)) {
+ Iterator<String> revisionIterator =
Iterators.transform(journalReader,
+ entry -> entry.getRevision());
+ return ListUtils.toList(revisionIterator);
+ } catch (Exception e) {
+ log.error("Error while reading from journal file");
+ e.printStackTrace();
}
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureConfigurationParserUtils.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureConfigurationParserUtils.java
index e2279f9d81..9ee8f1098f 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureConfigurationParserUtils.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureConfigurationParserUtils.java
@@ -147,14 +147,15 @@ public class AzureConfigurationParserUtils {
int dotPosHost = host.indexOf(".");
String accountName = host.substring(0, dotPosHost);
- String container = path.substring(0, lastSlashPosPath);
- String storageUri = scheme + "://" + host + container;
+ String container = path.substring(1, lastSlashPosPath);
+ String storageUri = scheme + "://" + host + "/" + container;
String dir = path.substring(lastSlashPosPath + 1);
Map<String, String> config = new HashMap<>();
config.put(KEY_ACCOUNT_NAME, accountName);
config.put(KEY_STORAGE_URI, storageUri);
config.put(KEY_DIR, dir);
+ config.put(KEY_CONTAINER_NAME, container);
if (sasToken != null) {
config.put(KEY_SHARED_ACCESS_SIGNATURE, sasToken);
}
diff --git
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManagerTest.java
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManagerTest.java
new file mode 100644
index 0000000000..6909edc07e
--- /dev/null
+++
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistenceManagerTest.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.segment.azure;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertThrows;
+import org.apache.jackrabbit.oak.segment.azure.util.Environment;
+import org.osgi.util.converter.Converters;
+
+import java.util.HashMap;
+
+public class AzurePersistenceManagerTest {
+
+ @Test
+ public void bothConnectionStringAndSasTokenNotConfiguredTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence(null, null, "accountName",
"containerName", "aem", false, false));
+ }
+
+ @Test
+ public void bothConnectionStringAndSasTokenBlankTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("", "", "accountName",
"containerName", "aem", false, false));
+ }
+
+ @Test
+ public void connectionStringBlankAndSasTokenNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("", null, "accountName",
"containerName", "aem", false, false));
+ }
+
+ @Test
+ public void connectionStringNullAndSasTokenBlankTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence(null, "", "accountName",
"containerName", "aem", false, false));
+ }
+
+ @Test
+ public void accountNameIsNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("connectionString", "sasToken",
null, "containerName", "aem", false, false));
+ }
+
+ @Test
+ public void accountNameIsEmptyTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("connectionString", "sasToken",
"", "containerName", "aem", false, false));
+ }
+
+ @Test
+ public void containerNameIsNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("connectionString", "sasToken",
"accountName", null, "aem", false, false));
+ }
+
+ @Test
+ public void containerNameIsEmptyTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("connectionString", "sasToken",
"accountName", "", "aem", false, false));
+ }
+
+ @Test
+ public void rootPrefixIsNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("connectionString", "sasToken",
"accountName", "containerName", null, false, false));
+ }
+
+ @Test
+ public void rootPrefixIsEmptyTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistence("connectionString", "sasToken",
"accountName", "containerName", "", false, false));
+ }
+
+ @Test
+ public void servicePrincipalsAccountNameIsNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createPersistenceFromServicePrincipalCredentials(null,
"containerName", "rootPrefix", "clientId", "clientSecret", "tenantId", false,
false));
+ }
+
+ @Test
+ public void servicePrincipalAccountNameIsEmptyTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createPersistenceFromServicePrincipalCredentials("",
"containerName", "rootPrefix", "clientId", "clientSecret", "tenantId", false,
false));
+ }
+
+ @Test
+ public void servicePrincipalsContainerNameIsNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createPersistenceFromServicePrincipalCredentials("accountName",
null, "rootPrefix", "clientId", "clientSecret", "tenantId", false, false));
+ }
+
+ @Test
+ public void servicePrincipalsContainerNameIsEmptyTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createPersistenceFromServicePrincipalCredentials("accountName",
"", "rootPrefix", "clientId", "clientSecret", "tenantId", false, false));
+ }
+
+ @Test
+ public void servicePrincipalsRootPrefixIsNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createPersistenceFromServicePrincipalCredentials("accountName",
"containerName", null, "clientId", "clientSecret", "tenantId", false, false));
+ }
+
+ @Test
+ public void servicePrincipalsRootPrefixIsEmptyTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createPersistenceFromServicePrincipalCredentials("accountName",
"containerName", "", "clientId", "clientSecret", "tenantId", false, false));
+ }
+
+ @Test
+ public void createAzurePersistenceAllNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistenceFrom(null, null, null,
"sasToken"));
+ }
+
+ @Test
+ public void createAzurePersistenceFromEnvAllNullTest() {
+ Environment env = new Environment();
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistenceFrom(null, null, null, env));
+ }
+
+ @Test
+ public void createAzurePersistenceFromConfigurationAllNullTest() {
+ assertThrows(IllegalArgumentException.class, () ->
AzurePersistenceManager.createAzurePersistenceFrom(getConfiguration()));
+ }
+
+ private static Configuration getConfiguration() {
+ return Converters.standardConverter()
+ .convert(new HashMap<Object, Object>() {{
+ put("accountName", null);
+ put("accessKey", null);
+ put("connectionURL",
"https://accounts.blob.core.windows.net");
+ put("sharedAccessSignature", "sharedAccessSignature");
+ put("clientId", "clientId");
+ put("clientSecret", "clientSecret");
+ put("tenantId", "tenantId");
+ put("blobEndpoint", "blobEndpoint");
+ }})
+ .to(Configuration.class);
+ }
+
+}
\ No newline at end of file
diff --git
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyAzureServicePrincipalToTarTest.java
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyAzureServicePrincipalToTarTest.java
index 7d7ada9e3b..c6e36ab070 100644
---
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyAzureServicePrincipalToTarTest.java
+++
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyAzureServicePrincipalToTarTest.java
@@ -18,18 +18,16 @@
*/
package org.apache.jackrabbit.oak.segment.azure.tool;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzurePersistenceV8;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.azure.util.Environment;
import
org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence;
import org.junit.Test;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_ACCOUNT_NAME;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_CLIENT_ID;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_CLIENT_SECRET;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_TENANT_ID;
+import java.io.IOException;
+
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_ACCOUNT_NAME;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_CLIENT_ID;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_CLIENT_SECRET;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_TENANT_ID;
import static org.junit.Assume.assumeNotNull;
public class SegmentCopyAzureServicePrincipalToTarTest extends
SegmentCopyTestBase {
@@ -53,11 +51,7 @@ public class SegmentCopyAzureServicePrincipalToTarTest
extends SegmentCopyTestBa
protected SegmentNodeStorePersistence getSrcPersistence() {
String accountName = ENVIRONMENT.getVariable(AZURE_ACCOUNT_NAME);
String path = String.format(SEGMENT_STORE_PATH_FORMAT, accountName,
CONTAINER_NAME, DIR);
- CloudBlobDirectory cloudBlobDirectory;
- try (AzureStorageCredentialManagerV8 azureStorageCredentialManagerV8 =
new AzureStorageCredentialManagerV8()) {
- cloudBlobDirectory = ToolUtils.createCloudBlobDirectory(path,
ENVIRONMENT, azureStorageCredentialManagerV8);
- }
- return new AzurePersistenceV8(cloudBlobDirectory);
+ return ToolUtils.createAzurePersistence(path, ENVIRONMENT);
}
@Override
diff --git
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
index 05e7d32b9e..f259939e53 100644
---
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
+++
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
@@ -231,7 +231,7 @@ public abstract class SegmentCopyTestBase {
}
protected SegmentNodeStorePersistence getTarPersistence() {
- return newSegmentNodeStorePersistence(SegmentStoreType.TAR,
folder.getRoot().getAbsolutePath(), null);
+ return newSegmentNodeStorePersistence(SegmentStoreType.TAR,
folder.getRoot().getAbsolutePath());
}
protected SegmentNodeStorePersistence getAzurePersistence() throws
Exception {
diff --git
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtilsTest.java
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtilsTest.java
index 4fbb51555e..049cfdb5ee 100644
---
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtilsTest.java
+++
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/ToolUtilsTest.java
@@ -23,44 +23,30 @@ import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.read.ListAppender;
-import com.microsoft.azure.storage.StorageCredentials;
-import com.microsoft.azure.storage.StorageCredentialsAccountAndKey;
-import com.microsoft.azure.storage.StorageCredentialsSharedAccessSignature;
-import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import com.microsoft.azure.storage.StorageException;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import
org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage.AzuriteDockerRule;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
import org.apache.jackrabbit.oak.segment.azure.util.Environment;
import org.jetbrains.annotations.NotNull;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.MockedStatic;
import org.slf4j.LoggerFactory;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_ACCOUNT_NAME;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_CLIENT_ID;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_CLIENT_SECRET;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_SECRET_KEY;
-import static
org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8.AZURE_TENANT_ID;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_ACCOUNT_NAME;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_CLIENT_ID;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_CLIENT_SECRET;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_SECRET_KEY;
+import static
org.apache.jackrabbit.oak.segment.azure.AzureUtilities.AZURE_TENANT_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNotNull;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mockStatic;
public class ToolUtilsTest {
private static final Environment ENVIRONMENT = new Environment();
@@ -71,75 +57,56 @@ public class ToolUtilsTest {
private static final String DEFAULT_ACCOUNT_NAME = "myaccount";
private static final String DEFAULT_CONTAINER_NAME = "oak";
private static final String DEFAULT_REPO_DIR = "repository";
- private static final String DEFAULT_CONTAINER_URL =
String.format(CONTAINER_URL_FORMAT, DEFAULT_ACCOUNT_NAME,
DEFAULT_CONTAINER_NAME);
private static final String DEFAULT_SEGMENT_STORE_PATH =
String.format(SEGMENT_STORE_PATH_FORMAT, DEFAULT_ACCOUNT_NAME,
DEFAULT_CONTAINER_NAME, DEFAULT_REPO_DIR);
public static final String AZURE_SECRET_KEY_WARNING = "AZURE_CLIENT_ID,
AZURE_CLIENT_SECRET and AZURE_TENANT_ID environment variables empty or missing.
Switching to authentication with AZURE_SECRET_KEY.";
private final TestEnvironment environment = new TestEnvironment();
- private AzureStorageCredentialManagerV8 azureStorageCredentialManagerV8;
-
- @Before
- public void init() {
- this.azureStorageCredentialManagerV8 = new
AzureStorageCredentialManagerV8();
- }
-
- @After
- public void clear() {
- this.azureStorageCredentialManagerV8.close();
- }
@Test
- public void createCloudBlobDirectoryWithAccessKey() {
+ public void createAzurePersistenceWithAccessKey() {
environment.setVariable(AZURE_SECRET_KEY,
AzuriteDockerRule.ACCOUNT_KEY);
final ListAppender<ILoggingEvent> logAppender = subscribeAppender();
- StorageCredentialsAccountAndKey credentials = expectCredentials(
- StorageCredentialsAccountAndKey.class,
- () ->
ToolUtils.createCloudBlobDirectory(DEFAULT_SEGMENT_STORE_PATH, environment,
azureStorageCredentialManagerV8),
- DEFAULT_CONTAINER_URL
- );
+ AzurePersistence azurePersistence =
ToolUtils.createAzurePersistence(DEFAULT_SEGMENT_STORE_PATH, environment);
assertTrue(checkLogContainsMessage(AZURE_SECRET_KEY_WARNING,
logAppender.list.stream().map(ILoggingEvent::getFormattedMessage).collect(Collectors.toList())));
assertEquals(Level.WARN, logAppender.list.get(0).getLevel());
- assertEquals(DEFAULT_ACCOUNT_NAME, credentials.getAccountName());
- assertEquals(AzuriteDockerRule.ACCOUNT_KEY,
credentials.exportBase64EncodedKey());
+ assertEquals(DEFAULT_ACCOUNT_NAME,
azurePersistence.getReadBlobContainerClient().getAccountName());
+ assertEquals(DEFAULT_CONTAINER_NAME,
azurePersistence.getReadBlobContainerClient().getBlobContainerName());
unsubscribe(logAppender);
}
@Test
- public void createCloudBlobDirectoryFailsWhenAccessKeyNotPresent() {
+ public void createAzurePersistenceFailsWhenAccessKeyNotPresent() {
environment.setVariable(AZURE_SECRET_KEY, null);
assertThrows(IllegalArgumentException.class, () ->
- ToolUtils.createCloudBlobDirectory(DEFAULT_SEGMENT_STORE_PATH,
environment, azureStorageCredentialManagerV8)
+ ToolUtils.createAzurePersistence(DEFAULT_SEGMENT_STORE_PATH,
environment)
);
}
@Test
- public void createCloudBlobDirectoryFailsWhenAccessKeyIsInvalid() {
+ public void createAzurePersistenceFailsWhenAccessKeyIsInvalid() {
environment.setVariable(AZURE_SECRET_KEY, "invalid");
- assertThrows(IllegalArgumentException.class, () ->
- ToolUtils.createCloudBlobDirectory(DEFAULT_SEGMENT_STORE_PATH,
environment, azureStorageCredentialManagerV8)
+ AzurePersistence azurePersistence =
ToolUtils.createAzurePersistence(DEFAULT_SEGMENT_STORE_PATH, environment);
+
+ assertThrows(Exception.class, () ->
+ azurePersistence.getReadBlobContainerClient().exists()
);
}
@Test
- public void createCloudBlobDirectoryWithSasUri() {
+ public void createAzurePersistenceWithSasUri() {
String sasToken =
"sig=qL%2Fi%2BP7J6S0sA8Ihc%2BKq75U5uJcnukpfktT2fm1ckXk%3D&se=2022-02-09T11%3A52%3A42Z&sv=2019-02-02&sp=rl&sr=c";
- StorageCredentialsSharedAccessSignature credentials =
expectCredentials(
- StorageCredentialsSharedAccessSignature.class,
- () ->
ToolUtils.createCloudBlobDirectory(DEFAULT_SEGMENT_STORE_PATH + '?' + sasToken,
azureStorageCredentialManagerV8),
- DEFAULT_CONTAINER_URL
- );
+ AzurePersistence azurePersistence =
ToolUtils.createAzurePersistence(DEFAULT_SEGMENT_STORE_PATH + '?' + sasToken);
- assertEquals(sasToken, credentials.getToken());
- assertNull("AccountName should be null when SAS credentials are used",
credentials.getAccountName());
+ assertEquals(DEFAULT_CONTAINER_NAME,
azurePersistence.getReadBlobContainerClient().getBlobContainerName());
}
@Test
- public void createCloudBlobDirectoryWithServicePrincipal() throws
URISyntaxException, StorageException {
+ public void createAzurePersistenceWithServicePrincipal() {
assumeNotNull(ENVIRONMENT.getVariable(AZURE_ACCOUNT_NAME));
assumeNotNull(ENVIRONMENT.getVariable(AZURE_TENANT_ID));
assumeNotNull(ENVIRONMENT.getVariable(AZURE_CLIENT_ID));
@@ -149,24 +116,9 @@ public class ToolUtilsTest {
String containerName = "oak";
String segmentStorePath = String.format(SEGMENT_STORE_PATH_FORMAT,
accountName, containerName, DEFAULT_REPO_DIR);
- CloudBlobDirectory cloudBlobDirectory =
ToolUtils.createCloudBlobDirectory(segmentStorePath, ENVIRONMENT,
azureStorageCredentialManagerV8);
- assertNotNull(cloudBlobDirectory);
- assertEquals(containerName,
cloudBlobDirectory.getContainer().getName());
- }
-
- private static <T extends StorageCredentials> T expectCredentials(Class<T>
clazz, Runnable body, String containerUrl) {
- ArgumentCaptor<T> credentialsCaptor = ArgumentCaptor.forClass(clazz);
- try (MockedStatic<AzureUtilitiesV8> mockedAzureUtilities =
mockStatic(AzureUtilitiesV8.class)) {
- body.run();
-
- mockedAzureUtilities.verify(() ->
AzureUtilitiesV8.cloudBlobDirectoryFrom(
- credentialsCaptor.capture(),
- eq(containerUrl),
- eq(DEFAULT_REPO_DIR)
- )
- );
- return credentialsCaptor.getValue();
- }
+ AzurePersistence azurePersistence =
ToolUtils.createAzurePersistence(segmentStorePath, ENVIRONMENT);
+ assertNotNull(azurePersistence);
+ assertEquals(containerName,
azurePersistence.getReadBlobContainerClient().getBlobContainerName());
}
private boolean checkLogContainsMessage(String toCheck, List<String>
messages) {
diff --git
a/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/SegmentAzureServicePrincipalNodeStoreContainer.java
b/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/SegmentAzureServicePrincipalNodeStoreContainer.java
index 34f6bcc987..b3535646e3 100644
---
a/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/SegmentAzureServicePrincipalNodeStoreContainer.java
+++
b/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/SegmentAzureServicePrincipalNodeStoreContainer.java
@@ -16,11 +16,9 @@
*/
package org.apache.jackrabbit.oak.upgrade.cli.container;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzurePersistenceV8;
-import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
+import org.apache.jackrabbit.oak.segment.azure.AzureUtilities;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.azure.util.Environment;
import org.apache.jackrabbit.oak.segment.file.FileStore;
@@ -43,8 +41,7 @@ public class SegmentAzureServicePrincipalNodeStoreContainer
implements NodeStore
private final BlobStore blobStore;
private FileStore fs;
private File tmpDir;
- private AzurePersistenceV8 azurePersistenceV8;
- private final AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8;
+ private AzurePersistence azurePersistence;
public SegmentAzureServicePrincipalNodeStoreContainer() {
this(null);
@@ -52,21 +49,20 @@ public class SegmentAzureServicePrincipalNodeStoreContainer
implements NodeStore
public SegmentAzureServicePrincipalNodeStoreContainer(BlobStore blobStore)
{
this.blobStore = blobStore;
- this.azureStorageCredentialManagerV8 = new
AzureStorageCredentialManagerV8();
}
@Override
public NodeStore open() throws IOException {
try {
- azurePersistenceV8 = createAzurePersistence();
+ azurePersistence = createAzurePersistence();
} catch (Exception e) {
throw new IllegalStateException(e);
}
tmpDir = Files.createTempDirectory(getClass().getSimpleName() +
"-").toFile();
FileStoreBuilder builder = FileStoreBuilder.fileStoreBuilder(tmpDir)
-
.withCustomPersistence(azurePersistenceV8).withMemoryMapping(false);
+
.withCustomPersistence(azurePersistence).withMemoryMapping(false);
if (blobStore != null) {
builder.withBlobStore(blobStore);
}
@@ -80,14 +76,13 @@ public class SegmentAzureServicePrincipalNodeStoreContainer
implements NodeStore
return new
FileStoreUtils.NodeStoreWithFileStore(SegmentNodeStoreBuilders.builder(fs).build(),
fs);
}
- private AzurePersistenceV8 createAzurePersistence() {
- if (azurePersistenceV8 != null) {
- return azurePersistenceV8;
+ private AzurePersistence createAzurePersistence() {
+ if (azurePersistence != null) {
+ return azurePersistence;
}
- String path = String.format(AZURE_SEGMENT_STORE_PATH,
ENVIRONMENT.getVariable(AzureUtilitiesV8.AZURE_ACCOUNT_NAME),
+ String path = String.format(AZURE_SEGMENT_STORE_PATH,
ENVIRONMENT.getVariable(AzureUtilities.AZURE_ACCOUNT_NAME),
CONTAINER_NAME, DIR);
- CloudBlobDirectory cloudBlobDirectory =
ToolUtils.createCloudBlobDirectory(path, ENVIRONMENT,
azureStorageCredentialManagerV8);
- return new AzurePersistenceV8(cloudBlobDirectory);
+ return ToolUtils.createAzurePersistence(path, ENVIRONMENT);
}
@Override
@@ -99,16 +94,13 @@ public class SegmentAzureServicePrincipalNodeStoreContainer
implements NodeStore
if (tmpDir != null) {
tmpDir.delete();
}
- if (azureStorageCredentialManagerV8 != null) {
- azureStorageCredentialManagerV8.close();
- }
}
@Override
public void clean() throws IOException {
- AzurePersistenceV8 azurePersistenceV8 = createAzurePersistence();
+ AzurePersistence azurePersistence = createAzurePersistence();
try {
-
AzureUtilitiesV8.deleteAllBlobs(azurePersistenceV8.getSegmentstoreDirectory());
+
AzureUtilities.deleteAllEntries(azurePersistence.getReadBlobContainerClient(),
null);
} catch (Exception e) {
throw new IOException(e);
}
@@ -116,7 +108,7 @@ public class SegmentAzureServicePrincipalNodeStoreContainer
implements NodeStore
@Override
public String getDescription() {
- return "az:" + String.format(AZURE_SEGMENT_STORE_PATH,
ENVIRONMENT.getVariable(AzureUtilitiesV8.AZURE_ACCOUNT_NAME),
+ return "az:" + String.format(AZURE_SEGMENT_STORE_PATH,
ENVIRONMENT.getVariable(AzureUtilities.AZURE_ACCOUNT_NAME),
CONTAINER_NAME, DIR);
}
}
\ No newline at end of file
diff --git
a/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentAzureFactoryTest.java
b/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentAzureFactoryTest.java
index 393cd34b28..1114121348 100644
---
a/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentAzureFactoryTest.java
+++
b/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentAzureFactoryTest.java
@@ -21,12 +21,12 @@ import
com.microsoft.azure.storage.SharedAccessAccountPermissions;
import com.microsoft.azure.storage.SharedAccessAccountPolicy;
import com.microsoft.azure.storage.SharedAccessAccountResourceType;
import com.microsoft.azure.storage.SharedAccessAccountService;
-import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import org.apache.commons.lang3.StringUtils;
-import
org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage.AzuriteDockerRule;
import org.apache.jackrabbit.oak.commons.pio.Closer;
+import
org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage.AzuriteDockerRule;
+import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
+import org.apache.jackrabbit.oak.segment.azure.AzureUtilities;
import
org.apache.jackrabbit.oak.segment.azure.v8.AzureStorageCredentialManagerV8;
-import org.apache.jackrabbit.oak.segment.azure.v8.AzureUtilitiesV8;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils;
import org.apache.jackrabbit.oak.segment.azure.util.Environment;
import org.apache.jackrabbit.oak.upgrade.cli.CliUtils;
@@ -122,7 +122,7 @@ public class SegmentAzureFactoryTest {
assertEquals(1, nodeStore.getFileStore().getSegmentCount());
} finally {
closer.close();
- cleanup(uri, azureStorageCredentialManagerV8);
+ cleanup(uri);
}
}
}
@@ -149,16 +149,16 @@ public class SegmentAzureFactoryTest {
assertEquals(1, nodeStore.getFileStore().getSegmentCount());
} finally {
closer.close();
- cleanup(uri, azureStorageCredentialManagerV8);
+ cleanup(uri);
}
}
}
- private void cleanup(String uri, AzureStorageCredentialManagerV8
azureStorageCredentialManagerV8) {
+ private void cleanup(String uri) {
uri = uri + "/" + DIR;
try {
- CloudBlobDirectory cloudBlobDirectory =
ToolUtils.createCloudBlobDirectory(uri, ENVIRONMENT,
azureStorageCredentialManagerV8);
- AzureUtilitiesV8.deleteAllBlobs(cloudBlobDirectory);
+ AzurePersistence azurePersistence =
ToolUtils.createAzurePersistence(uri, ENVIRONMENT);
+
AzureUtilities.deleteAllEntries(azurePersistence.getReadBlobContainerClient(),
null);
} catch (Exception e) {
throw new IllegalStateException(e);
}