diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs index 275e2e662b55b..4846db78997e5 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs @@ -18,8 +18,8 @@ public BackupOperation(Azure.Security.KeyVault.Administration.KeyVaultBackupClie public partial class BackupResult { internal BackupResult() { } - public System.Uri BackupFolderUri { get { throw null; } } public System.DateTimeOffset EndTime { get { throw null; } } + public System.Uri FolderUri { get { throw null; } } public System.DateTimeOffset StartTime { get { throw null; } } } public partial class KeyVaultAccessControlClient @@ -51,11 +51,12 @@ public enum ServiceVersion public static partial class KeyVaultAdministrationModelFactory { public static Azure.Security.KeyVault.Administration.BackupOperation BackupOperation(Azure.Response response, Azure.Security.KeyVault.Administration.KeyVaultBackupClient client, string id, System.Uri blobContainerUri, System.DateTimeOffset? startTime = default(System.DateTimeOffset?), System.DateTimeOffset? endTime = default(System.DateTimeOffset?), string errorMessage = null) { throw null; } - public static Azure.Security.KeyVault.Administration.BackupResult BackupResult(System.Uri backupFolderUri, System.DateTimeOffset startTime, System.DateTimeOffset endTime) { throw null; } + public static Azure.Security.KeyVault.Administration.BackupResult BackupResult(System.Uri folderUri, System.DateTimeOffset startTime, System.DateTimeOffset endTime) { throw null; } public static Azure.Security.KeyVault.Administration.RestoreOperation RestoreOperation(Azure.Response response, Azure.Security.KeyVault.Administration.KeyVaultBackupClient client, string id, System.DateTimeOffset? startTime = default(System.DateTimeOffset?), System.DateTimeOffset? endTime = default(System.DateTimeOffset?), string errorMessage = null) { throw null; } public static Azure.Security.KeyVault.Administration.RestoreResult RestoreResult(System.DateTimeOffset startTime, System.DateTimeOffset endTime) { throw null; } public static Azure.Security.KeyVault.Administration.KeyVaultRoleAssignment RoleAssignment(string id, string name, string type, Azure.Security.KeyVault.Administration.KeyVaultRoleAssignmentPropertiesWithScope properties) { throw null; } public static Azure.Security.KeyVault.Administration.KeyVaultRoleDefinition RoleDefinition(string id, string name, string type, string roleName, string description, string roleType, System.Collections.Generic.IList permissions, System.Collections.Generic.IList assignableScopes) { throw null; } + public static Azure.Security.KeyVault.Administration.RestoreResult SelectiveKeyRestoreResult(System.DateTimeOffset startTime, System.DateTimeOffset endTime) { throw null; } } public partial class KeyVaultBackupClient { @@ -65,10 +66,10 @@ public KeyVaultBackupClient(System.Uri vaultUri, Azure.Core.TokenCredential cred public virtual System.Uri VaultUri { get { throw null; } } public virtual Azure.Security.KeyVault.Administration.BackupOperation StartBackup(System.Uri blobStorageUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task StartBackupAsync(System.Uri blobStorageUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual Azure.Security.KeyVault.Administration.RestoreOperation StartRestore(System.Uri backupFolderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task StartRestoreAsync(System.Uri backupFolderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual Azure.Security.KeyVault.Administration.RestoreOperation StartSelectiveRestore(string keyName, System.Uri backupFolderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task StartSelectiveRestoreAsync(string keyName, System.Uri backupFolderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Security.KeyVault.Administration.RestoreOperation StartRestore(System.Uri folderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task StartRestoreAsync(System.Uri folderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Security.KeyVault.Administration.SelectiveKeyRestoreOperation StartSelectiveRestore(string keyName, System.Uri folderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task StartSelectiveRestoreAsync(string keyName, System.Uri folderUri, string sasToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public partial class KeyVaultPermission { @@ -145,4 +146,25 @@ internal RestoreResult() { } public System.DateTimeOffset EndTime { get { throw null; } } public System.DateTimeOffset StartTime { get { throw null; } } } + public partial class SelectiveKeyRestoreOperation : Azure.Operation + { + public SelectiveKeyRestoreOperation(Azure.Security.KeyVault.Administration.KeyVaultBackupClient client, string id) { } + public System.DateTimeOffset? EndTime { get { throw null; } } + public override bool HasCompleted { get { throw null; } } + public override bool HasValue { get { throw null; } } + public override string Id { get { throw null; } } + public System.DateTimeOffset? StartTime { get { throw null; } } + public override Azure.Security.KeyVault.Administration.SelectiveKeyRestoreResult Value { get { throw null; } } + public override Azure.Response GetRawResponse() { throw null; } + public override Azure.Response UpdateStatus(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask UpdateStatusAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask> WaitForCompletionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask> WaitForCompletionAsync(System.TimeSpan pollingInterval, System.Threading.CancellationToken cancellationToken) { throw null; } + } + public partial class SelectiveKeyRestoreResult + { + internal SelectiveKeyRestoreResult() { } + public System.DateTimeOffset EndTime { get { throw null; } } + public System.DateTimeOffset StartTime { get { throw null; } } + } } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldAsync.md b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldAsync.md index 1655e1d1bb43f..cd6c10f3ee2d0 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldAsync.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldAsync.md @@ -39,7 +39,7 @@ BackupOperation backupOperation = await Client.StartBackupAsync(builder.Uri, sas Response backupResult = await backupOperation.WaitForCompletionAsync(); // Get the Uri for the location of you backup blob. -Uri backupFolderUri = backupResult.Value.BackupFolderUri; +Uri folderUri = backupResult.Value.FolderUri; ``` ## Performing a full key restore @@ -50,7 +50,7 @@ Alternatively, it is possible to [generate a SAS token in Storage Explorer](http ```C# Snippet:HelloFullRestoreAsync // Start the restore using the backupBlobUri returned from a previous BackupOperation. -RestoreOperation restoreOperation = await Client.StartRestoreAsync(backupFolderUri, sasToken); +RestoreOperation restoreOperation = await Client.StartRestoreAsync(folderUri, sasToken); // Wait for completion of the RestoreOperation. Response restoreResult = await restoreOperation.WaitForCompletionAsync(); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldSync.md b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldSync.md index 783226035e1f6..a3c637e7eab4e 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldSync.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample1_BackupHelloWorldSync.md @@ -43,7 +43,7 @@ while (!backupOperation.HasCompleted) } // Get the Uri for the location of you backup blob. -Uri backupFolderUri = backupOperation.Value.BackupFolderUri; +Uri folderUri = backupOperation.Value.FolderUri; ``` ## Performing a full key restore @@ -54,7 +54,7 @@ Alternatively, it is possible to [generate a SAS token in Storage Explorer](http ```C# Snippet:HelloFullRestoreSync // Start the restore using the backupBlobUri returned from a previous BackupOperation. -RestoreOperation restoreOperation = Client.StartRestore(backupFolderUri, sasToken); +RestoreOperation restoreOperation = Client.StartRestore(folderUri, sasToken); // Wait for completion of the RestoreOperation. while (!restoreOperation.HasCompleted) @@ -62,7 +62,7 @@ while (!restoreOperation.HasCompleted) restoreOperation.UpdateStatus(); Thread.Sleep(3000); } -Uri restoreResult = backupOperation.Value.BackupFolderUri; +Uri restoreResult = backupOperation.Value.FolderUri; ``` diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample2_SelectiveRestore.md b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample2_SelectiveRestore.md index 045317bc64f88..39a725ad925b9 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample2_SelectiveRestore.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample2_SelectiveRestore.md @@ -11,8 +11,8 @@ Alternatively, it is possible to [generate a SAS token in Storage Explorer](http string keyName = ""; // Start the restore for a specific key that was previously backed up using the backupBlobUri returned from a previous BackupOperation. -RestoreOperation restoreOperation = await Client.StartSelectiveRestoreAsync(keyName, backupFolderUri, sasToken); +SelectiveKeyRestoreOperation restoreOperation = await Client.StartSelectiveRestoreAsync(keyName, folderUri, sasToken); // Wait for completion of the RestoreOperation. -RestoreResult restoreResult = await restoreOperation.WaitForCompletionAsync(); +SelectiveKeyRestoreResult restoreResult = await restoreOperation.WaitForCompletionAsync(); ``` diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample3_BackRestoreResume.md b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample3_BackRestoreResume.md index 198787f3ce31a..5892f875103c5 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample3_BackRestoreResume.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/samples/Sample3_BackRestoreResume.md @@ -21,7 +21,7 @@ BackupOperation backupOperation = new BackupOperation(client, backupOperationId) Response backupResult = await backupOperation.WaitForCompletionAsync(); // Get the Uri for the location of you backup blob. -Uri backupFolderUri = backupResult.Value.BackupFolderUri; +Uri folderUri = backupResult.Value.FolderUri; ``` ## Checking status of a full key restore operation diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/BackupResult.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/BackupResult.cs index 7ef78068ab0b4..51c136629a16b 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/BackupResult.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/BackupResult.cs @@ -11,18 +11,19 @@ namespace Azure.Security.KeyVault.Administration /// public class BackupResult { - internal BackupResult(Uri backupFolderUri, DateTimeOffset startTime, DateTimeOffset endTime) + internal BackupResult(Uri folderUri, DateTimeOffset startTime, DateTimeOffset endTime) { - Argument.AssertNotNull(backupFolderUri, nameof(backupFolderUri)); + Argument.AssertNotNull(folderUri, nameof(folderUri)); - this.BackupFolderUri = backupFolderUri; + FolderUri = folderUri; StartTime = startTime; EndTime = endTime; } + /// /// Gets the location of the full backup. /// - public Uri BackupFolderUri { get; } + public Uri FolderUri { get; } /// /// Gets the start time of the backup operation. diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationModelFactory.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationModelFactory.cs index da3c02a8ad394..d452ce82652fd 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationModelFactory.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationModelFactory.cs @@ -77,12 +77,12 @@ public static BackupOperation BackupOperation(Response response, KeyVaultBackupC /// /// Initializes a new instance of a for mocking purposes. /// - /// The location of the backup. + /// The location of the backup. /// The start time of the backup operation. /// The end time of the backup operation. /// A new instance. - public static BackupResult BackupResult(Uri backupFolderUri, DateTimeOffset startTime, DateTimeOffset endTime) => - new BackupResult(backupFolderUri, startTime, endTime); + public static BackupResult BackupResult(Uri folderUri, DateTimeOffset startTime, DateTimeOffset endTime) => + new BackupResult(folderUri, startTime, endTime); /// @@ -93,5 +93,14 @@ public static BackupResult BackupResult(Uri backupFolderUri, DateTimeOffset star /// A new instance. public static RestoreResult RestoreResult(DateTimeOffset startTime, DateTimeOffset endTime) => new RestoreResult(startTime, endTime); + + /// + /// Initializes a new instance of a for mocking purposes. + /// + /// The start time of the restore operation. + /// The end time of the restore operation. + /// A new instance. + public static RestoreResult SelectiveKeyRestoreResult(DateTimeOffset startTime, DateTimeOffset endTime) => + new RestoreResult(startTime, endTime); } } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs index 4fd861b616d3f..742431c616bdd 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs @@ -126,26 +126,26 @@ public virtual BackupOperation StartBackup(Uri blobStorageUri, string sasToken, /// /// Initiates a full restore of the Key Vault. /// - /// + /// /// The for the blob storage resource, including the path to the blob container where the backup resides. /// This would be the exact value that is returned as the result of a . /// An example Uri may look like the following: https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313. /// /// A Shared Access Signature (SAS) token to authorize access to the blob. /// A controlling the request lifetime. - /// or is null. + /// or is null. /// The server returned an error. See for details returned from the server. /// A to wait on this long-running operation. - public virtual async Task StartRestoreAsync(Uri backupFolderUri, string sasToken, CancellationToken cancellationToken = default) + public virtual async Task StartRestoreAsync(Uri folderUri, string sasToken, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(KeyVaultBackupClient)}.{nameof(StartRestore)}"); scope.Start(); try { // Get the folder name from the backupBlobUri returned from a previous BackupOperation - string[] uriSegments = backupFolderUri.Segments; + string[] uriSegments = folderUri.Segments; string folderName = uriSegments[uriSegments.Length - 1]; - string containerUriString = backupFolderUri.AbsoluteUri.Substring(0, backupFolderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); + string containerUriString = folderUri.AbsoluteUri.Substring(0, folderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); var response = await _restClient.FullRestoreOperationAsync( VaultUri.AbsoluteUri, @@ -167,26 +167,26 @@ public virtual async Task StartRestoreAsync(Uri backupFolderUr /// /// Initiates a full Restore of the Key Vault. /// - /// + /// /// The for the blob storage resource, including the path to the blob container where the backup resides. /// This would be the exact value that is returned as the result of a . /// An example Uri path may look like the following: https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313. /// /// A Shared Access Signature (SAS) token to authorize access to the blob. /// A controlling the request lifetime. - /// or is null. + /// or is null. /// The server returned an error. See for details returned from the server. /// A to wait on this long-running operation. - public virtual RestoreOperation StartRestore(Uri backupFolderUri, string sasToken, CancellationToken cancellationToken = default) + public virtual RestoreOperation StartRestore(Uri folderUri, string sasToken, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(KeyVaultBackupClient)}.{nameof(StartRestore)}"); scope.Start(); try { // Get the folder name from the backupBlobUri returned from a previous BackupOperation - string[] uriSegments = backupFolderUri.Segments; + string[] uriSegments = folderUri.Segments; string folderName = uriSegments[uriSegments.Length - 1]; - string containerUriString = backupFolderUri.AbsoluteUri.Substring(0, backupFolderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); + string containerUriString = folderUri.AbsoluteUri.Substring(0, folderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); var response = _restClient.FullRestoreOperation( VaultUri.AbsoluteUri, @@ -209,26 +209,26 @@ public virtual RestoreOperation StartRestore(Uri backupFolderUri, string sasToke /// Initiates a selective restore of the Key Vault. /// /// The name of the key to be restored from the supplied backup. - /// + /// /// The for the blob storage resource, including the path to the blob container where the backup resides. /// This would be the exact value that is returned as the result of a . /// An example Uri path may look like the following: https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313. /// /// A Shared Access Signature (SAS) token to authorize access to the blob. /// A controlling the request lifetime. - /// or is null. + /// or is null. /// The server returned an error. See for details returned from the server. /// A to wait on this long-running operation. - public virtual async Task StartSelectiveRestoreAsync(string keyName, Uri backupFolderUri, string sasToken, CancellationToken cancellationToken = default) + public virtual async Task StartSelectiveRestoreAsync(string keyName, Uri folderUri, string sasToken, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(KeyVaultBackupClient)}.{nameof(StartSelectiveRestore)}"); scope.Start(); try { // Get the folder name from the backupBlobUri returned from a previous BackupOperation - string[] uriSegments = backupFolderUri.Segments; + string[] uriSegments = folderUri.Segments; string folderName = uriSegments[uriSegments.Length - 1]; - string containerUriString = backupFolderUri.AbsoluteUri.Substring(0, backupFolderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); + string containerUriString = folderUri.AbsoluteUri.Substring(0, folderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); var response = await _restClient.SelectiveKeyRestoreOperationAsync( VaultUri.AbsoluteUri, @@ -239,7 +239,7 @@ public virtual async Task StartSelectiveRestoreAsync(string ke folderName), cancellationToken).ConfigureAwait(false); - return new RestoreOperation(this, response); + return new SelectiveKeyRestoreOperation(this, response); } catch (Exception ex) { @@ -252,26 +252,26 @@ public virtual async Task StartSelectiveRestoreAsync(string ke /// Initiates a selective Restore of the Key Vault. /// /// The name of the key to be restored from the supplied backup. - /// + /// /// The for the blob storage resource, including the path to the blob container where the backup resides. /// This would be the exact value that is returned as the result of a . /// An example Uri path may look like the following: https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313. /// /// A Shared Access Signature (SAS) token to authorize access to the blob. /// A controlling the request lifetime. - /// or is null. + /// or is null. /// The server returned an error. See for details returned from the server. /// A to wait on this long-running operation. - public virtual RestoreOperation StartSelectiveRestore(string keyName, Uri backupFolderUri, string sasToken, CancellationToken cancellationToken = default) + public virtual SelectiveKeyRestoreOperation StartSelectiveRestore(string keyName, Uri folderUri, string sasToken, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(KeyVaultBackupClient)}.{nameof(StartSelectiveRestore)}"); scope.Start(); try { // Get the folder name from the backupBlobUri returned from a previous BackupOperation - string[] uriSegments = backupFolderUri.Segments; + string[] uriSegments = folderUri.Segments; string folderName = uriSegments[uriSegments.Length - 1]; - string containerUriString = backupFolderUri.AbsoluteUri.Substring(0, backupFolderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); + string containerUriString = folderUri.AbsoluteUri.Substring(0, folderUri.AbsoluteUri.LastIndexOf("/", StringComparison.OrdinalIgnoreCase)); var response = _restClient.SelectiveKeyRestoreOperation( VaultUri.AbsoluteUri, @@ -282,7 +282,7 @@ public virtual RestoreOperation StartSelectiveRestore(string keyName, Uri backup folderName), cancellationToken); - return new RestoreOperation(this, response); + return new SelectiveKeyRestoreOperation(this, response); } catch (Exception ex) { diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperation.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperation.cs index 87a73cae7b6e9..094fe8c4ad68a 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperation.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperation.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Azure.Core; @@ -14,14 +15,7 @@ namespace Azure.Security.KeyVault.Administration /// public class RestoreOperation : Operation { - /// - /// The number of seconds recommended by the service to delay before checking on completion status. - /// - private readonly int? _retryAfterSeconds; - private readonly KeyVaultBackupClient _client; - private Response _response; - private RestoreDetailsInternal _value; - private readonly string _id; + private readonly RestoreOperationInternal _operationInternal; /// /// Creates an instance of a RestoreOperation from a previously started operation. , , @@ -33,11 +27,7 @@ public class RestoreOperation : Operation /// or is null. public RestoreOperation(KeyVaultBackupClient client, string id) { - Argument.AssertNotNull(id, nameof(id)); - Argument.AssertNotNull(client, nameof(client)); - - _client = client; - _id = id; + _operationInternal = new RestoreOperationInternal(client, id); } /// @@ -48,30 +38,7 @@ public RestoreOperation(KeyVaultBackupClient client, string id) /// or is null. internal RestoreOperation(KeyVaultBackupClient client, ResponseWithHeaders response) { - Argument.AssertNotNull(client, nameof(client)); - Argument.AssertNotNull(response, nameof(response)); - - _id = response.Headers.JobId() ?? throw new InvalidOperationException("The response does not contain an Id"); - _client = client; - _response = response.GetRawResponse(); - _retryAfterSeconds = response.Headers.RetryAfter; - } - - /// - /// Initializes a new instance of a RestoreOperation. - /// - /// An instance of . - /// The returned from or . - /// or is null. - internal RestoreOperation(KeyVaultBackupClient client, ResponseWithHeaders response) - { - Argument.AssertNotNull(client, nameof(client)); - Argument.AssertNotNull(response, nameof(response)); - - _id = response.Headers.JobId() ?? throw new InvalidOperationException("The response does not contain an Id"); - _client = client; - _response = response.GetRawResponse(); - _retryAfterSeconds = response.Headers.RetryAfter; + _operationInternal = new RestoreOperationInternal(client, response); } /// @@ -83,90 +50,47 @@ internal RestoreOperation(KeyVaultBackupClient client, ResponseWithHeaders or or is null. internal RestoreOperation(RestoreDetailsInternal value, Response response, KeyVaultBackupClient client) { - Argument.AssertNotNull(value, nameof(value)); - Argument.AssertNotNull(response, nameof(response)); - Argument.AssertNotNull(client, nameof(client)); - - _client = client; - _response = response; - _value = value; - _id = value.JobId; + _operationInternal = new RestoreOperationInternal(value, response, client); } /// /// The start time of the restore operation. /// - public DateTimeOffset? StartTime => _value?.StartTime; + public DateTimeOffset? StartTime => _operationInternal.StartTime; /// /// The end time of the restore operation. /// - public DateTimeOffset? EndTime => _value?.EndTime; + public DateTimeOffset? EndTime => _operationInternal.EndTime; /// - public override string Id => _id; + public override string Id => _operationInternal.Id; /// - public override RestoreResult Value - { - get - { -#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations - if (!HasCompleted) - { - throw new InvalidOperationException("The operation is not complete."); - } - if (_value != null && _value.EndTime.HasValue && _value.Error != null) - { - throw new RequestFailedException($"{_value.Error.Message}\nInnerError: {_value.Error.InnerError}\nCode: {_value.Error.Code}"); - } -#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations - return new RestoreResult(_value.StartTime.Value, _value.EndTime.Value); - } - } + public override RestoreResult Value => _operationInternal.Value; /// - public override bool HasCompleted => _value?.EndTime.HasValue ?? false; + public override bool HasCompleted => _operationInternal.HasCompleted; /// - public override bool HasValue => _response != null && _value?.Error == null && HasCompleted; + public override bool HasValue => _operationInternal.HasValue; /// - public override Response GetRawResponse() => _response; + public override Response GetRawResponse() => _operationInternal.GetRawResponse(); /// - public override Response UpdateStatus(CancellationToken cancellationToken = default) - { - if (!HasCompleted) - { - Response response = _client.GetRestoreDetails(Id, cancellationToken); - _value = response.Value; - _response = response.GetRawResponse(); - } - - return GetRawResponse(); - } + public override Response UpdateStatus(CancellationToken cancellationToken = default) => _operationInternal.UpdateStatus(cancellationToken); /// - public override async ValueTask UpdateStatusAsync(CancellationToken cancellationToken = default) - { - if (!HasCompleted) - { - Response response = await _client.GetRestoreDetailsAsync(Id, cancellationToken).ConfigureAwait(false); - _value = response.Value; - _response = response.GetRawResponse(); - } - - return GetRawResponse(); - } + public override async ValueTask UpdateStatusAsync(CancellationToken cancellationToken = default) => + await _operationInternal.UpdateStatusAsync(cancellationToken).ConfigureAwait(false); /// public override ValueTask> WaitForCompletionAsync(CancellationToken cancellationToken = default) => - _retryAfterSeconds.HasValue ? this.DefaultWaitForCompletionAsync(TimeSpan.FromSeconds(_retryAfterSeconds.Value), cancellationToken) : - this.DefaultWaitForCompletionAsync(cancellationToken); + _operationInternal.WaitForCompletionAsync(cancellationToken); /// public override ValueTask> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken) => - this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken); + _operationInternal.WaitForCompletionAsync(pollingInterval, cancellationToken); } } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperationInternal.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperationInternal.cs new file mode 100644 index 0000000000000..9b9397903c687 --- /dev/null +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperationInternal.cs @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Security.KeyVault.Administration.Models; + +namespace Azure.Security.KeyVault.Administration +{ + internal class RestoreOperationInternal : Operation where TResult : class + { + /// + /// The number of seconds recommended by the service to delay before checking on completion status. + /// + private readonly int? _retryAfterSeconds; + private readonly KeyVaultBackupClient _client; + private Response _response; + private RestoreDetailsInternal _value; + private readonly string _id; + + /// + /// Creates an instance of a RestoreOperation from a previously started operation. + /// , or must be called + /// to re-populate the details of this operation. + /// + /// An instance of . + /// The from a previous . + /// or is null. + public RestoreOperationInternal(KeyVaultBackupClient client, string id) + { + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(client, nameof(client)); + + _client = client; + _id = id; + } + + /// + /// Initializes a new instance of a RestoreOperation. + /// + /// An instance of . + /// The returned from or . + /// or is null. + internal RestoreOperationInternal(KeyVaultBackupClient client, ResponseWithHeaders response) + { + Argument.AssertNotNull(client, nameof(client)); + Argument.AssertNotNull(response, nameof(response)); + + _client = client; + _response = response.GetRawResponse(); + + if (response is ResponseWithHeaders fullRestoreHeaders) + { + _id = fullRestoreHeaders.Headers.JobId() ?? throw new InvalidOperationException("The response does not contain an Id"); + _retryAfterSeconds = fullRestoreHeaders.Headers.RetryAfter; + } + else if (response is ResponseWithHeaders selectiveRestoreHeaders) + { + _id = selectiveRestoreHeaders.Headers.JobId() ?? throw new InvalidOperationException("The response does not contain an Id"); + _retryAfterSeconds = selectiveRestoreHeaders.Headers.RetryAfter; + } + else + { + throw new ArgumentException("Invalid header type", nameof(response)); + } + } + + /// + /// Initializes a new instance of a RestoreOperation. + /// + /// An instance of . + /// The returned from or . + /// or is null. + internal RestoreOperationInternal(KeyVaultBackupClient client, ResponseWithHeaders response) + { + Argument.AssertNotNull(client, nameof(client)); + Argument.AssertNotNull(response, nameof(response)); + + _id = response.Headers.JobId() ?? throw new InvalidOperationException("The response does not contain an Id"); + _client = client; + _response = response.GetRawResponse(); + _retryAfterSeconds = response.Headers.RetryAfter; + } + + /// + /// Initializes a new instance of a RestoreOperation for mocking purposes. + /// + /// The that will be used to populate various properties. + /// The that will be returned from . + /// An instance of . + /// or or is null. + internal RestoreOperationInternal(RestoreDetailsInternal value, Response response, KeyVaultBackupClient client) + { + Argument.AssertNotNull(value, nameof(value)); + Argument.AssertNotNull(response, nameof(response)); + Argument.AssertNotNull(client, nameof(client)); + + _client = client; + _response = response; + _value = value; + _id = value.JobId; + } + + /// + /// The start time of the restore operation. + /// + public DateTimeOffset? StartTime => _value?.StartTime; + + /// + /// The end time of the restore operation. + /// + public DateTimeOffset? EndTime => _value?.EndTime; + + /// + public override string Id => _id; + + /// + public override TResult Value + { + get + { +#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations + if (!HasCompleted) + { + throw new InvalidOperationException("The operation is not complete."); + } + if (_value != null && _value.EndTime.HasValue && _value.Error != null) + { + throw new RequestFailedException($"{_value.Error.Message}\nInnerError: {_value.Error.InnerError}\nCode: {_value.Error.Code}"); + } +#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations + TResult result = null; + Type resultType = typeof(TResult); + + if (resultType == typeof(RestoreResult)) + { + result = new RestoreResult(_value.StartTime.Value, _value.EndTime.Value) as TResult; + } + else if (resultType == typeof(SelectiveKeyRestoreResult)) + { + result = new SelectiveKeyRestoreResult(_value.StartTime.Value, _value.EndTime.Value) as TResult; + } + return result; + } + } + + /// + public override bool HasCompleted => _value?.EndTime.HasValue ?? false; + + /// + public override bool HasValue => _response != null && _value?.Error == null && HasCompleted; + + /// + public override Response GetRawResponse() => _response; + + /// + public override Response UpdateStatus(CancellationToken cancellationToken = default) + { + if (!HasCompleted) + { + Response response = _client.GetRestoreDetails(Id, cancellationToken); + _value = response.Value; + _response = response.GetRawResponse(); + } + + return GetRawResponse(); + } + + /// + public override async ValueTask UpdateStatusAsync(CancellationToken cancellationToken = default) + { + if (!HasCompleted) + { + Response response = await _client.GetRestoreDetailsAsync(Id, cancellationToken).ConfigureAwait(false); + _value = response.Value; + _response = response.GetRawResponse(); + } + + return GetRawResponse(); + } + + /// + public override ValueTask> WaitForCompletionAsync(CancellationToken cancellationToken = default) => + _retryAfterSeconds.HasValue ? this.DefaultWaitForCompletionAsync(TimeSpan.FromSeconds(_retryAfterSeconds.Value), cancellationToken) : + this.DefaultWaitForCompletionAsync(cancellationToken); + + /// + public override ValueTask> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken) => + this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken); + } +} diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/SelectiveKeyRestoreOperation.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/SelectiveKeyRestoreOperation.cs new file mode 100644 index 0000000000000..4f54610896871 --- /dev/null +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/SelectiveKeyRestoreOperation.cs @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Security.KeyVault.Administration.Models; + +namespace Azure.Security.KeyVault.Administration +{ + /// + /// A long-running operation for or . + /// + public class SelectiveKeyRestoreOperation : Operation + { + private readonly RestoreOperationInternal _operationInternal; + + /// + /// Creates an instance of a SelectiveKeyRestoreOperation from a previously started operation. , , + /// , or must be called + /// to re-populate the details of this operation. + /// + /// An instance of . + /// The from a previous . + /// or is null. + public SelectiveKeyRestoreOperation(KeyVaultBackupClient client, string id) + { + _operationInternal = new RestoreOperationInternal(client, id); + } + + /// + /// Initializes a new instance of a SelectiveKeyRestoreOperation. + /// + /// An instance of . + /// The returned from or . + /// or is null. + internal SelectiveKeyRestoreOperation(KeyVaultBackupClient client, ResponseWithHeaders response) + { + _operationInternal = new RestoreOperationInternal(client, response); + } + + /// + /// Initializes a new instance of a SelectiveKeyRestoreOperation for mocking purposes. + /// + /// The that will be used to populate various properties. + /// The that will be returned from . + /// An instance of . + /// or or is null. + internal SelectiveKeyRestoreOperation(RestoreDetailsInternal value, Response response, KeyVaultBackupClient client) + { + _operationInternal = new RestoreOperationInternal(value, response, client); + } + + /// + /// The start time of the restore operation. + /// + public DateTimeOffset? StartTime => _operationInternal.StartTime; + + /// + /// The end time of the restore operation. + /// + public DateTimeOffset? EndTime => _operationInternal.EndTime; + + /// + public override string Id => _operationInternal.Id; + + /// + public override SelectiveKeyRestoreResult Value => _operationInternal.Value; + + /// + public override bool HasCompleted => _operationInternal.HasCompleted; + + /// + public override bool HasValue => _operationInternal.HasValue; + + /// + public override Response GetRawResponse() => _operationInternal.GetRawResponse(); + + /// + public override Response UpdateStatus(CancellationToken cancellationToken = default) => _operationInternal.UpdateStatus(cancellationToken); + + /// + public override async ValueTask UpdateStatusAsync(CancellationToken cancellationToken = default) => + await _operationInternal.UpdateStatusAsync(cancellationToken).ConfigureAwait(false); + + /// + public override ValueTask> WaitForCompletionAsync(CancellationToken cancellationToken = default) => + _operationInternal.WaitForCompletionAsync(cancellationToken); + + /// + public override ValueTask> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken) => + _operationInternal.WaitForCompletionAsync(pollingInterval, cancellationToken); + } +} diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/SelectiveKeyRestoreResult.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/SelectiveKeyRestoreResult.cs new file mode 100644 index 0000000000000..440edd3031634 --- /dev/null +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/SelectiveKeyRestoreResult.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Security.KeyVault.Administration +{ + /// + /// The result of a selective key restore operation. + /// + public class SelectiveKeyRestoreResult + { + internal SelectiveKeyRestoreResult(DateTimeOffset startTime, DateTimeOffset endTime) + { + StartTime = startTime; + EndTime = endTime; + } + + /// + /// Gets the start time of the selective key restore operation. + /// + public DateTimeOffset StartTime { get; } + + /// + /// Gets the end time of the selective key restore operation. + /// + public DateTimeOffset EndTime { get; } + } +} diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/FullBackupClientLiveTests.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/FullBackupClientLiveTests.cs index 551af08d584ff..8cabcc594c0d4 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/FullBackupClientLiveTests.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/FullBackupClientLiveTests.cs @@ -36,7 +36,7 @@ public async Task BackupAndRestore() Assert.That(backupOperation.HasValue, Is.True); // Start the restore. - RestoreOperation restoreOperation = await Client.StartRestoreAsync(backupResult.BackupFolderUri, "?" + SasToken, source.Token); + RestoreOperation restoreOperation = await Client.StartRestoreAsync(backupResult.FolderUri, "?" + SasToken, source.Token); // Wait for completion of the LRO var restoreResult = await restoreOperation.WaitForCompletionAsync(source.Token); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample1_BackupHelloWorld.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample1_BackupHelloWorld.cs index 75ed03c3dab8a..11cfee0abac74 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample1_BackupHelloWorld.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample1_BackupHelloWorld.cs @@ -47,17 +47,17 @@ public async Task BackupAndRestoreSampleAsync() Response backupResult = await backupOperation.WaitForCompletionAsync(); // Get the Uri for the location of you backup blob. - Uri backupFolderUri = backupResult.Value.BackupFolderUri; + Uri folderUri = backupResult.Value.FolderUri; #endregion - Assert.That(backupFolderUri, Is.Not.Null); + Assert.That(folderUri, Is.Not.Null); Assert.That(backupOperation.HasValue, Is.True); await WaitForOperationAsync(); #region Snippet:HelloFullRestoreAsync // Start the restore using the backupBlobUri returned from a previous BackupOperation. - RestoreOperation restoreOperation = await Client.StartRestoreAsync(backupFolderUri, sasToken); + RestoreOperation restoreOperation = await Client.StartRestoreAsync(folderUri, sasToken); // Wait for completion of the RestoreOperation. Response restoreResult = await restoreOperation.WaitForCompletionAsync(); @@ -97,17 +97,17 @@ public async Task BackupAndRestoreSampleSync() } // Get the Uri for the location of you backup blob. - Uri backupFolderUri = backupOperation.Value.BackupFolderUri; + Uri folderUri = backupOperation.Value.FolderUri; #endregion - Assert.That(backupFolderUri, Is.Not.Null); + Assert.That(folderUri, Is.Not.Null); Assert.That(backupOperation.HasValue, Is.True); await WaitForOperationAsync(); #region Snippet:HelloFullRestoreSync // Start the restore using the backupBlobUri returned from a previous BackupOperation. - RestoreOperation restoreOperation = Client.StartRestore(backupFolderUri, sasToken); + RestoreOperation restoreOperation = Client.StartRestore(folderUri, sasToken); // Wait for completion of the RestoreOperation. while (!restoreOperation.HasCompleted) @@ -116,7 +116,7 @@ public async Task BackupAndRestoreSampleSync() /*@@*/ await DelayAsync(TimeSpan.FromSeconds(3)); //@@Thread.Sleep(3000); } - Uri restoreResult = backupOperation.Value.BackupFolderUri; + Uri restoreResult = backupOperation.Value.FolderUri; #endregion Assert.That(restoreResult, Is.Not.Null); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample2_SelectiveRestore.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample2_SelectiveRestore.cs index c69bb9a42c468..14e8205ce54e8 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample2_SelectiveRestore.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample2_SelectiveRestore.cs @@ -43,19 +43,19 @@ public async Task BackupAndRestoreSampleAsync() await WaitForOperationAsync(); // Get the Uri for the location of you backup blob. - Uri backupFolderUri = backupResult.Value.BackupFolderUri; + Uri folderUri = backupResult.Value.FolderUri; - Assert.That(backupFolderUri, Is.Not.Null); + Assert.That(folderUri, Is.Not.Null); Assert.That(backupOperation.HasValue, Is.True); #region Snippet:SelectiveRestoreAsync //@@ string keyName = ""; // Start the restore for a specific key that was previously backed up using the backupBlobUri returned from a previous BackupOperation. - RestoreOperation restoreOperation = await Client.StartSelectiveRestoreAsync(keyName, backupFolderUri, sasToken); + SelectiveKeyRestoreOperation restoreOperation = await Client.StartSelectiveRestoreAsync(keyName, folderUri, sasToken); // Wait for completion of the RestoreOperation. - RestoreResult restoreResult = await restoreOperation.WaitForCompletionAsync(); + SelectiveKeyRestoreResult restoreResult = await restoreOperation.WaitForCompletionAsync(); #endregion Assert.That(restoreOperation.HasValue, Is.True); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample3_BackRestoreResume.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample3_BackRestoreResume.cs index 51016677ffa7d..008418b8bf09d 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample3_BackRestoreResume.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/samples/Sample3_BackRestoreResume.cs @@ -42,16 +42,16 @@ public async Task ResumeBackupRestore() Response backupResult = await backupOperation.WaitForCompletionAsync(); // Get the Uri for the location of you backup blob. - Uri backupFolderUri = backupResult.Value.BackupFolderUri; + Uri folderUri = backupResult.Value.FolderUri; #endregion - Assert.That(backupFolderUri, Is.Not.Null); + Assert.That(folderUri, Is.Not.Null); Assert.That(backupOperation.HasValue, Is.True); await WaitForOperationAsync(); // Start the restore using the backupBlobUri returned from a previous BackupOperation. - RestoreOperation originalRestoreOperation = await Client.StartRestoreAsync(backupFolderUri, sasToken); + RestoreOperation originalRestoreOperation = await Client.StartRestoreAsync(folderUri, sasToken); var restoreOperationId = originalRestoreOperation.Id; #region Snippet:ResumeRestoreAsync