Skip to content

additional input validation for Get-AzurermProviderOperation cmdlet #1141

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

Merged
merged 4 commits into from
Oct 21, 2015
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 @@ -53,17 +53,17 @@ function Test-AzureProvider
#>
function Test-AzureProviderOperation
{
# Get all actions by all providers
# Get all operations by all providers
$allActions = Get-AzureRmProviderOperation *
Assert-True { $allActions.Length -gt 0 }

# Get all actions of microsoft.insights provider
# Get all operations of microsoft.insights provider
$insightsActions = Get-AzureRmProviderOperation Microsoft.Insights/*
$insightsActions
Assert-True { $insightsActions.Length -gt 0 }
Assert-True { $allActions.Length -gt $insightsActions.Length }

# Filter non-Microsoft.Insights actions and match the lengths
# Filter non-Microsoft.Insights operations and match the lengths
$nonInsightsActions = $allActions | Where-Object { $_.Operation.ToLower().StartsWith("microsoft.insights/") -eq $false }
$actualLength = $allActions.Length - $nonInsightsActions.Length;
$expectedLength = $insightsActions.Length;
Expand All @@ -83,7 +83,7 @@ function Test-AzureProviderOperation
Assert-True { $action.Operation.ToLower().Startswith("microsoft.insights/"); }
}

# Get all Read actions of microsoft.insights provider
# Get all Read operations of microsoft.insights provider
$insightsReadActions = Get-AzureRmProviderOperation Microsoft.Insights/*/read
Assert-True { $insightsReadActions.Length -gt 0 }
Assert-True { $insightsActions.Length -gt $insightsReadActions.Length }
Expand All @@ -93,7 +93,7 @@ function Test-AzureProviderOperation
Assert-True { $action.Operation.ToLower().StartsWith("microsoft.insights/");}
}

# Get all Read actions of all providers
# Get all Read operations of all providers
$readActions = Get-AzureRmProviderOperation */read
Assert-True { $readActions.Length -gt 0 }
Assert-True { $readActions.Length -lt $allActions.Length }
Expand All @@ -104,18 +104,30 @@ function Test-AzureProviderOperation
Assert-True { $action.Operation.ToLower().EndsWith("/read"); }
}

# Get a particular action
# Get a particular operation
$action = Get-AzureRmProviderOperation Microsoft.OperationalInsights/workspaces/usages/read
Assert-AreEqual $action.Operation.ToLower() "Microsoft.OperationalInsights/workspaces/usages/read".ToLower();

# Get an invalid action
# Get an invalid operation
$action = Get-AzureRmProviderOperation Microsoft.OperationalInsights/workspaces/usages/read/123
Assert-True { $action.Length -eq 0 }

# Get actions for non-existing provider
# Get operations for non-existing provider
$exceptionMessage = "ProviderNotFound: Provider NonExistentProvider not found.";
Assert-Throws { Get-AzureRmProviderOperation NonExistentProvider/* } $exceptionMessage

# Get action for non-existing provider
# Get operations for non-existing provider
Assert-Throws { Get-AzureRmProviderOperation NonExistentProvider/servers/read } $exceptionMessage

# Get operations with invalid search string parts
$exceptionMessage = "Individual parts in the search string should either equal * or not contain *.";
Assert-Throws {Get-AzureRmProviderOperation Microsoft.ClassicCompute/virtual*/read } $exceptionMessage

# Get operations with invalid provider name
$exceptionMessage = "To get all operations under Microsoft.Sql, please specify the search string as Microsoft.Sql/*.";
Assert-Throws {Get-AzureRmProviderOperation Microsoft.Sql } $exceptionMessage

