Modules/BenchPress.Azure/Public/Confirm-Resource.ps1 (241 lines of code) (raw):
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
using module ./../Classes/ResourceType.psm1
. $PSScriptRoot/Get-ResourceByType.ps1
# end INLINE_SKIP
function Confirm-Resource {
<#
.SYNOPSIS
Confirms whether a resource exists or properties on a resource are configured correctly.
.DESCRIPTION
The Confirm-AzBPResource cmdlet confirms whether an Azure resource exists and/or confirms whether properties
on a resource exist and are configured to the correct value. The cmdlet will return a ConfirmResult object
which contains the following properties:
- Success: True if the resource exists and/or the property is set to the expected value. Otherwise, false.
- ResourceDetails: System.Object that contains the details of the Azure Resource that is being confirmed.
.PARAMETER ResourceName
The name of the Resource.
.PARAMETER ResourceGroupName
The name of the Resource Group. The name is case insensitive.
.PARAMETER ResourceType
The type of the Resource as a [ResourceType].
.PARAMETER ServerName
If testing an Azure SQL Database resource, the name of the Server to which the Database is assigned.
.PARAMETER DataFactoryName
If testing an Azure Data Factory Linked Service resource, the name of the Data Factory to which the Linked
Service is assigned.
.PARAMETER NamespaceName
If testing an Azure resource that is associated with a Namespace (e.g., Event Hub), the name of the associated
Namespace.
.PARAMETER EventHubName
If testing a component of Event Hub (e.g., Consumer Group), the name of the Event Hub to which the component
is assigned.
.PARAMETER WorkspaceName
If testing an Azure resource that belongs to some sort of Azure Workspace (e.g., SQL Pool in a Synapse
Workspace), the name of the Workspace to which the resource is assigned.
.PARAMETER AccountName
If testing an Azure resource that is associated with an Account (e.g., Cosmos DB SQL Database,
Storage Container), the name of the associated Account.
.PARAMETER ServicePrincipalId
If testing an Azure Role Assignment, the Enterprise/Managed Application Object ID of the Service Principal.
.PARAMETER Scope
If testing an Azure Role Assignment, the Scope of the Role Assignment (e.g.,
/subscriptions/{id}/resourceGroups/{resourceGroupName}).
It must start with "/subscriptions/{id}".
.PARAMETER RoleDefinitionName
If testing an Azure Role Assignment, the name of the Role Definition (e.g., Reader, Contributor etc.).
.PARAMETER ServiceName
If testing an Azure resource that is associated with a Service (e.g., API Management Service), the name of
the associated Service.
.PARAMETER KeyVaultName
If testing an Azure Key Vault resource (e.g., Key Vault Key), the name of the Key Vault to which the resource is
assigned.
.PARAMETER JobName
If testing an Azure resource that is associated with a Job (e.g., Stream Analytics Output), the name of
the associated Job.
.PARAMETER RoleAssignmentId
If testing an Azure resource that is associated with a Role Assignment (e.g., Cosmos DB SQL Role Assignment),
the id of the Role Assignment.
.PARAMETER RoleDefinitionId
If testing an Azure resource that is associated with a Role Definition (e.g., Cosmos DB SQL Role Definition),
the id of the Role Definition.
.PARAMETER ClusterName
If testing an Azure resource that is associated with an AKS Cluster (e.g, AKS Node Pool) this is the parameter
to use to pass the AKS cluster name.
.PARAMETER ResourceId
If testing an Azure resource that is associated with a Resource ID (e.g., Diagnostic Setting)
this is the parameter to use to pass the Resource ID.
.PARAMETER PropertyKey
The name of the property to check on the resource.
.PARAMETER PropertyValue
The expected value of the property to check.
.EXAMPLE
Checking whether a resource exists (i.e. Resource Group).
Confirm-AzBPResource -ResourceType $resourceType -ResourceName $resourceGroupName
.EXAMPLE
Confirm whether a resource has a property configured correctly (i.e. Resource Group located in West US 3).
Confirm-AzBPResource -ResourceType $resourceType -ResourceName $resourceGroupName -PropertyKey "Location" `
-PropertyValue "WestUS3"
.EXAMPLE
Checking whether a nested property on a resource is configured correctly (i.e. OS of VM is Linux).
$params = @{
ResourceGroupName = "rg-test";
ResourceType = "VirtualMachine";
ResourceName = "testvm";
PropertyKey = "StorageProfile.OsDisk.OsType";
PropertyValue = "Linux"
}
$result = Confirm-AzBPResource @params
.INPUTS
ResourceType
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $false)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[ResourceType]$ResourceType,
[Parameter(Mandatory = $false)]
[string]$ServerName,
[Parameter(Mandatory = $false)]
[string]$KeyVaultName,
[Parameter(Mandatory = $false)]
[string]$DataFactoryName,
[Parameter(Mandatory = $false)]
[string]$NamespaceName,
[Parameter(Mandatory = $false)]
[string]$EventHubName,
[Parameter(Mandatory = $false)]
[string]$WorkspaceName,
[Parameter(Mandatory = $false)]
[string]$ServicePrincipalId,
[Parameter(Mandatory = $false)]
[string]$Scope,
[Parameter(Mandatory = $false)]
[string]$RoleDefinitionName,
[Parameter(Mandatory = $false)]
[string]$AccountName,
[Parameter(Mandatory = $false)]
[string]$ServiceName,
[Parameter(Mandatory = $false)]
[string]$ClusterName,
[Parameter(Mandatory = $false)]
[string]$JobName,
[Parameter(Mandatory = $false)]
[string]$ResourceId,
[Parameter(Mandatory = $false)]
[string]$RoleAssignmentId,
[Parameter(Mandatory = $false)]
[string]$RoleDefinitionId,
[Parameter(Mandatory = $false)]
[string]$PropertyKey,
[Parameter(Mandatory = $false)]
[string]$PropertyValue
)
Begin { }
Process {
$resourceParams = @{
ResourceType = $ResourceType
NamespaceName = $NamespaceName
EventHubName = $EventHubName
JobName = $JobName
ResourceName = $ResourceName
ResourceGroupName = $ResourceGroupName
ServerName = $ServerName
KeyVaultName = $KeyVaultName
DataFactoryName = $DataFactoryName
WorkspaceName = $WorkspaceName
AccountName = $AccountName
RoleDefinitionName = $RoleDefinitionName
Scope = $Scope
ServicePrincipalId = $ServicePrincipalId
ServiceName = $ServiceName
RoleAssignmentId = $RoleAssignmentId
RoleDefinitionId = $RoleDefinitionId
ClusterName = $ClusterName
ResourceId = $ResourceId
}
$confirmResult = Get-ResourceByType @resourceParams
if ($null -eq $confirmResult) {
Write-Error "Resource not found" -Category InvalidResult -ErrorId "InvalidResource"
$confirmResult = [ConfirmResult]::new($null)
} elseif ($confirmResult.Success -and -not [string]::IsNullOrWhiteSpace($PropertyKey)) {
$actualValue = $confirmResult.ResourceDetails
# Split property path on open and close square brackets and periods. Remove empty items from array.
$keys = ($PropertyKey -split '[\[\]\.]').Where({ $_ -ne "" })
foreach ($key in $keys) {
# If key is a numerical value, index into array
if ($key -match "^\d+$") {
# Check to be sure the current $actualValue is an array and the index is present
# Both arrays and lists that have indexers (generic lists as well) implement the IList interface
if (-not ($actualValue -is [System.Collections.IList])) {
# It is not indexable
$errorParams = @{
Message = "The path '$PropertyKey' attempted to index into the [$($actualValue.GetType())] object " +
"that does not implement the [IList] interface."
Category = [System.Management.Automation.ErrorCategory]::InvalidArgument
ErrorId = "InvalidKey"
}
Write-Error @errorParams
$confirmResult = [ConfirmResult]::new($null)
break
} elseif ([int]$key -lt 0 -or [int]$key -ge ([System.Collections.IList] $actualValue).Count) {
# Index out of bounds
$errorParams = @{
Message = "The path '$PropertyKey' with the index [$key] was out of bounds for the array with the " +
"size $(([System.Collections.IList]$actualValue).Count)"
Category = [System.Management.Automation.ErrorCategory]::InvalidArgument
ErrorId = "InvalidKey"
}
Write-Error @errorParams
$confirmResult = [ConfirmResult]::new($null)
break
}
$actualValue = $actualValue[$key]
} else {
# Check to be sure that the next key exists in the object, if it doesn't we fail
if (-not [bool]($actualValue.PSObject.Properties.Name -match $key)) {
# There is no property in the object with the key, fail.
$errorParams = @{
Message = "The key '$key' in the path '$PropertyKey' does not exist in the " +
"[$($confirmResult.ResourceDetails.GetType())] object."
Category = [System.Management.Automation.ErrorCategory]::InvalidArgument
ErrorId = "InvalidKey"
}
Write-Error @errorParams
$confirmResult = [ConfirmResult]::new($null)
break
}
$actualValue = $actualValue.$key
}
}
if ($PropertyValue -ne $null -and $confirmResult.Success -and $actualValue -ne $PropertyValue) {
$confirmResult.Success = $false
if ($null -eq $actualValue) {
$errorParams = @{
Message = "A value for the property key: ${$PropertyKey}, was not found."
Category = [System.Management.Automation.ErrorCategory]::InvalidArgument
ErrorId = "InvalidKey"
}
Write-Error @errorParams
} else {
$errorParams = @{
Message = "The value provided: ${$PropertyValue}, does not match the actual value: ${actualValue} for " +
"property key: ${$PropertyKey}"
Category = [System.Management.Automation.ErrorCategory]::InvalidResult
ErrorId = "InvalidPropertyValue"
}
Write-Error @errorParams
}
}
}
$confirmResult
}
End { }
}