Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nibhati - 5142 - Add param checking to ResourceContainerBase and ResourceGroupContainer #19134

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.");
}
}
}
}