diff --git a/README.md b/README.md index f4b3284..3ed2305 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ The repository contains 3 projects: | UploadDirectory | UploadDirectory | [UploadDirectory](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/UploadDirectory.cs) | | UploadDirectoryWithCustomizedRetryPolicy | UploadDirectory | [UploadDirectoryWithCustomizedRetryPolicy](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/UploadDirectoryWithCustomizedRetryPolicy.cs) | | UploadDirectoryWithExclusionPolicy | UploadDirectory | [UploadDirectoryWithExclusionPolicy](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/UploadDirectoryWithExclusionPolicy.cs) | +| CloudUpload | CloudUpload | [CloudUpload](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/CloudUpload.cs) | | UploadFile | UploadFile | [UploadFile](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/UploadFile.cs) | | UploadItems | UploadFile | [UploadItems](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/UploadItems.cs) | | UploadToFilesharePathBasedOnWorkspaceId | UploadDirectoryByWorkspaceId | [UploadToFilesharePathBasedOnWorkspaceId](https://github.com/relativitydev/relativity-transfer-sdk-samples/blob/main/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/UploadToFileSharePathBasedOnWorkspaceId.cs) | diff --git a/Source/Relativity.Transfer.SDK.Samples.CLI/Program.cs b/Source/Relativity.Transfer.SDK.Samples.CLI/Program.cs index 50781f2..21e3c90 100644 --- a/Source/Relativity.Transfer.SDK.Samples.CLI/Program.cs +++ b/Source/Relativity.Transfer.SDK.Samples.CLI/Program.cs @@ -11,12 +11,6 @@ using Relativity.Transfer.SDK.Samples.Core.Runner; using Relativity.Transfer.SDK.Samples.Core.Services; using Relativity.Transfer.SDK.Samples.Core.UI; -using Relativity.Transfer.SDK.Samples.Repository.FullPathWorkflow; -using Relativity.Transfer.SDK.Samples.Repository.JobBasedWorkflow; -using FullPathWorkflowUploadDirectory = Relativity.Transfer.SDK.Samples.Repository.FullPathWorkflow.UploadDirectory; -using FullPathWorkflowDownloadDirectory = Relativity.Transfer.SDK.Samples.Repository.FullPathWorkflow.DownloadDirectory; -using JobBasedWorkflowUploadDirectory = Relativity.Transfer.SDK.Samples.Repository.JobBasedWorkflow.UploadDirectory; -using JobBasedWorkflowDownloadDirectory = Relativity.Transfer.SDK.Samples.Repository.JobBasedWorkflow.DownloadDirectory; namespace Relativity.Transfer.SDK.Samples.CLI; diff --git a/Source/Relativity.Transfer.SDK.Samples.CLI/Relativity.Transfer.SDK.Samples.CLI.csproj b/Source/Relativity.Transfer.SDK.Samples.CLI/Relativity.Transfer.SDK.Samples.CLI.csproj index 1990c8a..5dd4eab 100644 --- a/Source/Relativity.Transfer.SDK.Samples.CLI/Relativity.Transfer.SDK.Samples.CLI.csproj +++ b/Source/Relativity.Transfer.SDK.Samples.CLI/Relativity.Transfer.SDK.Samples.CLI.csproj @@ -9,12 +9,10 @@ - - diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/SampleOrder.cs b/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/SampleOrder.cs index 135e8f4..8164fe8 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/SampleOrder.cs +++ b/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/SampleOrder.cs @@ -7,6 +7,7 @@ internal enum SampleOrder UploadFile, UploadItems, UploadDirectory, + CloudUpload, UploadDirectoryWithCustomizedRetryPolicy, UploadDirectoryWithExclusionPolicy, DownloadFile, diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/TransferType.cs b/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/TransferType.cs index 1ab7316..710d11e 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/TransferType.cs +++ b/Source/Relativity.Transfer.SDK.Samples.Core/Attributes/TransferType.cs @@ -6,6 +6,7 @@ internal enum TransferType UploadDirectory, UploadFile, UploadItems, + CloudUpload, DownloadDirectory, DownloadFile, UploadDirectoryByWorkspaceId, diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/Configuration/Configuration.cs b/Source/Relativity.Transfer.SDK.Samples.Core/Configuration/Configuration.cs index 5899570..bc3ee9f 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/Configuration/Configuration.cs +++ b/Source/Relativity.Transfer.SDK.Samples.Core/Configuration/Configuration.cs @@ -1,9 +1,12 @@ -namespace Relativity.Transfer.SDK.Samples.Core.Configuration; +using System; + +namespace Relativity.Transfer.SDK.Samples.Core.Configuration; internal record Configuration( CommonConfiguration Common, SourceAndDestinationConfiguration UploadFile, SourceAndDestinationConfiguration UploadDirectory, + SourceAndDestinationConfiguration CloudUpload, SourceAndDestinationConfiguration DownloadFile, SourceAndDestinationConfiguration DownloadDirectory, SourceAndWorkspaceIdConfiguration UploadDirectoryByWorkspaceId, @@ -11,7 +14,8 @@ internal record Configuration( SourceAndTwoDestinationsConfiguration DownloadDirectoryBasedOnExistingJob) { public void Deconstruct(out CommonConfiguration common, out SourceAndDestinationConfiguration uploadFile, - out SourceAndDestinationConfiguration uploadDirectory, out SourceAndDestinationConfiguration downloadFile, + out SourceAndDestinationConfiguration uploadDirectory, out SourceAndDestinationConfiguration cloudUpload, + out SourceAndDestinationConfiguration downloadFile, out SourceAndDestinationConfiguration downloadDirectory, out SourceAndWorkspaceIdConfiguration uploadDirectoryByWorkspaceId, out TwoSourcesAndDestinationConfiguration uploadDirectoryBasedOnExistingJob, @@ -20,6 +24,7 @@ public void Deconstruct(out CommonConfiguration common, out SourceAndDestination common = Common; uploadFile = UploadFile; uploadDirectory = UploadDirectory; + cloudUpload = CloudUpload; downloadFile = DownloadFile; downloadDirectory = DownloadDirectory; uploadDirectoryByWorkspaceId = UploadDirectoryByWorkspaceId; @@ -35,6 +40,21 @@ internal static Configuration ForUploadDirectory(CommonConfiguration common, uploadDirectory, new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndWorkspaceIdConfiguration(string.Empty, -1), + new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), + new SourceAndTwoDestinationsConfiguration(string.Empty, string.Empty, string.Empty)); + } + + internal static Configuration ForCloudUpload(CommonConfiguration common, + SourceAndDestinationConfiguration cloudUpload) + { + return new Configuration(common, + new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), + cloudUpload, + new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndWorkspaceIdConfiguration(string.Empty, -1), new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), new SourceAndTwoDestinationsConfiguration(string.Empty, string.Empty, string.Empty)); @@ -47,6 +67,8 @@ internal static Configuration ForUploadFile(CommonConfiguration common, uploadFile, new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndWorkspaceIdConfiguration(string.Empty, -1), new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), @@ -61,6 +83,7 @@ internal static Configuration ForUploadItems(CommonConfiguration common, new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndWorkspaceIdConfiguration(string.Empty, -1), new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), new SourceAndTwoDestinationsConfiguration(string.Empty, string.Empty, string.Empty)); @@ -73,6 +96,7 @@ internal static Configuration ForDownloadDirectory(CommonConfiguration common, new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), downloadDirectory, new SourceAndWorkspaceIdConfiguration(string.Empty, -1), new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), @@ -83,6 +107,7 @@ internal static Configuration ForDownloadFile(CommonConfiguration common, SourceAndDestinationConfiguration downloadFile) { return new Configuration(common, + new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), downloadFile, @@ -100,6 +125,7 @@ internal static Configuration ForUploadDirectoryByWorkspaceId(CommonConfiguratio new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), uploadDirectory, new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), new SourceAndTwoDestinationsConfiguration(string.Empty, string.Empty, string.Empty)); @@ -113,6 +139,7 @@ internal static Configuration ForUploadDirectoryBasedOnExistingJob(CommonConfigu new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndWorkspaceIdConfiguration(string.Empty, -1), uploadDirectory, new SourceAndTwoDestinationsConfiguration(string.Empty, string.Empty, string.Empty)); @@ -126,6 +153,7 @@ internal static Configuration ForDownloadDirectoryBasedOnExistingJob(CommonConfi new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndDestinationConfiguration(string.Empty, string.Empty), + new SourceAndDestinationConfiguration(string.Empty, string.Empty), new SourceAndWorkspaceIdConfiguration(string.Empty, -1), new TwoSourcesAndDestinationConfiguration(string.Empty, string.Empty, string.Empty), downloadDirectory); diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/ConsoleLogger.cs b/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/ConsoleLogger.cs index 485fd90..ca191db 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/ConsoleLogger.cs +++ b/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/ConsoleLogger.cs @@ -42,6 +42,18 @@ public void PrintCreatingTransfer(Guid jobId, PathBase source, PathBase destinat AnsiConsole.WriteLine(); } + public void PrintCreatingTransfer(Guid jobId, CloudLocation source, PathBase destination, params string[] additionalLines) + { + AnsiConsole.WriteLine(); + AnsiConsole.MarkupLine($"Creating transfer [green]{jobId}[/]:"); + if (source != null) AnsiConsole.MarkupLine($"\tFrom: [purple3]{source}[/]"); + if (destination != null) AnsiConsole.MarkupLine($"\tTo: [orange4]{destination}[/]"); + + AddAdditionalLinesIfRequired(additionalLines); + + AnsiConsole.WriteLine(); + } + public void PrintTransferResult(TransferJobResult result, string headerLine = "Transfer has finished:", bool waitForKeyHit = true) { diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/IConsoleLogger.cs b/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/IConsoleLogger.cs index ddbc518..6f4805c 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/IConsoleLogger.cs +++ b/Source/Relativity.Transfer.SDK.Samples.Core/Helpers/IConsoleLogger.cs @@ -12,6 +12,7 @@ internal interface IConsoleLogger { Task PrintExitMessageAsync(); void PrintCreatingTransfer(Guid jobId, PathBase source, PathBase destination, params string[] additionalLines); + void PrintCreatingTransfer(Guid jobId, CloudLocation source, PathBase destination, params string[] additionalLines); void PrintTransferResult(TransferJobResult result, string headerLine = "Transfer has finished:", bool waitForKeyHit = true); void Info(string msg); void PrintError(Exception exception); diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/Relativity.Transfer.SDK.Samples.Core.csproj b/Source/Relativity.Transfer.SDK.Samples.Core/Relativity.Transfer.SDK.Samples.Core.csproj index 3466c05..43f1561 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/Relativity.Transfer.SDK.Samples.Core.csproj +++ b/Source/Relativity.Transfer.SDK.Samples.Core/Relativity.Transfer.SDK.Samples.Core.csproj @@ -8,13 +8,13 @@ - + - + diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/UI/ConfigurationScreen.cs b/Source/Relativity.Transfer.SDK.Samples.Core/UI/ConfigurationScreen.cs index c77a426..af2b6cc 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/UI/ConfigurationScreen.cs +++ b/Source/Relativity.Transfer.SDK.Samples.Core/UI/ConfigurationScreen.cs @@ -34,7 +34,8 @@ private Configuration.Configuration AskForParameters(Configuration.Configuration SampleAttribute sampleAttribute) { PrintTitle("Sample configuration (press enter to use default value)"); - var newCommon = AskForCommonParameters(configuration); + + var newCommon = sampleAttribute.TransferType == TransferType.CloudUpload ? AskForCloudUploadParameters(configuration) : AskForCommonParameters(configuration); return AskForTransferTypeSpecificParameters(configuration, sampleAttribute, newCommon); } @@ -53,6 +54,12 @@ private Configuration.Configuration AskForTransferTypeSpecificParameters( return Configuration.Configuration.ForUploadDirectory(common, new SourceAndDestinationConfiguration(source, destination)); + + case TransferType.CloudUpload: + source = AnsiConsole.Ask("Source SasURL", configuration.CloudUpload.Source); + destination = AnsiConsole.Ask("Destination directory", GetDefaultUploadDirectoryDestination(common, configuration.CloudUpload.Destination)); + + return Configuration.Configuration.ForCloudUpload(common, new SourceAndDestinationConfiguration(source, destination)); case TransferType.UploadFile: source = AnsiConsole.Ask("Source file", configuration.UploadFile.Source); @@ -175,6 +182,22 @@ private static CommonConfiguration AskForCommonParameters(Configuration.Configur JobId = jobId }; } + + private static CommonConfiguration AskForCloudUploadParameters(Configuration.Configuration configuration) + { + AnsiConsole.MarkupLine($"Client name [green]({configuration.Common.ClientName})[/]"); + var jobId = Guid.NewGuid(); + AnsiConsole.MarkupLine($"Job ID [green]({jobId})[/]"); + var instanceUrl = AnsiConsole.Ask("Instance URL", configuration.Common.InstanceUrl); + var clientId = AnsiConsole.Ask("Client secret ID", configuration.Common.OAuthCredentials.ClientId); + var clientSecret = AnsiConsole.Ask("Client secret", configuration.Common.OAuthCredentials.ClientSecret); + + return new CommonConfiguration(configuration.Common.ClientName, instanceUrl, string.Empty, + string.Empty, new OAuthCredentials(clientId, clientSecret)) + { + JobId = jobId + }; + } private static void PrintDescription(SampleAttribute sampleAttribute) { diff --git a/Source/Relativity.Transfer.SDK.Samples.Core/appsettings.json b/Source/Relativity.Transfer.SDK.Samples.Core/appsettings.json index d287210..70bdd34 100644 --- a/Source/Relativity.Transfer.SDK.Samples.Core/appsettings.json +++ b/Source/Relativity.Transfer.SDK.Samples.Core/appsettings.json @@ -42,6 +42,12 @@ // Should be an UNC format path to the directory on RelativityOne fileshare. "Destination": "" }, + "CloudUpload": { + // Should be a Azure DataLake Storage SasURL with Read and List permissions. + "Source": "", + // Should be an UNC format path to the directory on RelativityOne fileshare. + "Destination": "" + }, "DownloadFile": { // Should be an UNC format path to the file RelativityOne fileshare. "Source": "", diff --git a/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/CloudUpload.cs b/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/CloudUpload.cs new file mode 100644 index 0000000..222cf9c --- /dev/null +++ b/Source/Relativity.Transfer.SDK.Samples.Repository/FullPathWorkflow/CloudUpload.cs @@ -0,0 +1,61 @@ +using System.Threading; +using System.Threading.Tasks; +using Relativity.Transfer.SDK.Interfaces.Options; +using Relativity.Transfer.SDK.Interfaces.Paths; +using Relativity.Transfer.SDK.Samples.Core.Attributes; +using Relativity.Transfer.SDK.Samples.Core.Authentication; +using Relativity.Transfer.SDK.Samples.Core.Configuration; +using Relativity.Transfer.SDK.Samples.Core.Helpers; +using Relativity.Transfer.SDK.Samples.Core.ProgressHandler; +using Relativity.Transfer.SDK.Samples.Core.Runner; + +namespace Relativity.Transfer.SDK.Samples.Repository.FullPathWorkflow; + +[Sample(SampleOrder.CloudUpload, + "Cloud upload", + "The sample illustrates how to implement Cloud (Azure ADLS) upload to a RelativityOne file share. ", + typeof(CloudUpload), + TransferType.CloudUpload)] +internal class CloudUpload : ISample +{ + private readonly IConsoleLogger _consoleLogger; + private readonly IPathExtension _pathExtension; + private readonly IRelativityAuthenticationProviderFactory _relativityAuthenticationProviderFactory; + private readonly IProgressHandlerFactory _progressHandlerFactory; + + public CloudUpload(IConsoleLogger consoleLogger, IPathExtension pathExtension, IRelativityAuthenticationProviderFactory relativityAuthenticationProviderFactory, IProgressHandlerFactory progressHandlerFactory) + { + _consoleLogger = consoleLogger; + _pathExtension = pathExtension; + _relativityAuthenticationProviderFactory = relativityAuthenticationProviderFactory; + _progressHandlerFactory = progressHandlerFactory; + } + + public async Task ExecuteAsync(Configuration configuration, CancellationToken token) + { + var clientName = configuration.Common.ClientName; + var jobId = configuration.Common.JobId; + var source = new CloudLocation(configuration.CloudUpload.Source); + var destination = string.IsNullOrWhiteSpace(configuration.CloudUpload.Destination) + ? _pathExtension.GetDefaultRemoteDirectoryPathForUpload(configuration.Common) + : new DirectoryPath(configuration.CloudUpload.Destination); + var authenticationProvider = _relativityAuthenticationProviderFactory.Create(configuration.Common); + var progressHandler = _progressHandlerFactory.Create(); + + // The builder follows the Fluent convention, and more options will be added in the future. The only required component (besides the client name) + // is the authentication provider - a provided one that utilizes an OAuth-based approach has been provided, but the custom implementation can be created. + var transferClient = TransferClientBuilder.FullPathWorkflow + .WithAuthentication(authenticationProvider) + .WithClientName(clientName) + .WithStagingExplorerContext() + .Build(); + + _consoleLogger.PrintCreatingTransfer(jobId, source, destination); + + var result = await transferClient + .CloudUploadAsync(jobId, source, destination, new CloudUploadOptions(), progressHandler, token) + .ConfigureAwait(false); + + _consoleLogger.PrintTransferResult(result); + } +} \ No newline at end of file