CWJAzureRegionIPRange.psm1

function Get-CWJAzureRegionIPRange
{
    [cmdletbinding(DefaultParameterSetName='All')]
    param(
        [Parameter(ParameterSetName='All',        Mandatory=$false)]
        [switch]
        $All,
        
        [Parameter(ParameterSetName='RegionName', Mandatory=$true, Position=1)]
        [ValidateNotNullOrEmpty()]
        [CWJ.Azure.RegionName]
        $RegionName
    )
    
    $AzureRegionIPRanges = Get-Variable -Name "$($ModuleSpecificGuid)-AzureRegionIPRangeCache" -ValueOnly
    
    if($PSCmdlet.ParameterSetName -eq 'All')
    {
        $AzureRegionIPRanges
    }
    else #if($PSCmdlet.ParameterSetName -eq 'RegionName')
    {
        $AzureRegionIPRanges.Where({$_.RegionName -eq $RegionName})
    }
}

function Update-CWJAzureRegionIPRangeCache
{
    $xmlRegions      = (Get-CWJAzureRegionIPRangeFile -Object       ).AzurePublicIpAddresses.Region
    $xmlRegionsChina = (Get-CWJAzureRegionIPRangeFile -Object -China).AzurePublicIpAddresses.Region

    $xmlRegions = $xmlRegions + $xmlRegionsChina

    [System.Collections.ArrayList]$AzureRegionIPRanges = @()

    foreach($xmlRegion in $xmlRegions)
    {
        $RegionName = $xmlRegion.Name

        $IpRanges = $xmlRegion.IpRange

        foreach($IpRange in $IpRanges)
        {
            $CIDR = $IpRange.Subnet

            $AzureRegionIPRange = [PSCustomObject]@{
                RegionName     = $RegionName
                CIDR           = $CIDR
                NetworkID      = $CIDR.Split('/')[0]
                NetMaskLength  = $CIDR.Split('/')[1]
                TotalAddresses = ([System.Net.IPNetwork]$CIDR).Total
            }

            [void]$AzureRegionIPRanges.Add($AzureRegionIPRange)
        }
    }

    Set-Variable -Name "$($ModuleSpecificGuid)-AzureRegionIPRangeCache" -Value $AzureRegionIPRanges -Scope Global -Force
}

function Get-CWJAzureRegionIPRangeFile
{
    [cmdletbinding(DefaultParameterSetName='OutputDir')]
    param(
        [Parameter(ParameterSetName='OutputDir',  Mandatory=$false, Position=0)]
        #[ValidateNotNullOrEmpty()]
        [string]
        $OutputDir = (Get-Location -PSProvider FileSystem).Path,
        
        [Parameter(ParameterSetName='Object',     Mandatory=$true)]
        [switch]
        $Object,

        [Parameter(ParameterSetName='Uri',        Mandatory=$true)]
        [switch]
        $Uri,

        [Parameter(ParameterSetName='Object',     Mandatory=$false)]
        [Parameter(ParameterSetName='Uri',        Mandatory=$false)]
        [Parameter(ParameterSetName='OutputDir',  Mandatory=$false)]
        [switch]
        $China,

        [Parameter(ParameterSetName='OutputDir',  Mandatory=$false)]
        [switch]
        $Force
    )

    if($China)
    {
        
        $downloadPageUri = 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=42064'
    }
    else
    {
        $downloadPageUri = 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=41653'
    }
    
    [uri]$xmlUri = (Invoke-WebRequest -Uri $downloadPageUri -UseBasicParsing).Links | ? class -eq 'mscom-link failoverLink' | % href

    if($PSCmdlet.ParameterSetName -eq 'OutputDir')
    {
        $xmlFileName = 'Azure_' + $xmlUri.Segments[-1]
        
        $OutputPath = Join-Path -Path $OutputDir -ChildPath $xmlFileName
        
        $OutputPathExists = Test-Path -Path $OutputPath

        if( ($OutputPathExists -and $Force) -or -not $OutputPathExists )
        {
            Invoke-WebRequest -Uri $xmlUri -UseBasicParsing -OutFile $OutputPath
        }
        else
        {
            throw "'$OutputPath' exists, use -Force to overwrite."
        }
    }
    elseif($PSCmdlet.ParameterSetName -eq 'Object')
    {
        return [xml](Invoke-WebRequest -Uri $xmlUri -UseBasicParsing).toString()
    }
    else #if($PSCmdlet.ParameterSetName -eq 'Uri')
    {
        return $xmlUri
    }
}

# GUID for use for module-specific data: c283f8ef-df75-4b52-ad12-b8a17299ee47
$ModuleSpecificGuid = 'c283f8ef-df75-4b52-ad12-b8a17299ee47'

Update-CWJAzureRegionIPRangeCache




#try{ [void][System.Threading.AbandonedMutexException] }catch
#{
    $AzureRegionIPRange = Get-Variable -Name "$($ModuleSpecificGuid)-AzureRegionIPRangeCache" -ValueOnly

    $global:RegionNames = $AzureRegionIPRange.RegionName | Sort-Object -Unique
    #TODO: Does this need to be global? Can I remove it when done?

    $TypeDefinition = "namespace CWJ.Azure`n{`n public enum RegionName`n {`n"
    $RegionNames | % { $TypeDefinition += " $_,`n" }
    $TypeDefinition += " }`n}"
    Add-Type -TypeDefinition $TypeDefinition
#}

#Export-ModuleMember -Cmdlet Get-CWJAzureRegionIPRange