diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs index 46a89fa6a2b98..5327523908a2d 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs @@ -45,6 +45,8 @@ protected override void Validate(ResourceIdentifier identifier) /// The name of the resource. /// The desired resource configuration. /// A response with the operation for this resource. + /// Name of the resource cannot be null or a whitespace. + /// resourceDetails cannot be null. public abstract ArmResponse CreateOrUpdate( string name, TResource resourceDetails); @@ -56,6 +58,8 @@ public abstract ArmResponse CreateOrUpdate( /// The desired resource configuration. /// A token to allow the caller to cancel the call to the service. The default value is . /// A that on completion returns a response with the operation for this resource. + /// Name of the resource cannot be null or a whitespace. + /// resourceDetails cannot be null. public abstract Task> CreateOrUpdateAsync( string name, TResource resourceDetails, @@ -71,6 +75,8 @@ public abstract Task> CreateOrUpdateAsync( /// /// Details on long running operation object. /// + /// Name of the resource cannot be null or a whitespace. + /// resourceDetails cannot be null. public abstract ArmOperation StartCreateOrUpdate( string name, TResource resourceDetails, @@ -86,6 +92,8 @@ public abstract ArmOperation StartCreateOrUpdate( /// /// Details on long running operation object. /// + /// Name of the resource cannot be null or a whitespace. + /// resourceDetails cannot be null. public abstract Task> StartCreateOrUpdateAsync( string name, TResource resourceDetails, @@ -124,6 +132,7 @@ protected TParent GetParentResource() /// /// The name of the resource to get. /// A response with the operation for this resource. + /// resourceName cannot be null or a whitespace. public abstract ArmResponse Get(string resourceName); /// @@ -132,6 +141,7 @@ protected TParent GetParentResource() /// The name of the resource to get. /// A token to allow the caller to cancel the call to the service. The default value is . /// A that on completion returns a response with the operation for this resource. + /// resourceName cannot be null or a whitespace. public abstract Task> GetAsync(string resourceName, CancellationToken cancellationToken = default); } } diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupContainer.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupContainer.cs index 8374a6c812561..8e12072abc83e 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupContainer.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -38,8 +39,12 @@ internal ResourceGroupContainer(SubscriptionOperations subscription) /// The tags of the resource group. /// Who the resource group is managed by. /// A builder with and . + /// Location cannot be null. public ArmBuilder Construct(LocationData location, IDictionary tags = default, string managedBy = default) { + if (location is null) + throw new ArgumentNullException(nameof(location)); + var model = new ResourceManager.Resources.Models.ResourceGroup(location); if (!(tags is null)) model.Tags.ReplaceWith(tags); @@ -50,6 +55,11 @@ public ArmBuilder Construct(LocationData locat /// public override ArmResponse CreateOrUpdate(string name, ResourceGroupData resourceDetails) { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("name cannot be null or a whitespace.", nameof(name)); + if (resourceDetails is null) + throw new ArgumentNullException(nameof(resourceDetails)); + var response = Operations.CreateOrUpdate(name, resourceDetails); return new PhArmResponse( response, @@ -59,6 +69,11 @@ public override ArmResponse CreateOrUpdate(string name, ResourceG /// public override async Task> CreateOrUpdateAsync(string name, ResourceGroupData resourceDetails, CancellationToken cancellationToken = default) { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("name cannot be null or a whitespace.", nameof(name)); + if (resourceDetails is null) + throw new ArgumentNullException(nameof(resourceDetails)); + var response = await Operations.CreateOrUpdateAsync(name, resourceDetails, cancellationToken).ConfigureAwait(false); return new PhArmResponse( response, @@ -68,6 +83,11 @@ public override async Task> CreateOrUpdateAsync(strin /// public override ArmOperation StartCreateOrUpdate(string name, ResourceGroupData resourceDetails, CancellationToken cancellationToken = default) { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("name cannot be null or a whitespace.", nameof(name)); + if (resourceDetails is null) + throw new ArgumentNullException(nameof(resourceDetails)); + return new PhArmOperation( Operations.CreateOrUpdate(name, resourceDetails, cancellationToken), g => new ResourceGroup(Parent, new ResourceGroupData(g))); @@ -76,6 +96,11 @@ public override ArmOperation StartCreateOrUpdate(string name, Res /// public override async Task> StartCreateOrUpdateAsync(string name, ResourceGroupData resourceDetails, CancellationToken cancellationToken = default) { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("name cannot be null or a whitespace.", nameof(name)); + if (resourceDetails is null) + throw new ArgumentNullException(nameof(resourceDetails)); + return new PhArmOperation( await Operations.CreateOrUpdateAsync(name, resourceDetails, cancellationToken).ConfigureAwait(false), g => new ResourceGroup(Parent, new ResourceGroupData(g))); @@ -108,6 +133,9 @@ public AsyncPageable ListAsync(CancellationToken cancellationToke /// public override ArmResponse Get(string resourceGroupName) { + if (string.IsNullOrWhiteSpace(resourceGroupName)) + throw new ArgumentException("resourceGroupName cannot be null or a whitespace.", nameof(resourceGroupName)); + return new PhArmResponse(Operations.Get(resourceGroupName), g => { return new ResourceGroup(Parent, new ResourceGroupData(g)); @@ -117,6 +145,9 @@ public override ArmResponse Get(string resourceGroupName) /// public override async Task> GetAsync(string resourceGroupName, CancellationToken cancellationToken = default) { + if (string.IsNullOrWhiteSpace(resourceGroupName)) + throw new ArgumentException("resourceGroupName cannot be null or a whitespace.", nameof(resourceGroupName)); + return new PhArmResponse( await Operations.GetAsync(resourceGroupName, cancellationToken).ConfigureAwait(false), g => diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupOperations.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupOperations.cs index 295abe3e07362..0f7ddf4e539b8 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupOperations.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceGroupOperations.cs @@ -35,7 +35,7 @@ internal ResourceGroupOperations(SubscriptionOperations options, string rgName) throw new ArgumentOutOfRangeException(nameof(rgName), "ResourceGroupName cannot be longer than 90 characters."); if (!ValidationPattern.IsMatch(rgName)) - throw new ArgumentException("The name of the resource group can include alphanumeric, underscore, parentheses, hyphen, period (except at end), and Unicode characters that match the allowed characters."); + throw new ArgumentException("The name of the resource group can include alphanumeric, underscore, parentheses, hyphen, period (except at end), and Unicode characters that match the allowed characters.", nameof(rgName)); } private static readonly Regex ValidationPattern = new Regex(@"^[-\w\._\(\)]+$"); diff --git a/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs b/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs index fb0a13747bad3..07b94ea2a55e8 100644 --- a/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs +++ b/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs @@ -37,7 +37,8 @@ enum Scenarios UseParentLocation, GetByContainers, GetByContainersAsync, - CheckResourceGroupOpsAsync + CheckResourceGroupOpsAsync, + CheckResourceGroupContainerAsync } class ScenarioFactory diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/CheckResourceGroupContainerAsync.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/CheckResourceGroupContainerAsync.cs new file mode 100644 index 0000000000000..2269e23e534b9 --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/CheckResourceGroupContainerAsync.cs @@ -0,0 +1,97 @@ +using Azure.ResourceManager.Core; +using Proto.Compute; +using System; +using System.Threading.Tasks; + +namespace Proto.Client +{ + class CheckResourceGroupContainerAsync : Scenario + { + public CheckResourceGroupContainerAsync() : base() { } + + public CheckResourceGroupContainerAsync(ScenarioContext context) : base(context) { } + + public override void Execute() + { + ExecuteAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + } + + private async System.Threading.Tasks.Task ExecuteAsync() + { + var client = new AzureResourceManagerClient(); + var subscription = client.GetSubscriptionOperations(Context.SubscriptionId); + + // Create Resource Group + Console.WriteLine($"--------Start create group {Context.RgName}--------"); + var resourceGroup = subscription.GetResourceGroupContainer().Construct(Context.Loc).CreateOrUpdate(Context.RgName).Value; + CleanUp.Add(resourceGroup.Id); + var rgOps = subscription.GetResourceGroupOperations(Context.RgName); + var resourceGroupContainer = subscription.GetResourceGroupContainer(); + var rg = new Azure.ResourceManager.Resources.Models.ResourceGroup("East US"); + var resourceGroupData = new ResourceGroupData(rg); + + ShouldThrow( + () => resourceGroupContainer.Construct(null), + "Construct with null loc didn't throw", + "Construct"); + + ShouldThrow( + () => resourceGroupContainer.CreateOrUpdate("test", null), + "CreateOrUpdate with null resourceGroupData didn't throw", + "CreateOrUpdate"); + + await ShouldThrowAsync( + async () => await resourceGroupContainer.CreateOrUpdateAsync(" ", resourceGroupData), + "CreateOrUpdateAsync with whitespaces only string didn't throw", + "CreateOrUpdateAsync"); + + ShouldThrow( + () => resourceGroupContainer.StartCreateOrUpdate("test", null), + "StartCreateOrUpdate with null ResourceGroupData didn't throw", + "StartCreateOrUpdate"); + + await ShouldThrowAsync( + async () => await resourceGroupContainer.StartCreateOrUpdateAsync(" ", resourceGroupData), + "StartCreateOrUpdateAsync with whitespaces only string didn't throw", + "StartCreateOrUpdateAsync"); + + ShouldThrow( + () => resourceGroupContainer.Get(null), + "Get with null string didn't throw", + "Get"); + + await ShouldThrowAsync( + async () => await resourceGroupContainer.GetAsync(" "), + "GetAsync with whitespaces only string didn't throw", + "GetAsync"); + + Console.WriteLine("--------Done--------"); + } + + private static void ShouldThrow(Action lambda, string failMessage, string method) + { + try + { + lambda(); + throw new Exception(failMessage); + } + catch (Exception e) when (e.GetType() == typeof(T)) + { + Console.WriteLine($"{method} Exception was thrown as expected."); + } + } + + private static async Task ShouldThrowAsync(Func lambda, string failMessage, string method) + { + try + { + await lambda(); + throw new Exception(failMessage); + } + catch (Exception e) when (e.GetType() == typeof(T)) + { + Console.WriteLine($"{method} Exception was thrown as expected."); + } + } + } +}