Создание базы данных и коллекции на Cosmos Db (SQL API) внутри AzureDevOpps (VSTS) - PullRequest
0 голосов
/ 09 октября 2018

У нас есть бизнес-требование, согласно которому мы должны создать базу данных и коллекцию (ы) как часть нашего шага на компакт-диске внутри AzureDevOps.Насколько показывают мои исследования, это невозможно сделать с помощью ARM.

Билет в службу поддержки MS подтверждает, что это невозможно в ARM и должно быть сделано в вашем приложении.Как уже упоминалось, бизнес-требования не позволяют нам сделать это.

Базовые опции программно или REST API Cosmos Db.

1 Ответ

0 голосов
/ 09 октября 2018

Я в конечном итоге получил это с помощью сценария PowerShell!С помощью этой и этой публикаций я смог начать - Они особенно помогли с маркером аутентификации.

Затем я сослался на документы MS на КосмосеDb SQL REST API: Создание базы данных & Создание коллекции

Вот мой сценарий PS (работает в AzureDevOps / VSTS во время публикации):

param($endpoint, $masterKey, $databaseName, $collectionName, $collectionRUs)
Add-Type -AssemblyName System.Web

Add-Type -TypeDefinition @"
public enum CosmosResourceType
{
  Database,
  Collection
}
"@

Function Create-Resource
{
[CmdletBinding()]
Param
(
    [Parameter(Mandatory=$true)][String]$endPoint,
    [Parameter(Mandatory=$true)][String]$masterKey,
    [Parameter(Mandatory=$true)][String]$dataBaseName,
    [Parameter(Mandatory=$true)][String]$collectionName,
    [Parameter(Mandatory=$true)][CosmosResourceType]$cosmosResourceType
)

$verb = "POST";
$resourceType = "dbs";
$resourceLink = "dbs";
$header = "";
$idValue = "";
$contentType = "application/json";
$queryUri = "$endPoint$resourceLink"

if($cosmosResourceType -eq "Database")
{
    $header = Generate-Headers -verb $verb -resourceType $resourceType -key $masterKey
    $idValue = $dataBaseName        
}
elseif($cosmosResourceType -eq "Collection")
{
    $resourceType = "colls";
    $resourceLink = "dbs/$dataBaseName" 
    $header = Generate-Headers -verb $verb -resourceType $resourceType -resourceLink $resourceLink -key $masterKey

    # Not sure why but at this moment Cosmos Db ignores this setting
    $header | Add-Member -Name 'x-ms-offer-throughput' -Type NoteProperty -Value $collectionRUs

    $idValue = $collectionName
    $queryUri = "$endPoint$resourceLink/colls"
}
else
{
    Write-Host "Invalid Cosmos Resource Type:"$cosmosResourceType -ForeGroundColor Red 
}

$jsonDoc = [pscustomobject]@{ id = $idValue }
$jsonDoc = $jsonDoc | ConvertTo-Json

$response = InvokeRest -verb $Verb -ContentType $contentType -uri $queryUri -headers $header -body $jsonDoc

if($response.code.ToLowerInvariant() -eq "Conflict".ToLowerInvariant())
{
    Write-Host "Warning: $cosmosResourceType already existing" -ForeGroundColor Yellow  
}
elseif($response.code.ToLowerInvariant() -eq "Ok".ToLowerInvariant())
{
    Write-Host "$cosmosResourceType Created" -ForeGroundColor Green 
}
else
{
    Write-Host "response:"$response -ForeGroundColor Red 
}    
}

Function InvokeRest
{
[CmdletBinding()]
Param
(
    [Parameter(Mandatory=$true)]$verb,
    [Parameter(Mandatory=$true)]$contentType,
    [Parameter(Mandatory=$true)]$uri,    
    [Parameter(Mandatory=$true)]$headers,
    [Parameter(Mandatory=$false)]$body    
)

Try {
    $result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $uri -Headers $headers -Body $body
    Write-Host "InvokeRest: "$result -ForeGroundColor Green 

    $response = [pscustomobject]@{
        code = "OK"
        body = $result
    }

    return $response
}
Catch {        
    # Check if there is a response.
    if ($_.Exception.Response -eq $null) {
        $expMessage = $_.Exception.Message
        $failedItem = $_.Exception.Source
        $line = $_.InvocationInfo.ScriptLineNumber
        Write-Host "At $($line):`r`n$expMessage `r`n$failedItem" -ForeGroundColor Red   
        throw $_.Exception         
    }
    else {
        # Get the response body with more error detail.
        $respStream = $_.Exception.Response.GetResponseStream()
        $reader = New-Object System.IO.StreamReader($respStream)
        $response = $reader.ReadToEnd() | ConvertFrom-Json
        return $response
    } 
}
}

Function Generate-Headers
{
[CmdletBinding()]
Param
(
    [Parameter(Mandatory=$true)][String]$verb,
    [Parameter(Mandatory=$false)][String]$resourceLink,
    [Parameter(Mandatory=$true)][String]$resourceType,    
    [Parameter(Mandatory=$true)][String]$key    
)

$dateTime = [DateTime]::UtcNow.ToString("r")
$authHeader = Generate-MasterKeyAuthorizationSignature -verb $verb -resourceLink $resourceLink -resourceType $resourceType -key $masterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime
Write-Host $authHeader
$header = @{authorization=$authHeader;"x-ms-version"="2017-02-22";"x-ms-date"=$dateTime}

return $header
}

Function Generate-MasterKeyAuthorizationSignature
{
[CmdletBinding()]
Param
(
    [Parameter(Mandatory=$true)][String]$verb,
    [Parameter(Mandatory=$false)][String]$resourceLink,
    [Parameter(Mandatory=$true)][String]$resourceType,    
    [Parameter(Mandatory=$true)][String]$key,
    [Parameter(Mandatory=$true)][String]$keyType,
    [Parameter(Mandatory=$true)][String]$tokenVersion,
    [Parameter(Mandatory=$true)][String]$dateTime
)

$hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacSha256.Key = [System.Convert]::FromBase64String($key)

$payLoad = Generate-Payload -verb $verb -resourceLink $resourceLink -resourceType $resourceType -dateTime $dateTime
$hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad))
$signature = [System.Convert]::ToBase64String($hashPayLoad);

[System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature")
}

Function Generate-Payload
{
[CmdletBinding()]
Param
(
    [Parameter(Mandatory=$true)][String]$verb,
    [Parameter(Mandatory=$false)][String]$resourceLink,
    [Parameter(Mandatory=$true)][String]$resourceType,
    [Parameter(Mandatory=$true)][String]$dateTime
)

$payLoad = ""

if ( [string]::IsNullOrEmpty($resourceLink) ) 
{ 
    $payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n`n$($dateTime.ToLowerInvariant())`n`n"
}    
else 
{
    $payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n"
} 


return $payLoad
}

# Create Database
$cosmosResourceType =  [CosmosResourceType]::Database
Create-Resource -endPoint $endpoint -masterKey $masterKey -dataBaseName $databaseName -collectionName $collectionName -cosmosResourceType $cosmosResourceType

# Create Collection
$cosmosResourceType =  [CosmosResourceType]::Collection
Create-Resource -endPoint $endpoint -masterKey $masterKey -dataBaseName $databaseName -collectionName $collectionName -cosmosResourceType $cosmosResourceType

Надеюсь, это поможет кому-то еще.

...