-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathdeploy-dab-container-app.ps1
More file actions
352 lines (290 loc) · 13.2 KB
/
deploy-dab-container-app.ps1
File metadata and controls
352 lines (290 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
#Requires -Version 7.0
<#
.SYNOPSIS
Deploy Data API Builder (DAB) to Azure Container Apps with Storage Account and Managed Identity
.DESCRIPTION
This script deploys a Data A# Create Azure File share for DAB config
Write-Host "📁 Creating Azure File share for DAB configuration..." -ForegroundColor Blue
az storage share create `
--account-name $storageAccountName `
--name "dab-config" `
--quota 1 `
--output none
Write-Host "✅ Azure File share 'dab-config' created" -ForegroundColor Green application to Azure Container Apps using:
- Azure Storage Account to store the DAB configuration file
- User-assigned Managed Identity for secure access to storage
- Azure Container Registry for storing the DAB container image
- Azure SQL Database connection string from .env file (MSSQL variable)
.PARAMETER ResourceGroupName
Name of the Azure Resource Group (will be created if it doesn't exist)
.PARAMETER Location
Azure region for deployment (default: East US)
.PARAMETER AppName
Base name for all Azure resources (will be used as prefix)
.PARAMETER ContainerAppName
Name of the Container App (default: {AppName}-dab-api)
.PARAMETER Owner
Owner name to be added as a tag to all created resources
.PARAMETER SkipBuild
Skip building and pushing the container image (use existing image)
.NOTES
This script requires a .env file in the current directory with the MSSQL environment variable:
MSSQL="Server=tcp:yourserver.database.windows.net,1433;Database=yourdb;Authentication='Active Directory Default';"
.EXAMPLE
.\deploy-dab-container-app.ps1 -ResourceGroupName "rg-dab-demo" -AppName "dabdemo" -Owner "john.doe@company.com"
.EXAMPLE
.\deploy-dab-container-app.ps1 -ResourceGroupName "rg-dab-demo" -AppName "dabdemo" -Owner "john.doe@company.com" -Location "West US 2" -SkipBuild
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $false)]
[string]$Location = "Central US",
[Parameter(Mandatory = $true)]
[string]$AppName,
[Parameter(Mandatory = $false)]
[string]$ContainerAppName = "$AppName-dab-api",
[Parameter(Mandatory = $true)]
[string]$Owner,
[Parameter(Mandatory = $false)]
[switch]$SkipBuild
)
# Set error action preference
$ErrorActionPreference = "Stop"
# Validate prerequisites
Write-Host "🔍 Validating prerequisites..." -ForegroundColor Blue
# Check if Azure CLI is installed
try {
$azResult = az version --output json 2>$null | ConvertFrom-Json
if (-not $azResult) {
throw "Azure CLI not found"
}
$azVersion = $azResult.'azure-cli'
Write-Host "✅ Azure CLI version: $azVersion" -ForegroundColor Green
}
catch {
Write-Error "❌ Azure CLI is not installed. Please install it from: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli"
exit 1
}
# Check if Docker is installed and running
try {
$dockerVersion = docker version --format '{{.Client.Version}}' 2>$null
if (-not $dockerVersion) {
throw "Docker not found or not running"
}
Write-Host "✅ Docker version: $dockerVersion" -ForegroundColor Green
}
catch {
Write-Error "❌ Docker is not installed or not running. Please install Docker Desktop."
exit 1
}
# Check if logged into Azure
try {
$account = az account show --output json 2>$null | ConvertFrom-Json
if (-not $account) {
throw "Not logged in"
}
Write-Host "✅ Logged into Azure as: $($account.user.name)" -ForegroundColor Green
Write-Host "✅ Using subscription: $($account.name) ($($account.id))" -ForegroundColor Green
}
catch {
Write-Error "❌ Not logged into Azure. Please run 'az login' first."
exit 1
}
# Load environment variables from .env file
Write-Host "📄 Loading environment variables from .env file..." -ForegroundColor Blue
$envFilePath = ".env"
if (-not (Test-Path $envFilePath)) {
Write-Error "❌ .env file not found at: $envFilePath"
exit 1
}
$SqlConnectionString = $null
Get-Content $envFilePath | ForEach-Object {
if ($_ -match '^MSSQL=(.*)$') {
$SqlConnectionString = $matches[1].Trim('"')
}
}
if (-not $SqlConnectionString) {
Write-Error "❌ MSSQL environment variable not found in .env file"
exit 1
}
Write-Host "✅ MSSQL connection string loaded from .env file" -ForegroundColor Green
# Generate unique names for resources
$timestamp = Get-Date -Format "yyyyMMddHHmm"
$uniqueSuffix = "$AppName$timestamp".ToLower() -replace '[^a-z0-9]', ''
$acrName = "acr$($uniqueSuffix.Substring(0, [Math]::Min(15, $uniqueSuffix.Length)))"
$managedIdentityName = "id-$AppName-dab"
$containerAppEnvName = "cae-$AppName"
$logAnalyticsName = "law-$AppName"
Write-Host "🚀 Starting deployment with the following configuration:" -ForegroundColor Blue
Write-Host " Resource Group: $ResourceGroupName" -ForegroundColor White
Write-Host " Location: $Location" -ForegroundColor White
Write-Host " Container Registry: $acrName" -ForegroundColor White
Write-Host " Managed Identity: $managedIdentityName" -ForegroundColor White
Write-Host " Container App Environment: $containerAppEnvName" -ForegroundColor White
Write-Host " Container App: $ContainerAppName" -ForegroundColor White
# Enable required Azure CLI extensions
Write-Host "🔧 Enabling required Azure CLI extensions..." -ForegroundColor Blue
az extension add --name containerapp --upgrade --only-show-errors
az extension add --name log-analytics --only-show-errors
# Register required resource providers
Write-Host "📋 Registering required resource providers..." -ForegroundColor Blue
az provider register --namespace Microsoft.ContainerRegistry --only-show-errors
az provider register --namespace Microsoft.App --only-show-errors
az provider register --namespace Microsoft.OperationalInsights --only-show-errors
# Create resource group
Write-Host "📁 Creating resource group..." -ForegroundColor Blue
az group create --name $ResourceGroupName --location $Location --tags "Owner=$Owner" --output none
Write-Host "✅ Resource group '$ResourceGroupName' created/updated" -ForegroundColor Green
# Create user-assigned managed identity
Write-Host "🔐 Creating user-assigned managed identity..." -ForegroundColor Blue
$identityResult = az identity create `
--resource-group $ResourceGroupName `
--name $managedIdentityName `
--location $Location `
--tags "Owner=$Owner" `
--output json | ConvertFrom-Json
$identityId = $identityResult.id
$identityClientId = $identityResult.clientId
$identityPrincipalId = $identityResult.principalId
Write-Host "✅ Managed identity created: $managedIdentityName" -ForegroundColor Green
Write-Host " Client ID: $identityClientId" -ForegroundColor White
Write-Host " Principal ID: $identityPrincipalId" -ForegroundColor White
# Create Azure Container Registry
Write-Host "📒 Creating Azure Container Registry..." -ForegroundColor Blue
az acr create `
--resource-group $ResourceGroupName `
--name $acrName `
--sku Basic `
--location $Location `
--admin-enabled false `
--tags "Owner=$Owner" `
--output none
Write-Host "✅ Container registry '$acrName' created" -ForegroundColor Green
# Assign AcrPull role to managed identity
Write-Host "🔒 Assigning AcrPull role to managed identity..." -ForegroundColor Blue
$acrId = az acr show --resource-group $ResourceGroupName --name $acrName --query id --output tsv
az role assignment create `
--assignee $identityPrincipalId `
--role "AcrPull" `
--scope $acrId `
--output none
Write-Host "✅ AcrPull role assigned to managed identity" -ForegroundColor Green
# Build and push DAB container image with embedded config
if (-not $SkipBuild) {
Write-Host "🔨 Building and pushing DAB container image from docker folder..." -ForegroundColor Blue
# Verify docker folder and files exist
$dabFolder = "dab"
$dockerfilePath = "$dabFolder\Dockerfile"
$configPath = "$dabFolder\dab-config.json"
if (-not (Test-Path $dabFolder)) {
Write-Error "❌ DAB folder not found at: $dabFolder"
exit 1
}
if (-not (Test-Path $dockerfilePath)) {
Write-Error "❌ Dockerfile not found at: $dockerfilePath"
exit 1
}
if (-not (Test-Path $configPath)) {
Write-Error "❌ DAB configuration file not found at: $configPath"
exit 1
}
Write-Host " Using Dockerfile: $dockerfilePath" -ForegroundColor White
Write-Host " Using DAB config: $configPath" -ForegroundColor White
# Login to ACR using expose-token method
Write-Host " Logging into ACR..." -ForegroundColor White
$acrToken = az acr login --name $acrName --expose-token --output json | ConvertFrom-Json
# Login to Docker using the ACR token
$acrToken.accessToken | docker login $acrToken.loginServer --username 00000000-0000-0000-0000-000000000000 --password-stdin
$imageTag = "$acrName.azurecr.io/dab-api:latest"
Write-Host " Building container image..." -ForegroundColor White
docker build -t $imageTag -f $dockerfilePath $dockerFolder
Write-Host " Pushing container image..." -ForegroundColor White
docker push $imageTag
Write-Host "✅ Container image built and pushed: $imageTag" -ForegroundColor Green
}
else {
$imageTag = "$acrName.azurecr.io/dab-api:latest"
Write-Host "⏭️ Skipping build, using existing image: $imageTag" -ForegroundColor Yellow
}
# Create Log Analytics workspace
Write-Host "📊 Creating Log Analytics workspace..." -ForegroundColor Blue
az monitor log-analytics workspace create `
--resource-group $ResourceGroupName `
--workspace-name $logAnalyticsName `
--location $Location `
--tags "Owner=$Owner" `
--output none
$logAnalyticsId = az monitor log-analytics workspace show `
--resource-group $ResourceGroupName `
--workspace-name $logAnalyticsName `
--query customerId `
--output tsv
$logAnalyticsKey = az monitor log-analytics workspace get-shared-keys `
--resource-group $ResourceGroupName `
--workspace-name $logAnalyticsName `
--query primarySharedKey `
--output tsv
Write-Host "✅ Log Analytics workspace created" -ForegroundColor Green
# Create Container App Environment
Write-Host "🌍 Creating Container App Environment..." -ForegroundColor Blue
az containerapp env create `
--resource-group $ResourceGroupName `
--name $containerAppEnvName `
--location $Location `
--logs-workspace-id $logAnalyticsId `
--logs-workspace-key $logAnalyticsKey `
--tags "Owner=$Owner" `
--output none
Write-Host "✅ Container App Environment '$containerAppEnvName' created" -ForegroundColor Green
# Create Container App
Write-Host "🚀 Creating Container App..." -ForegroundColor Blue
az containerapp create `
--resource-group $ResourceGroupName `
--name $ContainerAppName `
--environment $containerAppEnvName `
--image $imageTag `
--target-port 5000 `
--ingress external `
--min-replicas 1 `
--max-replicas 10 `
--cpu 2 `
--memory 4Gi `
--registry-server "$acrName.azurecr.io" `
--user-assigned $identityId `
--env-vars "MSSQL=$SqlConnectionString" `
--tags "Owner=$Owner" `
--output none
Write-Host "✅ Container App '$ContainerAppName' created" -ForegroundColor Green
# Get Container App URL
$containerAppUrl = az containerapp show `
--resource-group $ResourceGroupName `
--name $ContainerAppName `
--query properties.configuration.ingress.fqdn `
--output tsv
Write-Host "🎉 Deployment completed successfully!" -ForegroundColor Green
Write-Host ""
Write-Host "📋 Deployment Summary:" -ForegroundColor Blue
Write-Host " Container App URL: https://$containerAppUrl" -ForegroundColor White
Write-Host " API Endpoint: https://$containerAppUrl/rest" -ForegroundColor White
Write-Host " Health Check: https://$containerAppUrl/health" -ForegroundColor White
Write-Host " Resource Group: $ResourceGroupName" -ForegroundColor White
Write-Host " Container Registry: $acrName" -ForegroundColor White
Write-Host " Container Image: $imageTag" -ForegroundColor White
Write-Host " Managed Identity: $managedIdentityName" -ForegroundColor White
Write-Host ""
Write-Host "🔗 Useful Commands:" -ForegroundColor Blue
Write-Host " View logs: az containerapp logs show --name $ContainerAppName --resource-group $ResourceGroupName --follow" -ForegroundColor White
Write-Host " Update config: Modify swa-db-connections/staticwebapp.database.config.json and rebuild/redeploy" -ForegroundColor White
Write-Host " Rebuild image: docker build -t $imageTag -f Dockerfile.dab . && docker push $imageTag" -ForegroundColor White
Write-Host " Restart app: az containerapp revision restart --name $ContainerAppName --resource-group $ResourceGroupName" -ForegroundColor White
Write-Host ""
Write-Host "🧪 Test your API:" -ForegroundColor Blue
Write-Host " curl https://$containerAppUrl/rest/samples" -ForegroundColor White
Write-Host " curl https://$containerAppUrl/rest/findSamples -X POST -H 'Content-Type: application/json' -d '{\"query\": \"semantic search\"}'" -ForegroundColor White
# Optional: Open the URL in default browser
$openUrl = Read-Host "Would you like to open the Container App URL in your browser? (y/N)"
if ($openUrl -eq 'y' -or $openUrl -eq 'Y') {
Start-Process "https://$containerAppUrl"
}