Skip to content

Commit

Permalink
add param checking to resource (#19134)
Browse files Browse the repository at this point in the history
  • Loading branch information
nisha-bhatia authored Mar 3, 2021
1 parent c7d5742 commit dafcd2b
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ protected override void Validate(ResourceIdentifier identifier)
/// <param name="name"> The name of the resource. </param>
/// <param name="resourceDetails"> The desired resource configuration. </param>
/// <returns> A response with the <see cref="ArmResponse{TOperations}"/> operation for this resource. </returns>
/// <exception cref="ArgumentException"> Name of the resource cannot be null or a whitespace. </exception>
/// <exception cref="ArgumentNullException"> resourceDetails cannot be null. </exception>
public abstract ArmResponse<TOperations> CreateOrUpdate(
string name,
TResource resourceDetails);
Expand All @@ -56,6 +58,8 @@ public abstract ArmResponse<TOperations> CreateOrUpdate(
/// <param name="resourceDetails"> The desired resource configuration. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service. The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> A <see cref="Task"/> that on completion returns a response with the <see cref="ArmResponse{TOperations}"/> operation for this resource. </returns>
/// <exception cref="ArgumentException"> Name of the resource cannot be null or a whitespace. </exception>
/// <exception cref="ArgumentNullException"> resourceDetails cannot be null. </exception>
public abstract Task<ArmResponse<TOperations>> CreateOrUpdateAsync(
string name,
TResource resourceDetails,
Expand All @@ -71,6 +75,8 @@ public abstract Task<ArmResponse<TOperations>> CreateOrUpdateAsync(
/// <remarks>
/// <see href="https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-longrunning">Details on long running operation object.</see>
/// </remarks>
/// <exception cref="ArgumentException"> Name of the resource cannot be null or a whitespace. </exception>
/// <exception cref="ArgumentNullException"> resourceDetails cannot be null. </exception>
public abstract ArmOperation<TOperations> StartCreateOrUpdate(
string name,
TResource resourceDetails,
Expand All @@ -86,6 +92,8 @@ public abstract ArmOperation<TOperations> StartCreateOrUpdate(
/// <remarks>
/// <see href="https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-longrunning">Details on long running operation object.</see>
/// </remarks>
/// <exception cref="ArgumentException"> Name of the resource cannot be null or a whitespace. </exception>
/// <exception cref="ArgumentNullException"> resourceDetails cannot be null. </exception>
public abstract Task<ArmOperation<TOperations>> StartCreateOrUpdateAsync(
string name,
TResource resourceDetails,
Expand Down Expand Up @@ -124,6 +132,7 @@ protected TParent GetParentResource<TParent, TParentOperations>()
/// </summary>
/// <param name="resourceName"> The name of the resource to get. </param>
/// <returns> A response with the <see cref="ArmResponse{TOperations}"/> operation for this resource. </returns>
/// <exception cref="ArgumentException"> resourceName cannot be null or a whitespace. </exception>
public abstract ArmResponse<TOperations> Get(string resourceName);

/// <summary>
Expand All @@ -132,6 +141,7 @@ protected TParent GetParentResource<TParent, TParentOperations>()
/// <param name="resourceName"> The name of the resource to get. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service. The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> A <see cref="Task"/> that on completion returns a response with the <see cref="ArmResponse{TOperations}"/> operation for this resource. </returns>
/// <exception cref="ArgumentException"> resourceName cannot be null or a whitespace. </exception>
public abstract Task<ArmResponse<TOperations>> GetAsync(string resourceName, CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -38,8 +39,12 @@ internal ResourceGroupContainer(SubscriptionOperations subscription)
/// <param name="tags"> The tags of the resource group. </param>
/// <param name="managedBy"> Who the resource group is managed by. </param>
/// <returns> A builder with <see cref="ResourceGroup"/> and <see cref="ResourceGroupData"/>. </returns>
/// <exception cref="ArgumentNullException"> Location cannot be null. </exception>
public ArmBuilder<ResourceGroup, ResourceGroupData> Construct(LocationData location, IDictionary<string, string> 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);
Expand All @@ -50,6 +55,11 @@ public ArmBuilder<ResourceGroup, ResourceGroupData> Construct(LocationData locat
/// <inheritdoc/>
public override ArmResponse<ResourceGroup> 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<ResourceGroup, ResourceManager.Resources.Models.ResourceGroup>(
response,
Expand All @@ -59,6 +69,11 @@ public override ArmResponse<ResourceGroup> CreateOrUpdate(string name, ResourceG
/// <inheritdoc/>
public override async Task<ArmResponse<ResourceGroup>> 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<ResourceGroup, ResourceManager.Resources.Models.ResourceGroup>(
response,
Expand All @@ -68,6 +83,11 @@ public override async Task<ArmResponse<ResourceGroup>> CreateOrUpdateAsync(strin
/// <inheritdoc/>
public override ArmOperation<ResourceGroup> 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<ResourceGroup, ResourceManager.Resources.Models.ResourceGroup>(
Operations.CreateOrUpdate(name, resourceDetails, cancellationToken),
g => new ResourceGroup(Parent, new ResourceGroupData(g)));
Expand All @@ -76,6 +96,11 @@ public override ArmOperation<ResourceGroup> StartCreateOrUpdate(string name, Res
/// <inheritdoc/>
public override async Task<ArmOperation<ResourceGroup>> 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<ResourceGroup, ResourceManager.Resources.Models.ResourceGroup>(
await Operations.CreateOrUpdateAsync(name, resourceDetails, cancellationToken).ConfigureAwait(false),
g => new ResourceGroup(Parent, new ResourceGroupData(g)));
Expand Down Expand Up @@ -108,6 +133,9 @@ public AsyncPageable<ResourceGroup> ListAsync(CancellationToken cancellationToke
/// <inheritdoc />
public override ArmResponse<ResourceGroup> Get(string resourceGroupName)
{
if (string.IsNullOrWhiteSpace(resourceGroupName))
throw new ArgumentException("resourceGroupName cannot be null or a whitespace.", nameof(resourceGroupName));

return new PhArmResponse<ResourceGroup, ResourceManager.Resources.Models.ResourceGroup>(Operations.Get(resourceGroupName), g =>
{
return new ResourceGroup(Parent, new ResourceGroupData(g));
Expand All @@ -117,6 +145,9 @@ public override ArmResponse<ResourceGroup> Get(string resourceGroupName)
/// <inheritdoc/>
public override async Task<ArmResponse<ResourceGroup>> 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<ResourceGroup, ResourceManager.Resources.Models.ResourceGroup>(
await Operations.GetAsync(resourceGroupName, cancellationToken).ConfigureAwait(false),
g =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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\._\(\)]+$");
Expand Down
3 changes: 2 additions & 1 deletion sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ enum Scenarios
UseParentLocation,
GetByContainers,
GetByContainersAsync,
CheckResourceGroupOpsAsync
CheckResourceGroupOpsAsync,
CheckResourceGroupContainerAsync
}

class ScenarioFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ArgumentNullException>(
() => resourceGroupContainer.Construct(null),
"Construct with null loc didn't throw",
"Construct");

ShouldThrow<ArgumentNullException>(
() => resourceGroupContainer.CreateOrUpdate("test", null),
"CreateOrUpdate with null resourceGroupData didn't throw",
"CreateOrUpdate");

await ShouldThrowAsync<ArgumentException>(
async () => await resourceGroupContainer.CreateOrUpdateAsync(" ", resourceGroupData),
"CreateOrUpdateAsync with whitespaces only string didn't throw",
"CreateOrUpdateAsync");

ShouldThrow<ArgumentNullException>(
() => resourceGroupContainer.StartCreateOrUpdate("test", null),
"StartCreateOrUpdate with null ResourceGroupData didn't throw",
"StartCreateOrUpdate");

await ShouldThrowAsync<ArgumentException>(
async () => await resourceGroupContainer.StartCreateOrUpdateAsync(" ", resourceGroupData),
"StartCreateOrUpdateAsync with whitespaces only string didn't throw",
"StartCreateOrUpdateAsync");

ShouldThrow<ArgumentException>(
() => resourceGroupContainer.Get(null),
"Get with null string didn't throw",
"Get");

await ShouldThrowAsync<ArgumentException>(
async () => await resourceGroupContainer.GetAsync(" "),
"GetAsync with whitespaces only string didn't throw",
"GetAsync");

Console.WriteLine("--------Done--------");
}

private static void ShouldThrow<T>(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<T>(Func<Task> 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.");
}
}
}
}

0 comments on commit dafcd2b

Please sign in to comment.