Skip to content

Commit 3caed68

Browse files
Added support for reusing existing Resource Groups by introducing two new parameters: environmentName and resourceGroupName. Updated the Bicep template and PowerShell script to skip resource group creation if it already exists and proceed with resource deployment.
1 parent 02b5528 commit 3caed68

File tree

2 files changed

+129
-54
lines changed

2 files changed

+129
-54
lines changed

Deployment/main.bicep

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,67 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT license.
3+
4+
targetScope = 'resourceGroup'
5+
6+
@minLength(3)
7+
@maxLength(20)
8+
@description('A unique prefix for all resources in this deployment. This should be 3-20 characters long:')
9+
param environmentName string
10+
311
@description('The Data Center where the model is deployed.')
412
param modeldatacenter string
5-
var abbrs = loadJsonContent('./abbreviations.json')
613

7-
targetScope = 'subscription'
8-
var resourceprefix = padLeft(take(uniqueString(deployment().name), 5), 5, '0')
14+
@description('Azure data center region where resources will be deployed. This should be a valid Azure region, e.g., eastus, westus, etc.')
15+
param location string
16+
17+
var uniqueId = toLower(uniqueString(subscription().id, environmentName, location))
18+
var resourceprefix = padLeft(take(uniqueId, 10), 10, '0')
919
var resourceprefix_name = 'kmgs'
1020

11-
// Create a resource group
12-
resource gs_resourcegroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
13-
name: '${abbrs.managementGovernance.resourceGroup}${resourceprefix_name}${resourceprefix}'
14-
location: deployment().location
15-
}
21+
var resourceGroupLocation = resourceGroup().location
22+
23+
// Load the abbrevations file required to name the azure resources.
24+
var abbrs = loadJsonContent('./abbreviations.json')
25+
1626

1727
// Create a storage account
1828
module gs_storageaccount 'bicep/azurestorageaccount.bicep' = {
1929
name: '${abbrs.storage.storageAccount}${resourceprefix_name}${resourceprefix}'
20-
scope: gs_resourcegroup
30+
scope: resourceGroup()
2131
params: {
2232
storageAccountName: '${abbrs.storage.storageAccount}${resourceprefix}'
23-
location: deployment().location
33+
location: resourceGroupLocation
2434
}
2535
}
2636

2737
// Create a Azure Search Service
2838
module gs_azsearch 'bicep/azuresearch.bicep' = {
2939
name: '${abbrs.ai.aiSearch}${resourceprefix_name}${resourceprefix}'
30-
scope: gs_resourcegroup
40+
scope: resourceGroup()
3141
params: {
3242
searchServiceName: '${abbrs.ai.aiSearch}${resourceprefix}'
33-
location: deployment().location
43+
location: resourceGroupLocation
3444
}
3545
}
3646

3747

3848
// Create Container Registry
3949
module gs_containerregistry 'bicep/azurecontainerregistry.bicep' = {
4050
name: '${abbrs.containers.containerRegistry}${resourceprefix_name}${resourceprefix}'
41-
scope: gs_resourcegroup
51+
scope: resourceGroup()
4252
params: {
4353
acrName: '${abbrs.containers.containerRegistry}${resourceprefix_name}${resourceprefix}'
44-
location: deployment().location
54+
location: resourceGroupLocation
4555
}
4656
}
4757

