Skip to content

Commit fc41346

Browse files
script reverted and updated
1 parent 243a1ec commit fc41346

File tree

2 files changed

+381
-0
lines changed

2 files changed

+381
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/bin/bash
2+
3+
# Parameters
4+
SqlServerName="$1"
5+
SqlDatabaseName="$2"
6+
UserRoleJSONArray="$3"
7+
ManagedIdentityClientId="$6"
8+
9+
# Function to check if a command exists or runs successfully
10+
function check_command() {
11+
if ! eval "$1" &> /dev/null; then
12+
echo "Error: Command '$1' failed or is not installed."
13+
exit 1
14+
fi
15+
}
16+
17+
# Ensure required commands are available
18+
check_command "az --version"
19+
check_command "sqlcmd '-?'"
20+
21+
# Authenticate with Azure
22+
if az account show &> /dev/null; then
23+
echo "Already authenticated with Azure."
24+
else
25+
if [ -n "$ManagedIdentityClientId" ]; then
26+
# Use managed identity if running in Azure
27+
echo "Authenticating with Managed Identity..."
28+
az login --identity --client-id ${ManagedIdentityClientId}
29+
else
30+
# Use Azure CLI login if running locally
31+
echo "Authenticating with Azure CLI..."
32+
az login
33+
fi
34+
echo "Not authenticated with Azure. Attempting to authenticate..."
35+
fi
36+
37+
SQL_QUERY=""
38+
#loop through the JSON array and create users and assign roles using grep and sed
39+
count=1
40+
while read -r json_object; do
41+
# Extract fields from the JSON object using grep and sed
42+
clientId=$(echo "$json_object" | grep -o '"clientId": *"[^"]*"' | sed 's/"clientId": *"\([^"]*\)"/\1/')
43+
displayName=$(echo "$json_object" | grep -o '"displayName": *"[^"]*"' | sed 's/"displayName": *"\([^"]*\)"/\1/')
44+
role=$(echo "$json_object" | grep -o '"role": *"[^"]*"' | sed 's/"role": *"\([^"]*\)"/\1/')
45+
46+
# Append to SQL_QUERY with dynamic variable names
47+
SQL_QUERY+="
48+
DECLARE @username$count nvarchar(max) = N'$displayName';
49+
DECLARE @clientId$count uniqueidentifier = '$clientId';
50+
DECLARE @sid$count NVARCHAR(max) = CONVERT(VARCHAR(max), CONVERT(VARBINARY(16), @clientId$count), 1);
51+
DECLARE @cmd$count NVARCHAR(max) = N'CREATE USER [' + @username$count + '] WITH SID = ' + @sid$count + ', TYPE = E;';
52+
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = @username$count)
53+
BEGIN
54+
EXEC(@cmd$count)
55+
END
56+
EXEC sp_addrolemember '$role', @username$count;
57+
"
58+
59+
# Increment the count
60+
count=$((count + 1))
61+
done < <(echo "$UserRoleJSONArray" | grep -o '{[^}]*}')
62+
63+
#create heredoc for the SQL query
64+
SQL_QUERY_FINAL=$(cat <<EOF
65+
$SQL_QUERY
66+
EOF
67+
)
68+
69+
70+
71+
# SQL query to create the user and assign the role
72+
# SQL_QUERY=$(cat <<EOF
73+
# DECLARE @username nvarchar(max) = N'$DisplayName';
74+
# DECLARE @clientId uniqueidentifier = '$ClientId';
75+
# DECLARE @sid NVARCHAR(max) = CONVERT(VARCHAR(max), CONVERT(VARBINARY(16), @clientId), 1);
76+
# DECLARE @cmd NVARCHAR(max) = N'CREATE USER [' + @username + '] WITH SID = ' + @sid + ', TYPE = E;';
77+
# IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = @username)
78+
# BEGIN
79+
# EXEC(@cmd)
80+
# END
81+
# EXEC sp_addrolemember '$DatabaseRole', @username;
82+
# EOF
83+
# )
84+
85+
# # Output the SQL query for debugging
86+
# echo "SQL Query:"
87+
# echo "$SQL_QUERY_FINAL"
88+
89+
# Check if OS is Windows
90+
OS=$(uname | tr '[:upper:]' '[:lower:]')
91+
92+
if [[ "$OS" == "mingw"* || "$OS" == "cygwin"* || "$OS" == "msys"* ]]; then
93+
echo "Running on Windows OS, will use interactive login"
94+
echo "Getting signed in user email"
95+
UserEmail=$(az ad signed-in-user show --query mail -o tsv)
96+
# If the email is null or empty, use userPrincipalName
97+
if [[ -z "$UserEmail" ]]; then
98+
UserEmail=$(az ad signed-in-user show --query userPrincipalName -o tsv)
99+
fi
100+
# Execute the SQL query
101+
echo "Executing SQL query..."
102+
sqlcmd -S "$SqlServerName" -d "$SqlDatabaseName" -G -U "$UserEmail" -Q "$SQL_QUERY_FINAL" || {
103+
echo "Failed to execute SQL query."
104+
exit 1
105+
}
106+
else
107+
echo "Running on Linux or macOS, will use access token"
108+
mkdir -p usersql
109+
# Get an access token for the Azure SQL Database
110+
echo "Retrieving access token..."
111+
az account get-access-token --resource https://database.windows.net --output tsv | cut -f 1 | tr -d '\n' | iconv -f ascii -t UTF-16LE > usersql/tokenFile
112+
if [ $? -ne 0 ]; then
113+
echo "Failed to retrieve access token."
114+
exit 1
115+
fi
116+
errorFlag=false
117+
# Execute the SQL query
118+
echo "Executing SQL query..."
119+
sqlcmd -S "$SqlServerName" -d "$SqlDatabaseName" -G -P usersql/tokenFile -Q "$SQL_QUERY_FINAL" || {
120+
echo "Failed to execute SQL query."
121+
errorFlag=true
122+
}
123+
#delete the usersql directory
124+
rm -rf usersql
125+
if [ "$errorFlag" = true ]; then
126+
exit 1
127+
fi
128+
fi
129+
130+
131+
echo "SQL user and role assignment completed successfully."
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
#!/bin/bash
2+
# VERBOSE=false
3+
4+
MODELS=""
5+
REGIONS=""
6+
VERBOSE=false
7+
8+
while [[ $# -gt 0 ]]; do
9+
case "$1" in
10+
--models)
11+
MODELS="$2"
12+
shift 2
13+
;;
14+
--regions)
15+
REGIONS="$2"
16+
shift 2
17+
;;
18+
--verbose)
19+
VERBOSE=true
20+
shift
21+
;;
22+
*)
23+
echo "Unknown option: $1"
24+
exit 1
25+
;;
26+
esac
27+
done
28+
29+
# Fallback to defaults if not provided
30+
[[ -z "$MODELS" ]]
31+
[[ -z "$REGIONS" ]]
32+
33+
echo "Models: $MODELS"
34+
echo "Regions: $REGIONS"
35+
echo "Verbose: $VERBOSE"
36+
37+
for arg in "$@"; do
38+
if [ "$arg" = "--verbose" ]; then
39+
VERBOSE=true
40+
fi
41+
done
42+
43+
log_verbose() {
44+
if [ "$VERBOSE" = true ]; then
45+
echo "$1"
46+
fi
47+
}
48+
49+
# Default Models and Capacities (Comma-separated in "model:capacity" format)
50+
DEFAULT_MODEL_CAPACITY="gpt-4o-mini:30,text-embedding-ada-002:80"
51+
52+
# Convert the comma-separated string into an array
53+
IFS=',' read -r -a MODEL_CAPACITY_PAIRS <<< "$DEFAULT_MODEL_CAPACITY"
54+
55+
echo "🔄 Fetching available Azure subscriptions..."
56+
SUBSCRIPTIONS=$(az account list --query "[?state=='Enabled'].{Name:name, ID:id}" --output tsv)
57+
SUB_COUNT=$(echo "$SUBSCRIPTIONS" | wc -l)
58+
59+
if [ "$SUB_COUNT" -eq 0 ]; then
60+
echo "❌ ERROR: No active Azure subscriptions found. Please log in using 'az login' and ensure you have an active subscription."
61+
exit 1
62+
elif [ "$SUB_COUNT" -eq 1 ]; then
63+
# If only one subscription, automatically select it
64+
AZURE_SUBSCRIPTION_ID=$(echo "$SUBSCRIPTIONS" | awk '{print $2}')
65+
if [ -z "$AZURE_SUBSCRIPTION_ID" ]; then
66+
echo "❌ ERROR: No active Azure subscriptions found. Please log in using 'az login' and ensure you have an active subscription."
67+
exit 1
68+
fi
69+
echo "✅ Using the only available subscription: $AZURE_SUBSCRIPTION_ID"
70+
else
71+
# If multiple subscriptions exist, prompt the user to choose one
72+
echo "Multiple subscriptions found:"
73+
echo "$SUBSCRIPTIONS" | awk '{print NR")", $1, "-", $2}'
74+
75+
while true; do
76+
echo "Enter the number of the subscription to use:"
77+
read SUB_INDEX
78+
79+
# Validate user input
80+
if [[ "$SUB_INDEX" =~ ^[0-9]+$ ]] && [ "$SUB_INDEX" -ge 1 ] && [ "$SUB_INDEX" -le "$SUB_COUNT" ]; then
81+
AZURE_SUBSCRIPTION_ID=$(echo "$SUBSCRIPTIONS" | awk -v idx="$SUB_INDEX" 'NR==idx {print $2}')
82+
echo "✅ Selected Subscription: $AZURE_SUBSCRIPTION_ID"
83+
break
84+
else
85+
echo "❌ Invalid selection. Please enter a valid number from the list."
86+
fi
87+
done
88+
fi
89+
90+
91+
# Set the selected subscription
92+
az account set --subscription "$AZURE_SUBSCRIPTION_ID"
93+
echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output tsv)"
94+
95+
# Default Regions to check (Comma-separated, now configurable)
96+
DEFAULT_REGIONS="australiaeast,eastus,eastus2,francecentral,japaneast,swedencentral,uksouth,westus,westus3"
97+
IFS=',' read -r -a DEFAULT_REGION_ARRAY <<< "$DEFAULT_REGIONS"
98+
99+
# Read parameters (if any)
100+
IFS=',' read -r -a USER_PROVIDED_PAIRS <<< "$MODELS"
101+
USER_REGION="$REGIONS"
102+
103+
IS_USER_PROVIDED_PAIRS=false
104+
105+
if [ ${#USER_PROVIDED_PAIRS[@]} -lt 1 ]; then
106+
echo "No parameters provided, using default model-capacity pairs: ${MODEL_CAPACITY_PAIRS[*]}"
107+
else
108+
echo "Using provided model and capacity pairs: ${USER_PROVIDED_PAIRS[*]}"
109+
IS_USER_PROVIDED_PAIRS=true
110+
MODEL_CAPACITY_PAIRS=("${USER_PROVIDED_PAIRS[@]}")
111+
fi
112+
113+
declare -a FINAL_MODEL_NAMES
114+
declare -a FINAL_CAPACITIES
115+
declare -a TABLE_ROWS
116+
117+
for PAIR in "${MODEL_CAPACITY_PAIRS[@]}"; do
118+
MODEL_NAME=$(echo "$PAIR" | cut -d':' -f1 | tr '[:upper:]' '[:lower:]')
119+
CAPACITY=$(echo "$PAIR" | cut -d':' -f2)
120+
121+
if [ -z "$MODEL_NAME" ] || [ -z "$CAPACITY" ]; then
122+
echo "❌ ERROR: Invalid model and capacity pair '$PAIR'. Both model and capacity must be specified."
123+
exit 1
124+
fi
125+
126+
FINAL_MODEL_NAMES+=("$MODEL_NAME")
127+
FINAL_CAPACITIES+=("$CAPACITY")
128+
129+
done
130+
131+
echo "🔄 Using Models: ${FINAL_MODEL_NAMES[*]} with respective Capacities: ${FINAL_CAPACITIES[*]}"
132+
echo "----------------------------------------"
133+
134+
# Check if the user provided a region, if not, use the default regions
135+
if [ -n "$USER_REGION" ]; then
136+
echo "🔍 User provided region: $USER_REGION"
137+
IFS=',' read -r -a REGIONS <<< "$USER_REGION"
138+
else
139+
echo "No region specified, using default regions: ${DEFAULT_REGION_ARRAY[*]}"
140+
REGIONS=("${DEFAULT_REGION_ARRAY[@]}")
141+
APPLY_OR_CONDITION=true
142+
fi
143+
144+
echo "✅ Retrieved Azure regions. Checking availability..."
145+
INDEX=1
146+
147+
VALID_REGIONS=()
148+
for REGION in "${REGIONS[@]}"; do
149+
log_verbose "----------------------------------------"
150+
log_verbose "🔍 Checking region: $REGION"
151+
152+
QUOTA_INFO=$(az cognitiveservices usage list --location "$REGION" --output json | tr '[:upper:]' '[:lower:]')
153+
if [ -z "$QUOTA_INFO" ]; then
154+
log_verbose "⚠️ WARNING: Failed to retrieve quota for region $REGION. Skipping."
155+
continue
156+
fi
157+
158+
TEXT_EMBEDDING_AVAILABLE=false
159+
AT_LEAST_ONE_MODEL_AVAILABLE=false
160+
TEMP_TABLE_ROWS=()
161+
162+
for index in "${!FINAL_MODEL_NAMES[@]}"; do
163+
MODEL_NAME="${FINAL_MODEL_NAMES[$index]}"
164+
REQUIRED_CAPACITY="${FINAL_CAPACITIES[$index]}"
165+
FOUND=false
166+
INSUFFICIENT_QUOTA=false
167+
168+
if [ "$MODEL_NAME" = "text-embedding-ada-002" ]; then
169+
MODEL_TYPES=("openai.standard.$MODEL_NAME")
170+
else
171+
MODEL_TYPES=("openai.standard.$MODEL_NAME" "openai.globalstandard.$MODEL_NAME")
172+
fi
173+
174+
for MODEL_TYPE in "${MODEL_TYPES[@]}"; do
175+
FOUND=false
176+
INSUFFICIENT_QUOTA=false
177+
log_verbose "🔍 Checking model: $MODEL_NAME with required capacity: $REQUIRED_CAPACITY ($MODEL_TYPE)"
178+
179+
MODEL_INFO=$(echo "$QUOTA_INFO" | awk -v model="\"value\": \"$MODEL_TYPE\"" '
180+
BEGIN { RS="},"; FS="," }
181+
$0 ~ model { print $0 }
182+
')
183+
184+
if [ -z "$MODEL_INFO" ]; then
185+
FOUND=false
186+
log_verbose "⚠️ WARNING: No quota information found for model: $MODEL_NAME in region: $REGION for model type: $MODEL_TYPE."
187+
continue
188+
fi
189+
190+
if [ -n "$MODEL_INFO" ]; then
191+
FOUND=true
192+
CURRENT_VALUE=$(echo "$MODEL_INFO" | awk -F': ' '/"currentvalue"/ {print $2}' | tr -d ',' | tr -d ' ')
193+
LIMIT=$(echo "$MODEL_INFO" | awk -F': ' '/"limit"/ {print $2}' | tr -d ',' | tr -d ' ')
194+
195+
CURRENT_VALUE=${CURRENT_VALUE:-0}
196+
LIMIT=${LIMIT:-0}
197+
198+
CURRENT_VALUE=$(echo "$CURRENT_VALUE" | cut -d'.' -f1)
199+
LIMIT=$(echo "$LIMIT" | cut -d'.' -f1)
200+
201+
AVAILABLE=$((LIMIT - CURRENT_VALUE))
202+
log_verbose "✅ Model: $MODEL_TYPE | Used: $CURRENT_VALUE | Limit: $LIMIT | Available: $AVAILABLE"
203+
204+
if [ "$AVAILABLE" -ge "$REQUIRED_CAPACITY" ]; then
205+
FOUND=true
206+
if [ "$MODEL_NAME" = "text-embedding-ada-002" ]; then
207+
TEXT_EMBEDDING_AVAILABLE=true
208+
fi
209+
AT_LEAST_ONE_MODEL_AVAILABLE=true
210+
TEMP_TABLE_ROWS+=("$(printf "| %-4s | %-20s | %-43s | %-10s | %-10s | %-10s |" "$INDEX" "$REGION" "$MODEL_TYPE" "$LIMIT" "$CURRENT_VALUE" "$AVAILABLE")")
211+
else
212+
INSUFFICIENT_QUOTA=true
213+
fi
214+
fi
215+
216+
if [ "$FOUND" = false ]; then
217+
log_verbose "❌ No models found for model: $MODEL_NAME in region: $REGION (${MODEL_TYPES[*]})"
218+
219+
elif [ "$INSUFFICIENT_QUOTA" = true ]; then
220+
log_verbose "⚠️ Model $MODEL_NAME in region: $REGION has insufficient quota (${MODEL_TYPES[*]})."
221+
fi
222+
done
223+
done
224+
225+
if { [ "$IS_USER_PROVIDED_PAIRS" = true ] && [ "$INSUFFICIENT_QUOTA" = false ] && [ "$FOUND" = true ]; } || { [ "$TEXT_EMBEDDING_AVAILABLE" = true ] && { [ "$APPLY_OR_CONDITION" != true ] || [ "$AT_LEAST_ONE_MODEL_AVAILABLE" = true ]; }; }; then
226+
VALID_REGIONS+=("$REGION")
227+
TABLE_ROWS+=("${TEMP_TABLE_ROWS[@]}")
228+
INDEX=$((INDEX + 1))
229+
elif [ ${#USER_PROVIDED_PAIRS[@]} -eq 0 ]; then
230+
echo "🚫 Skipping $REGION as it does not meet quota requirements."
231+
fi
232+
233+
done
234+
235+
if [ ${#TABLE_ROWS[@]} -eq 0 ]; then
236+
echo "--------------------------------------------------------------------------------------------------------------------"
237+
238+
echo "❌ No regions have sufficient quota for all required models. Please request a quota increase: https://aka.ms/oai/stuquotarequest"
239+
else
240+
echo "---------------------------------------------------------------------------------------------------------------------"
241+
printf "| %-4s | %-20s | %-43s | %-10s | %-10s | %-10s |\n" "No." "Region" "Model Name" "Limit" "Used" "Available"
242+
echo "---------------------------------------------------------------------------------------------------------------------"
243+
for ROW in "${TABLE_ROWS[@]}"; do
244+
echo "$ROW"
245+
done
246+
echo "---------------------------------------------------------------------------------------------------------------------"
247+
echo "➡️ To request a quota increase, visit: https://aka.ms/oai/stuquotarequest"
248+
fi
249+
250+
echo "✅ Script completed."

0 commit comments

Comments
 (0)