PsModDev.psm1

#Region './prefix.ps1' 0
<#
.EXTERNALHELP PsModDev-help.xml
#>


$script:moduleRoot = Split-Path `
    -Path $MyInvocation.MyCommand.Path `
    -Parent

# Import dependent Az modules
#Import-Module -Name Az.Accounts -MinimumVersion 1.0.0 -Scope Global
#Import-Module -Name Az.Resources -MinimumVersion 1.0.0 -Scope Global

#region LocalizedData
$culture = $PSUICulture

if ([System.String]::IsNullOrEmpty($culture))
{
    $culture = 'en-US'
}
else
{
    if (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath $culture)))
    {
        $culture = 'en-US'
    }
}

Import-LocalizedData `
    -BindingVariable LocalizedData `
    -Filename 'PsModDev.strings.psd1' `
    -BaseDirectory $script:moduleRoot `
    -UICulture $culture
#endregion

#region Types
if (-not ([System.Management.Automation.PSTypeName]'PsModDev.Context').Type)
{
    <#
        Attempt to load the classes from within the PsModDev.dll in the
        same folder as the module. If the file doesn't exist then load
        them from the PsModDev.cs file.

        Loading the classes from the PsModDev.cs file requires compilation
        which currently fails in PowerShell on Azure Functions 2.0.

        See https://github.com/Azure/azure-functions-powershell-worker/issues/220
    #>

    $classDllPath = Join-Path -Path $script:moduleRoot -ChildPath 'PsModDev.dll'

    if (Test-Path -Path $classDllPath)
    {
        Write-Verbose -Message $($LocalizedData.LoadingTypesFromDll -f $classDllPath)
        Add-Type -Path $classDllPath
    }
    else
    {
        $typeDefinitionPath = Join-Path -Path $script:moduleRoot -ChildPath 'classes\PsModDev\PsModDev.cs'
        Write-Verbose -Message $($LocalizedData.LoadingTypesFromCS -f $typeDefinitionPath)
        $typeDefinition = Get-Content -Path $typeDefinitionPath -Raw
        Add-Type -TypeDefinition $typeDefinition
    }
}

<#
    This type is available in PowerShell Core, but it is not available in
    Windows PowerShell. It is needed to check the exception type within the
    Invoke-PsModDevRequest function.
#>

