11#! /bin/bash
2- set -e
32
4- # ================================================
5- # Azure Quota Validator for Pipelines (CI/CD Safe)
6- # Logs in using Service Principal credentials.
7- # Exports VALID_REGION to $GITHUB_ENV if found.
8- # Default model capacity: o3:500
9- # ================================================
3+ # List of Azure regions to check for quota (update as needed)
4+ IFS=' , ' read -ra REGIONS <<< " $AZURE_REGIONS"
105
11- # ----- Configuration -----
12- DEFAULT_MODEL_CAPACITY=" o3:500"
13- DEFAULT_REGIONS=" eastus,uksouth,eastus2,northcentralus,swedencentral,westus,westus2,southcentralus,canadacentral"
14-
15- # ----- Environment Variables -----
6+ SUBSCRIPTION_ID=" ${AZURE_SUBSCRIPTION_ID} "
7+ GPT_MIN_CAPACITY=" ${GPT_MIN_CAPACITY} "
168AZURE_CLIENT_ID=" ${AZURE_CLIENT_ID} "
179AZURE_TENANT_ID=" ${AZURE_TENANT_ID} "
1810AZURE_CLIENT_SECRET=" ${AZURE_CLIENT_SECRET} "
19- AZURE_SUBSCRIPTION_ID=" ${AZURE_SUBSCRIPTION_ID} "
20- REGIONS=" ${AZURE_REGIONS:- $DEFAULT_REGIONS } "
21-
22- # ----- Authenticate -----
23- echo " 🔐 Authenticating with Azure using Service Principal..."
24- if ! az login --service-principal -u " $AZURE_CLIENT_ID " -p " $AZURE_CLIENT_SECRET " --tenant " $AZURE_TENANT_ID " & > /dev/null; then
25- echo " ❌ ERROR: Azure authentication failed."
26- exit 1
27- fi
2811
29- # ----- Validate Required Variables -----
30- if [[ -z " $AZURE_SUBSCRIPTION_ID " || -z " $AZURE_CLIENT_ID " || -z " $AZURE_TENANT_ID " || -z " $AZURE_CLIENT_SECRET " ]]; then
31- echo " ❌ ERROR: Missing required environment variables."
32- exit 1
12+ # Authenticate using Managed Identity
13+ echo " Authentication using Managed Identity..."
14+ if ! az login --service-principal -u " $AZURE_CLIENT_ID " -p " $AZURE_CLIENT_SECRET " --tenant " $AZURE_TENANT_ID " ; then
15+ echo " ❌ Error: Failed to login using Managed Identity."
16+ exit 1
3317fi
3418
35- # ----- Set Subscription -----
36- echo " 🎯 Setting active subscription..."
37- if ! az account set --subscription " $AZURE_SUBSCRIPTION_ID " & > /dev/null; then
38- echo " ❌ ERROR: Invalid or inaccessible subscription ID."
39- exit 1
19+ echo " 🔄 Validating required environment variables..."
20+ if [[ -z " $SUBSCRIPTION_ID " || -z " $GPT_MIN_CAPACITY " || -z " $REGIONS " ]]; then
21+ echo " ❌ ERROR: Missing required environment variables."
22+ exit 1
4023fi
41- echo " ✅ Subscription set successfully: $AZURE_SUBSCRIPTION_ID "
42-
43- # ----- Parse Model-Capacity Pairs -----
44- IFS=' ,' read -r -a MODEL_CAPACITY_PAIRS <<< " $DEFAULT_MODEL_CAPACITY"
45- declare -a FINAL_MODEL_NAMES
46- declare -a FINAL_CAPACITIES
4724
48- for PAIR in " ${MODEL_CAPACITY_PAIRS[@]} " ; do
49- MODEL_NAME=$( echo " $PAIR " | cut -d' :' -f1 | tr ' [:upper:]' ' [:lower:]' )
50- CAPACITY=$( echo " $PAIR " | cut -d' :' -f2)
51-
52- if [[ -z " $MODEL_NAME " || -z " $CAPACITY " ]]; then
53- echo " ❌ ERROR: Invalid model-capacity pair '$PAIR '."
25+ echo " 🔄 Setting Azure subscription..."
26+ if ! az account set --subscription " $SUBSCRIPTION_ID " ; then
27+ echo " ❌ ERROR: Invalid subscription ID or insufficient permissions."
5428 exit 1
55- fi
29+ fi
30+ echo " ✅ Azure subscription set successfully."
5631
57- FINAL_MODEL_NAMES+=(" $MODEL_NAME " )
58- FINAL_CAPACITIES+=(" $CAPACITY " )
59- done
32+ # Define models and their minimum required capacities
33+ declare -A MIN_CAPACITY=(
34+ [" OpenAI.GlobalStandard.gpt-4o" ]=$GPT_MIN_CAPACITY
35+ )
6036
61- # ----- Split Regions -----
62- IFS=' ,' read -r -a REGIONS_ARRAY <<< " $REGIONS"
37+ VALID_REGION=" "
38+ for REGION in " ${REGIONS[@]} " ; do
39+ echo " ----------------------------------------"
40+ echo " 🔍 Checking region: $REGION "
6341
64- echo " 🧩 Models: ${FINAL_MODEL_NAMES[*]} (Capacities: ${FINAL_CAPACITIES[*]} )"
65- echo " 🌍 Checking regions: ${REGIONS_ARRAY[*]} "
66- echo " -----------------------------------------------"
42+ QUOTA_INFO=$( az cognitiveservices usage list --location " $REGION " --output json)
43+ if [ -z " $QUOTA_INFO " ]; then
44+ echo " ⚠️ WARNING: Failed to retrieve quota for region $REGION . Skipping."
45+ continue
46+ fi
6747
68- VALID_REGION=" "
69- TABLE_ROWS=()
70- INDEX=1
71-
72- # ----- Region Loop -----
73- for REGION in " ${REGIONS_ARRAY[@]} " ; do
74- echo " 🔍 Checking region: $REGION "
75-
76- QUOTA_INFO=$( az cognitiveservices usage list --location " $REGION " --output json 2> /dev/null | tr ' [:upper:]' ' [:lower:]' )
77- if [[ -z " $QUOTA_INFO " ]]; then
78- echo " ⚠️ WARNING: Unable to fetch quota for $REGION . Skipping."
79- continue
80- fi
81-
82- REGION_VALID=true
83- TEMP_ROWS=()
84-
85- for i in " ${! FINAL_MODEL_NAMES[@]} " ; do
86- MODEL_NAME=" ${FINAL_MODEL_NAMES[$i]} "
87- REQUIRED_CAPACITY=" ${FINAL_CAPACITIES[$i]} "
88- FOUND=false
8948 INSUFFICIENT_QUOTA=false
49+ for MODEL in " ${! MIN_CAPACITY[@]} " ; do
50+ MODEL_INFO=$( echo " $QUOTA_INFO " | awk -v model=" \" value\" : \" $MODEL \" " '
51+ BEGIN { RS="},"; FS="," }
52+ $0 ~ model { print $0 }
53+ ' )
9054
91- MODEL_TYPES=(" openai.standard.$MODEL_NAME " " openai.globalstandard.$MODEL_NAME " )
55+ if [ -z " $MODEL_INFO " ]; then
56+ echo " ⚠️ WARNING: No quota information found for model: $MODEL in $REGION . Skipping."
57+ INSUFFICIENT_QUOTA=true
58+ continue
59+ fi
9260
93- for MODEL_TYPE in " ${MODEL_TYPES[@]} " ; do
94- MODEL_INFO=$( echo " $QUOTA_INFO " | awk -v model=" \" value\" : \" $MODEL_TYPE \" " '
95- BEGIN { RS="},"; FS="," }
96- $0 ~ model { print $0 }
97- ' )
61+ CURRENT_VALUE=$( echo " $MODEL_INFO " | awk -F' : ' ' /"currentValue"/ {print $2}' | tr -d ' ,' | tr -d ' ' )
62+ LIMIT=$( echo " $MODEL_INFO " | awk -F' : ' ' /"limit"/ {print $2}' | tr -d ' ,' | tr -d ' ' )
9863
99- if [[ -z " $MODEL_INFO " ]]; then
100- continue
101- fi
64+ CURRENT_VALUE=${CURRENT_VALUE:- 0}
65+ LIMIT=${LIMIT:- 0}
10266
103- FOUND=true
104- CURRENT_VALUE=$( echo " $MODEL_INFO " | awk -F' : ' ' /"currentvalue"/ {print $2}' | tr -d ' , ' )
105- LIMIT=$( echo " $MODEL_INFO " | awk -F' : ' ' /"limit"/ {print $2}' | tr -d ' , ' )
67+ CURRENT_VALUE=$( echo " $CURRENT_VALUE " | cut -d' .' -f1)
68+ LIMIT=$( echo " $LIMIT " | cut -d' .' -f1)
10669
107- CURRENT_VALUE=${CURRENT_VALUE:- 0}
108- LIMIT=${LIMIT:- 0}
109- CURRENT_VALUE=$( echo " $CURRENT_VALUE " | cut -d' .' -f1)
110- LIMIT=$( echo " $LIMIT " | cut -d' .' -f1)
111- AVAILABLE=$(( LIMIT - CURRENT_VALUE))
70+ AVAILABLE=$(( LIMIT - CURRENT_VALUE))
11271
113- printf " ▪ %s | Used: %s | Limit: %s | Available: %s\n " " $MODEL_TYPE " " $CURRENT_VALUE " " $LIMIT " " $AVAILABLE "
72+ echo " ✅ Model: $MODEL | Used: $CURRENT_VALUE | Limit: $LIMIT | Available: $AVAILABLE "
11473
115- if (( AVAILABLE < REQUIRED_CAPACITY )) ; then
116- echo " ❌ Insufficient quota for $MODEL_TYPE in $REGION (required: $REQUIRED_CAPACITY )"
117- REGION_VALID=false
118- INSUFFICIENT_QUOTA=true
119- break
120- else
121- TEMP_ROWS+=(" $( printf " | %-3s | %-15s | %-40s | %-8s | %-8s | %-8s |" " $INDEX " " $REGION " " $MODEL_TYPE " " $LIMIT " " $CURRENT_VALUE " " $AVAILABLE " ) " )
122- fi
74+ if [ " $AVAILABLE " -lt " ${MIN_CAPACITY[$MODEL]} " ]; then
75+ echo " ❌ ERROR: $MODEL in $REGION has insufficient quota."
76+ INSUFFICIENT_QUOTA=true
77+ break
78+ fi
12379 done
12480
125- if [[ " $INSUFFICIENT_QUOTA " == true ]]; then
126- break
81+ if [ " $INSUFFICIENT_QUOTA " = false ]; then
82+ VALID_REGION=" $REGION "
83+ break
12784 fi
128- done
129-
130- if [[ " $REGION_VALID " == true ]]; then
131- VALID_REGION=" $REGION "
132- TABLE_ROWS+=(" ${TEMP_ROWS[@]} " )
133- echo " ✅ Region $REGION has sufficient quota."
134- break
135- else
136- echo " 🚫 Region $REGION skipped (insufficient quota)."
137- fi
138-
139- INDEX=$(( INDEX + 1 ))
85+
14086done
14187
142- # ----- Final Results -----
143- echo " -----------------------------------------------"
144- if [[ -z " $VALID_REGION " ]]; then
145- echo " ❌ No region found with sufficient quota."
146- echo " QUOTA_FAILED=true" >> " $GITHUB_ENV "
147- echo " ➡️ To request a quota increase: https://aka.ms/oai/stuquotarequest"
148- exit 0
88+ if [ -z " $VALID_REGION " ]; then
89+ echo " ❌ No region with sufficient quota found. Blocking deployment."
90+ echo " QUOTA_FAILED=true" >> " $GITHUB_ENV "
91+ exit 0
14992else
150- echo " ✅ VALID REGION FOUND: $VALID_REGION "
151- echo " VALID_REGION=$VALID_REGION " >> " $GITHUB_ENV "
152-
153- echo " -----------------------------------------------------------"
154- printf " | %-3s | %-15s | %-40s | %-8s | %-8s | %-8s |\n" " No." " Region" " Model Name" " Limit" " Used" " Avail"
155- echo " -----------------------------------------------------------"
156- for ROW in " ${TABLE_ROWS[@]} " ; do
157- echo " $ROW "
158- done
159- echo " -----------------------------------------------------------"
160- exit 0
161- fi
93+ echo " ✅ Final Region: $VALID_REGION "
94+ echo " VALID_REGION=$VALID_REGION " >> " $GITHUB_ENV "
95+ exit 0
96+ fi
0 commit comments