# Get operations with ? in search string
$exceptionMessage = "Wildcard character ? is not supported.";
Assert-Throws {Get-AzureRmProviderOperation Microsoft.Sql/servers/*/rea? } $exceptionMessage
}

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,13 @@
<data name="RoleDefinitionIdShouldBeAGuid" xml:space="preserve">
<value>Role definition id should be a valid guid.</value>
</data>
<data name="OperationSearchStringInvalidProviderName" xml:space="preserve">
<value>To get all operations under {0}, please specify the search string as {0}/*.</value>
</data>
<data name="OperationSearchStringInvalidWildcard" xml:space="preserve">
<value>Individual parts in the search string should either equal * or not contain *.</value>
</data>
<data name="ProviderOperationUnsupportedWildcard" xml:space="preserve">
<value>Wildcard character ? is not supported.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Microsoft.Azure.Commands.Resources
using System.Management.Automation;
using Microsoft.Azure.Commands.Resources.Models;
using Microsoft.Azure.Management.Resources.Models;
using ProjectResources = Microsoft.Azure.Commands.Resources.Properties.Resources;

/// <summary>
/// Get an existing resource.
Expand All @@ -28,90 +29,93 @@ namespace Microsoft.Azure.Commands.Resources
public class GetAzureProviderOperationCommand : ResourcesBaseCmdlet
{
private const string WildCardCharacter = "*";
private static readonly char Separator = '/';

/// <summary>
/// Gets or sets the provider namespace
/// </summary>
[Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = false, ValueFromPipeline = true, HelpMessage = "The action string.")]
[ValidateNotNullOrEmpty]
public string ActionString { get; set; }
public string OperationSearchString { get; set; }

/// <summary>
/// Executes the cmdlet
/// </summary>
protected override void ProcessRecord()
{
// remove leading and trailing whitespaces
this.ActionString = this.ActionString.Trim();
this.OperationSearchString = this.OperationSearchString.Trim();

List<PSResourceProviderOperation> operationsToDisplay;
ValidateActionSearchString(this.OperationSearchString);

List<PSResourceProviderOperation> operationsToDisplay;

if (this.ActionString.Contains(WildCardCharacter))
if (this.OperationSearchString.Contains(WildCardCharacter))
{
operationsToDisplay = this.ProcessProviderOperationsWithWildCard(ActionString);
operationsToDisplay = this.ProcessProviderOperationsWithWildCard(OperationSearchString);
}
else
{
operationsToDisplay = this.ProcessProviderOperationsWithoutWildCard(ActionString);
operationsToDisplay = this.ProcessProviderOperationsWithoutWildCard(OperationSearchString);
}

this.WriteObject(operationsToDisplay, enumerateCollection: true);
}

private static void ValidateActionSearchString(string actionSearchString)
{
if (actionSearchString.Contains("?"))
{
throw new ArgumentException(ProjectResources.ProviderOperationUnsupportedWildcard);
}

string[] parts = actionSearchString.Split(Separator);
if (parts.Any(p => p.Contains(WildCardCharacter) && p.Length != 1))
{
throw new ArgumentException(ProjectResources.OperationSearchStringInvalidWildcard);
}

if(parts.Length == 1 && parts[0] != WildCardCharacter)
{
throw new ArgumentException(string.Format(ProjectResources.OperationSearchStringInvalidProviderName, parts[0]));
}
}

/// <summary>
/// Get a list of Provider operations in the case that the Actionstring input contains a wildcard
/// </summary>
private List<PSResourceProviderOperation> ProcessProviderOperationsWithWildCard(string actionString)
private List<PSResourceProviderOperation> ProcessProviderOperationsWithWildCard(string actionSearchString)
{
// Filter the list of all operation names to what matches the wildcard
WildcardPattern wildcard = new WildcardPattern(actionString, WildcardOptions.IgnoreCase | WildcardOptions.Compiled);
WildcardPattern wildcard = new WildcardPattern(actionSearchString, WildcardOptions.IgnoreCase | WildcardOptions.Compiled);

List<ProviderOperationsMetadata> providers = new List<ProviderOperationsMetadata>();

string nonWildCardPrefix = GetAzureProviderOperationCommand.GetNonWildcardPrefix(actionString);
if (string.IsNullOrWhiteSpace(nonWildCardPrefix))
string provider = this.OperationSearchString.Split(Separator).First();
if (provider.Equals(WildCardCharacter))
{
// 'Get-AzureRmProviderOperation *' or 'Get-AzureRmProviderOperation */virtualmachines/*'
// get operations for all providers
providers.AddRange(this.ResourcesClient.ListProviderOperationsMetadata());
}
else
{
// Some string exists before the wild card character - potentially the full name of the provider.
string providerFullName = GetAzureProviderOperationCommand.GetResourceProviderFullName(nonWildCardPrefix);
if (!string.IsNullOrWhiteSpace(providerFullName))
{
// we have the full name of the provider. 'Get-AzureRmProviderOperation Microsoft.Sql/servers/*'
// only query for that provider
providers.Add(this.ResourcesClient.GetProviderOperationsMetadata(providerFullName));
}
else
{
// We have only a partial name of the provider, say Microsoft.*/* or Microsoft.*/*/read.
// query for all providers and then do prefix match on the operations
providers.AddRange(this.ResourcesClient.ListProviderOperationsMetadata());
}
// 'Get-AzureRmProviderOperation Microsoft.Compute/virtualmachines/*' or 'Get-AzureRmProviderOperation Microsoft.Sql/*'
providers.Add(this.ResourcesClient.GetProviderOperationsMetadata(provider));
}

return providers.SelectMany(p => GetPSOperationsFromProviderOperationsMetadata(p)).Where(operation => wildcard.IsMatch(operation.Operation)).ToList();
return providers.SelectMany(p => GetPSOperationsFromProviderOperationsMetadata(p)).Where(operation => wildcard.IsMatch(operation.Operation)).ToList();
}

/// <summary>
/// Gets a list of Provider operations in the case that the Actionstring input does not contain a wildcard
/// </summary>
private List<PSResourceProviderOperation> ProcessProviderOperationsWithoutWildCard(string actionString)
private List<PSResourceProviderOperation> ProcessProviderOperationsWithoutWildCard(string operationString)
{
List<PSResourceProviderOperation> operationsToDisplay = new List<PSResourceProviderOperation>();
string providerFullName = GetAzureProviderOperationCommand.GetResourceProviderFullName(actionString);
if (!string.IsNullOrWhiteSpace(providerFullName))
{
// We have the full name of the provider. get operations metadata for this provider
ProviderOperationsMetadata providerOperations = this.ResourcesClient.GetProviderOperationsMetadata(providerFullName);
IEnumerable<PSResourceProviderOperation> flattenedProviderOperations = GetAzureProviderOperationCommand.GetPSOperationsFromProviderOperationsMetadata(providerOperations);
operationsToDisplay.AddRange(flattenedProviderOperations.Where(op => string.Equals(op.Operation, actionString, StringComparison.OrdinalIgnoreCase)));
}
string providerFullName = operationString.Split(Separator).First();

return operationsToDisplay;
ProviderOperationsMetadata providerOperations = this.ResourcesClient.GetProviderOperationsMetadata(providerFullName);
IEnumerable<PSResourceProviderOperation> flattenedProviderOperations = GetAzureProviderOperationCommand.GetPSOperationsFromProviderOperationsMetadata(providerOperations);
return flattenedProviderOperations.Where(op => string.Equals(op.Operation, operationString, StringComparison.OrdinalIgnoreCase)).ToList();
}

private static IEnumerable<PSResourceProviderOperation> GetPSOperationsFromProviderOperationsMetadata(ProviderOperationsMetadata providerOperationsMetadata)
Expand Down Expand Up @@ -150,7 +154,7 @@ private static PSResourceProviderOperation ToPSResourceProviderOperation(Operati
/// </summary>
private static string GetResourceProviderFullName(string nonWildCardPrefix)
{
int index = nonWildCardPrefix.IndexOf("/", 0);
int index = nonWildCardPrefix.IndexOf(Separator.ToString(), 0);
return index > 0 ? nonWildCardPrefix.Substring(0, index) : string.Empty;
}

Expand Down