if (-not ([System.Management.Automation.PSTypeName]'Microsoft.PowerShell.Commands.HttpResponseException').Type)
{
    $httpResponseExceptionClassDefinition = @'
namespace Microsoft.PowerShell.Commands
{
    public class HttpResponseException : System.Net.WebException
    {
        public System.Int32 dummy;
    }
}
'@


    Add-Type -TypeDefinition $httpResponseExceptionClassDefinition
}
#endregion
#EndRegion './prefix.ps1' 84
#Region './Public/collections/Get-CosmosDbCollection.ps1' 0
function Get-PsModDevCollection
{

    [CmdletBinding(DefaultParameterSetName = 'Context')]
    [OutputType([Object])]
    param
    (
        [Alias('Connection')]
        [Parameter(Mandatory = $true, ParameterSetName = 'Context')]
        [ValidateNotNullOrEmpty()]
        [PsModDev.Context]
        $Context,

        [Parameter(Mandatory = $true, ParameterSetName = 'Account')]
        [ValidateScript({ Assert-PsModDevAccountNameValid -Name $_ -ArgumentName 'Account' })]
        [System.String]
        $Account,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Security.SecureString]
        $Key,

        [Parameter()]
        [ValidateSet('master', 'resource')]
        [System.String]
        $KeyType = 'master',

        [Parameter()]
        [ValidateScript({ Assert-PsModDevDatabaseIdValid -Id $_ -ArgumentName 'Database' })]
        [System.String]
        $Database,

        [Alias('Name')]
        [Parameter()]
        [ValidateScript({ Assert-PsModDevCollectionIdValid -Id $_ })]
        [System.String]
        $Id,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Int32]
        $MaxItemCount = -1,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $ContinuationToken,

        [Alias("ResultHeaders")]
        [Parameter()]
        [ref]
        $ResponseHeader
    )

    $null = $PSBoundParameters.Remove('MaxItemCount')
    $null = $PSBoundParameters.Remove('ContinuationToken')

    if ($PSBoundParameters.ContainsKey('ResponseHeader'))
    {
        $ResponseHeaderPassed = $true
        $null = $PSBoundParameters.Remove('ResponseHeader')
    }

    if ($PSBoundParameters.ContainsKey('Id'))
    {
        $null = $PSBoundParameters.Remove('Id')

        $result = Invoke-PsModDevRequest @PSBoundParameters `
            -Method 'Get' `
            -ResourceType 'colls' `
            -ResourcePath ('colls/{0}' -f $Id)

        $collection = ConvertFrom-Json -InputObject $result.Content
    }
    else
    {
        $headers = @{
            'x-ms-max-item-count' = $MaxItemCount
        }

        if (-not [System.String]::IsNullOrEmpty($ContinuationToken))
        {
            $headers += @{
                'x-ms-continuation' = $ContinuationToken
            }
        }

        $result = Invoke-PsModDevRequest @PSBoundParameters `
            -Method 'Get' `
            -ResourceType 'colls' `
            -Headers $headers

        $body = ConvertFrom-Json -InputObject $result.Content
        $collection = $body.DocumentCollections
    }


    if ($ResponseHeaderPassed)
    {
        # Return the result headers
        $ResponseHeader.value = $result.Headers
    }

    if ($collection)
    {
        return (Set-PsModDevCollectionType -Collection $collection)
    }
}
#EndRegion './Public/collections/Get-CosmosDbCollection.ps1' 110
#Region './Public/collections/New-CosmosDbCollection.ps1' 0
function New-PsModDevCollection
{

    [CmdletBinding(DefaultParameterSetName = 'ContextIndexPolicy')]
    [OutputType([Object])]
    param
    (
        [Alias('Connection')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ContextIndexPolicy')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ContextIndexPolicyJson')]
        [ValidateNotNullOrEmpty()]
        [PsModDev.Context]
        $Context,

        [Parameter(Mandatory = $true, ParameterSetName = 'AccountIndexPolicy')]
        [Parameter(Mandatory = $true, ParameterSetName = 'AccountIndexPolicyJson')]
        [ValidateScript( { Assert-PsModDevAccountNameValid -Name $_ -ArgumentName 'Account' })]
        [System.String]
        $Account,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Security.SecureString]
        $Key,

        [Parameter()]
        [ValidateSet('master', 'resource')]
        [System.String]
        $KeyType = 'master',

        [Parameter()]
        [ValidateScript( { Assert-PsModDevDatabaseIdValid -Id $_ -ArgumentName 'Database' })]
        [System.String]
        $Database,

        [Alias('Name')]
        [Parameter(Mandatory = $true)]
        [ValidateScript( { Assert-PsModDevCollectionIdValid -Id $_ })]
        [System.String]
        $Id,

        [Parameter()]
        [ValidateRange(400, 250000)]
        [System.Int32]
        $OfferThroughput,

        [Parameter()]
        [ValidateSet('S1', 'S2', 'S3')]
        [System.String]
        $OfferType,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $PartitionKey,

        [Parameter(ParameterSetName = 'ContextIndexPolicy')]
        [Parameter(ParameterSetName = 'AccountIndexPolicy')]
        [ValidateNotNullOrEmpty()]
        [PsModDev.IndexingPolicy.Policy]
        $IndexingPolicy,

        [Parameter(ParameterSetName = 'ContextIndexPolicyJson')]
        [Parameter(ParameterSetName = 'AccountIndexPolicyJson')]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $IndexingPolicyJson,

        [Parameter()]
        [ValidateRange(-1, 2147483647)]
        [System.Int32]
        $DefaultTimeToLive,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [PsModDev.UniqueKeyPolicy.Policy]
        $UniqueKeyPolicy,

        [Alias('AutopilotThroughput')]
        [ValidateRange(4000, 1000000)]
        [System.Int32]
        $AutoscaleThroughput
    )

    $headers = @{ }

    if (($PSBoundParameters.ContainsKey('OfferThroughput') -and $PSBoundParameters.ContainsKey('OfferType')) -or `
        ($PSBoundParameters.ContainsKey('OfferThroughput') -and $PSBoundParameters.ContainsKey('AutoscaleThroughput')) -or `
        ($PSBoundParameters.ContainsKey('OfferType') -and $PSBoundParameters.ContainsKey('AutoscaleThroughput')))
    {
        New-PsModDevInvalidOperationException -Message $($LocalizedData.ErrorNewCollectionOfferParameterConflict)
    }

    if ($PSBoundParameters.ContainsKey('OfferThroughput'))
    {
        if ($OfferThroughput -gt 10000 -and -not ($PSBoundParameters.ContainsKey('PartitionKey')))
        {
            New-PsModDevInvalidOperationException -Message $($LocalizedData.ErrorNewCollectionParitionKeyOfferRequired)
        }

        $headers += @{
            'x-ms-offer-throughput' = $OfferThroughput
        }
        $null = $PSBoundParameters.Remove('OfferThroughput')
    }

    if ($PSBoundParameters.ContainsKey('OfferType'))
    {
        Write-Warning -Message $LocalizedData.WarningNewCollectionOfferTypeDeprecated
        $headers += @{
            'x-ms-offer-type' = $OfferType
        }
        $null = $PSBoundParameters.Remove('OfferType')
    }

    if ($PSBoundParameters.ContainsKey('AutoscaleThroughput'))
    {
        if (-not ($PSBoundParameters.ContainsKey('PartitionKey')))
        {
            New-PsModDevInvalidOperationException -Message $($LocalizedData.ErrorNewCollectionParitionKeyAutoscaleRequired)
        }

        $headers += @{
            'x-ms-cosmos-offer-autopilot-settings' = ConvertTo-Json -InputObject @{
                maxThroughput = $AutoscaleThroughput
            } -Compress
        }
        $null = $PSBoundParameters.Remove('AutoscaleThroughput')
    }

    $null = $PSBoundParameters.Remove('Id')

    $bodyObject = @{
        id = $id
    }

    if ($PSBoundParameters.ContainsKey('PartitionKey'))
    {
        $bodyObject += @{
            partitionKey = @{
                paths = @('/{0}' -f $PartitionKey.TrimStart('/'))
                kind  = 'Hash'
            }
        }
        $null = $PSBoundParameters.Remove('PartitionKey')
    }
    else
    {
        Write-Warning -Message $($LocalizedData.NonPartitionedCollectionWarning)
    }

    if ($PSBoundParameters.ContainsKey('IndexingPolicy'))
    {
        $bodyObject += @{
            indexingPolicy = $IndexingPolicy
        }
        $null = $PSBoundParameters.Remove('IndexingPolicy')
    }
    elseif ($PSBoundParameters.ContainsKey('IndexingPolicyJson'))
    {
        $bodyObject += @{
            indexingPolicy = ConvertFrom-Json -InputObject $IndexingPolicyJson
        }
        $null = $PSBoundParameters.Remove('IndexingPolicyJson')
    }

    if ($PSBoundParameters.ContainsKey('DefaultTimeToLive'))
    {
        $bodyObject += @{
            defaultTtl = $DefaultTimeToLive
        }
        $null = $PSBoundParameters.Remove('DefaultTimeToLive')
    }

    if ($PSBoundParameters.ContainsKey('UniqueKeyPolicy'))
    {
        $bodyObject += @{
            uniqueKeyPolicy = $UniqueKeyPolicy
        }
        $null = $PSBoundParameters.Remove('UniqueKeyPolicy')
    }

    $body = ConvertTo-Json -InputObject $bodyObject -Depth 20

    $result = Invoke-PsModDevRequest @PSBoundParameters `
        -Method 'Post' `
        -ResourceType 'colls' `
        -Headers $headers `
        -Body $body

    $collection = ConvertFrom-Json -InputObject $result.Content

    if ($collection)
    {
        return (Set-PsModDevCollectionType -Collection $collection)
    }
}
#EndRegion './Public/collections/New-CosmosDbCollection.ps1' 198
#Region './Public/collections/Remove-CosmosDbCollection.ps1' 0
function Remove-PsModDevCollection
{

    [CmdletBinding(DefaultParameterSetName = 'Context')]
    param
    (
        [Alias('Connection')]
        [Parameter(Mandatory = $true, ParameterSetName = 'Context')]
        [ValidateNotNullOrEmpty()]
        [PsModDev.Context]
        $Context,

        [Parameter(Mandatory = $true, ParameterSetName = 'Account')]
        [ValidateScript({ Assert-PsModDevAccountNameValid -Name $_ -ArgumentName 'Account' })]
        [System.String]
        $Account,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Security.SecureString]
        $Key,

        [Parameter()]
        [ValidateSet('master', 'resource')]
        [System.String]
        $KeyType = 'master',

        [Parameter()]
        [ValidateScript({ Assert-PsModDevDatabaseIdValid -Id $_ -ArgumentName 'Database' })]
        [System.String]
        $Database,

        [Alias('Name')]
        [Parameter(Mandatory = $true)]
        [ValidateScript({ Assert-PsModDevCollectionIdValid -Id $_ })]
        [System.String]
        $Id
    )

    $null = $PSBoundParameters.Remove('Id')

    $null = Invoke-PsModDevRequest @PSBoundParameters `
        -Method 'Delete' `
        -ResourceType 'colls' `
        -ResourcePath ('colls/{0}' -f $Id)
}
#EndRegion './Public/collections/Remove-CosmosDbCollection.ps1' 47
#Region './Public/collections/Set-CosmosDbCollection.ps1' 0
function Set-PsModDevCollection
{

    [CmdletBinding(DefaultParameterSetName = 'ContextIndexPolicy')]
    [OutputType([Object])]
    param
    (
        [Alias('Connection')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ContextIndexPolicy')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ContextIndexPolicyJson')]
        [ValidateNotNullOrEmpty()]
        [PsModDev.Context]
        $Context,

        [Parameter(Mandatory = $true, ParameterSetName = 'AccountIndexPolicy')]
        [Parameter(Mandatory = $true, ParameterSetName = 'AccountIndexPolicyJson')]
        [ValidateScript({ Assert-PsModDevAccountNameValid -Name $_ -ArgumentName 'Account' })]
        [System.String]
        $Account,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Security.SecureString]
        $Key,

        [Parameter()]
        [ValidateSet('master', 'resource')]
        [System.String]
        $KeyType = 'master',

        [Parameter()]
        [ValidateScript({ Assert-PsModDevDatabaseIdValid -Id $_ -ArgumentName 'Database' })]
        [System.String]
        $Database,

        [Alias('Name')]
        [Parameter(Mandatory = $true)]
        [ValidateScript({ Assert-PsModDevCollectionIdValid -Id $_ })]
        [System.String]
        $Id,

        [Parameter(ParameterSetName = 'ContextIndexPolicy')]
        [Parameter(ParameterSetName = 'AccountIndexPolicy')]
        [ValidateNotNullOrEmpty()]
        [PsModDev.IndexingPolicy.Policy]
        $IndexingPolicy,

        [Parameter(ParameterSetName = 'ContextIndexPolicyJson')]
        [Parameter(ParameterSetName = 'AccountIndexPolicyJson')]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $IndexingPolicyJson,

        [Parameter()]
        [ValidateRange(-1,2147483647)]
        [System.Int32]
        $DefaultTimeToLive,

        [Parameter()]
        [Switch]
        $RemoveDefaultTimeToLive,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [PsModDev.UniqueKeyPolicy.Policy]
        $UniqueKeyPolicy
    )

    if ($PSBoundParameters.ContainsKey('DefaultTimeToLive') -and $RemoveDefaultTimeToLive.IsPresent)
    {
        New-PsModDevInvalidArgumentException `
            -Message $LocalizedData.ErrorSetCollectionRemoveDefaultTimeToLiveConflict `
            -ArgumentName 'RemoveDefaultTimeToLive'
    }

    $headers = @{}

    $bodyObject = @{
        id = $id
    }

    $indexingPolicyIncluded = $false

    if ($PSBoundParameters.ContainsKey('IndexingPolicy'))
    {
        $ActualIndexingPolicy = $IndexingPolicy
        $indexingPolicyIncluded = $true
        $null = $PSBoundParameters.Remove('IndexingPolicy')
    }
    elseif ($PSBoundParameters.ContainsKey('IndexingPolicyJson'))
    {
        $ActualIndexingPolicy = ConvertFrom-Json -InputObject $IndexingPolicyJson
        $indexingPolicyIncluded = $true
        $null = $PSBoundParameters.Remove('IndexingPolicyJson')
    }

    $defaultTimeToLiveIncluded = $PSBoundParameters.ContainsKey('DefaultTimeToLive')
    $uniqueKeyPolicyIncluded = $PSBoundParameters.ContainsKey('UniqueKeyPolicy')

    $null = $PSBoundParameters.Remove('IndexingPolicy')
    $null = $PSBoundParameters.Remove('DefaultTimeToLive')
    $null = $PSBoundParameters.Remove('RemoveDefaultTimeToLive')
    $null = $PSBoundParameters.Remove('UniqueKeyPolicy')

    <#
        The partition key on an existing collection can not be changed.
        So to ensure an error does not occur, get the current collection
        and pass the existing partition key in the body.
    #>

    $existingCollection = Get-PsModDevCollection @PSBoundParameters

    $null = $PSBoundParameters.Remove('Id')

    if ($indexingPolicyIncluded)
    {
        $bodyObject += @{
            indexingPolicy = $ActualIndexingPolicy
        }
    }
    else
    {
        $bodyObject += @{
            indexingPolicy = $existingCollection.indexingPolicy
        }
    }

    if ($existingCollection.partitionKey)
    {
        $bodyObject += @{
            partitionKey = $existingCollection.partitionKey
        }
    }

    if ($defaultTimeToLiveIncluded)
    {
        $bodyObject += @{
            defaultTtl = $DefaultTimeToLive
        }
    }
    elseif ($existingCollection.defaultTtl -and -not $RemoveDefaultTimeToLive)
    {
        $bodyObject += @{
            defaultTtl = $existingCollection.defaultTtl
        }
    }

    if ($uniqueKeyPolicyIncluded)
    {
        $bodyObject += @{
            uniqueKeyPolicy = $UniqueKeyPolicy
        }
    }
    elseif ($existingCollection.uniqueKeyPolicy)
    {
        $bodyObject += @{
            uniqueKeyPolicy = $existingCollection.uniqueKeyPolicy
        }
    }

    $body = ConvertTo-Json -InputObject $bodyObject -Depth 10

    $result = Invoke-PsModDevRequest @PSBoundParameters `
        -Method 'Put' `
        -ResourceType 'colls' `
        -ResourcePath ('colls/{0}' -f $Id) `
        -Headers $headers `
        -Body $body

    $collection = ConvertFrom-Json -InputObject $result.Content

    if ($collection)
    {
        return (Set-PsModDevCollectionType -Collection $collection)
    }
}
#EndRegion './Public/collections/Set-CosmosDbCollection.ps1' 176
#Region './suffix.ps1' 0
# Add Aliases
#New-Alias -Name 'New-PsModDevConnection' -Value 'New-PsModDevContext' -Force
#EndRegion './suffix.ps1' 3