Az.PowerManager.psm1

If (Import-RequiredModules -ModuleFilePath $PSCommandPath -AutoInstall )
{
    Write-Verbose "All PSRequiredModules loaded !"

    Function Get-DateOrNull ([Parameter(Mandatory = $true)] [string]$Date)
    { Try { Get-Date $Date } Catch { $null } }

    Function Confirm-TimeWihtinTimeRange ([Parameter(Mandatory = $true)] [datetime]$Time, [Parameter(Mandatory = $true)] [datetime]$TimeRangeStart, [Parameter(Mandatory = $true)] [datetime]$TimeRangeEnd)
    {
        Try
        {
            If ($Time -ge $TimeRangeStart -and $Time -le $TimeRangeEnd) { return $true }
            Else { return $false }
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    
    }

    Function Get-AzPowerPolicyRuleType ([Parameter(Mandatory = $true)] [string]$PolicyRule) 
    {
        Try
        {
            switch ($PolicyRule) 
            {
                { $PolicyRule -like "*:*->*:*" } { $PolicyRuleType = "TimeRange" }
                { $PolicyRule -like "*:*" -and $_ -notlike "*->*" } { $PolicyRuleType = "Time" }
                { $PolicyRule -like "*-*" -and $PolicyRule -notlike "*->*" } { $PolicyRuleType = "DayOfMonth" }
                { [System.DayOfWeek].GetEnumValues() -contains $PolicyRule } { $PolicyRuleType = "DayOfWeek" }
                Default { $PolicyRuleType = "Unknown" }
            }

            [PSCustomObject]@{RuleValue = $PolicyRule ; RuleType = $PolicyRuleType } 
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    }

    If (!($PowerManager_ScheduleFrequency)) { $PowerManager_ScheduleFrequency = 60 }

    Function Expand-AzPowerPolicy ([Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)] [string]$ResourceId, [Parameter(Mandatory = $true)] [string]$ShutdownPolicy, [Parameter(Mandatory = $true)] [string]$ShutdownAssignment, [switch]$SkipInvalidRules, [datetime]$CurrentTime = $(Get-Date))
    {       
        Try 
        {
            $PolicyObject = @()
            $rangeStart, $rangeEnd, $parsedDay = $null
            $Midnight = $CurrentTime.AddDays(1).Date

            #1 Mono-rule Vs. Multi-rules
            If ($ShutdownPolicy -like "*,*") 
            {
                # Multi-Rules policy
                $PolicyRules = $ShutdownPolicy.Split(',')
                $PolicyRules | % { If ($_) { $PolicyObject += Get-AzPowerPolicyRuleType $_ } }
            }
            Else 
            {
                # Mono-Rule policy
                $PolicyObject += Get-AzPowerPolicyRuleType $ShutdownPolicy
            }

            #2 Rule Type
            $ShutdownPolicyRules = @()
            $PolicyObject | % {

                $RuleValue = $_.RuleValue
                $RuleValid = $null
                $TimeRangeStart = $null
                $TimeRangeEnd = $null

                Switch ($_)
                {
                    # Rule Type : Time
                    { $_.RuleType -eq 'Time' }
                    {
                        $ShutdownMode = "ShutdownOnly"
                        $TimeRangeStart = Get-DateOrNull $RuleValue
                        $TimeRangeEnd = $null
                        If ($TimeRangeStart) { $RuleValid = $true } Else { $RuleValid = $false }
                    }
                
                    # Rule Type : TimeRange
                    { $_.RuleType -eq 'TimeRange' }
                    {

                        $ShutdownMode = "Shutdown/Startup"

                        $TimeRangeStart = Get-DateOrNull ($RuleValue -split '->')[0]
                        $TimeRangeEnd = Get-DateOrNull ($RuleValue -split '->')[1]

                        If ($TimeRangeStart -and $TimeRangeEnd)
                        {
                            $RuleValid = $true
                            # Mono-Day Vs. Dual-Day TimeRange
                            If ($TimeRangeStart -gt $TimeRangeEnd) 
                            {
                                # Can't be the same day
                                # Current time within TimeRange AND before Midnight = TimeRangeEnd = Tomorrow
                                If ($CurrentTime -ge $TimeRangeStart -and $CurrentTime -lt $Midnight) { $TimeRangeEnd = $TimeRangeEnd.AddDays(1) }
                                #Else TimeRangeStart = Yesterday
                                Else { $TimeRangeStart = $TimeRangeStart.AddDays(-1) }
                            }
                        }
                        Else
                        {
                            $RuleValid = $false
                            Write-Warning "Wrong rule value ($RuleValue). Flag as invalid rule ..."
                        }
                    }

                    # Rule Type : DayOfWeek
                    { $_.RuleType -eq 'DayOfWeek' }
                    {

                        $RuleValid = $true
                        $ShutdownMode = "Shutdown/Startup"

                        # Is Today ?
                        #If ($RuleValue -eq (Get-Date).DayOfWeek) { $TimeRangeStart = Get-Date "00:00"; $TimeRangeEnd = Get-Date "23:59:59" }
                        If ($RuleValue -eq $CurrentTime.DayOfWeek) { $TimeRangeStart = $($CurrentTime.AddHours(-$CurrentTime.Hour).AddMinutes(-$CurrentTime.Minute).AddSeconds(-$CurrentTime.Second)); $TimeRangeEnd = $($CurrentTime.AddHours(23 - $CurrentTime.Hour).AddMinutes(59 - $CurrentTime.Minute).AddSeconds(59 - $CurrentTime.Second)) }
                        Else
                        {
                            #$TimeRangeStart = Get-Date "00:00"
                            $TimeRangeStart = $($CurrentTime.AddHours(-$CurrentTime.Hour).AddMinutes(-$CurrentTime.Minute).AddSeconds(-$CurrentTime.Second))
                            While ($TimeRangeStart.DayOfWeek -ne $RuleValue) { $TimeRangeStart = $TimeRangeStart.AddDays(1) }
                            $TimeRangeEnd = $TimeRangeStart.AddHours(23).AddMinutes(59).AddSeconds(59)
                        }
                    }

                    # Rule Type : DayOfMonth
                    { $_.RuleType -eq 'DayOfMonth' }
                    {

                        $ShutdownMode = "Shutdown/Startup"

                        $TimeRangeStart = Get-DateOrNull $RuleValue
                        If ($TimeRangeStart)
                        {
                            $RuleValid = $true
                            $TimeRangeEnd = $TimeRangeStart.AddHours(23).AddMinutes(59).AddSeconds(59)
                        }
                        Else
                        {
                            $RuleValid = $false
                            Write-Warning "Wrong rule value ($RuleValue). Flag as invalid rule ..."
                        } 
                    }

                    # Rule Type : Unknown
                    { $_.RuleType -eq 'Unknown' } { $RuleValid = $false }
                }

                # Set Shutdown period
                $ShutdownPeriod = $null
                If ($RuleValid)
                {
                    # Rule type : Time
                    If ( ($_.RuleType -eq 'Time') -and ($CurrentTime -ge $TimeRangeStart) -and ($CurrentTime -lt $TimeRangeStart.AddMinutes($PowerManager_ScheduleFrequency))) 
                    { 
                        $ShutdownPeriod = $true
                    }
                    ElseIf ($_.RuleType -ne 'Time')
                    {
                        $ShutdownPeriod = Confirm-TimeWihtinTimeRange -Time $CurrentTime -TimeRangeStart $TimeRangeStart -TimeRangeEnd $TimeRangeEnd
                    }
                    Else { $ShutdownPeriod = $false }
                }
                $ShutdownPolicyRules += [PSCustomObject]@{ResourceId = $ResourceId ; ShutdownAssignment = $ShutdownAssignment ; ShutdownMode = $ShutdownMode ; ShutdownRule = $RuleValue ; ShutdownRuleType = $_.RuleType ; ShutdownRuleValid = $RuleValid ; ShutdownStart = $TimeRangeStart ; ShutdownEnd = $TimeRangeEnd ; ShutdownPeriod = $ShutdownPeriod } 
            }

            # Rule Type "Time" (Shutdown only) conflict with another types (Shutdown/Startup)
            If ($ShutdownPolicyRules.Count -ge 2 -and $ShutdownPolicyRules.RuleType -contains 'Time')
            {
                Write-Warning "You shouldn't use Time rule type with other types like TimeRange. Please review your ShutdownPolicy to use one of these. Skipping Time for this process ..."
                $ShutdownPolicyRules = $ShutdownPolicyRules | ? { $_.RuleType -ne 'Time' }
            }

            # Option to skip invalide rules (unkown or wrong time ranges)
            If ($SkipInvalidRules) { $ShutdownPolicyRules | ? { $_.ShutdownRuleValid -eq $true } }
            Else { $ShutdownPolicyRules }
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    }

    Function Get-AzPowerPolicy
    {
        #### RGs ####

        # Get RGs with Shutdown Policy
        $rgsWithShutdownPolicy = Search-AzGraph -Query 'resourcecontainers
        | where type == "microsoft.resources/subscriptions/resourcegroups"
        | where notnull(tags.Shutdown)
        | extend shutdownPolicy=tags.Shutdown
        | project tenantId, subscriptionId, resourceGroupId=id, resourceGroupName=resourceGroup, resourceName=resourceGroup, resourceType=type, shutdownPolicy'


        # Build RG Shutdown Policy object
        $rgsPolicies = $null
        $rgsWithShutdownPolicy | % { [array]$rgsPolicies += [PSCustomObject]@{ resourceGroupId = $_.resourceGroupId  ; shutdownPolicy = $_.shutdownPolicy } }
        $rgsWithShutdownPolicy.resourceGroupId | % { [array]$rgIds += $_ }
        $rgIdsString = "'" + $($rgIds -join "','") + "'"

        #### VMs ####

        If (!($PowerManager_ExcludeVM))
        {
            ## Get VMs with RG Shutdown tag AND NO explicit tag (inherited)
            $vmsWithRgShutownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.compute/virtualmachines`" and isnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | where resourceGroupId in~ ($rgIdsString)
            | extend resourceCurrentState=strcat_array(split(properties.extended.instanceView.powerState.code,`"/`",1),`"`")
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState"

            # Append RG shutodwn policy
            $vmsWithRgShutownPolicy | % {
                $vmRgId = $_.resourceGroupId
                $ShutdownPolicy = ($rgsPolicies | ? { $_.resourceGroupId -eq $vmRgId }).shutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownPolicy -Value $ShutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownAssignment -Value "inherited"
            }

            ## Get VMs with explicit Shutdown tag (explicit)
            $vmsWithExplicitShutdownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.compute/virtualmachines`" and notnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | extend shutdownPolicy=tags.Shutdown
            | extend shutdownAssignment=`"explicit`"
            | extend resourceCurrentState=strcat_array(split(properties.extended.instanceView.powerState.code,`"/`",1),`"`")
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState, shutdownPolicy, shutdownAssignment"


            $vmsWithRgShutownPolicy
            $vmsWithExplicitShutdownPolicy

        }
        Else { Write-Warning "Virtual Machines excluded" }

    


        #### App Services ####

        If (!($PowerManager_ExcludeAppService))
        {
            ## Get App Services with RG Shutdown tag AND NO explicit tag (inherited)
            $appServiceWithRgShutdownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.web/sites`" and isnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | where resourceGroupId in~ ($rgIdsString)
            | extend resourceCurrentState=tolower(properties.state)
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState"

            # Append RG shutodwn policy
            $appServiceWithRgShutdownPolicy | % {
                $rgId = $_.resourceGroupId
                $ShutdownPolicy = ($rgsPolicies | ? { $_.resourceGroupId -eq $rgId }).shutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownPolicy -Value $ShutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownAssignment -Value "inherited"
            }

            ## Get App Services with explicit Shutdown tag (explicit)
            $appServiceWithExplicitShutdownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.web/sites`" and notnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | extend shutdownPolicy=tags.Shutdown
            | extend shutdownAssignment=`"explicit`"
            | extend resourceCurrentState=tolower(properties.state)
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState, shutdownPolicy, shutdownAssignment"


            $appServiceWithRgShutdownPolicy
            $appServiceWithExplicitShutdownPolicy
        }
        Else { Write-Warning "App Services excluded" }


        #### Azure Kubernetes Service ####

        If (!($PowerManager_ExcludeAKS))
        {
            ## Get Azure Kubernetes Service with RG Shutdown tag AND NO explicit tag (inherited)
            $aksWithRgShutdownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.containerservice/managedclusters`" and isnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | where resourceGroupId in~ ($rgIdsString)
            | extend resourceCurrentState=tolower(properties.powerState.code)
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState"

            # Append RG shutodwn policy
            $aksWithRgShutdownPolicy | % {
                $rgId = $_.resourceGroupId
                $ShutdownPolicy = ($rgsPolicies | ? { $_.resourceGroupId -eq $rgId }).shutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownPolicy -Value $ShutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownAssignment -Value "inherited"
            }

            ## Get Azure Kubernetes Service with explicit Shutdown tag (explicit)
            $aksWithExplicitShutdownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.containerservice/managedclusters`" and notnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | extend shutdownPolicy=tags.Shutdown
            | extend shutdownAssignment=`"explicit`"
            | extend resourceCurrentState=tolower(properties.powerState.code)
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState, shutdownPolicy, shutdownAssignment"


            $aksWithRgShutdownPolicy
            $aksWithExplicitShutdownPolicy
        }
        Else { Write-Warning "Azure Kubernetes Service excluded" }


        #### ADXs ####

        If (!($PowerManager_ExcludeADX))
        {
            ## Get ADXs with RG Shutdown tag AND NO explicit tag (inherited)
            $adxsWithRgShutownPolicy = Search-AzGraph -Query "resources
            | where type == `"microsoft.kusto/clusters`" and isnull(tags.Shutdown)
            | extend resourceGroupId=strcat(`"/subscriptions/`",subscriptionId,`"/resourceGroups/`",resourceGroup)
            | where resourceGroupId in~ ($rgIdsString)
            | extend resourceCurrentState=tolower(properties.state)
            | project tenantId, subscriptionId, resourceGroupId, resourceGroupName=resourceGroup, resourceId=id, resourceName=name, resourceType=type, resourceCurrentState"

            # Append RG shutodwn policy
            $adxsWithRgShutownPolicy | % {
                $rgId = $_.resourceGroupId
                $ShutdownPolicy = ($rgsPolicies | ? { $_.resourceGroupId -eq $rgId }).shutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownPolicy -Value $ShutdownPolicy
                $_ | Add-Member -MemberType NoteProperty -Name shutdownAssignment -Value "inherited"
            }

            $adxsWithRgShutownPolicy
        }
        Else { Write-Warning "Azure Data Explorer excluded" }
    }

    Function Get-AzPowerPolicyRules
    { 
        [CmdletBinding()]
        param ([Parameter(Mandatory = $true)] [object]$ShutdownPolicy, [datetime]$CurrentTime = $(Get-Date))

        Try
        {
            $ShutdownPolicy | % { Expand-AzPowerPolicy -ResourceId $_.resourceId -ShutdownPolicy $_.shutdownPolicy -ShutdownAssignment $_.shutdownAssignment -SkipInvalidRules -CurrentTime $CurrentTime } 
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    }

    Function Assert-AzPowerComputeStates
    {
        [CmdletBinding()]
        param ([Parameter(Mandatory = $true)] [object]$ShutdownPolicy, [datetime]$CurrentTime = $(Get-Date))

        Try
        {
            # Get shutdown policy rules
            $ShutdownPolicyRules = Get-AzPowerPolicyRules -ShutdownPolicy $ShutdownPolicy -CurrentTime $CurrentTime 

            # Add porperties foreeach itereation of the current object
            $ShutdownPolicy | % {

                $resourceId = $_.resourceId
                $resourcecurrentState = $_.resourceCurrentState
    
                $resourcePolicyRules = $null
                $resourcePolicyRules = $ShutdownPolicyRules | ? { $_.ResourceId -eq $resourceId }
                If ($resourcePolicyRules)
                {
                    # Manage deallocated state for VM Vs. stopped for other compute resources
                    $ResourceType = $ResourceId.Split('/')[6] + '/' + $ResourceId.Split('/')[7]
                    If ($ResourceType -eq 'Microsoft.Compute/virtualMachines')
                    {
                        If ($resourcePolicyRules.ShutdownPeriod -contains $True) { $desiredState = "deallocated" }
                        Else { If ($resourcePolicyRules.ShutdownRuleType -eq 'Time') { $desiredState = $null } Else { $desiredState = 'running' } }
                    } 
                    Else
                    {
                        If ($resourcePolicyRules.ShutdownPeriod -contains $True) { $desiredState = "stopped" }
                        Else { If ($resourcePolicyRules.ShutdownRuleType -eq 'Time') { $desiredState = $null } Else { $desiredState = 'running' } }
                    }

                    # Start
                    If (($resourcecurrentState -ne 'running') -and ($desiredState -eq 'running'))
                    { $powerManagerAction = 'start' }
                    # Deallocate
                    ElseIf (($resourcecurrentState -eq 'running') -and ($desiredState -eq 'deallocated'))
                    { $powerManagerAction = 'deallocate' }
                    # Stop
                    ElseIf (($resourcecurrentState -eq 'running') -and ($desiredState -eq 'stopped'))
                    { $powerManagerAction = 'stop' }
                    # Do nothing
                    Else { $powerManagerAction = 'none' }

                    $_ | Add-Member -MemberType NoteProperty -Name resourceDesiredState -Value $desiredState
                    $_ | Add-Member -MemberType NoteProperty -Name powerManagerSimulationMode -Value $SimulationMode
                    $_ | Add-Member -MemberType NoteProperty -Name powerManagerAction -Value $powerManagerAction
                }
            }
            $ShutdownPolicy | ? { Get-Member -InputObject $_ -Name "resourceDesiredState" -Membertype NoteProperty }
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    }

    Function Send-AzPowerComputeAction
    {
        [CmdletBinding()]
        Param 
        (
            [Parameter(Mandatory = $true)] 
            [String] $ResourceId,
            [Parameter(Mandatory = $true)] 
            [String] $Action,
            [Switch] $Simulation,
            [String] $BearerToken = (Get-AzAccessToken).Token
        )
    
        Try    
        {
            $headers = @{"authorization" = "bearer $bearerToken" }
            $baseUri = 'https://management.azure.com'
            $ResourceType = $ResourceId.Split('/')[6] + '/' + $ResourceId.Split('/')[7]
            $ResourceTypeValid = $true
            $ResourceName = Split-Path $ResourceId -Leaf

            Switch ($ResourceType)
            {
                'Microsoft.Compute/virtualMachines' { $uri = "$baseUri$ResourceId/$($Action)?api-version=2020-12-01" }
                'Microsoft.Kusto/clusters' { $uri = "$baseUri$ResourceId/$($Action)?api-version=2020-09-18" }
                'Microsoft.Web/sites' { $uri = "$baseUri$ResourceId/$($Action)?api-version=2019-08-01" }
                'Microsoft.ContainerService/managedClusters' { $uri = "$baseUri$ResourceId/$($Action)?api-version=2020-11-01" }
                default { $ResourceTypeValid = $false }
            }

            If ($ResourceTypeValid)
            {
                Write-Verbose "Resource type <$ResourceType> for <$ResourceName> is valid !"
                Write-Verbose "$($SimulationHeader)Sending action <$Action> to the compute resource <$ResourceId> ..."
                If (!($Simulation))
                {
                    $request = iwr -Uri $uri -Method POST -Headers $headers -UseBasicParsing
                    If ($request.StatusCode -eq 202 -or 200) { Write-Verbose "Action sent successfully!" } 
                    Else { Write-Warning "Action NOT sent successfully!"; $request }
                }
            }
            Else { Write-Warning "Resource type $ResourceType for <$ResourceName> is invalid !" }
        
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    }

    Function Get-AzPowerComputeState
    {
        [CmdletBinding()]
        Param 
        (
            [Parameter(Mandatory = $true)] 
            [String] $ResourceId,
            [String] $BearerToken = (Get-AzAccessToken).Token
        )
    
        Try    
        {
            $headers = @{"authorization" = "bearer $bearerToken" }
            $baseUri = 'https://management.azure.com'
            $ResourceType = $ResourceId.Split('/')[6] + '/' + $ResourceId.Split('/')[7]
            $ResourceTypeValid = $true
            $ResourceName = Split-Path $ResourceId -Leaf

            Switch ($ResourceType)
            {
                'Microsoft.Kusto/clusters' { $uri = "$baseUri$ResourceId`?api-version=2020-09-18" }
                'Microsoft.ContainerService/managedClusters' { $uri = "$baseUri$ResourceId`?api-version=2020-11-01" }
                default { $ResourceTypeValid = $false }
            }

            If ($ResourceTypeValid)
            {
                Write-Verbose "Resource type <$ResourceType> for <$ResourceName> is valid !"
                Write-Verbose "Getting state for the compute resource <$ResourceId> ..."
                $request = iwr -Uri $uri -Method GET -Headers $headers -UseBasicParsing
                If ($request.StatusCode -eq 202 -or 200) 
                {
                    Switch ($ResourceType)
                    {
                        'Microsoft.Kusto/clusters' { ($request.Content | ConvertFrom-Json).properties.state.ToLower() }
                        'Microsoft.ContainerService/managedClusters' { ($request.Content | ConvertFrom-Json).properties.powerState.code.ToLower() }
                    }
                } 
                Else { Write-Error $request }
            }
            Else { Write-Warning "Resource type $ResourceType for <$ResourceName> is invalid !" }
        
        }
        Catch { Write-Output "[ERROR] $($_)`n[ERROR] [$($_.InvocationInfo.ScriptLineNumber)] $($_.InvocationInfo.ScriptName) >> $($_.InvocationInfo.Line.TrimStart())" }
    }
} 
Else { Remove-Module PSRequiredModules ; throw "Some required modules versions aren't imported/installed. Can't load this module. See PSRequiredModules in module manifest for more details." }