CosmosDB.psm1
<#
.EXTERNALHELP CosmosDB-help.xml #> #Requires -Version 5.1 #Requires -Modules @{ ModuleName = 'Az.Accounts'; ModuleVersion = '1.0.0'; Guid = '17a2feff-488b-47f9-8729-e2cec094624c' } #Requires -Modules @{ ModuleName = 'Az.Resources'; ModuleVersion = '1.0.0'; Guid = '48bb344d-4c24-441e-8ea0-589947784700' } $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 Types if (-not ([System.Management.Automation.PSTypeName]'CosmosDB.Context').Type) { $typeDefinition = @' namespace CosmosDB { public class ContextToken { public System.String Resource; public System.DateTime TimeStamp; public System.DateTime Expires; public System.Security.SecureString Token; } public class BackoffPolicy { public System.Int32 MaxRetries; public System.String Method; public System.Int32 Delay; } public class Context { public System.String Account; public System.String Database; public System.Security.SecureString Key; public System.String KeyType; public System.String BaseUri; public CosmosDB.ContextToken[] Token; public CosmosDB.BackoffPolicy BackoffPolicy; } namespace IndexingPolicy { namespace Path { public class Index { public System.String dataType; public System.String kind; } public class IndexRange : CosmosDB.IndexingPolicy.Path.Index { public System.Int32 precision; } public class IndexHash : CosmosDB.IndexingPolicy.Path.Index { public System.Int32 precision; } public class IndexSpatial : CosmosDB.IndexingPolicy.Path.Index { } public class IncludedPath { public System.String path; public CosmosDB.IndexingPolicy.Path.Index[] indexes; } public class ExcludedPath { public System.String path; } } public class Policy { public System.Boolean automatic; public System.String indexingMode; public CosmosDB.IndexingPolicy.Path.IncludedPath[] includedPaths; public CosmosDB.IndexingPolicy.Path.ExcludedPath[] excludedPaths; } } namespace UniqueKeyPolicy { public class UniqueKey { public System.String[] paths; } public class Policy { public CosmosDB.UniqueKeyPolicy.UniqueKey[] uniqueKeys; } } } '@ 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-CosmosDbRequest 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 #region LocalizedData $culture = 'en-us' if (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath $PSUICulture)) { $culture = $PSUICulture } Import-LocalizedData ` -BindingVariable LocalizedData ` -Filename 'CosmosDB.strings.psd1' ` -BaseDirectory $moduleRoot ` -UICulture $culture #endregion #region Functions <# .SYNOPSIS Helper function that asserts a Cosmos DB Account name is valid. #> function Assert-CosmosDbAccountNameValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Name, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Name' ) $matches = [regex]::Match($Name,"[A-Za-z0-9\-]{3,50}") if ($matches.value -ne $Name) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.AccountNameInvalid -f $Name) ` -ArgumentName $ArgumentName } return $true } <# .SYNOPSIS Helper function that asserts a Azure Resource Group name is valid. #> function Assert-CosmosDbResourceGroupNameValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ResourceGroupName, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'ResourceGroupName' ) $matches = [regex]::Match($ResourceGroupName,"[A-Za-z0-9_\-\.]{1,90}(?<!\.)") if ($matches.value -ne $ResourceGroupName) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.ResourceGroupNameInvalid -f $ResourceGroupName) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbAccount { [CmdletBinding()] [OutputType([Object])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName ) $getAzResource_parameters = $PSBoundParameters + @{ ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' } Write-Verbose -Message $($LocalizedData.GettingAzureCosmosDBAccount -f $Name, $ResourceGroupName) return Get-AzResource @getAzResource_parameters } function Get-CosmosDbAccountConnectionString { [CmdletBinding()] [OutputType([Object])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName ) $invokeAzResourceAction_parameters = $PSBoundParameters + @{ ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' Action = 'listConnectionStrings' Force = $true } Write-Verbose -Message $($LocalizedData.GettingAzureCosmosDBAccountConnectionString -f $Name, $ResourceGroupName) Write-Warning -Message $LocalizedData.GettingAzureCosmosDBAccountConnectionStringWarning return Invoke-AzResourceAction @invokeAzResourceAction_parameters } function Get-CosmosDbAccountMasterKey { [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope = 'Function')] [OutputType([SecureString])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName, [Parameter(ParameterSetName = 'AzureAccount')] [ValidateSet('PrimaryMasterKey', 'SecondaryMasterKey', 'PrimaryReadonlyMasterKey', 'SecondaryReadonlyMasterKey')] [System.String] $MasterKeyType = 'PrimaryMasterKey' ) Write-Verbose -Message $($LocalizedData.GettingAzureCosmosDBAccountMasterKey -f $Name, $ResourceGroupName, $MasterKeyType) $action = 'listKeys' if ($MasterKeyType -in ('PrimaryReadonlyMasterKey', 'SecondaryReadonlyMasterKey')) { # Use the readonlykey Action if a ReadOnly key is required $action = 'readonlykeys' } $invokeAzResourceAction_parameters = @{ Name = $Name ResourceGroupName = $ResourceGroupName ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' Action = $action Force = $true ErrorAction = 'Stop' } $resource = Invoke-AzResourceAction @invokeAzResourceAction_parameters if ($resource) { return ConvertTo-SecureString ` -String ($resource.$MasterKeyType) ` -AsPlainText ` -Force } } function New-CosmosDbAccount { [CmdletBinding( SupportsShouldProcess = $true )] [OutputType([Object])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Location, [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $LocationRead, [Parameter()] [ValidateSet('Eventual', 'Strong', 'Session', 'BoundedStaleness')] [System.String] $DefaultConsistencyLevel = 'Session', [Parameter()] [ValidateRange(1, 100)] [System.Int32] $MaxIntervalInSeconds = 5, [Parameter()] [ValidateRange(1, [Int32]::MaxValue)] [System.Int32] $MaxStalenessPrefix = 100, [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $IpRangeFilter = @(), [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $AllowedOrigin, [Parameter()] [Switch] $AsJob ) <# Assemble a location object that will be used to generate the request JSON. It will consist of a single write location and 0 or more read locations. #> $locationObject = @( @{ locationName = $Location failoverPriority = 0 }) $failoverPriority = 1 foreach ($locationReadItem in $LocationRead) { $locationObject += @{ locationName = $locationReadItem failoverPriority = $failoverPriority } $failoverPriority++ } $consistencyPolicyObject = @{ defaultConsistencyLevel = $DefaultConsistencyLevel maxIntervalInSeconds = $MaxIntervalInSeconds maxStalenessPrefix = $MaxStalenessPrefix } $cosmosDBProperties = @{ databaseAccountOfferType = 'Standard' locations = $locationObject consistencyPolicy = $consistencyPolicyObject ipRangeFilter = ($IpRangeFilter -join ',') } if ($PSBoundParameters.ContainsKey('AllowedOrigin')) { $corsObject = @( @{ allowedOrigins = ($AllowedOrigin -join ',') } ) $cosmosDBProperties += @{ cors = $corsObject } } $null = $PSBoundParameters.Remove('LocationRead') $null = $PSBoundParameters.Remove('DefaultConsistencyLevel') $null = $PSBoundParameters.Remove('MaxIntervalInSeconds') $null = $PSBoundParameters.Remove('MaxStalenessPrefix') $null = $PSBoundParameters.Remove('IpRangeFilter') $null = $PSBoundParameters.Remove('AllowedOrigin') $newAzResource_parameters = $PSBoundParameters + @{ ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' Properties = $cosmosDBProperties } if ($PSCmdlet.ShouldProcess('Azure', ($LocalizedData.ShouldCreateAzureCosmosDBAccount -f $Name, $ResourceGroupName, $Location))) { Write-Verbose -Message $($LocalizedData.CreatingAzureCosmosDBAccount -f $Name, $ResourceGroupName, $Location) return (New-AzResource @newAzResource_parameters -Force) } } function New-CosmosDbAccountMasterKey { [CmdletBinding( SupportsShouldProcess = $true )] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope = 'Function')] [OutputType([SecureString])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName, [Parameter(ParameterSetName = 'AzureAccount')] [ValidateSet('PrimaryMasterKey', 'SecondaryMasterKey', 'PrimaryReadonlyMasterKey', 'SecondaryReadonlyMasterKey')] [System.String] $MasterKeyType = 'PrimaryMasterKey' ) Write-Verbose -Message $($LocalizedData.RegeneratingAzureCosmosDBAccountMasterKey -f $Name, $ResourceGroupName, $MasterKeyType) $invokeAzResourceAction_parameters = @{ Name = $Name ResourceGroupName = $ResourceGroupName ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' Action = 'regenerateKey' Force = $true Parameters = @{ keyKind = ($MasterKeyType -replace 'MasterKey','')} ErrorAction = 'Stop' } if ($PSCmdlet.ShouldProcess('Azure', ($LocalizedData.ShouldCreateAzureCosmosDBAccountMasterKey -f $Name, $ResourceGroupName, $MasterKeyType))) { Invoke-AzResourceAction @invokeAzResourceAction_parameters } } function Remove-CosmosDbAccount { [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High' )] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName, [Parameter()] [Switch] $AsJob, [Parameter()] [Switch] $Force ) if ($Force -or ` $PSCmdlet.ShouldProcess('Azure', ($LocalizedData.ShouldRemoveAzureCosmosDBAccount -f $Name, $ResourceGroupName))) { Write-Verbose -Message $($LocalizedData.RemovingAzureCosmosDBAccount -f $Name, $ResourceGroupName) $removeAzResource_parameters = $PSBoundParameters + @{ ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' } $removeAzResource_parameters['Force'] = $true $null = Remove-AzResource @removeAzResource_parameters } } function Set-CosmosDbAccount { [CmdletBinding( SupportsShouldProcess = $true )] [OutputType([Object])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Location, [Parameter()] [System.String[]] $LocationRead, [Parameter()] [ValidateSet('Eventual', 'Strong', 'Session', 'BoundedStaleness')] [System.String] $DefaultConsistencyLevel, [Parameter()] [ValidateRange(1, 100)] [System.Int32] $MaxIntervalInSeconds, [Parameter()] [ValidateRange(1, [Int32]::MaxValue)] [System.Int32] $MaxStalenessPrefix, [Parameter()] [System.String[]] $IpRangeFilter, [Parameter()] [System.String[]] $AllowedOrigin, [Parameter()] [Switch] $AsJob ) # Get the existing Cosmos DB Account $getCosmosDbAccount_parameters = @{} + $PSBoundParameters $null = $getCosmosDbAccount_parameters.Remove('Location') $null = $getCosmosDbAccount_parameters.Remove('LocationRead') $null = $getCosmosDbAccount_parameters.Remove('DefaultConsistencyLevel') $null = $getCosmosDbAccount_parameters.Remove('MaxIntervalInSeconds') $null = $getCosmosDbAccount_parameters.Remove('MaxStalenessPrefix') $null = $getCosmosDbAccount_parameters.Remove('IpRangeFilter') $null = $getCosmosDbAccount_parameters.Remove('AllowedOrigin') $null = $getCosmosDbAccount_parameters.Remove('AsJob') $existingAccount = Get-CosmosDbAccount @getCosmosDbAccount_parameters if (-not $existingAccount) { New-CosmosDbInvalidOperationException -Message ($LocalizedData.ErrorAccountDoesNotExist -f $Name, $ResourceGroupName) } <# Assemble a location object that will be used to generate the request JSON. It will consist of a single write location and 0 or more read locations. #> if (-not ($PSBoundParameters.ContainsKey('Location'))) { $Location = $existingAccount.Location } $locationObject = @( @{ locationName = $Location failoverPriority = 0 }) if ($PSBoundParameters.ContainsKey('LocationRead')) { $failoverPriority = 1 foreach ($locationReadItem in $LocationRead) { $locationObject += @{ locationName = $locationReadItem failoverPriority = $failoverPriority } $failoverPriority++ } } if (-not ($PSBoundParameters.ContainsKey('DefaultConsistencyLevel'))) { $DefaultConsistencyLevel = $existingAccount.Properties.consistencyPolicy.defaultConsistencyLevel } if (-not ($PSBoundParameters.ContainsKey('MaxIntervalInSeconds'))) { $MaxIntervalInSeconds = $existingAccount.Properties.consistencyPolicy.maxIntervalInSeconds } if (-not ($PSBoundParameters.ContainsKey('MaxStalenessPrefix'))) { $MaxStalenessPrefix = $existingAccount.Properties.consistencyPolicy.maxStalenessPrefix } $consistencyPolicyObject = @{ defaultConsistencyLevel = $DefaultConsistencyLevel maxIntervalInSeconds = $MaxIntervalInSeconds maxStalenessPrefix = $MaxStalenessPrefix } if ($PSBoundParameters.ContainsKey('IpRangeFilter')) { $ipRangeFilterString = ($IpRangeFilter -join ',') } else { $ipRangeFilterString = $existingAccount.Properties.ipRangeFilter } $cosmosDBProperties = @{ databaseAccountOfferType = 'Standard' locations = $locationObject consistencyPolicy = $consistencyPolicyObject ipRangeFilter = $ipRangeFilterString } if ($PSBoundParameters.ContainsKey('AllowedOrigin')) { $allowedOriginString = ($AllowedOrigin -join ',') } else { $allowedOriginString = $existingAccount.Properties.cors.allowedOrigins } if (-not ([System.String]::IsNullOrEmpty($allowedOriginString))) { $corsObject = @( @{ allowedOrigins = $allowedOriginString } ) $cosmosDBProperties += @{ cors = $corsObject } } $null = $PSBoundParameters.Remove('Location') $null = $PSBoundParameters.Remove('LocationRead') $null = $PSBoundParameters.Remove('DefaultConsistencyLevel') $null = $PSBoundParameters.Remove('MaxIntervalInSeconds') $null = $PSBoundParameters.Remove('MaxStalenessPrefix') $null = $PSBoundParameters.Remove('IpRangeFilter') $null = $PSBoundParameters.Remove('AllowedOrigin') $setAzResource_parameters = $PSBoundParameters + @{ ResourceType = 'Microsoft.DocumentDb/databaseAccounts' ApiVersion = '2015-04-08' Properties = $cosmosDBProperties } if ($PSCmdlet.ShouldProcess('Azure', ($LocalizedData.ShouldUpdateAzureCosmosDBAccount -f $Name, $ResourceGroupName))) { Write-Verbose -Message $($LocalizedData.UpdatingAzureCosmosDBAccount -f $Name, $ResourceGroupName) return (Set-AzResource @setAzResource_parameters -Force) } } <# .SYNOPSIS Helper function that asserts a Cosmos DB Attachment Id is valid. #> function Assert-CosmosDbAttachmentIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.AttachmentIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbAttachment { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ -ArgumentName 'DocumentId' })] [System.String] $DocumentId, [Parameter()] [ValidateScript({ Assert-CosmosDbAttachmentIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('DocumentId') $resourcePath = ('colls/{0}/docs/{1}/attachments' -f $CollectionId, $DocumentId) if (-not [String]::IsNullOrEmpty($Id)) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'attachments' ` -ResourcePath ('{0}/{1}' -f $resourcePath, $Id) $attachment = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'attachments' ` -ResourcePath $resourcePath $body = ConvertFrom-Json -InputObject $result.Content $attachment = $body.Attachments } if ($attachment) { return (Set-CosmosDbAttachmentType -Attachment $attachment) } } function Get-CosmosDbAttachmentResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ -ArgumentName 'DocumentId' })] [System.String] $DocumentId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAttachmentIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/colls/{1}/docs/{2}/attachments/{3}' -f $Database, $CollectionId, $DocumentId, $Id) } function New-CosmosDbAttachment { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ -ArgumentName 'DocumentId' })] [System.String] $DocumentId, [Parameter()] [ValidateScript({ Assert-CosmosDbAttachmentIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ContentType, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Media, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Slug ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('DocumentId') $resourcePath = ('colls/{0}/docs/{1}/attachments' -f $CollectionId, $DocumentId) $headers = @{} $bodyObject = @{} if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $bodyObject += @{ id = $Id } } if ($PSBoundParameters.ContainsKey('ContentType')) { $null = $PSBoundParameters.Remove('ContentType') $bodyObject += @{ contentType = $ContentType } } if ($PSBoundParameters.ContainsKey('Media')) { $null = $PSBoundParameters.Remove('Media') $bodyObject += @{ media = $Media } } if ($PSBoundParameters.ContainsKey('Slug')) { $headers += @{ 'Slug' = $Slug } $null = $PSBoundParameters.Remove('Slug') } $body = ConvertTo-Json -InputObject $bodyObject $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'attachments' ` -ResourcePath $resourcePath ` -Body $body ` -Headers $headers $attachment = ConvertFrom-Json -InputObject $result.Content if ($attachment) { return (Set-CosmosDbAttachmentType -Attachment $attachment) } } function Remove-CosmosDbAttachment { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ -ArgumentName 'DocumentId' })] [System.String] $DocumentId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAttachmentIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('DocumentId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/docs/{1}/attachments/{2}' -f $CollectionId, $DocumentId, $Id) $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'attachments' ` -ResourcePath $resourcePath } function Set-CosmosDbAttachment { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ -ArgumentName 'DocumentId' })] [System.String] $DocumentId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbAttachmentIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateScript({ Assert-CosmosDbAttachmentIdValid -Id $_ -ArgumentName 'NewId' })] [System.String] $NewId, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ContentType, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Media, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Slug ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('DocumentId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/docs/{1}/attachments/{2}' -f $CollectionId, $DocumentId, $Id) $headers = @{} $bodyObject = @{} if ($PSBoundParameters.ContainsKey('NewId')) { $null = $PSBoundParameters.Remove('NewId') $bodyObject += @{ id = $NewId } } else { $bodyObject += @{ id = $Id } } if ($PSBoundParameters.ContainsKey('ContentType')) { $null = $PSBoundParameters.Remove('ContentType') $bodyObject += @{ contentType = $ContentType } } if ($PSBoundParameters.ContainsKey('Media')) { $null = $PSBoundParameters.Remove('Media') $bodyObject += @{ media = $Media } } if ($PSBoundParameters.ContainsKey('Slug')) { $headers += @{ 'Slug' = $Slug } $null = $PSBoundParameters.Remove('Slug') } $body = ConvertTo-Json -InputObject $bodyObject $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'attachments' ` -ResourcePath $resourcePath ` -Body $body ` -Headers $headers $attachment = ConvertFrom-Json -InputObject $result.Content if ($attachment) { return (Set-CosmosDbAttachmentType -Attachment $attachment) } } function Set-CosmosDbAttachmentType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Attachment ) foreach ($item in $Attachment) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Attachment') } return $Attachment } <# .SYNOPSIS Helper function that asserts a Cosmos DB Collection Id is valid. #> function Assert-CosmosDbCollectionIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.CollectionIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbCollection { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.Int32] $MaxItemCount = -1, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ContinuationToken, [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-CosmosDbRequest @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 [String]::IsNullOrEmpty($ContinuationToken)) { $headers += @{ 'x-ms-continuation' = $ContinuationToken } } $result = Invoke-CosmosDbRequest @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-CosmosDbCollectionType -Collection $collection) } } function Get-CosmosDbCollectionResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/colls/{1}' -f $Database, $Id) } function Get-CosmosDbCollectionSize { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([System.Collections.Hashtable])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ })] [System.String] $Id ) <# per https://docs.microsoft.com/en-us/azure/cosmos-db/monitor-accounts, The quota and usage information for the collection is returned in the x-ms-resource-quota and x-ms-resource-usage headers in the response. #> $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'colls' ` -ResourcePath ('colls/{0}' -f $Id) $usageItems = @{} $resources = ($result.headers["x-ms-resource-usage"]).Split(';', [System.StringSplitOptions]::RemoveEmptyEntries) foreach ($resource in $resources) { [System.String] $k, $v = $resource.Split('=') $usageItems[$k] = $v } if ($usageItems) { return $usageItems } } function New-CosmosDbCollection { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -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()] [ValidateNotNullOrEmpty()] [CosmosDB.IndexingPolicy.Policy] $IndexingPolicy, [Parameter()] [ValidateRange(-1,2147483647)] [System.Int32] $DefaultTimeToLive, [Parameter()] [ValidateNotNullOrEmpty()] [CosmosDB.UniqueKeyPolicy.Policy] $UniqueKeyPolicy ) $headers = @{} if ($PSBoundParameters.ContainsKey('OfferThroughput') -and ` $PSBoundParameters.ContainsKey('OfferType')) { New-CosmosDbInvalidOperationException -Message $($LocalizedData.ErrorNewCollectionOfferParameterConflict) } if ($PSBoundParameters.ContainsKey('OfferThroughput')) { if ($OfferThroughput -gt 10000 -and $PartitionKey.Count -eq 0) { New-CosmosDbInvalidOperationException -Message $($LocalizedData.ErrorNewCollectionParitionKeyRequired) } $headers += @{ 'x-ms-offer-throughput' = $OfferThroughput } $null = $PSBoundParameters.Remove('OfferThroughput') } if ($PSBoundParameters.ContainsKey('OfferType')) { $headers += @{ 'x-ms-offer-type' = $OfferType } $null = $PSBoundParameters.Remove('OfferType') } $null = $PSBoundParameters.Remove('Id') $bodyObject = @{ id = $id } if ($PSBoundParameters.ContainsKey('PartitionKey')) { $bodyObject += @{ partitionKey = @{ paths = @('/{0}' -f $PartitionKey.TrimStart('/')) kind = 'Hash' } } $null = $PSBoundParameters.Remove('PartitionKey') } if ($PSBoundParameters.ContainsKey('IndexingPolicy')) { $bodyObject += @{ indexingPolicy = $IndexingPolicy } $null = $PSBoundParameters.Remove('IndexingPolicy') } 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 10 $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'colls' ` -Headers $headers ` -Body $body $collection = ConvertFrom-Json -InputObject $result.Content if ($collection) { return (Set-CosmosDbCollectionType -Collection $collection) } } function New-CosmosDbCollectionExcludedPath { [CmdletBinding()] [OutputType([CosmosDB.IndexingPolicy.Path.ExcludedPath])] param ( [Parameter()] [System.String] $Path = '/*' ) $excludedPath = [CosmosDB.IndexingPolicy.Path.ExcludedPath]::new() $excludedPath.Path = $Path return $excludedPath } function New-CosmosDbCollectionIncludedPath { [CmdletBinding()] [OutputType([CosmosDB.IndexingPolicy.Path.IncludedPath])] param ( [Parameter()] [System.String] $Path = '/*', [Parameter()] [CosmosDB.IndexingPolicy.Path.Index[]] $Index ) $includedPath = [CosmosDB.IndexingPolicy.Path.IncludedPath]::new() $includedPath.Path = $Path $includedPath.Indexes = $Index return $includedPath } function New-CosmosDbCollectionIncludedPathIndex { [CmdletBinding()] [OutputType([CosmosDB.IndexingPolicy.Path.Index])] param ( [Parameter(Mandatory = $true)] [ValidateSet('Hash', 'Range', 'Spatial')] [System.String] $Kind, [Parameter(Mandatory = $true)] [ValidateSet('String', 'Number', 'Point', 'Polygon', 'LineString')] [System.String] $DataType, [Parameter()] [Int32] $Precision ) # Validate the path index parameters switch ($Kind) { 'Hash' { if ($DataType -notin @('String', 'Number')) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.ErrorNewCollectionIncludedPathIndexInvalidDataType -f $Kind, $DataType, 'String, Number') ` -ArgumentName 'DataType' } } 'Range' { if ($DataType -notin @('String', 'Number')) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.ErrorNewCollectionIncludedPathIndexInvalidDataType -f $Kind, $DataType, 'String, Number') ` -ArgumentName 'DataType' } } 'Spatial' { if ($DataType -notin @('Point', 'Polygon', 'LineString')) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.ErrorNewCollectionIncludedPathIndexInvalidDataType -f $Kind, $DataType, 'Point, Polygon, LineString') ` -ArgumentName 'DataType' } if ($PSBoundParameters.ContainsKey('Precision')) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.ErrorNewCollectionIncludedPathIndexPrecisionNotSupported -f $Kind) ` -ArgumentName 'Precision' } } } $index = New-Object -TypeName ('CosmosDB.IndexingPolicy.Path.Index' + $Kind) $index.Kind = $Kind $index.DataType = $DataType if ($PSBoundParameters.ContainsKey('Precision')) { $index.Precision = $Precision } return $index } function New-CosmosDbCollectionIndexingPolicy { [CmdletBinding()] [OutputType([CosmosDB.IndexingPolicy.Policy])] param ( [Parameter()] [System.Boolean] $Automatic = $true, [Parameter()] [ValidateSet('Consistent', 'Lazy', 'None')] [System.String] $IndexingMode = 'Consistent', [Parameter()] [CosmosDB.IndexingPolicy.Path.IncludedPath[]] $IncludedPath = @(), [Parameter()] [CosmosDB.IndexingPolicy.Path.ExcludedPath[]] $ExcludedPath = @() ) if ($IndexingMode -eq 'None' -and $Automatic) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.ErrorNewCollectionIndexingPolicyInvalidMode) ` -ArgumentName 'Automatic' } $indexingPolicy = [CosmosDB.IndexingPolicy.Policy]::new() $indexingPolicy.Automatic = $Automatic $indexingPolicy.IndexingMode = $IndexingMode $indexingPolicy.IncludedPaths = $IncludedPath $indexingPolicy.ExcludedPaths = $ExcludedPath return $indexingPolicy } function New-CosmosDbCollectionUniqueKey { [CmdletBinding()] [OutputType([CosmosDB.UniqueKeyPolicy.UniqueKey])] param ( [Parameter(Mandatory = $true)] [System.String[]] $Path ) $uniqueKey = [CosmosDB.UniqueKeyPolicy.UniqueKey]::new() $uniqueKey.paths = $Path return $uniqueKey } function New-CosmosDbCollectionUniqueKeyPolicy { [CmdletBinding()] [OutputType([CosmosDB.UniqueKeyPolicy.Policy])] param ( [Parameter(Mandatory = $true)] [CosmosDb.UniqueKeyPolicy.UniqueKey[]] $UniqueKey ) $uniqueKeyPolicy = [CosmosDB.UniqueKeyPolicy.Policy]::new() $uniqueKeyPolicy.uniqueKeys = $UniqueKey return $uniqueKeyPolicy } function Remove-CosmosDbCollection { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('Id') $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'colls' ` -ResourcePath ('colls/{0}' -f $Id) } function Set-CosmosDbCollection { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [CosmosDB.IndexingPolicy.Policy] $IndexingPolicy, [Parameter()] [ValidateRange(-1,2147483647)] [System.Int32] $DefaultTimeToLive, [Parameter()] [Switch] $RemoveDefaultTimeToLive, [Parameter()] [ValidateNotNullOrEmpty()] [CosmosDB.UniqueKeyPolicy.Policy] $UniqueKeyPolicy ) if ($PSBoundParameters.ContainsKey('DefaultTimeToLive') -and $RemoveDefaultTimeToLive.IsPresent) { New-CosmosDbInvalidArgumentException ` -Message $LocalizedData.ErrorSetCollectionRemoveDefaultTimeToLiveConflict ` -ArgumentName 'RemoveDefaultTimeToLive' } $headers = @{} $bodyObject = @{ id = $id } $indexingPolicyIncluded = $PSBoundParameters.ContainsKey('IndexingPolicy') $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-CosmosDbCollection @PSBoundParameters $null = $PSBoundParameters.Remove('Id') if ($indexingPolicyIncluded) { $bodyObject += @{ indexingPolicy = $IndexingPolicy } } 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-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'colls' ` -ResourcePath ('colls/{0}' -f $Id) ` -Headers $headers ` -Body $body $collection = ConvertFrom-Json -InputObject $result.Content if ($collection) { return (Set-CosmosDbCollectionType -Collection $collection) } } function Set-CosmosDbCollectionType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Collection ) foreach ($item in $Collection) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Collection') $item.indexingPolicy.PSObject.TypeNames.Insert(0, 'CosmosDB.Collection.IndexingPolicy') foreach ($includedPath in $item.indexingPolicy.includedPaths) { $includedPath.PSObject.TypeNames.Insert(0, 'CosmosDB.Collection.IndexingPolicy.IncludedPath') foreach ($index in $includedPath.indexes) { $index.PSObject.TypeNames.Insert(0, 'CosmosDB.Collection.IndexingPolicy.Index') } } foreach ($excludedPath in $item.indexingPolicy.excludedPaths) { $excludedPath.PSObject.TypeNames.Insert(0, 'CosmosDB.Collection.IndexingPolicy.ExcludedPath') foreach ($index in $excludedPath.indexes) { $index.PSObject.TypeNames.Insert(0, 'CosmosDB.Collection.IndexingPolicy.Index') } } } return $Collection } <# .SYNOPSIS Helper function that asserts a Cosmos DB Database Id is valid. #> function Assert-CosmosDbDatabaseIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?=]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.DatabaseIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbDatabase { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ })] [System.String] $Id ) if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'dbs' ` -ResourcePath ('dbs/{0}' -f $Id) $database = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'dbs' $body = ConvertFrom-Json -InputObject $result.Content $database = $body.Databases } if ($database) { return (Set-CosmosDbDatabaseType -Database $database) } } function Get-CosmosDbDatabaseResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}' -f $Id) } function New-CosmosDbDatabase { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'dbs' ` -Body "{ `"id`": `"$id`" }" $database = ConvertFrom-Json -InputObject $result.Content if ($database) { return (Set-CosmosDbDatabaseType -Database $database) } } function Remove-CosmosDbDatabase { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('Id') $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'dbs' ` -ResourcePath ('dbs/{0}' -f $Id) } function Set-CosmosDbDatabaseType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Database ) foreach ($item in $Database) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Database') } return $Database } <# .SYNOPSIS Helper function that asserts a Cosmos DB Document Id is valid. #> function Assert-CosmosDbDocumentIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.DocumentIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbDocument { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $PartitionKey, [Parameter()] [ValidateNotNullOrEmpty()] [System.Int32] $MaxItemCount = -1, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ContinuationToken, [Parameter()] [ValidateSet('Strong', 'Bounded', 'Session', 'Eventual')] [System.String] $ConsistencyLevel, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $SessionToken, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $PartitionKeyRangeId, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Query, [Parameter()] [ValidateNotNullOrEmpty()] [Hashtable[]] $QueryParameters, [Parameter()] [ValidateNotNullOrEmpty()] [System.Boolean] $QueryEnableCrossPartition = $False, [Alias("ResultHeaders")] [Parameter()] [ref] $ResponseHeader ) $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('MaxItemCount') $null = $PSBoundParameters.Remove('ContinuationToken') $null = $PSBoundParameters.Remove('ConsistencyLevel') $null = $PSBoundParameters.Remove('SessionToken') $null = $PSBoundParameters.Remove('PartitionKeyRangeId') $null = $PSBoundParameters.Remove('Query') $null = $PSBoundParameters.Remove('QueryParameters') $null = $PSBoundParameters.Remove('QueryEnableCrossPartition') if ($PSBoundParameters.ContainsKey('ResponseHeader')) { $ResponseHeaderPassed = $true $null = $PSBoundParameters.Remove('ResponseHeader') } $resourcePath = ('colls/{0}/docs' -f $CollectionId) $method = 'Get' $headers = @{} if (-not [String]::IsNullOrEmpty($Id)) { # A document Id has been specified if ($PSBoundParameters.ContainsKey('PartitionKey')) { $headers += @{ 'x-ms-documentdb-partitionkey' = '["' + ($PartitionKey -join '","') + '"]' } $null = $PSBoundParameters.Remove('PartitionKey') } $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method $method ` -Headers $headers ` -ResourceType 'docs' ` -ResourcePath ('{0}/{1}' -f $resourcePath, $Id) $document = ConvertFrom-JSON -InputObject $result.Content } else { $body = '' if (-not [String]::IsNullOrEmpty($Query)) { # A query has been specified $method = 'Post' $headers += @{ 'x-ms-documentdb-isquery' = $True } if ($QueryEnableCrossPartition -eq $True) { $headers += @{ 'x-ms-documentdb-query-enablecrosspartition' = $True } } # Set the content type to application/query+json for querying $null = $PSBoundParameters.Add('ContentType', 'application/query+json') # Create the body JSON for the query $bodyObject = @{ query = $Query } if (-not [String]::IsNullOrEmpty($QueryParameters)) { $bodyObject += @{ parameters = $QueryParameters } } $body = ConvertTo-Json -InputObject $bodyObject } else { if (-not [String]::IsNullOrEmpty($PartitionKeyRangeId)) { $headers += @{ 'x-ms-documentdb-partitionkeyrangeid' = $PartitionKeyRangeId } } } # The following headers apply when querying documents or just getting a list if ($PSBoundParameters.ContainsKey('PartitionKey')) { $headers += @{ 'x-ms-documentdb-partitionkey' = '["' + ($PartitionKey -join '","') + '"]' } $null = $PSBoundParameters.Remove('PartitionKey') } $headers += @{ 'x-ms-max-item-count' = $MaxItemCount } if (-not [String]::IsNullOrEmpty($ContinuationToken)) { $headers += @{ 'x-ms-continuation' = $ContinuationToken } } if (-not [String]::IsNullOrEmpty($ConsistencyLevel)) { $headers += @{ 'x-ms-consistency-level' = $ConsistencyLevel } } if (-not [String]::IsNullOrEmpty($SessionToken)) { $headers += @{ 'x-ms-session-token' = $SessionToken } } <# Because the headers of this request will contain important information then we need to use a plain web request. #> $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method $method ` -ResourceType 'docs' ` -ResourcePath $resourcePath ` -Headers $headers ` -Body $body $body = ConvertFrom-JSON -InputObject $result.Content $document = $body.Documents if ($ResponseHeaderPassed) { # Return the result headers $ResponseHeader.value = $result.Headers } } if ($document) { return (Set-CosmosDbDocumentType -Document $document) } } function Get-CosmosDbDocumentResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/colls/{1}/docs/{2}' -f $Database, $CollectionId, $Id) } function New-CosmosDbDocument { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $DocumentBody, [Parameter()] [ValidateSet('Include', 'Exclude')] [System.String] $IndexingDirective, [Parameter()] [System.Boolean] $Upsert, [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $PartitionKey, [Parameter()] [ValidateSet('Default', 'UTF-8')] [System.String] $Encoding = 'Default' ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('DocumentBody') $resourcePath = ('colls/{0}/docs' -f $CollectionId) $headers = @{} if ($PSBoundParameters.ContainsKey('Upsert')) { $headers += @{ 'x-ms-documentdb-is-upsert' = $Upsert } $null = $PSBoundParameters.Remove('Upsert') } if ($PSBoundParameters.ContainsKey('IndexingDirective')) { $headers += @{ 'x-ms-indexing-directive' = $IndexingDirective } $null = $PSBoundParameters.Remove('IndexingDirective') } if ($PSBoundParameters.ContainsKey('PartitionKey')) { $headers += @{ 'x-ms-documentdb-partitionkey' = '["' + ($PartitionKey -join '","') + '"]' } $null = $PSBoundParameters.Remove('PartitionKey') } $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'docs' ` -ResourcePath $resourcePath ` -Body $DocumentBody ` -Headers $headers $document = ConvertFrom-Json -InputObject $result.Content if ($document) { return (Set-CosmosDbDocumentType -Document $document) } } function Remove-CosmosDbDocument { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $PartitionKey ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/docs/{1}' -f $CollectionId, $Id) $headers = @{} if ($PSBoundParameters.ContainsKey('PartitionKey')) { $headers += @{ 'x-ms-documentdb-partitionkey' = '["' + ($PartitionKey -join '","') + '"]' } $null = $PSBoundParameters.Remove('PartitionKey') } $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'docs' ` -ResourcePath $resourcePath ` -Headers $headers } function Set-CosmosDbDocument { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDocumentIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $DocumentBody, [Parameter()] [ValidateSet('Include', 'Exclude')] [System.String] $IndexingDirective, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $PartitionKey, [Parameter()] [ValidateSet('Default', 'UTF-8')] [System.String] $Encoding = 'Default' ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('DocumentBody') $resourcePath = ('colls/{0}/docs/{1}' -f $CollectionId, $Id) $headers = @{} if ($PSBoundParameters.ContainsKey('IndexingDirective')) { $headers += @{ 'x-ms-indexing-directive' = $IndexingDirective } $null = $PSBoundParameters.Remove('IndexingDirective') } if ($PSBoundParameters.ContainsKey('PartitionKey')) { $headers += @{ 'x-ms-documentdb-partitionkey' = '["' + ($PartitionKey -join '","') + '"]' } $null = $PSBoundParameters.Remove('PartitionKey') } $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'docs' ` -ResourcePath $resourcePath ` -Body $DocumentBody ` -Headers $headers $document = ConvertFrom-Json -InputObject $result.Content if ($document) { return (Set-CosmosDbDocumentType -Document $document) } } function Set-CosmosDbDocumentType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Document ) foreach ($item in $Document) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Document') } return $Document } function Get-CosmosDbOffer { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateNotNullOrEmpty()] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Query ) if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'offers' ` -ResourcePath ('offers/{0}' -f $Id) $offer = ConvertFrom-Json -InputObject $result.Content } else { if (-not [String]::IsNullOrEmpty($Query)) { $null = $PSBoundParameters.Remove('Query') # A query has been specified $headers += @{ 'x-ms-documentdb-isquery' = $True } # Set the content type to application/query+json for querying $null = $PSBoundParameters.Add('ContentType', 'application/query+json') # Create the body JSON for the query $bodyObject = @{ query = $Query } $body = ConvertTo-Json -InputObject $bodyObject $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'offers' ` -Headers $headers ` -Body $body } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'offers' } $body = ConvertFrom-Json -InputObject $result.Content $offer = $body.Offers } if ($offer) { return (Set-CosmosDbOfferType -Offer $offer) } } function Get-CosmosDbOfferResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id ) return ('offers/{0}' -f $Id) } function Set-CosmosDbOffer { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateNotNullOrEmpty()] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [System.Object[]] $InputObject, [Parameter()] [ValidateSet('V1', 'V2')] [System.String] $OfferVersion, [Parameter()] [ValidateSet('S1', 'S2', 'S3', 'Invalid')] [System.String] $OfferType, [Parameter()] [ValidateRange(400, 250000)] [System.Int32] $OfferThroughput, [Parameter()] [System.Boolean] $OfferIsRUPerMinuteThroughputEnabled ) begin { $invokeCosmosDbRequest = @{} + $PSBoundParameters } process { $null = $invokeCosmosDbRequest.Remove('InputObject') foreach ($object in $InputObject) { $bodyObject = @{ '_rid' = $object._rid id = $object.id '_ts' = $object._ts '_self' = $object._self '_etag' = $object._etag resource = $object.resource offerType = $object.offerType offerResourceId = $object.offerResourceId offerVersion = $object.offerVersion } if ($PSBoundParameters.ContainsKey('OfferVersion')) { $null = $invokeCosmosDbRequest.Remove('OfferVersion') $bodyObject.offerVersion = $OfferVersion } if ($PSBoundParameters.ContainsKey('OfferType')) { $null = $invokeCosmosDbRequest.Remove('OfferType') $bodyObject.offerType = $OfferType } if ($bodyObject.offerVersion -eq 'V2') { <# Setting the Offer Throughput and RU Per minute settings only applicable for Offer Version V2 #> $content = @{ offerThroughput = $object.Content.offerThroughput offerIsRUPerMinuteThroughputEnabled = $object.Content.offerIsRUPerMinuteThroughputEnabled } if ($PSBoundParameters.ContainsKey('OfferThroughput')) { $null = $invokeCosmosDbRequest.Remove('OfferThroughput') $content.offerThroughput = $OfferThroughput } else { if ($content.offerThroughput -lt 1000) { <# If no offer throughput specified set to min for V2 of 400 However for partitioned collections minimum is 1000 #> $content.offerThroughput = 1000 } } if ($PSBoundParameters.ContainsKey('OfferIsRUPerMinuteThroughputEnabled')) { $null = $invokeCosmosDbRequest.Remove('OfferIsRUPerMinuteThroughputEnabled') $content.offerIsRUPerMinuteThroughputEnabled = $OfferIsRUPerMinuteThroughputEnabled } $bodyObject += @{ content = $content } } $result = Invoke-CosmosDbRequest @invokeCosmosDbRequest ` -Method 'Put' ` -ResourceType 'offers' ` -ResourcePath ('offers/{0}' -f $bodyObject.id) ` -Body (ConvertTo-Json -InputObject $bodyObject) $offer = ConvertFrom-Json -InputObject $result.Content if ($offer) { (Set-CosmosDbOfferType -Offer $offer) } } } end {} } function Set-CosmosDbOfferType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Offer ) foreach ($item in $Offer) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Offer') } return $Offer } <# .SYNOPSIS Helper function that asserts a Cosmos DB Permission Id is valid. #> function Assert-CosmosDbPermissionIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.PermissionIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbPermission { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ -ArgumentName 'UserId' })] [System.String] $UserId, [Parameter()] [ValidateScript({ Assert-CosmosDbPermissionIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateRange(600,18000)] [System.Int32] $TokenExpiry ) $null = $PSBoundParameters.Remove('UserId') $resourcePath = ('users/{0}/permissions' -f $UserId) $headers = @{} if ($PSBoundParameters.ContainsKey('TokenExpiry')) { $null = $PSBoundParameters.Remove('TokenExpiry') $headers += @{ 'x-ms-documentdb-expiry-seconds' = $TokenExpiry } } if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'permissions' ` -ResourcePath ('{0}/{1}' -f $resourcePath, $Id) ` -Headers $headers $permission = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'permissions' ` -ResourcePath $resourcePath ` -Headers $headers $body = ConvertFrom-Json -InputObject $result.Content $permission = $body.Permissions } if ($permission) { return (Set-CosmosDbPermissionType -Permission $permission) } } function Get-CosmosDbPermissionResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ -ArgumentName 'UserId' })] [System.String] $UserId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbPermissionIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/users/{1}/permissions/{2}' -f $Database, $UserId, $Id) } function New-CosmosDbPermission { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ -ArgumentName 'UserId' })] [System.String] $UserId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbPermissionIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Resource, [Parameter()] [ValidateSet('All', 'Read')] [System.String] $PermissionMode = 'All' ) $null = $PSBoundParameters.Remove('UserId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('Resource') $null = $PSBoundParameters.Remove('PermissionMode') $resourcePath = ('users/{0}/permissions' -f $UserId) $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'permissions' ` -ResourcePath $resourcePath ` -Body "{ `"id`": `"$id`", `"permissionMode`" : `"$PermissionMode`", `"resource`" : `"$Resource`" }" $permission = ConvertFrom-Json -InputObject $result.Content if ($permission) { return (Set-CosmosDbPermissionType -Permission $permission) } } function Remove-CosmosDbPermission { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ -ArgumentName 'UserId' })] [System.String] $UserId, [Parameter()] [ValidateScript({ Assert-CosmosDbPermissionIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('UserId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('users/{0}/permissions/{1}' -f $UserId,$Id) $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'permissions' ` -ResourcePath $resourcePath } function Set-CosmosDbPermissionType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Permission ) foreach ($item in $Permission) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Permission') } return $Permission } <# .SYNOPSIS Helper function that asserts a Cosmos DB Stored Procedure Id is valid. #> function Assert-CosmosDbStoredProcedureIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.StoredProcedureIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbStoredProcedure { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbStoredProcedureIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $resourcePath = ('colls/{0}/sprocs' -f $CollectionId) if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'sprocs' ` -ResourcePath ('{0}/{1}' -f $resourcePath, $Id) $storedProcedure = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'sprocs' ` -ResourcePath $resourcePath $body = ConvertFrom-Json -InputObject $result.Content $storedProcedure = $body.StoredProcedures } if ($storedProcedure) { return (Set-CosmosDbStoredProcedureType -StoredProcedure $storedProcedure) } } function Get-CosmosDbStoredProcedureResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbStoredProcedureIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/colls/{1}/sprocs/{2}' -f $Database, $CollectionId, $Id) } function Invoke-CosmosDbStoredProcedure { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateNotNullOrEmpty()] [System.String[]] $PartitionKey, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbStoredProcedureIdValid -Id $_ })] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.Object[]] $StoredProcedureParameter ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/sprocs/{1}' -f $CollectionId, $Id) $headers = @{} if ($PSBoundParameters.ContainsKey('PartitionKey')) { $headers += @{ 'x-ms-documentdb-partitionkey' = '["' + ($PartitionKey -join '","') + '"]' } $null = $PSBoundParameters.Remove('PartitionKey') } if ($PSBoundParameters.ContainsKey('Debug')) { $headers += @{ 'x-ms-documentdb-script-enable-logging' = $true } $null = $PSBoundParameters.Remove('Debug') } if ($PSBoundParameters.ContainsKey('StoredProcedureParameter')) { $body = ConvertTo-Json -InputObject $StoredProcedureParameter -Depth 10 -Compress $null = $PSBoundParameters.Remove('StoredProcedureParameter') } else { $body = '[]' } <# Because the headers of this request will contain important information then we need to use a plain web request. #> $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'sprocs' ` -ResourcePath $resourcePath ` -Headers $headers ` -Body $body if ($result.Headers.'x-ms-documentdb-script-log-results') { $logs = [Uri]::UnescapeDataString($result.Headers.'x-ms-documentdb-script-log-results').Trim() Write-Verbose -Message $($LocalizedData.StoredProcedureScriptLogResults -f $Id, $logs) } if ($result.Content) { return (ConvertFrom-Json -InputObject $result.Content) } } function New-CosmosDbStoredProcedure { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbStoredProcedureIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $StoredProcedureBody ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('StoredProcedureBody') $resourcePath = ('colls/{0}/sprocs' -f $CollectionId) $requestBody = Convert-CosmosDbRequestBody -RequestBodyObject @{ id = $id body = $StoredProcedureBody } $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'sprocs' ` -ResourcePath $resourcePath ` -Body $requestBody $storedProcedure = ConvertFrom-Json -InputObject $result.Content if ($storedProcedure) { return (Set-CosmosDbStoredProcedureType -StoredProcedure $storedProcedure) } } function Remove-CosmosDbStoredProcedure { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbStoredProcedureIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/sprocs/{1}' -f $CollectionId, $Id) $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'sprocs' ` -ResourcePath $resourcePath } function Set-CosmosDbStoredProcedure { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbStoredProcedureIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $StoredProcedureBody ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('StoredProcedureBody') $resourcePath = ('colls/{0}/sprocs/{1}' -f $CollectionId, $Id) $requestBody = Convert-CosmosDbRequestBody -RequestBodyObject @{ id = $id body = $StoredProcedureBody } $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'sprocs' ` -ResourcePath $resourcePath ` -Body $requestBody $storedProcedure = ConvertFrom-Json -InputObject $result.Content if ($storedProcedure) { return (Set-CosmosDbStoredProcedureType -StoredProcedure $storedProcedure) } } function Set-CosmosDbStoredProcedureType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $StoredProcedure ) foreach ($item in $StoredProcedure) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.StoredProcedure') } return $StoredProcedure } <# .SYNOPSIS Helper function that asserts a Cosmos DB Trigger Id is valid. #> function Assert-CosmosDbTriggerIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.TriggerIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbTrigger { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbTriggerIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $resourcePath = ('colls/{0}/triggers' -f $CollectionId) if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'triggers' ` -ResourcePath ('{0}/{1}' -f $resourcePath, $Id) $trigger = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'triggers' ` -ResourcePath $resourcePath $body = ConvertFrom-Json -InputObject $result.Content $trigger = $body.Triggers } if ($trigger) { return (Set-CosmosDbTriggerType -Trigger $trigger) } } function Get-CosmosDbTriggerResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbTriggerIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/colls/{1}/triggers/{2}' -f $Database, $CollectionId, $Id) } function New-CosmosDbTrigger { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbTriggerIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $TriggerBody, [Parameter(Mandatory = $true)] [ValidateSet('All', 'Create', 'Replace', 'Delete')] [System.String] $TriggerOperation, [Parameter(Mandatory = $true)] [ValidateSet('Pre', 'Post')] [System.String] $TriggerType ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('TriggerBody') $null = $PSBoundParameters.Remove('TriggerOperation') $null = $PSBoundParameters.Remove('TriggerType') $resourcePath = ('colls/{0}/triggers' -f $CollectionId) $TriggerBody = ((($TriggerBody -replace '`n', '\n') -replace '`r', '\r') -replace '"', '\"') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'triggers' ` -ResourcePath $resourcePath ` -Body "{ `"id`": `"$id`", `"body`" : `"$TriggerBody`", `"triggerOperation`" : `"$triggerOperation`", `"triggerType`" : `"$triggerType`" }" $trigger = ConvertFrom-Json -InputObject $result.Content if ($trigger) { return (Set-CosmosDbTriggerType -Trigger $trigger) } } function Remove-CosmosDbTrigger { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbTriggerIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/triggers/{1}' -f $CollectionId, $Id) $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'triggers' ` -ResourcePath $resourcePath } function Set-CosmosDbTrigger { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbTriggerIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $TriggerBody, [Parameter(Mandatory = $true)] [ValidateSet('All', 'Create', 'Replace', 'Delete')] [System.String] $TriggerOperation, [Parameter(Mandatory = $true)] [ValidateSet('Pre', 'Post')] [System.String] $TriggerType ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('TriggerBody') $null = $PSBoundParameters.Remove('TriggerOperation') $null = $PSBoundParameters.Remove('TriggerType') $resourcePath = ('colls/{0}/triggers/{1}' -f $CollectionId, $Id) $TriggerBody = ((($TriggerBody -replace '`n', '\n') -replace '`r', '\r') -replace '"', '\"') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'triggers' ` -ResourcePath $resourcePath ` -Body "{ `"id`": `"$id`", `"body`" : `"$TriggerBody`", `"triggerOperation`" : `"$triggerOperation`", `"triggerType`" : `"$triggerType`" }" $trigger = ConvertFrom-Json -InputObject $result.Content if ($trigger) { return (Set-CosmosDbTriggerType -Trigger $trigger) } } function Set-CosmosDbTriggerType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Trigger ) foreach ($item in $Trigger) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.Trigger') } return $Trigger } <# .SYNOPSIS Helper function that asserts a Cosmos DB User Defined Function Id is valid. #> function Assert-CosmosDbUserDefinedFunctionIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.UserDefinedFunctionIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbUserDefinedFunction { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbUserDefinedFunctionIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $resourcePath = ('colls/{0}/udfs' -f $CollectionId) if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'udfs' ` -ResourcePath ('{0}/{1}' -f $resourcePath, $Id) $userDefinedFunction = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'udfs' ` -ResourcePath $resourcePath $body = ConvertFrom-Json -InputObject $result.Content $userDefinedFunction = $body.UserDefinedFunctions } if ($userDefinedFunction) { return (Set-CosmosDbUserDefinedFunctionType -UserDefinedFunction $userDefinedFunction) } } function Get-CosmosDbUserDefinedFunctionResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserDefinedFunctionIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/colls/{1}/udfs/{2}' -f $Database, $CollectionId, $Id) } function New-CosmosDbUserDefinedFunction { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserDefinedFunctionIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $UserDefinedFunctionBody ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('UserDefinedFunctionBody') $resourcePath = ('colls/{0}/udfs' -f $CollectionId) $UserDefinedFunctionBody = ((($UserDefinedFunctionBody -replace '`n', '\n') -replace '`r', '\r') -replace '"', '\"') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'udfs' ` -ResourcePath $resourcePath ` -Body "{ `"id`": `"$id`", `"body`" : `"$UserDefinedFunctionBody`" }" $userDefinedFunction = ConvertFrom-Json -InputObject $result.Content if ($userDefinedFunction) { return (Set-CosmosDbUserDefinedFunctionType -UserDefinedFunction $userDefinedFunction) } } function Remove-CosmosDbUserDefinedFunction { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter()] [ValidateScript({ Assert-CosmosDbUserDefinedFunctionIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $resourcePath = ('colls/{0}/udfs/{1}' -f $CollectionId, $Id) $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'udfs' ` -ResourcePath $resourcePath } function Set-CosmosDbUserDefinedFunction { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbCollectionIdValid -Id $_ -ArgumentName 'CollectionId' })] [System.String] $CollectionId, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserDefinedFunctionIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $UserDefinedFunctionBody ) $null = $PSBoundParameters.Remove('CollectionId') $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('UserDefinedFunctionBody') $resourcePath = ('colls/{0}/udfs/{1}' -f $CollectionId, $Id) $UserDefinedFunctionBody = ((($UserDefinedFunctionBody -replace '`n', '\n') -replace '`r', '\r') -replace '"', '\"') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'udfs' ` -ResourcePath $resourcePath ` -Body "{ `"id`": `"$id`", `"body`" : `"$UserDefinedFunctionBody`" }" $userDefinedFunction = ConvertFrom-Json -InputObject $result.Content if ($userDefinedFunction) { return (Set-CosmosDbUserDefinedFunctionType -UserDefinedFunction $userDefinedFunction) } } function Set-CosmosDbUserDefinedFunctionType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $UserDefinedFunction ) foreach ($item in $UserDefinedFunction) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.UserDefinedFunction') } return $UserDefinedFunction } <# .SYNOPSIS Helper function that asserts a Cosmos DB User Id is valid. #> function Assert-CosmosDbUserIdValid { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName = 'Id' ) $matches = [regex]::Match($Id,"[^\\/#?]{1,255}(?<!\s)") if ($matches.value -ne $Id) { New-CosmosDbInvalidArgumentException ` -Message $($LocalizedData.UserIdInvalid -f $Id) ` -ArgumentName $ArgumentName } return $true } function Get-CosmosDbUser { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ })] [System.String] $Id ) if ($PSBoundParameters.ContainsKey('Id')) { $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'users' ` -ResourcePath ('users/{0}' -f $Id) $user = ConvertFrom-Json -InputObject $result.Content } else { $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Get' ` -ResourceType 'users' $body = ConvertFrom-Json -InputObject $result.Content $user = $body.Users } if ($user) { return (Set-CosmosDbUserType -User $user) } } function Get-CosmosDbUserResourcePath { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ })] [System.String] $Id ) return ('dbs/{0}/users/{1}' -f $Database, $Id) } function New-CosmosDbUser { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('Id') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Post' ` -ResourceType 'users' ` -Body "{ `"id`": `"$Id`" }" $user = ConvertFrom-Json -InputObject $result.Content if ($user) { return (Set-CosmosDbUserType -User $user) } } function Remove-CosmosDbUser { [CmdletBinding(DefaultParameterSetName = 'Context')] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ })] [System.String] $Id ) $null = $PSBoundParameters.Remove('Id') $null = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Delete' ` -ResourceType 'users' ` -ResourcePath ('users/{0}' -f $Id) } function Set-CosmosDbUser { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([Object])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDb.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ -ArgumentName 'Account' })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ -ArgumentName 'Database' })] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ })] [System.String] $Id, [Parameter(Mandatory = $true)] [ValidateScript({ Assert-CosmosDbUserIdValid -Id $_ -ArgumentName 'NewId' })] [System.String] $NewId ) $null = $PSBoundParameters.Remove('Id') $null = $PSBoundParameters.Remove('NewId') $result = Invoke-CosmosDbRequest @PSBoundParameters ` -Method 'Put' ` -ResourceType 'users' ` -ResourcePath ('users/{0}' -f $Id) ` -Body "{ `"id`": `"$NewId`" }" $user = ConvertFrom-Json -InputObject $result.Content if ($user) { return (Set-CosmosDbUserType -User $user) } } function Set-CosmosDbUserType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $User ) foreach ($item in $User) { $item.PSObject.TypeNames.Insert(0, 'CosmosDB.User') } return $User } function Convert-CosmosDbRequestBody { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateNotNull()] [System.Object] $RequestBodyObject ) <# On PowerShell Core 6.0.x, ConvertTo-Json does not correctly escape this string. See https://github.com/PowerShell/PowerShell/issues/7693 This means that on PowerShell Core, certain strings when passed as Stored Procedure or Function bodies will not be accepted. This means that this issue https://github.com/PlagueHO/CosmosDB/issues/137 needs to remain open. #> return ConvertTo-Json -InputObject $RequestBodyObject -Depth 100 -Compress } function ConvertTo-CosmosDbTokenDateString { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [System.DateTime] $Date ) return $Date.ToUniversalTime().ToString("r", [System.Globalization.CultureInfo]::InvariantCulture) } function Get-CosmosDbBackoffDelay { [CmdletBinding()] [OutputType([System.Int32])] param ( [Parameter()] [CosmosDB.BackoffPolicy] $BackoffPolicy, [Parameter()] [System.Int32] $Retry = 0, [Parameter()] [System.Int32] $RequestedDelay = 0 ) if ($null -ne $BackoffPolicy) { # A back-off policy has been provided Write-Verbose -Message $($LocalizedData.CollectionProvisionedThroughputExceededWithBackoffPolicy) if ($Retry -le $BackoffPolicy.MaxRetries) { switch ($BackoffPolicy.Method) { 'Default' { $backoffPolicyDelay = $backoffPolicy.Delay } 'Additive' { $backoffPolicyDelay = $RequestedDelay + $backoffPolicy.Delay } 'Linear' { $backoffPolicyDelay = $backoffPolicy.Delay * ($Retry + 1) } 'Exponential' { $backoffPolicyDelay = $backoffPolicy.Delay * [Math]::pow(($Retry + 1),2) } 'Random' { $backoffDelayMin = -($backoffPolicy.Delay/2) $backoffDelayMax = $backoffPolicy.Delay/2 $backoffPolicyDelay = $backoffPolicy.Delay + (Get-Random -Minimum $backoffDelayMin -Maximum $backoffDelayMax) } } if ($backoffPolicyDelay -gt $RequestedDelay) { $delay = $backoffPolicyDelay Write-Verbose -Message $($LocalizedData.BackOffPolicyAppliedPolicyDelay -f $BackoffPolicy.Method, $backoffPolicyDelay, $requestedDelay) } else { $delay = $requestedDelay Write-Verbose -Message $($LocalizedData.BackOffPolicyAppliedRequestedDelay -f $BackoffPolicy.Method, $backoffPolicyDelay, $requestedDelay) } return $delay } else { Write-Verbose -Message $($LocalizedData.CollectionProvisionedThroughputExceededMaxRetriesHit -f $BackoffPolicy.MaxRetries) return $null } } else { # A back-off policy has not been defined Write-Verbose -Message $($LocalizedData.CollectionProvisionedThroughputExceededNoBackoffPolicy) return $null } } function Get-CosmosDbUri { [CmdletBinding()] [OutputType([uri])] param ( [Parameter(Mandatory = $true)] [System.String] $Account, [Parameter()] [System.String] $BaseUri = 'documents.azure.com' ) return [uri]::new(('https://{0}.{1}' -f $Account, $BaseUri)) } function Invoke-CosmosDbRequest { [CmdletBinding(DefaultParameterSetName = 'Context')] [OutputType([System.String])] param ( [Alias("Connection")] [Parameter(Mandatory = $true, ParameterSetName = 'Context')] [ValidateNotNullOrEmpty()] [CosmosDB.Context] $Context, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [ValidateNotNullOrEmpty()] [System.String] $Account, [Parameter()] [System.String] $Database, [Parameter()] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateSet('Delete', 'Get', 'Head', 'Merge', 'Options', 'Patch', 'Post', 'Put', 'Trace')] [System.String] $Method = 'Get', [Parameter(Mandatory = $True)] [ValidateSet('attachments', 'colls', 'dbs', 'docs', 'users', 'permissions', 'triggers', 'sprocs', 'udfs', 'offers')] [System.String] $ResourceType, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ResourcePath, [Parameter()] [System.String] $Body = '', [Parameter()] [ValidateSet('2014-08-21', '2015-04-08', '2015-06-03', '2015-08-06', '2015-12-16', '2016-07-11', '2017-01-19', '2017-02-22')] [System.String] $ApiVersion = '2017-02-22', [Parameter()] [Hashtable] $Headers = @{}, [Parameter()] [System.String] $ContentType = 'application/json', [Parameter()] [ValidateSet('Default', 'UTF-8')] [System.String] $Encoding = 'Default' ) if ($PSCmdlet.ParameterSetName -eq 'Account') { $Context = New-CosmosDbContext -Account $Account -Database $Database -Key $Key -KeyType $KeyType } if (-not ($PSBoundParameters.ContainsKey('Database'))) { $Database = $Context.Database } # Generate the resource link value that will be used in the URI and to generate the resource id switch ($resourceType) { 'dbs' { # Request for a database object (not containined in a database) if ([String]::IsNullOrEmpty($ResourcePath)) { $ResourceLink = 'dbs' } else { $resourceLink = $ResourcePath $resourceId = $resourceLink } } 'offers' { # Request for an offer object (not contained in a database) if ([String]::IsNullOrEmpty($ResourcePath)) { $ResourceLink = 'offers' } else { $resourceLink = $ResourcePath $resourceId = ($ResourceLink -split '/')[1].ToLowerInvariant() } } default { # Request for an object that is within a database $resourceLink = ('dbs/{0}' -f $Database) if ($PSBoundParameters.ContainsKey('ResourcePath')) { $resourceLink = ('{0}/{1}' -f $resourceLink, $ResourcePath) } else { $resourceLink = ('{0}/{1}' -f $resourceLink, $ResourceType) } # Generate the resource Id from the resource link value $resourceElements = [System.Collections.ArrayList] ($resourceLink -split '/') if (($resourceElements.Count % 2) -eq 0) { $resourceId = $resourceLink } else { $resourceElements.RemoveAt($resourceElements.Count - 1) $resourceId = $resourceElements -Join '/' } } } # Generate the URI from the base connection URI and the resource link $baseUri = $Context.BaseUri.ToString() $uri = [uri]::New(('{0}{1}' -f $baseUri, $resourceLink)) # Determine the token to use to gain access to the resource $token = $null if ($null -ne $Context.Token) { Write-Verbose -Message $($LocalizedData.FindResourceTokenInContext -f $resourceLink) # Find the most recent token non-expired matching the resource link $matchToken = $context.Token | Where-Object -FilterScript { $_.Resource -eq $resourceLink } if ($matchToken) { # One or more matching tokens could be found Write-Verbose -Message $($LocalizedData.FoundResourceTokenInContext -f $matchToken.Count, $matchToken.Resource) $now = (Get-Date) $validToken = $matchToken | Where-Object -FilterScript { $_.Expires -gt $now } | Sort-Object -Property Expires -Descending | Select-Object -First 1 if ($validToken) { # One or more matching tokens could be found Write-Verbose -Message $($LocalizedData.FoundUnExpiredResourceTokenInContext -f $validToken.Resource, $validToken.TimeStamp) $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($validToken.Token) $decryptedToken = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) $token = [System.Web.HttpUtility]::UrlEncode($decryptedToken) $date = $validToken.TimeStamp $dateString = ConvertTo-CosmosDbTokenDateString -Date $date } else { # No un-expired matching token could be found, so fall back to using a master key if possible Write-Verbose -Message $($LocalizedData.NoMatchingUnexpiredResourceTokenInContext -f $resourceLink) } } else { # No matching token could be found, so fall back to using a master key if possible Write-Verbose -Message $($LocalizedData.NotFoundResourceTokenInContext -f $resourceLink) } } if ($null -eq $token) { <# A token in the context that matched the resource link could not be found. So use the master key to generate the resource link. #> if (-not ($PSBoundParameters.ContainsKey('Key'))) { if (-not [System.String]::IsNullOrEmpty($Context.Key)) { $Key = $Context.Key } } if ([System.String]::IsNullOrEmpty($Key)) { New-CosmosDbInvalidOperationException -Message ($LocalizedData.ErrorAuthorizationKeyEmpty) } # Generate the date used for the authorization token $date = Get-Date $dateString = ConvertTo-CosmosDbTokenDateString -Date $date $token = New-CosmosDbAuthorizationToken ` -Key $Key ` -KeyType $KeyType ` -Method $Method ` -ResourceType $ResourceType ` -ResourceId $resourceId ` -Date $date } $Headers += @{ 'authorization' = $token 'x-ms-date' = $dateString 'x-ms-version' = $ApiVersion } $invokeWebRequestParameters = @{ Uri = $uri Headers = $Headers Method = $method ContentType = $ContentType UseBasicParsing = $true } if ($Method -in ('Put', 'Post', 'Patch')) { if ($Method -eq 'Patch') { $invokeWebRequestParameters['ContentType'] = 'application/json-patch+json' } if ($Encoding -eq 'UTF-8') { <# An encoding type of UTF-8 was passed so explictly set this in the request and convert to the body string to UTF8 bytes. #> $invokeWebRequestParameters['ContentType'] = ('{0}; charset={1}' -f $invokeWebRequestParameters['ContentType'], $Encoding) $invokeWebRequestParameters += @{ Body = [System.Text.Encoding]::UTF8.GetBytes($Body) } } else { $invokeWebRequestParameters += @{ Body = $Body } } } $requestComplete = $false $retry = 0 <# This should initially be set to $false and changed to $true when fatal error is caught #> $fatal = $false do { try { $requestResult = Invoke-WebRequest @invokeWebRequestParameters $requestComplete = $true } catch [System.Net.WebException],[Microsoft.PowerShell.Commands.HttpResponseException] { if ($_.Exception.Response.StatusCode -eq 429) { <# The exception was caused by exceeding provisioned throughput so determine is we should delay and try again or exit #> [System.Int32] $retryAfter = ($_.Exception.Response.Headers | Where-Object -Property Key -eq 'x-ms-retry-after-ms').Value[0] $delay = Get-CosmosDbBackoffDelay ` -BackOffPolicy $Context.BackoffPolicy ` -Retry $retry ` -RequestedDelay $retryAfter # A null delay means retries have been exceeded or no back-off policy specified if ($null -ne $delay) { $retry++ Write-Verbose -Message $($LocalizedData.WaitingBackoffPolicyDelay -f $retry, $delay) Start-Sleep -Milliseconds $delay continue } } if ($_.Exception.Response) { <# Write out additional exception information into the verbose stream In a future version a custom exception type for CosmosDB that contains this additional information. #> if($PSEdition -eq 'Core') { # https://get-powershellblog.blogspot.com/2017/11/powershell-core-web-cmdlets-in-depth.html#L13 $exceptionResponse = $_.ErrorDetails } else { $exceptionStream = $_.Exception.Response.GetResponseStream() $streamReader = New-Object -TypeName System.IO.StreamReader -ArgumentList $exceptionStream $exceptionResponse = $streamReader.ReadToEnd() } if ($exceptionResponse) { Write-Verbose -Message $exceptionResponse } } # A non-recoverable exception occurred $fatal = $true Throw $_ } catch { # A non-recoverable exception occurred $fatal = $true Throw $_ } } while ($requestComplete -eq $false -and -not $fatal) # Display the Request Charge as a verbose message $requestCharge = [Uri]::UnescapeDataString($requestResult.Headers.'x-ms-request-charge').Trim() if ($requestCharge) { Write-Verbose -Message $($LocalizedData.RequestChargeResults -f $method, $uri, $requestCharge) } return $requestResult } function New-CosmosDbAuthorizationToken { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter()] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Parameter()] [ValidateSet('', 'Delete', 'Get', 'Head', 'Merge', 'Options', 'Patch', 'Post', 'Put', 'Trace')] [System.String] $Method = '', [Parameter()] [System.String] $ResourceType = '', [Parameter()] [System.String] $ResourceId = '', [Parameter(Mandatory = $true)] [System.DateTime] $Date, [Parameter()] [ValidateSet('1.0')] [System.String] $TokenVersion = '1.0' ) Write-Verbose -Message $($LocalizedData.CreateAuthorizationToken -f $Method, $ResourceType, $ResourceId, $Date) $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Key) $decryptedKey = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) $base64Key = [System.Convert]::FromBase64String($decryptedKey) $hmacSha256 = New-Object -TypeName System.Security.Cryptography.HMACSHA256 -ArgumentList (, $base64Key) $dateString = ConvertTo-CosmosDbTokenDateString -Date $Date $payLoad = @( $Method.ToLowerInvariant() + "`n" + ` $ResourceType.ToLowerInvariant() + "`n" + ` $ResourceId + "`n" + ` $dateString.ToLowerInvariant() + "`n" + ` "" + "`n" ) $body = [System.Text.Encoding]::UTF8.GetBytes($payLoad) $hashPayLoad = $hmacSha256.ComputeHash($body) $signature = [Convert]::ToBase64String($hashPayLoad) Add-Type -AssemblyName 'System.Web' $token = [System.Web.HttpUtility]::UrlEncode(('type={0}&ver={1}&sig={2}' -f $KeyType, $TokenVersion, $signature)) return $token } function New-CosmosDbBackoffPolicy { [CmdletBinding()] [OutputType([System.Management.Automation.PSCustomObject])] param ( [Parameter()] [System.Int32] $MaxRetries = 10, [Parameter()] [ValidateSet('Default', 'Additive', 'Linear', 'Exponential', 'Random')] [System.String] $Method = 'Default', [Parameter()] [ValidateRange(0, 3600000)] [System.Int32] $Delay = 0 ) $backoffPolicy = New-Object -TypeName 'CosmosDB.BackoffPolicy' -Property @{ MaxRetries = $MaxRetries Method = $Method Delay = $Delay } return $backoffPolicy } function New-CosmosDbContext { [CmdletBinding( SupportsShouldProcess = $true, DefaultParameterSetName = 'Account' )] [OutputType([System.Management.Automation.PSCustomObject])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope = 'Function')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [Parameter(Mandatory = $true, ParameterSetName = 'Token')] [Parameter(Mandatory = $true, ParameterSetName = 'AzureAccount')] [ValidateScript({ Assert-CosmosDbAccountNameValid -Name $_ })] [System.String] $Account, [Parameter()] [ValidateScript({ Assert-CosmosDbDatabaseIdValid -Id $_ })] [System.String] $Database, [Parameter(Mandatory = $true, ParameterSetName = 'Account')] [Parameter(ParameterSetName = 'Emulator')] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Key, [Parameter(ParameterSetName = 'Account')] [ValidateSet('master', 'resource')] [System.String] $KeyType = 'master', [Alias("ResourceGroup")] [Parameter(Mandatory = $true, ParameterSetName = 'AzureAccount')] [ValidateScript({ Assert-CosmosDbResourceGroupNameValid -ResourceGroupName $_ })] [System.String] $ResourceGroupName, [Parameter(ParameterSetName = 'AzureAccount')] [ValidateSet('PrimaryMasterKey', 'SecondaryMasterKey', 'PrimaryReadonlyMasterKey', 'SecondaryReadonlyMasterKey')] [System.String] $MasterKeyType = 'PrimaryMasterKey', [Parameter(ParameterSetName = 'Emulator')] [Switch] $Emulator, [Parameter(ParameterSetName = 'Emulator')] [System.Int16] $Port = 8081, [Parameter(ParameterSetName = 'Emulator')] [System.String] $URI = 'localhost', [Parameter(Mandatory = $true, ParameterSetName = 'Token')] [Parameter(ParameterSetName = 'Emulator')] [ValidateNotNullOrEmpty()] [CosmosDB.ContextToken[]] $Token, [Parameter()] [ValidateNotNullOrEmpty()] [CosmosDB.BackoffPolicy] $BackoffPolicy ) switch ($PSCmdlet.ParameterSetName) { 'Emulator' { $Account = 'emulator' if (-not ($PSBoundParameters.ContainsKey('Key'))) { # This is a publically known fixed master key (see https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator#authenticating-requests) $Key = ConvertTo-SecureString ` -String 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==' ` -AsPlainText ` -Force } $BaseUri = [uri]::new(('https://{0}:{1}' -f $URI, $Port)) } 'AzureAccount' { try { $null = Get-AzContext -ErrorAction SilentlyContinue } catch { $null = Connect-AzAccount } $Key = Get-CosmosDbAccountMasterKey ` -ResourceGroupName $ResourceGroupName ` -Name $Account ` -MasterKeyType $MasterKeyType $BaseUri = (Get-CosmosDbUri -Account $Account) } 'Account' { $BaseUri = (Get-CosmosDbUri -Account $Account) } 'Token' { $BaseUri = (Get-CosmosDbUri -Account $Account) } } if ($PSCmdlet.ShouldProcess('Azure', ($LocalizedData.ShouldCreateAzureCosmosDBContext -f $Account, $Database, $BaseUri))) { $context = New-Object -TypeName 'CosmosDB.Context' -Property @{ Account = $Account Database = $Database Key = $Key KeyType = $KeyType BaseUri = $BaseUri Token = $Token BackoffPolicy = $BackoffPolicy } return $context } } function New-CosmosDbContextToken { [CmdletBinding()] [OutputType([System.Management.Automation.PSCustomObject])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope = 'Function')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Resource, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.DateTime] $TimeStamp, [Parameter()] [ValidateRange(600, 18000)] [System.Int32] $TokenExpiry = 3600, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Security.SecureString] $Token ) $contextToken = New-Object -TypeName 'CosmosDB.ContextToken' -Property @{ Resource = $Resource TimeStamp = $TimeStamp Expires = $TimeStamp.AddSeconds($TokenExpiry) Token = $Token } return $contextToken } function New-CosmosDbInvalidArgumentException { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Message, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ArgumentName ) $argumentException = New-Object -TypeName 'ArgumentException' -ArgumentList @( $Message, $ArgumentName ) $newObjectParams = @{ TypeName = 'System.Management.Automation.ErrorRecord' ArgumentList = @( $argumentException, $ArgumentName, 'InvalidArgument', $null ) } $errorRecord = New-Object @newObjectParams throw $errorRecord } function New-CosmosDbInvalidOperationException { [CmdletBinding()] param ( [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $Message, [Parameter()] [ValidateNotNull()] [System.Management.Automation.ErrorRecord] $ErrorRecord ) if ($null -eq $Message) { $invalidOperationException = New-Object -TypeName 'InvalidOperationException' } elseif ($null -eq $ErrorRecord) { $invalidOperationException = New-Object -TypeName 'InvalidOperationException' -ArgumentList @( $Message ) } else { $invalidOperationException = New-Object -TypeName 'InvalidOperationException' -ArgumentList @( $Message, $ErrorRecord.Exception ) } $newObjectParams = @{ TypeName = 'System.Management.Automation.ErrorRecord' ArgumentList = @( $invalidOperationException.ToString(), 'MachineStateIncorrect', 'InvalidOperation', $null ) } $errorRecordToThrow = New-Object @newObjectParams throw $errorRecordToThrow } #endregion # Add Aliases New-Alias -Name 'New-CosmosDbConnection' -Value 'New-CosmosDbContext' -Force |