Private/New-TemplateResolver.ps1

function New-TemplateResolver
{
    <#
    .SYNOPSIS
        Resolve template location from path/url given on command lines

    .DESCRIPTION
        Returns an object that has methods for retrieving the template body
        and the size of the template file such that it can be checked for size limitations

    .PARAMETER TemplateLocation
        Location of the template. May be either
        - Path to local file
        - S3 URI (which is converted to HTTPS URI for the current region)
          Note that this only works if a default region is set in the shell and
          you don't try to point to a different region with -Region
        - HTTP(S) Uri

    .PARAMETER StackName
        Used if -UsePreviousTemplate is true

    .PARAMETER CredentialArguments
        Credential arguments passed to public function.

    .PARAMETER UsePreviousTemplate
        Setting of -UsePreviousTemplate if updating; else $false

    .OUTPUTS
        Custom Object.
    #>


    param
    (
        [string]$TemplateLocation,
        [bool]$UsePreviousTemplate = $false,
        [string]$StackName,
        [hashtable]$CredentialArguments
    )

    $resolver = New-Object PSObject -Property @{

        Type                = $null
        BucketName          = $null
        Key                 = $null
        Path                = $null
        Url                 = $null
        StackName           = $null
        UsePreviousTemplate = $UsePreviousTemplate
    } |
        Add-Member -PassThru -Name ReadTemplate -MemberType ScriptMethod -Value {

        # Reads the template contents from either S3, previous tempalte or file system as approriate.
        if ($this.StackName -and $this.UsePreviousTemplate)
        {
            Get-CFNTemplate -StackName $this.StackName
        }
        elseif ($this.Path)
        {
            Get-Content -Raw -Path $this.Path
        }
        elseif ($this.BucketName -and $this.Key)
        {
            $tmpFile = "$([Guid]::NewGuid().ToString()).tmp"

            try
            {
                Read-S3Object -BucketName $this.BucketName -Key $this.Key -File $tmpFile | Out-Null
                Get-Content -Raw -Path $tmpFile
            }
            finally
            {
                Remove-Item -Path $tmpFile
            }
        }
        else
        {
            throw "Template location undefined"
        }
    } |
        Add-Member -PassThru -Name Length -MemberType ScriptMethod -Value {

        # Gets the file szie of the template
        if ($this.StackName)
        {
            # Template is always of acceptable size.
            0
        }
        elseif ($this.Path)
        {
            (Get-ItemProperty -Name Length -Path $this.Path).Length
        }
        elseif ($this.BucketName -and $this.Key)
        {
            (Get-S3Object -BucketName $this.BucketName -Key $this.Key).Size
        }
        else
        {
            throw "Template location undefined"
        }
    }

    $u = $null

    if ($StackName -and $UsePreviousTemplate)
    {
        # UsePreviousTemplate
        $resolver.StackName = $StackName
        $resolver.Type = 'UsePreviousTemplate'
    }
    elseif ([Uri]::TryCreate($TemplateLocation, 'Absolute', [ref]$u))
    {
        switch ($u.Scheme)
        {
            's3'
            {

                $r = Get-CurrentRegion -CredentialArguments $CredentialArguments

                # Convert to full URL
                if (-not $r)
                {
                    throw "Cannot determine region. Please use Initialize-AWSDefaults or Set-DefaultAWSRegion"
                }

                $resolver.Url = [Uri]("https://s3-{0}.amazonaws.com/{1}{2}" -f $r, $u.Authority, $u.LocalPath)
                $resolver.BucketName = $u.Authority
                $resolver.Key = $u.LocalPath.TrimStart('/')
                $resolver.Type = 'Url'
            }

            'file'
            {

                $resolver.Path = $TemplateLocation
                $resolver.Type = 'File'
            }

            { $_ -ieq 'http' -or $_ -ieq 'https' }
            {

                $resolver.Url = $u
                $resolver.BucketName = $u.Segments[1].Trim('/');
                $resolver.Key = $u.Segments[2..($u.Segments.Length - 1)] -join ''
                $resolver.Type = 'Url'
            }

            default
            {

                throw "Unsupported URI: $($u.ToString())"
            }
        }
    }
    else
    {
        $resolver.Path = $TemplateLocation
        $resolver.Type = 'File'
    }

    $resolver
}