Skip to content

Commit 82c6792

Browse files
fix: Fixed deployment script issue for AVM module, fixed relative path issues & refactored bicep
1 parent a250c27 commit 82c6792

File tree

9 files changed

+9191
-3715
lines changed

9 files changed

+9191
-3715
lines changed

infra/main.bicep

Lines changed: 146 additions & 164 deletions
Large diffs are not rendered by default.

infra/main.json

Lines changed: 8755 additions & 3507 deletions
Large diffs are not rendered by default.

infra/modules/ai-services.bicep

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ resource cognitiveServiceNew 'Microsoft.CognitiveServices/accounts@2025-06-01' =
190190
? {
191191
defaultAction: networkAcls.?defaultAction
192192
virtualNetworkRules: networkAcls.?virtualNetworkRules ?? []
193-
ipRules: networkAcls.?ipRules ?? []
193+
ipRules: networkAcls.?ipRules ?? []
194194
bypass: networkAcls.?bypass ?? 'None'
195195
}
196196
: null
@@ -236,7 +236,7 @@ resource cognitiveServiceNew 'Microsoft.CognitiveServices/accounts@2025-06-01' =
236236

237237
var existingCognitiveServiceDetails = split(existingFoundryProjectResourceId, '/')
238238

239-
resource cognitiveServiceExisting 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = if(useExistingService) {
239+
resource cognitiveServiceExisting 'Microsoft.CognitiveServices/accounts@2025-09-01' existing = if(useExistingService) {
240240
name: existingCognitiveServiceDetails[8]
241241
scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4])
242242
}
@@ -245,7 +245,7 @@ module cognitive_service_dependencies './dependencies.bicep' = if(!useExistingSe
245245
params: {
246246
projectName: projectName
247247
projectDescription: projectDescription
248-
name: cognitiveServiceNew.name
248+
name: cognitiveServiceNew.name
249249
location: location
250250
deployments: deployments
251251
diagnosticSettings: diagnosticSettings
@@ -259,7 +259,7 @@ module cognitive_service_dependencies './dependencies.bicep' = if(!useExistingSe
259259

260260
module existing_cognitive_service_dependencies './dependencies.bicep' = if(useExistingService) {
261261
params: {
262-
name: cognitiveServiceExisting.name
262+
name: cognitiveServiceExisting.name
263263
projectName: projectName
264264
projectDescription: projectDescription
265265
existingFoundryProjectResourceId: existingFoundryProjectResourceId

infra/modules/dependencies.bicep

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSetti
248248
}
249249
]
250250

251-
module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [
251+
module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.1' = [
252252
for (privateEndpoint, index) in (privateEndpoints ?? []): {
253253
name: '${uniqueString(deployment().name, location)}-cognitiveService-PrivateEndpoint-${index}'
254254
scope: resourceGroup(
@@ -322,7 +322,6 @@ resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignmen
322322
}
323323
]
324324

325-
326325
module aiProject 'project.bicep' = if(!empty(projectName) || !empty(existingFoundryProjectResourceId)) {
327326
name: take('${name}-ai-project-${projectName}-deployment', 64)
328327
params: {

infra/modules/virtualNetwork.bicep

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Networking - NSGs, VNET and Subnets. Each subnet has its own NSG
33
/****************************************************************************************************************************/
44
@description('Name of the virtual network.')
5-
param name string
5+
param name string
66

77
@description('Azure region to deploy resources.')
88
param location string = resourceGroup().location
@@ -155,14 +155,14 @@ param subnets subnetType[] = [
155155
}
156156
}
157157
{
158-
name: 'deployment-scripts'
159-
addressPrefixes: ['10.0.4.0/24']
160-
networkSecurityGroup: {
161-
name: 'nsg-deployment-scripts'
162-
securityRules: []
163-
}
164-
delegation: 'Microsoft.ContainerInstance/containerGroups'
165-
serviceEndpoints: ['Microsoft.Storage']
158+
name: 'deployment-scripts'
159+
addressPrefixes: ['10.0.4.0/24']
160+
networkSecurityGroup: {
161+
name: 'nsg-deployment-scripts'
162+
securityRules: []
163+
}
164+
delegation: 'Microsoft.ContainerInstance/containerGroups'
165+
serviceEndpoints: ['Microsoft.Storage']
166166
}
167167
]
168168

@@ -185,7 +185,6 @@ param resourceSuffix string
185185
// Standard_D2s_v3 (2 vCPU, 8 GiB RAM, Premium SSD) // next most common
186186
// Standard_D2s_v4 (2 vCPU, 8 GiB RAM, Premium SSD) // Newest, so fewer regions availabl
187187

188-
189188
// Subnet Classless Inter-Doman Routing (CIDR) Sizing Reference Table (Best Practices)
190189
// | CIDR | # of Addresses | # of /24s | Notes |
191190
// |-----------|---------------|-----------|----------------------------------------|
@@ -215,12 +214,12 @@ param resourceSuffix string
215214
// - Document subnet usage and purpose in code comments.
216215
// - For AVM modules, ensure only one delegation per subnet and leave delegations empty if not required.
217216

218-
// 1. Create NSGs for subnets
217+
// 1. Create NSGs for subnets
219218
// using AVM Network Security Group module
220219
// https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/network/network-security-group
221220

222221
@batchSize(1)
223-
module nsgs 'br/public:avm/res/network/network-security-group:0.5.1' = [
222+
module nsgs 'br/public:avm/res/network/network-security-group:0.5.2' = [
224223
for (subnet, i) in subnets: if (!empty(subnet.?networkSecurityGroup)) {
225224
name: take('avm.res.network.network-security-group.${subnet.?networkSecurityGroup.name}.${resourceSuffix}', 64)
226225
params: {
@@ -237,7 +236,7 @@ module nsgs 'br/public:avm/res/network/network-security-group:0.5.1' = [
237236
// using AVM Virtual Network module
238237
// https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/network/virtual-network
239238

240-
module virtualNetwork 'br/public:avm/res/network/virtual-network:0.7.0' = {
239+
module virtualNetwork 'br/public:avm/res/network/virtual-network:0.7.1' = {
241240
name: take('avm.res.network.virtual-network.${name}', 64)
242241
params: {
243242
name: name
@@ -290,11 +289,21 @@ output subnets subnetOutputType[] = [
290289
]
291290

292291
// Dynamic outputs for individual subnets for backward compatibility
293-
output webSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'web') ? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'web')] : ''
294-
output pepsSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'peps') ? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'peps')] : ''
295-
output bastionSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'AzureBastionSubnet') ? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'AzureBastionSubnet')] : ''
296-
output jumpboxSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'jumpbox') ? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'jumpbox')] : ''
297-
output deploymentScriptsSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'deployment-scripts') ? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'deployment-scripts')] : ''
292+
output webSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'web')
293+
? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'web')]
294+
: ''
295+
output pepsSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'peps')
296+
? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'peps')]
297+
: ''
298+
output bastionSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'AzureBastionSubnet')
299+
? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'AzureBastionSubnet')]
300+
: ''
301+
output jumpboxSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'jumpbox')
302+
? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'jumpbox')]
303+
: ''
304+
output deploymentScriptsSubnetResourceId string = contains(map(subnets, subnet => subnet.name), 'deployment-scripts')
305+
? virtualNetwork.outputs.subnetResourceIds[indexOf(map(subnets, subnet => subnet.name), 'deployment-scripts')]
306+
: ''
298307

