Skip to content

Commit fbe2cb9

Browse files
fix: Model Deployment When Reusing Existing Foundry Projects
2 parents 13aa4cc + a279612 commit fbe2cb9

File tree

4 files changed

+296
-104
lines changed

4 files changed

+296
-104
lines changed

infra/deploy_ai_foundry.bicep

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,19 @@ module assignFoundryRoleToMIExisting 'deploy_foundry_role_assignment.bicep' = if
250250
params: {
251251
roleDefinitionId: aiUser.id
252252
roleAssignmentName: guid(resourceGroup().id, managedIdentityObjectId, aiUser.id, 'foundry')
253-
aiServicesName: !empty(azureExistingAIProjectResourceId) ? existingAIServicesName : aiServicesName
254-
aiProjectName: !empty(azureExistingAIProjectResourceId) ? existingAIProjectName : aiProjectName
253+
aiServicesName: existingAIServicesName
254+
aiProjectName: existingAIProjectName
255255
principalId: managedIdentityObjectId
256-
aiLocation: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.location : solutionLocation
257-
aiKind: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.kind : 'AIServices'
258-
aiSkuName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.skuName : 'S0'
259-
customSubDomainName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.customSubDomainName : aiServicesName
260-
publicNetworkAccess: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.publicNetworkAccess : 'Enabled'
256+
aiLocation: existing_aiServicesModule.outputs.location
257+
aiKind: existing_aiServicesModule.outputs.kind
258+
aiSkuName: existing_aiServicesModule.outputs.skuName
259+
customSubDomainName: existing_aiServicesModule.outputs.customSubDomainName
260+
publicNetworkAccess: existing_aiServicesModule.outputs.publicNetworkAccess
261261
enableSystemAssignedIdentity: true
262-
defaultNetworkAction: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.defaultNetworkAction : 'Allow'
263-
vnetRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.vnetRules : []
264-
ipRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.ipRules : []
262+
defaultNetworkAction: existing_aiServicesModule.outputs.defaultNetworkAction
263+
vnetRules: existing_aiServicesModule.outputs.vnetRules
264+
ipRules: existing_aiServicesModule.outputs.ipRules
265+
aiModelDeployments: aiModelDeployments // Pass the model deployments to the module if model not already deployed
265266
}
266267
}
267268

@@ -279,24 +280,26 @@ resource cognitiveServicesOpenAIUser 'Microsoft.Authorization/roleDefinitions@20
279280
name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'
280281
}
281282

282-
module assignOpenAIRoleToAISearch 'deploy_foundry_role_assignment.bicep' = {
283-
name: 'assignOpenAIRoleToAISearch'
283+
resource assignOpenAIRoleToAISearch 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (empty(azureExistingAIProjectResourceId)) {
284+
name: guid(resourceGroup().id, aiServices.id, cognitiveServicesOpenAIUser.id)
285+
scope: aiServices
286+
properties: {
287+
principalId: aiSearch.identity.principalId
288+
roleDefinitionId: cognitiveServicesOpenAIUser.id
289+
principalType: 'ServicePrincipal'
290+
}
291+
}
292+
293+
module assignOpenAIRoleToAISearchExisting 'deploy_foundry_role_assignment.bicep' = if (!empty(azureExistingAIProjectResourceId)) {
294+
name: 'assignOpenAIRoleToAISearchExisting'
284295
scope: resourceGroup(existingAIServiceSubscription, existingAIServiceResourceGroup)
285296
params: {
286297
roleDefinitionId: cognitiveServicesOpenAIUser.id
287298
roleAssignmentName: guid(resourceGroup().id, aiSearch.id, cognitiveServicesOpenAIUser.id, 'openai-foundry')
288-
aiServicesName: !empty(azureExistingAIProjectResourceId) ? existingAIServicesName : aiServicesName
289-
aiProjectName: !empty(azureExistingAIProjectResourceId) ? existingAIProjectName : aiProjectName
299+
aiServicesName: existingAIServicesName
300+
aiProjectName: existingAIProjectName
290301
principalId: aiSearch.identity.principalId
291-
aiLocation: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.location : solutionLocation
292-
aiKind: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.kind : 'AIServices'
293-
aiSkuName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.skuName : 'S0'
294-
customSubDomainName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.customSubDomainName : aiServicesName
295-
publicNetworkAccess: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.publicNetworkAccess : 'Enabled'
296-
enableSystemAssignedIdentity: true
297-
defaultNetworkAction: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.defaultNetworkAction : 'Allow'
298-
vnetRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.vnetRules : []
299-
ipRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.ipRules : []
302+
enableSystemAssignedIdentity: false
300303
}
301304
}
302305

@@ -318,7 +321,7 @@ resource assignSearchIndexDataReaderToExistingAiProject 'Microsoft.Authorization
318321
name: guid(resourceGroup().id, existingAIProjectName, searchIndexDataReader.id, 'Existing')
319322
scope: aiSearch
320323
properties: {
321-
principalId: assignOpenAIRoleToAISearch.outputs.aiProjectPrincipalId
324+
principalId: assignOpenAIRoleToAISearchExisting.outputs.aiProjectPrincipalId
322325
roleDefinitionId: searchIndexDataReader.id
323326
principalType: 'ServicePrincipal'
324327
}
@@ -342,7 +345,7 @@ resource assignSearchServiceContributorToExistingAiProject 'Microsoft.Authorizat
342345
name: guid(resourceGroup().id, existingAIProjectName, searchServiceContributor.id, 'Existing')
343346
scope: aiSearch
344347
properties: {
345-
principalId: assignOpenAIRoleToAISearch.outputs.aiProjectPrincipalId
348+
principalId: assignOpenAIRoleToAISearchExisting.outputs.aiProjectPrincipalId
346349
roleDefinitionId: searchServiceContributor.id
347350
principalType: 'ServicePrincipal'
348351
}

infra/deploy_backend_docker.bicep

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,7 @@ module assignAiUserRoleToAiProject 'deploy_foundry_role_assignment.bicep' = {
185185
roleAssignmentName: guid(appService.name, aiServices.id, aiUser.id)
186186
aiServicesName: !empty(azureExistingAIProjectResourceId) ? existingAIServicesName : aiServicesName
187187
aiProjectName: !empty(azureExistingAIProjectResourceId) ? split(azureExistingAIProjectResourceId, '/')[10] : ''
188-
aiLocation: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.location : aideploymentsLocation
189-
aiKind: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.kind : 'AIServices'
190-
aiSkuName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.skuName : 'S0'
191-
customSubDomainName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.customSubDomainName : aiServicesName
192-
publicNetworkAccess: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.publicNetworkAccess : 'Enabled'
193-
enableSystemAssignedIdentity: true
194-
defaultNetworkAction: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.defaultNetworkAction : 'Allow'
195-
vnetRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.vnetRules : []
196-
ipRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.ipRules : []
188+
enableSystemAssignedIdentity: false
197189
}
198190
}
199191

