diff --git a/eng/Packages.Data.props b/eng/Packages.Data.props index 82cd7fdde4aa3..89de4b3848332 100644 --- a/eng/Packages.Data.props +++ b/eng/Packages.Data.props @@ -204,6 +204,7 @@ + diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/CHANGELOG.md b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/CHANGELOG.md index 8ebd80338d761..9c00de86bafb3 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/CHANGELOG.md +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/CHANGELOG.md @@ -7,6 +7,7 @@ ### Breaking Changes ### Bugs Fixed +- Fix LRO in ProtectionContainers PUT operation ### Other Changes diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/assets.json b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/assets.json index 61c30fa890ac5..61471e3d4b347 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/assets.json +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup", - "Tag": "" + "Tag": "net/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup_6b115f5f54" } diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerCollection.cs b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerCollection.cs index 9bc03b642712c..015c7a032cb12 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerCollection.cs +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerCollection.cs @@ -86,7 +86,7 @@ public virtual async Task> Creat try { var response = await _backupProtectionContainerProtectionContainersRestClient.RegisterAsync(Id.SubscriptionId, Id.ResourceGroupName, vaultName, fabricName, containerName, data, cancellationToken).ConfigureAwait(false); - var operation = new RecoveryServicesBackupArmOperation(Response.FromValue(new BackupProtectionContainerResource(Client, response), response.GetRawResponse())); + var operation = new RecoveryServicesBackupArmOperation(new BackupProtectionContainerOperationSource(Client), _backupProtectionContainerProtectionContainersClientDiagnostics, Pipeline, _backupProtectionContainerProtectionContainersRestClient.CreateRegisterRequest(Id.SubscriptionId, Id.ResourceGroupName, vaultName, fabricName, containerName, data).Request, response, OperationFinalStateVia.Location); if (waitUntil == WaitUntil.Completed) await operation.WaitForCompletionAsync(cancellationToken).ConfigureAwait(false); return operation; @@ -133,7 +133,7 @@ public virtual ArmOperation CreateOrUpdate(Wa try { var response = _backupProtectionContainerProtectionContainersRestClient.Register(Id.SubscriptionId, Id.ResourceGroupName, vaultName, fabricName, containerName, data, cancellationToken); - var operation = new RecoveryServicesBackupArmOperation(Response.FromValue(new BackupProtectionContainerResource(Client, response), response.GetRawResponse())); + var operation = new RecoveryServicesBackupArmOperation(new BackupProtectionContainerOperationSource(Client), _backupProtectionContainerProtectionContainersClientDiagnostics, Pipeline, _backupProtectionContainerProtectionContainersRestClient.CreateRegisterRequest(Id.SubscriptionId, Id.ResourceGroupName, vaultName, fabricName, containerName, data).Request, response, OperationFinalStateVia.Location); if (waitUntil == WaitUntil.Completed) operation.WaitForCompletion(cancellationToken); return operation; diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerResource.cs b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerResource.cs index 5bf9b31a046a9..4d66fc870fe13 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerResource.cs +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/BackupProtectionContainerResource.cs @@ -313,7 +313,7 @@ public virtual async Task> Updat try { var response = await _backupProtectionContainerProtectionContainersRestClient.RegisterAsync(Id.SubscriptionId, Id.ResourceGroupName, Id.Parent.Parent.Name, Id.Parent.Name, Id.Name, data, cancellationToken).ConfigureAwait(false); - var operation = new RecoveryServicesBackupArmOperation(Response.FromValue(new BackupProtectionContainerResource(Client, response), response.GetRawResponse())); + var operation = new RecoveryServicesBackupArmOperation(new BackupProtectionContainerOperationSource(Client), _backupProtectionContainerProtectionContainersClientDiagnostics, Pipeline, _backupProtectionContainerProtectionContainersRestClient.CreateRegisterRequest(Id.SubscriptionId, Id.ResourceGroupName, Id.Parent.Parent.Name, Id.Parent.Name, Id.Name, data).Request, response, OperationFinalStateVia.Location); if (waitUntil == WaitUntil.Completed) await operation.WaitForCompletionAsync(cancellationToken).ConfigureAwait(false); return operation; @@ -353,7 +353,7 @@ public virtual ArmOperation Update(WaitUntil try { var response = _backupProtectionContainerProtectionContainersRestClient.Register(Id.SubscriptionId, Id.ResourceGroupName, Id.Parent.Parent.Name, Id.Parent.Name, Id.Name, data, cancellationToken); - var operation = new RecoveryServicesBackupArmOperation(Response.FromValue(new BackupProtectionContainerResource(Client, response), response.GetRawResponse())); + var operation = new RecoveryServicesBackupArmOperation(new BackupProtectionContainerOperationSource(Client), _backupProtectionContainerProtectionContainersClientDiagnostics, Pipeline, _backupProtectionContainerProtectionContainersRestClient.CreateRegisterRequest(Id.SubscriptionId, Id.ResourceGroupName, Id.Parent.Parent.Name, Id.Parent.Name, Id.Name, data).Request, response, OperationFinalStateVia.Location); if (waitUntil == WaitUntil.Completed) operation.WaitForCompletion(cancellationToken); return operation; diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/LongRunningOperation/BackupProtectionContainerOperationSource.cs b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/LongRunningOperation/BackupProtectionContainerOperationSource.cs new file mode 100644 index 0000000000000..a6011f3c76f98 --- /dev/null +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/LongRunningOperation/BackupProtectionContainerOperationSource.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Azure; +using Azure.Core; +using Azure.ResourceManager; + +namespace Azure.ResourceManager.RecoveryServicesBackup +{ + internal class BackupProtectionContainerOperationSource : IOperationSource + { + private readonly ArmClient _client; + + internal BackupProtectionContainerOperationSource(ArmClient client) + { + _client = client; + } + + BackupProtectionContainerResource IOperationSource.CreateResult(Response response, CancellationToken cancellationToken) + { + using var document = JsonDocument.Parse(response.ContentStream); + var data = BackupProtectionContainerData.DeserializeBackupProtectionContainerData(document.RootElement); + return new BackupProtectionContainerResource(_client, data); + } + + async ValueTask IOperationSource.CreateResultAsync(Response response, CancellationToken cancellationToken) + { + using var document = await JsonDocument.ParseAsync(response.ContentStream, default, cancellationToken).ConfigureAwait(false); + var data = BackupProtectionContainerData.DeserializeBackupProtectionContainerData(document.RootElement); + return new BackupProtectionContainerResource(_client, data); + } + } +} diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/RestOperations/ProtectionContainersRestOperations.cs b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/RestOperations/ProtectionContainersRestOperations.cs index 0b9d9189f586e..4fec37f0a9d30 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/RestOperations/ProtectionContainersRestOperations.cs +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/Generated/RestOperations/ProtectionContainersRestOperations.cs @@ -172,7 +172,7 @@ internal HttpMessage CreateRegisterRequest(string subscriptionId, string resourc /// The cancellation token to use. /// , , , , or is null. /// , , , or is an empty string, and was expected to be non-empty. - public async Task> RegisterAsync(string subscriptionId, string resourceGroupName, string vaultName, string fabricName, string containerName, BackupProtectionContainerData data, CancellationToken cancellationToken = default) + public async Task RegisterAsync(string subscriptionId, string resourceGroupName, string vaultName, string fabricName, string containerName, BackupProtectionContainerData data, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(subscriptionId, nameof(subscriptionId)); Argument.AssertNotNullOrEmpty(resourceGroupName, nameof(resourceGroupName)); @@ -186,14 +186,8 @@ public async Task> RegisterAsync(string switch (message.Response.Status) { case 200: - { - BackupProtectionContainerData value = default; - using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); - value = BackupProtectionContainerData.DeserializeBackupProtectionContainerData(document.RootElement); - return Response.FromValue(value, message.Response); - } case 202: - return Response.FromValue((BackupProtectionContainerData)null, message.Response); + return message.Response; default: throw new RequestFailedException(message.Response); } @@ -213,7 +207,7 @@ public async Task> RegisterAsync(string /// The cancellation token to use. /// , , , , or is null. /// , , , or is an empty string, and was expected to be non-empty. - public Response Register(string subscriptionId, string resourceGroupName, string vaultName, string fabricName, string containerName, BackupProtectionContainerData data, CancellationToken cancellationToken = default) + public Response Register(string subscriptionId, string resourceGroupName, string vaultName, string fabricName, string containerName, BackupProtectionContainerData data, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(subscriptionId, nameof(subscriptionId)); Argument.AssertNotNullOrEmpty(resourceGroupName, nameof(resourceGroupName)); @@ -227,14 +221,8 @@ public Response Register(string subscriptionId, s switch (message.Response.Status) { case 200: - { - BackupProtectionContainerData value = default; - using var document = JsonDocument.Parse(message.Response.ContentStream); - value = BackupProtectionContainerData.DeserializeBackupProtectionContainerData(document.RootElement); - return Response.FromValue(value, message.Response); - } case 202: - return Response.FromValue((BackupProtectionContainerData)null, message.Response); + return message.Response; default: throw new RequestFailedException(message.Response); } diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/autorest.md b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/autorest.md index 059b80575e894..b10abdde01b44 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/autorest.md +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/src/autorest.md @@ -476,4 +476,9 @@ directive: where: $.definitions.RecoveryPointProperties.properties.expiryTime transform: > $["format"] = "date-time"; + # TODO: Remove this workaround once we have the swagger issue fixed + - from: bms.json + where: $.paths['/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.RecoveryServices/vaults/{vaultName}/backupFabrics/{fabricName}/protectionContainers/{containerName}'] + transform: > + $.put['x-ms-long-running-operation'] = true; ``` diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/Azure.ResourceManager.RecoveryServicesBackup.Tests.csproj b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/Azure.ResourceManager.RecoveryServicesBackup.Tests.csproj index 380a9130f6a8b..147b69574551c 100644 --- a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/Azure.ResourceManager.RecoveryServicesBackup.Tests.csproj +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/Azure.ResourceManager.RecoveryServicesBackup.Tests.csproj @@ -1,5 +1,7 @@  + + diff --git a/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/ScenarioTests/BackupProtectionContainerTests.cs b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/ScenarioTests/BackupProtectionContainerTests.cs new file mode 100644 index 0000000000000..079322a295582 --- /dev/null +++ b/sdk/recoveryservices-backup/Azure.ResourceManager.RecoveryServicesBackup/tests/ScenarioTests/BackupProtectionContainerTests.cs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Azure.Core; +using Azure.Core.TestFramework; +using Azure.ResourceManager.RecoveryServices; +using Azure.ResourceManager.RecoveryServices.Models; +using Azure.ResourceManager.RecoveryServicesBackup.Models; +using Azure.ResourceManager.Storage; +using Azure.ResourceManager.Storage.Models; +using NUnit.Framework; + +namespace Azure.ResourceManager.RecoveryServicesBackup.Tests +{ + public class BackupProtectionContainerTests : RecoveryServicesBackupManagementTestBase + { + public BackupProtectionContainerTests(bool isAsnyc) + : base(isAsnyc)//, RecordedTestMode.Record) + { + } + + [Test] + public async Task CreateTest() + { + var sub = await Client.GetDefaultSubscriptionAsync(); + var rg = await CreateResourceGroup(sub, "sdktest", AzureLocation.EastUS); + + var storageName = Recording.GenerateAssetName("teststorage"); + var storageData = new StorageAccountCreateOrUpdateContent( + new StorageSku(StorageSkuName.StandardGrs), StorageKind.StorageV2, AzureLocation.EastUS); + var storage = (await rg.GetStorageAccounts() + .CreateOrUpdateAsync(WaitUntil.Completed, storageName, storageData)).Value; + + var vaultName = Recording.GenerateAssetName("testvalut"); + var vaultData = new RecoveryServicesVaultData(AzureLocation.EastUS) + { + Sku = new RecoveryServicesSku(RecoveryServicesSkuName.RS0) { Tier = "Standard" }, + Properties = new RecoveryServicesVaultProperties() + { + PublicNetworkAccess = VaultPublicNetworkAccess.Enabled + } + }; + var vault = (await rg.GetRecoveryServicesVaults().CreateOrUpdateAsync(WaitUntil.Completed, vaultName, vaultData)).Value; + + var containerName = $"StorageContainer;Storage;{rg.Data.Name};{storageName}"; + var containerData = new BackupProtectionContainerData(AzureLocation.EastUS) + { + Properties = new StorageContainer() + { + FriendlyName = storageName, + BackupManagementType = BackupManagementType.AzureStorage, + SourceResourceId = storage.Id, + AcquireStorageAccountLock = AcquireStorageAccountLock.Acquire + } + }; + var container = (await rg.GetBackupProtectionContainers() + .CreateOrUpdateAsync(WaitUntil.Completed, vaultName, "Azure", containerName, containerData)).Value; + Assert.AreEqual(container.Data.Properties.RegistrationStatus, "Registered"); + Assert.AreEqual(container.Data.Name, containerName); + + // Remove the auto-lock before we delete the resource group + var deleteLock = (await storage.GetManagementLocks().GetAsync("AzureBackupProtectionLock")).Value; + await deleteLock.DeleteAsync(WaitUntil.Completed); + } + } +}