Skip to content

Commit b0601af

Browse files
authored
AI resources automated connection
Added role assignments for storage account permissions and automated AI model deployments. Created .env file for Azure resource configuration.
1 parent 03d8368 commit b0601af

1 file changed

Lines changed: 319 additions & 0 deletions

File tree

terraform-infrastructure/main.tf

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,322 @@ resource "azurerm_role_assignment" "search_project_contributor" {
278278
principal_id = azurerm_search_service.search.identity[0].principal_id
279279
principal_type = "ServicePrincipal"
280280
}
281+
282+
# Storage account permissions for Azure AI Foundry project
283+
resource "azurerm_role_assignment" "storage_blob_data_contributor_user" {
284+
scope = azapi_resource.storage.id
285+
role_definition_id = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe"
286+
principal_id = local.principal_id
287+
principal_type = "User"
288+
}
289+
290+
resource "azurerm_role_assignment" "storage_blob_data_contributor_project" {
291+
scope = azapi_resource.storage.id
292+
role_definition_id = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe"
293+
principal_id = azapi_resource.ai_project.identity[0].principal_id
294+
principal_type = "ServicePrincipal"
295+
}
296+
297+
# Azure AI model deployments automation
298+
resource "null_resource" "ai_model_deployments" {
299+
count = var.enable_ai_automation ? 1 : 0
300+
301+
depends_on = [
302+
azapi_resource.ai_project,
303+
azapi_resource.ai_foundry,
304+
azurerm_role_assignment.storage_blob_data_contributor_user
305+
]
306+
307+
provisioner "local-exec" {
308+
command = <<-EOT
309+
# Create AI model deployments
310+
Write-Host "Creating Azure AI model deployments..."
311+
312+
# Wait for AI Foundry to be fully ready
313+
Write-Host "Waiting for AI Foundry to be ready..."
314+
Start-Sleep -Seconds 30
315+
316+
try {
317+
# Create gpt-4o-mini deployment
318+
Write-Host "Creating gpt-4o-mini deployment..."
319+
az cognitiveservices account deployment create `
320+
--resource-group "${azurerm_resource_group.rg.name}" `
321+
--name "${local.ai_foundry_name}" `
322+
--deployment-name "gpt-4o-mini" `
323+
--model-name "gpt-4o-mini" `
324+
--model-version "2024-07-18" `
325+
--model-format "OpenAI" `
326+
--sku-capacity 10 `
327+
--sku-name "GlobalStandard"
328+
329+
if ($LASTEXITCODE -eq 0) {
330+
Write-Host "gpt-4o-mini deployment created successfully"
331+
} else {
332+
Write-Host "gpt-4o-mini deployment may already exist or failed to create"
333+
} # Create text-embedding-3-small deployment
334+
Write-Host "Creating text-embedding-3-small deployment..."
335+
az cognitiveservices account deployment create `
336+
--resource-group "${azurerm_resource_group.rg.name}" `
337+
--name "${local.ai_foundry_name}" `
338+
--deployment-name "text-embedding-3-small" `
339+
--model-name "text-embedding-3-small" `
340+
--model-version "1" `
341+
--model-format "OpenAI" `
342+
--sku-capacity 10 `
343+
--sku-name "GlobalStandard"
344+
345+
if ($LASTEXITCODE -eq 0) {
346+
Write-Host "text-embedding-3-small deployment created successfully"
347+
} else {
348+
Write-Host "text-embedding-3-small deployment may already exist or failed to create"
349+
} # Create phi-4 deployment
350+
Write-Host "Creating phi-4 deployment..."
351+
try {
352+
az cognitiveservices account deployment create `
353+
--resource-group "${azurerm_resource_group.rg.name}" `
354+
--name "${local.ai_foundry_name}" `
355+
--deployment-name "phi-4" `
356+
--model-name "phi-4" `
357+
--model-version "1" `
358+
--model-format "OpenAI" `
359+
--sku-capacity 5 `
360+
--sku-name "GlobalStandard"
361+
362+
if ($LASTEXITCODE -eq 0) {
363+
Write-Host "phi-4 deployment created successfully"
364+
$phi4Available = $true
365+
} else {
366+
Write-Host "phi-4 model not available in this region/tier, skipping"
367+
$phi4Available = $false
368+
}
369+
} catch {
370+
Write-Host "phi-4 model not supported, skipping"
371+
$phi4Available = $false
372+
}
373+
374+
# List all deployments to verify
375+
Write-Host "`nCurrent model deployments:"
376+
az cognitiveservices account deployment list `
377+
--resource-group "${azurerm_resource_group.rg.name}" `
378+
--name "${local.ai_foundry_name}" `
379+
--query "[].{Name:name,Model:properties.model.name,Version:properties.model.version,Capacity:properties.currentCapacity}" `
380+
--output table
381+
382+
Write-Host "`nModel deployment process completed successfully."
383+
}
384+
catch {
385+
Write-Host "Error during model deployment: $_"
386+
Write-Host "This may be expected if deployments already exist."
387+
}
388+
EOT
389+
interpreter = ["PowerShell", "-Command"]
390+
}
391+
392+
triggers = {
393+
ai_foundry_id = azapi_resource.ai_foundry.id
394+
ai_project_id = azapi_resource.ai_project.id
395+
}
396+
}
397+
398+
# Connect resources to Azure AI Foundry project
399+
resource "null_resource" "ai_project_connections" {
400+
count = var.enable_ai_automation ? 1 : 0
401+
402+
depends_on = [
403+
null_resource.ai_model_deployments,
404+
azurerm_application_insights.appinsights,
405+
azapi_resource.storage
406+
]
407+
408+
provisioner "local-exec" {
409+
command = <<-EOT
410+
Write-Host "Verifying Azure AI Foundry project configuration..."
411+
412+
# Check if Azure ML extension is installed
413+
$mlExtension = az extension list --query "[?name=='ml'].name" --output tsv
414+
if (-not $mlExtension) {
415+
Write-Host "Installing Azure ML extension..."
416+
az extension add --name ml
417+
}
418+
419+
# Set the AI project as the default workspace for future ML operations
420+
az config set defaults.workspace="${local.ai_project_name}"
421+
az config set defaults.group="${azurerm_resource_group.rg.name}"
422+
423+
Write-Host "Azure AI project configuration completed successfully."
424+
Write-Host "Project Name: ${local.ai_project_name}"
425+
Write-Host "AI Foundry: ${local.ai_foundry_name}"
426+
Write-Host "Resource Group: ${azurerm_resource_group.rg.name}"
427+
EOT
428+
interpreter = ["PowerShell", "-Command"]
429+
}
430+
431+
triggers = {
432+
storage_id = azapi_resource.storage.id
433+
app_insights_id = azurerm_application_insights.appinsights.id
434+
ai_project_id = azapi_resource.ai_project.id
435+
}
436+
}
437+
438+
# Create .env file with all necessary configuration
439+
resource "null_resource" "create_env_file" {
440+
count = var.enable_ai_automation ? 1 : 0
441+
442+
depends_on = [
443+
null_resource.ai_project_connections,
444+
azurerm_cosmosdb_account.cosmos,
445+
azurerm_search_service.search
446+
]
447+
448+
provisioner "local-exec" {
449+
command = <<-EOT
450+
Write-Host "Creating .env file with Azure resource configuration..."
451+
452+
# Create src directory if it doesn't exist
453+
if (!(Test-Path "../src")) {
454+
New-Item -ItemType Directory -Path "../src" -Force
455+
}
456+
457+
# Get Azure AI Foundry endpoint
458+
$aiFoundryEndpoint = az cognitiveservices account show `
459+
--resource-group "${azurerm_resource_group.rg.name}" `
460+
--name "${local.ai_foundry_name}" `
461+
--query "properties.endpoint" `
462+
--output tsv
463+
464+
# Get Azure AI Foundry access key
465+
$aiFoundryKey = az cognitiveservices account keys list `
466+
--resource-group "${azurerm_resource_group.rg.name}" `
467+
--name "${local.ai_foundry_name}" `
468+
--query "key1" `
469+
--output tsv
470+
471+
# Get Cosmos DB primary key
472+
$cosmosKey = az cosmosdb keys list `
473+
--resource-group "${azurerm_resource_group.rg.name}" `
474+
--name "${local.cosmos_account_name}" `
475+
--query "primaryMasterKey" `
476+
--output tsv
477+
478+
# Get Azure Search admin key
479+
$searchKey = az search admin-key show `
480+
--resource-group "${azurerm_resource_group.rg.name}" `
481+
--service-name "${local.search_service_name}" `
482+
--query "primaryKey" `
483+
--output tsv
484+
485+
# Get storage account connection string
486+
$storageConnectionString = az storage account show-connection-string `
487+
--resource-group "${azurerm_resource_group.rg.name}" `
488+
--name "${local.storage_account}" `
489+
--query "connectionString" `
490+
--output tsv
491+
492+
# Create .env file content
493+
if ($phi4Available) {
494+
$envContent = @"
495+
# Azure AI Foundry Configuration
496+
AZURE_AI_FOUNDRY_ENDPOINT=$aiFoundryEndpoint
497+
AZURE_AI_FOUNDRY_API_KEY=$aiFoundryKey
498+
AZURE_AI_PROJECT_NAME=${local.ai_project_name}
499+
500+
# Azure OpenAI Model Deployments
501+
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-4o-mini
502+
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-3-small
503+
AZURE_OPENAI_PHI_DEPLOYMENT=phi-4
504+
AZURE_OPENAI_ENDPOINT=$aiFoundryEndpoint
505+
AZURE_OPENAI_API_KEY=$aiFoundryKey
506+
AZURE_OPENAI_API_VERSION=2024-02-01
507+
508+
# Azure Cosmos DB Configuration
509+
COSMOS_DB_ENDPOINT=${azurerm_cosmosdb_account.cosmos.endpoint}
510+
COSMOS_DB_KEY=$cosmosKey
511+
COSMOS_DB_NAME=${local.cosmos_db_name}
512+
COSMOS_DB_CONTAINER_NAME=products
513+
514+
# Azure AI Search Configuration
515+
SEARCH_SERVICE_ENDPOINT=https://${local.search_service_name}.search.windows.net
516+
SEARCH_SERVICE_KEY=$searchKey
517+
SEARCH_INDEX_NAME=products-index
518+
519+
# Azure Storage Configuration
520+
STORAGE_ACCOUNT_NAME=${local.storage_account}
521+
STORAGE_CONNECTION_STRING=$storageConnectionString
522+
523+
# Azure Application Insights
524+
APPLICATION_INSIGHTS_CONNECTION_STRING=${azurerm_application_insights.appinsights.connection_string}
525+
526+
# Azure Resource Information
527+
AZURE_SUBSCRIPTION_ID=${data.azurerm_client_config.current.subscription_id}
528+
AZURE_RESOURCE_GROUP=${azurerm_resource_group.rg.name}
529+
AZURE_LOCATION=${var.location}
530+
"@
531+
} else {
532+
$envContent = @"
533+
# Azure AI Foundry Configuration
534+
AZURE_AI_FOUNDRY_ENDPOINT=$aiFoundryEndpoint
535+
AZURE_AI_FOUNDRY_API_KEY=$aiFoundryKey
536+
AZURE_AI_PROJECT_NAME=${local.ai_project_name}
537+
538+
# Azure OpenAI Model Deployments
539+
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-4o-mini
540+
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-3-small
541+
AZURE_OPENAI_ENDPOINT=$aiFoundryEndpoint
542+
AZURE_OPENAI_API_KEY=$aiFoundryKey
543+
AZURE_OPENAI_API_VERSION=2024-02-01
544+
545+
# Azure Cosmos DB Configuration
546+
COSMOS_DB_ENDPOINT=${azurerm_cosmosdb_account.cosmos.endpoint}
547+
COSMOS_DB_KEY=$cosmosKey
548+
COSMOS_DB_NAME=${local.cosmos_db_name}
549+
COSMOS_DB_CONTAINER_NAME=products
550+
551+
# Azure AI Search Configuration
552+
SEARCH_SERVICE_ENDPOINT=https://${local.search_service_name}.search.windows.net
553+
SEARCH_SERVICE_KEY=$searchKey
554+
SEARCH_INDEX_NAME=products-index
555+
556+
# Azure Storage Configuration
557+
STORAGE_ACCOUNT_NAME=${local.storage_account}
558+
STORAGE_CONNECTION_STRING=$storageConnectionString
559+
560+
# Azure Application Insights
561+
APPLICATION_INSIGHTS_CONNECTION_STRING=${azurerm_application_insights.appinsights.connection_string}
562+
563+
# Azure Resource Information
564+
AZURE_SUBSCRIPTION_ID=${data.azurerm_client_config.current.subscription_id}
565+
AZURE_RESOURCE_GROUP=${azurerm_resource_group.rg.name}
566+
AZURE_LOCATION=${var.location}
567+
"@
568+
}
569+
570+
# Write .env file
571+
$envContent | Out-File -FilePath "../src/.env" -Encoding UTF8
572+
573+
Write-Host ".env file created successfully at ../src/.env"
574+
Write-Host "Environment variables configured for:"
575+
if ($phi4Available) {
576+
Write-Host " - Models: gpt-4o-mini, text-embedding-3-small, phi-4"
577+
} else {
578+
Write-Host " - Models: gpt-4o-mini, text-embedding-3-small (phi-4 not available)"
579+
}
580+
Write-Host " - Azure AI Foundry: ${local.ai_foundry_name}"
581+
Write-Host " - Azure AI Project: ${local.ai_project_name}"
582+
Write-Host " - Cosmos DB: ${local.cosmos_account_name}"
583+
Write-Host " - Search Service: ${local.search_service_name}"
584+
Write-Host " - Storage Account: ${local.storage_account}"
585+
Write-Host " - Application Insights: ${local.app_insights_name}"
586+
EOT
587+
interpreter = ["PowerShell", "-Command"]
588+
}
589+
590+
triggers = {
591+
# Trigger recreation when any of these resources change
592+
ai_foundry_id = azapi_resource.ai_foundry.id
593+
ai_project_id = azapi_resource.ai_project.id
594+
cosmos_id = azurerm_cosmosdb_account.cosmos.id
595+
search_id = azurerm_search_service.search.id
596+
storage_id = azapi_resource.storage.id
597+
app_insights_id = azurerm_application_insights.appinsights.id
598+
}
599+
}

0 commit comments

Comments
 (0)