4858
// Create AKS Cluster
4959
module gs_aks 'bicep/azurekubernetesservice.bicep' = {
5060
name: '${abbrs.compute.arcEnabledKubernetesCluster}${resourceprefix_name}${resourceprefix}'
51-
scope: gs_resourcegroup
61+
scope: resourceGroup()
5262
params: {
5363
aksName: '${abbrs.compute.arcEnabledKubernetesCluster}${resourceprefix_name}${resourceprefix}'
54-
location: deployment().location
64+
location: resourceGroupLocation
5565
}
5666
dependsOn: [
5767
gs_containerregistry
@@ -76,7 +86,7 @@ module gs_aks 'bicep/azurekubernetesservice.bicep' = {
7686
// Create Azure Cognitive Service
7787
module gs_azcognitiveservice 'bicep/azurecognitiveservice.bicep' = {
7888
name: '${abbrs.ai.documentIntelligence}${resourceprefix_name}${resourceprefix}'
79-
scope: gs_resourcegroup
89+
scope: resourceGroup()
8090
params: {
8191
cognitiveServiceName: '${abbrs.ai.documentIntelligence}${resourceprefix_name}${resourceprefix}'
8292
location: 'eastus'
@@ -86,7 +96,7 @@ module gs_azcognitiveservice 'bicep/azurecognitiveservice.bicep' = {
8696
// Create Azure Open AI Service
8797
module gs_openaiservice 'bicep/azureopenaiservice.bicep' = {
8898
name: '${abbrs.ai.openAIService}${resourceprefix_name}${resourceprefix}'
89-
scope: gs_resourcegroup
99+
scope: resourceGroup()
90100
params: {
91101
openAIServiceName: '${abbrs.ai.openAIService}${resourceprefix_name}${resourceprefix}'
92102
// GPT-4-32K model & GPT-4o available Data center information.
@@ -99,7 +109,7 @@ module gs_openaiservice 'bicep/azureopenaiservice.bicep' = {
99109
// Set the minimum capacity of each model
100110
// Based on customer's Model capacity, it needs to be updated in Azure Portal.
101111
module gs_openaiservicemodels_gpt4o 'bicep/azureopenaiservicemodel.bicep' = {
102-
scope: gs_resourcegroup
112+
scope: resourceGroup()
103113
name: 'gpt-4o-mini'
104114
params: {
105115
parentResourceName: gs_openaiservice.outputs.openAIServiceName
@@ -119,7 +129,7 @@ module gs_openaiservicemodels_gpt4o 'bicep/azureopenaiservicemodel.bicep' = {
119129
}
120130

121131
module gs_openaiservicemodels_text_embedding 'bicep/azureopenaiservicemodel.bicep' = {
122-
scope: gs_resourcegroup
132+
scope: resourceGroup()
123133
name: 'text-embedding-large'
124134
params: {
125135
parentResourceName: gs_openaiservice.outputs.openAIServiceName
@@ -140,25 +150,26 @@ module gs_openaiservicemodels_text_embedding 'bicep/azureopenaiservicemodel.bice
140150
// Create Azure Cosmos DB Mongo
141151
module gs_cosmosdb 'bicep/azurecosmosdb.bicep' = {
142152
name: '${abbrs.databases.cosmosDBDatabase}${resourceprefix_name}${resourceprefix}'
143-
scope: gs_resourcegroup
153+
scope: resourceGroup()
144154
params: {
145155
cosmosDbAccountName: '${abbrs.databases.cosmosDBDatabase}${resourceprefix_name}${resourceprefix}'
146-
location: deployment().location
156+
location: resourceGroupLocation
147157
}
148158
}
149159

150160
// Create Azure App Configuration
151161
module gs_appconfig 'bicep/azureappconfigservice.bicep' = {
152162
name: 'appconfig-${resourceprefix_name}${resourceprefix}'
153-
scope: gs_resourcegroup
163+
scope: resourceGroup()
154164
params: {
155165
appConfigName: 'appconfig-${resourceprefix_name}${resourceprefix}'
156-
location: deployment().location
166+
location: resourceGroupLocation
157167
}
158168
}
159169

160170
// return all resource names as a output
161-
output gs_resourcegroup_name string = '${abbrs.managementGovernance.resourceGroup}${resourceprefix_name}${resourceprefix}'
171+
// output gs_resourcegroup_name string = '${abbrs.managementGovernance.resourceGroup}${resourceprefix_name}${resourceprefix}'
172+
output gs_resourcegroup_name string = resourceGroup().name
162173
output gs_solution_prefix string = '${resourceprefix_name}${resourceprefix}'
163174
output gs_storageaccount_name string = gs_storageaccount.outputs.storageAccountName
164175
output gs_azsearch_name string = gs_azsearch.outputs.searchServiceName
@@ -189,5 +200,5 @@ output gs_appconfig_endpoint string = gs_appconfig.outputs.appConfigEndpoint
189200
output gs_containerregistry_endpoint string = gs_containerregistry.outputs.acrEndpoint
190201

191202
//return resourcegroup resource ID
192-
output gs_resourcegroup_id string = gs_resourcegroup.id
203+
output gs_resourcegroup_id string = resourceGroup().id
193204

Deployment/resourcedeployment.ps1

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ function ValidateVariableIsNullOrEmpty {
7474
function PromptForParameters {
7575
param(
7676
[string]$subscriptionID,
77+
[string]$environmentName,
78+
[string]$resourceGroupName,
7779
[string]$location,
7880
[string]$modelLocation,
7981
[string]$email
@@ -105,6 +107,16 @@ function PromptForParameters {
105107
$subscriptionID = Read-Host -Prompt '> '
106108
}
107109

110+
if (-not $environmentName) {
111+
Write-Host "Please enter Environment name" -ForegroundColor Cyan
112+
$environmentName = Read-Host -Prompt '> '
113+
}
114+
115+
if (-not $resourceGroupName) {
116+
Write-Host "Please enter your Azure Resource Group Name to deploy your resources (leave blank to auto-generate one)" -ForegroundColor Cyan
117+
$resourceGroupName = Read-Host -Prompt '> '
118+
}
119+
108120
if (-not $location) {
109121
Write-Host "Please enter the Azure Data Center Region to deploy your resources" -ForegroundColor Cyan
110122
Write-Host "Available regions are:" -ForegroundColor Cyan
@@ -125,37 +137,41 @@ function PromptForParameters {
125137
}
126138

127139
return @{
128-
subscriptionID = $subscriptionID
129-
location = $location
130-
modelLocation = $modelLocation
131-
email = $email
140+
subscriptionID = $subscriptionID
141+
environmentName = $environmentName
142+
resourceGroupName = $resourceGroupName
143+
location = $location
144+
modelLocation = $modelLocation
145+
email = $email
132146
}
133147
}
134148

135149
# Prompt for parameters with kind messages
136-
$params = PromptForParameters -subscriptionID $subscriptionID -location $location -modelLocation $modelLocation -email $email
150+
$params = PromptForParameters -subscriptionID $subscriptionID -environmentName $environmentName -resourceGroupName $resourceGroupName -location $location -modelLocation $modelLocation -email $email
137151
# Assign the parameters to variables
138152
$subscriptionID = $params.subscriptionID
153+
$environmentName = $params.environmentName
154+
$resourceGroupName = $params.resourceGroupName
139155
$location = $params.location
140156
$modelLocation = $params.modelLocation
141157
$email = $params.email
142158

143159
function LoginAzure([string]$subscriptionID) {
144-
Write-Host "Log in to Azure.....`r`n" -ForegroundColor Yellow
160+
Write-Host "Log in to Azure.....`r`n" -ForegroundColor Yellow
145161
if ($env:CI -eq "true"){
146162

147163
az login --service-principal `
148-
--username $env:AZURE_CLIENT_ID `
149-
--password $env:AZURE_CLIENT_SECRET `
150-
--tenant $env:AZURE_TENANT_ID
164+
--username $env:AZURE_CLIENT_ID `
165+
--password $env:AZURE_CLIENT_SECRET `
166+
--tenant $env:AZURE_TENANT_ID
151167
write-host "CI deployment mode"
152-
}
168+
}
153169
else{
154-
az login
170+
az login
155171
write-host "manual deployment mode"
156-
}
157-
az account set --subscription $subscriptionID
158-
Write-Host "Switched subscription to '$subscriptionID' `r`n" -ForegroundColor Yellow
172+
}
173+
az account set --subscription $subscriptionID
174+
Write-Host "Switched subscription to '$subscriptionID' `r`n" -ForegroundColor Yellow
159175
}
160176

161177
function DeployAzureResources([string]$location, [string]$modelLocation) {
@@ -169,9 +185,53 @@ function DeployAzureResources([string]$location, [string]$modelLocation) {
169185
# Make deployment name unique by appending random number
170186
$deploymentName = "KM_SA_Deployment$randomNumberPadded"
171187

188+
189+
if (-not $resourceGroupName) {
190+
# Generate a new RG name using your existing logic
191+
192+
# Load abbreviation from abbreviations.json (optional)
193+
$abbrs = Get-Content -Raw -Path "./abbreviations.json" | ConvertFrom-Json
194+
if (-not $abbrs -or -not $abbrs.managementGovernance.resourceGroup) {
195+
Write-Host "abbreviations.json is missing or malformed."
196+
failureBanner
197+
exit 1
198+
}
199+
$rgPrefix = $abbrs.managementGovernance.resourceGroup # e.g., "rg-"
200+
201+
# Constants
202+
$resourceprefix_name = "kmgs"
203+
204+
# Call Bicep to generate resourcePrefix
205+
$resourcePrefix = az deployment sub create `
206+
--location $location `
207+
--name $deploymentName `
208+
--template-file ./resourcePrefix.bicep `
209+
--parameters environmentName=$environmentName location=$location `
210+
--query "properties.outputs.resourcePrefix.value" `
211+
-o tsv
212+
213+
# Final Resource Group Name
214+
$resourceGroupName = "$rgPrefix$resourceprefix_name$resourcePrefix"
215+
216+
Write-Host "Generated Resource Group Name: $resourceGroupName"
217+
218+
Write-Host "No RG provided. Creating new RG: $resourceGroupName" -ForegroundColor Yellow
219+
az group create --name $resourceGroupName --location $location --tags EnvironmentName=$environmentName | Out-Null
220+
}
221+
else {
222+
$exists = az group exists --name $resourceGroupName | ConvertFrom-Json
223+
if (-not $exists) {
224+
Write-Host "Specified RG does not exist. Creating RG: $resourceGroupName" -ForegroundColor Yellow
225+
az group create --name $resourceGroupName --location $location --tags EnvironmentName=$environmentName | Out-Null
226+
}
227+
else {
228+
Write-Host "Using existing RG: $resourceGroupName" -ForegroundColor Green
229+
}
230+
}
231+
172232
# Perform a what-if deployment to preview changes
173233
Write-Host "Evaluating Deployment resource availabilities to preview changes..." -ForegroundColor Yellow
174-
$whatIfResult = az deployment sub what-if --template-file .\main.bicep --location $location --name $deploymentName --parameters modeldatacenter=$modelLocation
234+
$whatIfResult = az deployment group what-if --resource-group $resourceGroupName --template-file .\main.bicep --name $deploymentName --parameters modeldatacenter=$modelLocation location=$location environmentName=$environmentName
175235

176236
if ($LASTEXITCODE -ne 0) {
177237
Write-Host "There might be something wrong with your deployment." -ForegroundColor Red
@@ -181,7 +241,8 @@ function DeployAzureResources([string]$location, [string]$modelLocation) {
181241
}
182242
# Proceed with the actual deployment
183243
Write-Host "Proceeding with Deployment..." -ForegroundColor Yellow
184-
$deploymentResult = az deployment sub create --template-file .\main.bicep --location $location --name $deploymentName --parameters modeldatacenter=$modelLocation
244+
Write-Host "Resource Group Name: $resourceGroupName" -ForegroundColor Yellow
245+
$deploymentResult = az deployment group create --resource-group $resourceGroupName --template-file .\main.bicep --name $deploymentName --parameters modeldatacenter=$modelLocation location=$location environmentName=$environmentName
185246
# Check if deploymentResult is valid
186247
ValidateVariableIsNullOrEmpty -variableValue $deploymentResult -variableName "Deployment Result"
187248
if ($LASTEXITCODE -ne 0) {
@@ -391,7 +452,7 @@ class DeploymentResult {
391452
# Azure App Configuration
392453
$this.AzAppConfigEndpoint = $jsonString.properties.outputs.gs_appconfig_endpoint.value
393454
# App Config Name
394-
$this.AzAppConfigName = "appconfig" + $this.ResourceGroupName
455+
$this.AzAppConfigName = "appconfig-" + $jsonString.properties.outputs.gs_solution_prefix.value
395456

396457
}
397458
}
@@ -438,6 +499,9 @@ try {
438499
Write-Host "Deploying Azure resources in $location region.....`r`n" -ForegroundColor Yellow
439500

440501
$resultJson = DeployAzureResources -location $location -modelLocation $modelLocation
502+
503+
# Ensure ResourceGroupName is set correctly
504+
$deploymentResult.ResourceGroupName = $resourceGroupName
441505
# Map the deployment result to DeploymentResult object
442506
$deploymentResult.MapResult($resultJson)
443507
# Display the deployment result
@@ -530,7 +594,7 @@ try {
530594
'{gpt-4o-modelname}' = $deploymentResult.AzGPT4oModelName
531595
'{azureopenaiembedding-deployment}' = $deploymentResult.AzGPTEmbeddingModelName
532596
'{kernelmemory-endpoint}' = "http://kernelmemory-service"
533-
}
597+
}
534598

535599
## Load and update the AI service configuration template
536600
$aiServiceConfigTemplate = Get-Content -Path .\appconfig\aiservice\appconfig.jsonl -Raw
@@ -550,7 +614,7 @@ try {
550614
$filePath = Join-Path $scriptDirectory ".\appconfig\aiservice\appsettings.dev.jsonl"
551615

552616
## Other variables
553-
$appConfigName = $deploymentResult.AzAppConfigName -replace "rg-", "-"
617+
$appConfigName = $deploymentResult.AzAppConfigName
554618

555619
## Output the file path for verification
556620
#write-host "Using file path: $filePath"
@@ -731,7 +795,7 @@ try {
731795
# Validate if System Assigned Identity is null or empty
732796
ValidateVariableIsNullOrEmpty -variableValue $systemAssignedIdentity -variableName "System-assigned managed identity"
733797

734-
# Validate if ResourceGroupId is null or empty
798+
# Validate if ResourceGroupId is null or empty
735799
ValidateVariableIsNullOrEmpty -variableValue $deploymentResult.ResourceGroupId -variableName "ResourceGroupId"
736800

737801
# Assign the role for aks system assigned managed identity to App Configuration Data Reader role with the scope of Resourcegroup
@@ -848,7 +912,7 @@ try {
848912
Wait-ForCertManager
849913

850914

851-
#======================================================================================================================================================================
915+
#======================================================================================================================================================================
852916
# Validate AzAppConfigEndpoint IsNull Or Empty.
853917
ValidateVariableIsNullOrEmpty -variableValue $deploymentResult.AzAppConfigEndpoint -variableName "Azure App Configuration Endpoint"
854918
# App Deployment after finishing the AKS infrastructure setup
@@ -933,7 +997,7 @@ try {
933997
docker build "../App/frontend-app/." --no-cache -t $acrFrontAppTag
934998
docker push $acrFrontAppTag
935999

936-
#======================================================================================================================================================================
1000+
#======================================================================================================================================================================
9371001

9381002
# 7.2. Deploy ClusterIssuer in Kubernetes for SSL/TLS certificate
9391003
kubectl apply -f "./kubernetes/deploy.certclusterissuer.yaml"
@@ -962,12 +1026,12 @@ try {
9621026
successBanner
9631027

9641028
$messageString = "Please find the deployment details below: `r`n" +
965-
"1. Check Front Web Application with this URL - https://${fqdn} `n`r" +
966-
"2. Check GPT Model's TPM rate in your resource group - $($deploymentResult.ResourceGroupName) `n`r" +
967-
"Please set each value high as much as you can set`n`r" +
968-
"`t- Open AI Resource Name - $($deploymentResult.AzOpenAiServiceName) `n`r" +
969-
"`t- GPT4o Model - $($deploymentResult.AzGPT4oModelName) `n`r" +
970-
"`t- GPT Embedding Model - $($deploymentResult.AzGPTEmbeddingModelName) `n`r"
1029+
"1. Check Front Web Application with this URL - https://${fqdn} `n`r" +
1030+
"2. Check GPT Model's TPM rate in your resource group - $($deploymentResult.ResourceGroupName) `n`r" +
1031+
"Please set each value high as much as you can set`n`r" +
1032+
"`t- Open AI Resource Name - $($deploymentResult.AzOpenAiServiceName) `n`r" +
1033+
"`t- GPT4o Model - $($deploymentResult.AzGPT4oModelName) `n`r" +
1034+
"`t- GPT Embedding Model - $($deploymentResult.AzGPTEmbeddingModelName) `n`r"
9711035
Write-Host $messageString -ForegroundColor Yellow
9721036
Write-Host "Don't forget to control the TPM rate for your GPT and Embedding Model in Azure Open AI Studio Deployments section." -ForegroundColor Red
9731037
Write-Host "After controlling the TPM rate for your GPT and Embedding Model, let's start Data file import process with this command." -ForegroundColor Yellow

0 commit comments

Comments
 (0)