infra/deploy_foundry_role_assignment.bicep

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ param aiProjectName string = ''
66
param aiLocation string=''
77
param aiKind string=''
88
param aiSkuName string=''
9-
param enableSystemAssignedIdentity bool = true
9+
param enableSystemAssignedIdentity bool = false
1010
param customSubDomainName string = ''
1111
param publicNetworkAccess string = ''
12-
param defaultNetworkAction string
12+
param defaultNetworkAction string = ''
1313
param vnetRules array = []
1414
param ipRules array = []
15+
param aiModelDeployments array = []
1516

16-
// AI Services with Identity (enabled only if flag is true)
17-
resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = if (enableSystemAssignedIdentity) {
17+
resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = if (!enableSystemAssignedIdentity) {
18+
name: aiServicesName
19+
}
20+
21+
resource aiServicesWithIdentity 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = if (enableSystemAssignedIdentity) {
1822
name: aiServicesName
1923
location: aiLocation
2024
kind: aiKind
@@ -37,10 +41,31 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' =
3741
}
3842
}
3943

40-
// AI Project with Identity (only if name provided and flag is true)
41-
resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = if (!empty(aiProjectName) && enableSystemAssignedIdentity) {
44+
@batchSize(1)
45+
resource aiServicesDeployments 'Microsoft.CognitiveServices/accounts/deployments@2025-04-01-preview' = [for aiModeldeployment in aiModelDeployments: if (!empty(aiModelDeployments)) {
46+
parent: aiServicesWithIdentity
47+
name: aiModeldeployment.name
48+
properties: {
49+
model: {
50+
format: 'OpenAI'
51+
name: aiModeldeployment.model
52+
}
53+
raiPolicyName: aiModeldeployment.raiPolicyName
54+
}
55+
sku:{
56+
name: aiModeldeployment.sku.name
57+
capacity: aiModeldeployment.sku.capacity
58+
}
59+
}]
60+
61+
resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' existing = if (!empty(aiProjectName) && !enableSystemAssignedIdentity) {
4262
name: aiProjectName
4363
parent: aiServices
64+
}
65+
66+
resource aiProjectWithIdentity 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = if (!empty(aiProjectName) && enableSystemAssignedIdentity) {
67+
name: aiProjectName
68+
parent: aiServicesWithIdentity
4469
location: aiLocation
4570
identity: {
4671
type: 'SystemAssigned'
@@ -49,7 +74,16 @@ resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-pre
4974
}
5075

5176
// Role Assignment to AI Services
52-
resource roleAssignmentToFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
77+
resource roleAssignmentToFoundryExisting 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (enableSystemAssignedIdentity) {
78+
name: roleAssignmentName
79+
scope: aiServicesWithIdentity
80+
properties: {
81+
roleDefinitionId: roleDefinitionId
82+
principalId: principalId
83+
}
84+
}
85+
86+
resource roleAssignmentToFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!enableSystemAssignedIdentity) {
5387
name: roleAssignmentName
5488
scope: aiServices
5589
properties: {
@@ -58,6 +92,14 @@ resource roleAssignmentToFoundry 'Microsoft.Authorization/roleAssignments@2022-0
5892
}
5993
}
6094

61-
// Outputs
62-
output aiServicesPrincipalId string = aiServices.identity.principalId
63-
output aiProjectPrincipalId string = !empty(aiProjectName) ? aiProject.identity.principalId : ''
95+
// ========== Outputs ==========
96+
97+
output aiServicesPrincipalId string = enableSystemAssignedIdentity
98+
? aiServicesWithIdentity.identity.principalId
99+
: aiServices.identity.principalId
100+
101+
output aiProjectPrincipalId string = !empty(aiProjectName)
102+
? (enableSystemAssignedIdentity
103+
? aiProjectWithIdentity.identity.principalId
104+
: aiProject.identity.principalId)
105+
: ''

0 commit comments

Comments
 (0)