299308
@export()
300309
@description('Custom type definition for subnet resource information as output')
@@ -318,8 +327,8 @@ type subnetType = {
318327
@description('Required. The Name of the subnet resource.')
319328
name: string
320329

321-
@description('Required. Prefixes for the subnet.') // Required to ensure at least one prefix is provided
322-
addressPrefixes: string[]
330+
@description('Required. Prefixes for the subnet.') // Required to ensure at least one prefix is provided
331+
addressPrefixes: string[]
323332

324333
@description('Optional. The delegation to enable on the subnet.')
325334
delegation: string?

infra/modules/web-sites.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-0
260260
}
261261
]
262262

263-
module app_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [
263+
module app_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.1' = [
264264
for (privateEndpoint, index) in (privateEndpoints ?? []): {
265265
name: '${uniqueString(deployment().name, location)}-app-PrivateEndpoint-${index}'
266266
scope: resourceGroup(

infra/scripts/process_custom_data.sh

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/bin/bash
22

3+
# Get the directory where this script is located
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
36
# Variables - Grouped by service for clarity
47
# General Azure
58
resourceGroupName="${1}"
@@ -345,6 +348,92 @@ get_values_from_azd_env() {
345348
return 0
346349
}
347350

351+
get_values_from_az_deployment() {
352+
echo "Getting values from Azure deployment outputs..."
353+
354+
deploymentName=$(az group show --name "$resourceGroupName" --query "tags.DeploymentName" -o tsv)
355+
echo "Deployment Name (from tag): $deploymentName"
356+
357+
echo "Fetching deployment outputs..."
358+
# Get all outputs
359+
deploymentOutputs=$(az deployment group show \
360+
--name "$deploymentName" \
361+
--resource-group "$resourceGroupName" \
362+
--query "properties.outputs" -o json)
363+
364+
# Helper function to extract value from deployment outputs
365+
# Usage: extract_value "primaryKey" "fallbackKey"
366+
extract_value() {
367+
local primary_key="$1"
368+
local fallback_key="$2"
369+
local value
370+
371+
value=$(echo "$deploymentOutputs" | grep -A 3 "\"$primary_key\"" | grep '"value"' | sed 's/.*"value": *"\([^"]*\)".*/\1/')
372+
if [ -z "$value" ] && [ -n "$fallback_key" ]; then
373+
value=$(echo "$deploymentOutputs" | grep -A 3 "\"$fallback_key\"" | grep '"value"' | sed 's/.*"value": *"\([^"]*\)".*/\1/')
374+
fi
375+
echo "$value"
376+
}
377+
378+
# Extract each value using the helper function
379+
storageAccountName=$(extract_value "storageAccountName" "storagE_ACCOUNT_NAME")
380+
fileSystem=$(extract_value "storageContainerName" "storagE_CONTAINER_NAME")
381+
sqlServerName=$(extract_value "sqlDBServer" "sqldB_SERVER")
382+
SqlDatabaseName=$(extract_value "sqlDBDatabase" "sqldB_DATABASE")
383+
backendUserMidClientId=$(extract_value "backendUserMid" "backenD_USER_MID")
384+
backendUserMidDisplayName=$(extract_value "backendUserMidName" "backenD_USER_MID_NAME")
385+
aiSearchName=$(extract_value "azureAISearchName" "azurE_AI_SEARCH_NAME")
386+
searchEndpoint=$(extract_value "azureAISearchEndpoint" "azurE_AI_SEARCH_ENDPOINT")
387+
aif_resource_id=$(extract_value "aiFoundryResourceId" "aI_FOUNDRY_RESOURCE_ID")
388+
cu_foundry_resource_id=$(extract_value "cuFoundryResourceId" "cU_FOUNDRY_RESOURCE_ID")
389+
openaiEndpoint=$(extract_value "azureOpenAIEndpoint" "azurE_OPENAI_ENDPOINT")
390+
embeddingModel=$(extract_value "azureOpenAIEmbeddingModel" "azurE_OPENAI_EMBEDDING_MODEL")
391+
cuEndpoint=$(extract_value "azureOpenAICuEndpoint" "azurE_OPENAI_CU_ENDPOINT")
392+
aiAgentEndpoint=$(extract_value "azureAiAgentEndpoint" "azurE_AI_AGENT_ENDPOINT")
393+
cuApiVersion=$(extract_value "azureContentUnderstandingApiVersion" "azurE_CONTENT_UNDERSTANDING_API_VERSION")
394+
deploymentModel=$(extract_value "azureOpenAIDeploymentModel" "azurE_OPENAI_DEPLOYMENT_MODEL")
395+
usecase=$(extract_value "useCase" "usE_CASE")
396+
397+
# Strip FQDN suffix from SQL server name if present (Azure CLI needs just the server name)
398+
sqlServerName="${sqlServerName%.database.windows.net}"
399+
400+
# Define required values with their display names for error reporting
401+
declare -A required_values=(
402+
["storageAccountName"]="STORAGE_ACCOUNT_NAME"
403+
["fileSystem"]="STORAGE_CONTAINER_NAME"
404+
["sqlServerName"]="SQLDB_SERVER"
405+
["SqlDatabaseName"]="SQLDB_DATABASE"
406+
["backendUserMidClientId"]="BACKEND_USER_MID"
407+
["backendUserMidDisplayName"]="BACKEND_USER_MID_NAME"
408+
["aiSearchName"]="AZURE_AI_SEARCH_NAME"
409+
["aif_resource_id"]="AI_FOUNDRY_RESOURCE_ID"
410+
["cu_foundry_resource_id"]="CU_FOUNDRY_RESOURCE_ID"
411+
["searchEndpoint"]="AZURE_AI_SEARCH_ENDPOINT"
412+
["openaiEndpoint"]="AZURE_OPENAI_ENDPOINT"
413+
["embeddingModel"]="AZURE_OPENAI_EMBEDDING_MODEL"
414+
["cuEndpoint"]="AZURE_OPENAI_CU_ENDPOINT"
415+
["aiAgentEndpoint"]="AZURE_AI_AGENT_ENDPOINT"
416+
["cuApiVersion"]="AZURE_CONTENT_UNDERSTANDING_API_VERSION"
417+
["deploymentModel"]="AZURE_OPENAI_DEPLOYMENT_MODEL"
418+
["usecase"]="USE_CASE"
419+
)
420+
421+
# Validate and collect missing values
422+
missing_values=()
423+
for var_name in "${!required_values[@]}"; do
424+
if [ -z "${!var_name}" ]; then
425+
missing_values+=("${required_values[$var_name]}")
426+
fi
427+
done
428+
429+
if [ ${#missing_values[@]} -gt 0 ]; then
430+
echo "Error: The following required values could not be retrieved from Azure deployment outputs:"
431+
printf ' - %s\n' "${missing_values[@]}" | sort
432+
return 1
433+
fi
434+
return 0
435+
}
436+
348437
# Check if user is logged in to Azure
349438
echo "Checking Azure authentication..."
350439
if az account show &> /dev/null; then
@@ -404,10 +493,39 @@ fi
404493
echo ""
405494

406495
echo ""
407-
if ! get_values_from_azd_env; then
408-
echo "Failed to get values from azd environment."
409-
echo ""
410-
exit 1
496+
497+
if [ -z "$resourceGroupName" ]; then
498+
# No resource group provided - use azd env
499+
if ! get_values_from_azd_env; then
500+
echo "Failed to get values from azd environment."
501+
echo ""
502+
echo "If you want to use deployment outputs instead, please provide the resource group name as an argument."
503+
echo "Usage: $0 [ResourceGroupName]"
504+
echo "Example: $0 my-resource-group"
505+
echo ""
506+
exit 1
507+
fi
508+
else
509+
# Resource group provided - use deployment outputs
510+
echo ""
511+
echo "Resource group provided: $resourceGroupName"
512+
513+
# Call deployment function
514+
if ! get_values_from_az_deployment; then
515+
echo "Failed to get values from deployment outputs."
516+
echo ""
517+
echo "Would you like to enter the values manually? (y/n): "
518+
read -r manual_input_choice
519+
if [[ "$manual_input_choice" == "y" || "$manual_input_choice" == "Y" ]]; then
520+
if ! get_values_from_user; then
521+
echo "Error: Manual input failed."
522+
exit 1
523+
fi
524+
else
525+
echo "Exiting script."
526+
exit 1
527+
fi
528+
fi
411529
fi
412530

413531
echo ""
@@ -441,7 +559,7 @@ if [ $? -ne 0 ]; then
441559
exit 1
442560
fi
443561

444-
pythonScriptPath="infra/scripts/index_scripts/"
562+
pythonScriptPath="$SCRIPT_DIR/index_scripts/"
445563

446564
# Install the requirements
447565
pip install --quiet -r ${pythonScriptPath}requirements.txt
@@ -452,13 +570,13 @@ fi
452570

453571
# Create Content Understanding analyzers
454572
echo "✓ Creating Content Understanding analyzer templates"
455-
python infra/scripts/index_scripts/02_create_cu_template_text.py --cu_endpoint="$cuEndpoint" --cu_api_version="$cuApiVersion"
573+
python "${pythonScriptPath}02_create_cu_template_text.py" --cu_endpoint="$cuEndpoint" --cu_api_version="$cuApiVersion"
456574
if [ $? -ne 0 ]; then
457575
echo "Error: 02_create_cu_template_text.py failed."
458576
exit 1
459577
fi
460578

461-
python infra/scripts/index_scripts/02_create_cu_template_audio.py --cu_endpoint="$cuEndpoint" --cu_api_version="$cuApiVersion"
579+
python "${pythonScriptPath}02_create_cu_template_audio.py" --cu_endpoint="$cuEndpoint" --cu_api_version="$cuApiVersion"
462580
if [ $? -ne 0 ]; then
463581
echo "Error: 02_create_cu_template_audio.py failed."
464582
exit 1
@@ -467,7 +585,7 @@ fi
467585
# Run 04_cu_process_custom_data.py
468586
echo "✓ Processing custom data"
469587
sql_server_fqdn="$sqlServerName.database.windows.net"
470-
python infra/scripts/index_scripts/04_cu_process_custom_data.py \
588+
python "${pythonScriptPath}04_cu_process_custom_data.py" \
471589
--search_endpoint "$searchEndpoint" \
472590
--openai_endpoint "$openaiEndpoint" \
473591
--ai_project_endpoint "$aiAgentEndpoint" \

0 commit comments

Comments
 (0)