Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions azure_custom.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

# This file contains a developer‑focused Azure Developer CLI configuration. It
# extends the default template by defining three services (backend API,
# processor and frontend) and instructs azd to build container images from
# your local source code. All three services are packaged as container apps
# using the Dockerfiles located in their respective project directories.
# After deployment a post‑deploy hook prints the endpoints of the deployed
# container apps.

name: container-migration-solution-accelerator
metadata:
template: container-migration-solution-accelerator@1.0

requiredVersions:
# Require a recent version of azd that supports the packaging
# functionality used here. Versions less than 1.17.1 had a bug in
# remoteBuild.
azd: ">=1.18.2"

infra:
parameters:
backendImageName: ${SERVICE_BACKEND_IMAGE_NAME}
processorImageName: ${SERVICE_PROCESSOR_IMAGE_NAME}
frontendImageName: ${SERVICE_FRONTEND_IMAGE_NAME}

services:
# Backend API service. This is a Python FastAPI application defined in
# src/backend-api. The azd packaging stage builds a Docker image using
# the Dockerfile in that directory. The image name 'backend-api' is
# combined with the automatically created Azure Container Registry login
# server to form the final image reference.
backend:
project: ./src/backend-api
language: py
host: containerapp
docker:
image: backend-api
remoteBuild: true

# Processor service. This service reads messages from storage queues and
# orchestrates long‑running migrations. It is also packaged as a
# container and deployed to a container app environment. The Dockerfile
# in the src/processor directory defines how the image is built.
processor:
project: ./src/processor
language: py
host: containerapp
docker:
image: processor
remoteBuild: true

# Frontend service. The frontend consists of a React single‑page
# application and a lightweight Python server that serves the compiled
# assets. azd packages the frontend by building a Docker image using
# the Dockerfile in the src/frontend directory and deploys it to a
# container app.
frontend:
project: ./src/frontend
language: py
host: containerapp
docker:
image: frontend
remoteBuild: true

hooks:
# After deployment prints the names and endpoints of the deployed
# container apps. This reproduces the behaviour of the default
# configuration so that developers can easily discover their services.
postdeploy:
posix:
shell: sh
run: |
echo "-----"
echo "🧭 Frontend Container App Details:"
echo "✅ Name: $CONTAINER_FRONTEND_APP_NAME"
echo "🌐 Endpoint: https://$CONTAINER_FRONTEND_APP_FQDN"
echo "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$CONTAINER_FRONTEND_APP_NAME"
echo "-----"
echo "🧭 Backend API Container App Details:"
echo "✅ Name: $CONTAINER_API_APP_NAME"
echo "🌐 Endpoint: https://$CONTAINER_API_APP_FQDN"
echo "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$CONTAINER_API_APP_NAME"
echo "-----"
echo "🧭 Processor Container App Details:"
echo "✅ Name: $SERVICE_PROCESSOR_NAME"
echo "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$SERVICE_PROCESSOR_NAME"
echo "-----"
interactive: true
windows:
shell: pwsh
run: |
Write-Host "-----"
Write-Host "🧭 Frontend Container App Details:"
Write-Host "✅ Name: $env:CONTAINER_FRONTEND_APP_NAME"
Write-Host "🌐 Endpoint: https://$env:CONTAINER_FRONTEND_APP_FQDN"
Write-Host "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$env:AZURE_SUBSCRIPTION_ID/resourceGroups/$env:AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$env:CONTAINER_FRONTEND_APP_NAME" -ForegroundColor Cyan
Write-Host "-----"
Write-Host "🧭 Backend API Container App Details:"
Write-Host "✅ Name: $env:CONTAINER_API_APP_NAME"
Write-Host "🌐 Endpoint: https://$env:CONTAINER_API_APP_FQDN"
Write-Host "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$env:AZURE_SUBSCRIPTION_ID/resourceGroups/$env:AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$env:CONTAINER_API_APP_NAME" -ForegroundColor Cyan
Write-Host "-----"
Write-Host "🧭 Processor Container App Details:"
Write-Host "✅ Name: $env:SERVICE_PROCESSOR_NAME"
Write-Host "🔗 Portal URL: https://portal.azure.com/#resource/subscriptions/$env:AZURE_SUBSCRIPTION_ID/resourceGroups/$env:AZURE_RESOURCE_GROUP/providers/Microsoft.App/containerApps/$env:SERVICE_PROCESSOR_NAME" -ForegroundColor Cyan
Write-Host "-----"
interactive: true
9 changes: 8 additions & 1 deletion docs/DeploymentGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,11 @@ If you encounter any issues during the deployment process, please refer [trouble

## Running the application

To help you get started, here's the [Sample Workflow](./SampleWorkflow.md) you can follow to try it out.
To help you get started, here's the [Sample Workflow](../docs/SampleWorkflow.md) you can follow to try it out.

### Deploy Your local changes
To Deploy your local changes rename the below files.

Rename `azure.yaml` to `azure_custom2.yaml` and `azure_custom.yaml` to `azure.yaml`.
Go to `infra` directory
Rename `main.bicep` to `main_custom2.bicep` and `main_custom.bicep` to `main.bicep`. Continue with the [deploying steps](#deploying-with-azd).
65 changes: 60 additions & 5 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ param azureAiServiceLocation string
'westus3'
])
@description('Required. Azure region for AI model deployment. Should match azureAiServiceLocation for optimal performance.')
#disable-next-line no-unused-params
param aiDeploymentLocation string = azureAiServiceLocation

@description('Optional. The host (excluding https://) of an existing container registry. This is the `loginServer` when using Azure Container Registry.')
Expand Down Expand Up @@ -103,6 +104,11 @@ param createdBy string = contains(deployer(), 'userPrincipalName')
? split(deployer().userPrincipalName, '@')[0]
: deployer().objectId

// Get the current deployer's information for local debugging permissions
var deployerInfo = deployer()
var deployingUserPrincipalId = deployerInfo.objectId
var deployingUserType = !empty(deployerInfo.userPrincipalName) ? 'User' : 'ServicePrincipal'

@description('Optional. Resource ID of an existing Foundry project')
param existingFoundryProjectResourceId string = ''

Expand Down Expand Up @@ -469,6 +475,17 @@ module storageAccount 'br/public:avm/res/storage/storage-account:0.20.0' = {
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
}
// Add deployer permissions
{
roleDefinitionIdOrName: 'Storage Blob Data Contributor'
principalId: deployingUserPrincipalId
principalType: deployingUserType
}
{
roleDefinitionIdOrName: 'Storage Queue Data Contributor'
principalId: deployingUserPrincipalId
principalType: deployingUserType
}
]
// WAF aligned networking
networkAcls: {
Expand Down Expand Up @@ -655,6 +672,12 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = {
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: 'DocumentDB Account Contributor'
}
// Add deployer for local debugging
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'DocumentDB Account Contributor'
}
]
// Create custom data plane role definition and assignment
dataPlaneRoleDefinitions: [
Expand All @@ -669,6 +692,8 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = {
]
assignments: [
{ principalId: appIdentity.outputs.principalId }
// ADD THIS for local debugging support:
{ principalId: deployingUserPrincipalId }
]
}
]
Expand Down Expand Up @@ -699,7 +724,7 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b
name: take('module.ai-services-model-deployments.${existingAiFoundryAiServices.name}', 64)
scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName)
params: {
name: existingAiFoundryAiServices.name
name: aiFoundryAiServicesResourceName // Fix: use variable instead of resource reference
deployments: [
{
name: aiModelDeploymentName
Expand All @@ -715,6 +740,7 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b
}
]
roleAssignments: [
// Service Principal permissions
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
Expand All @@ -723,12 +749,23 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer
roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee'
}
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
}
// Deployer permissions
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
}
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services User'
}
]
}
Expand All @@ -746,6 +783,7 @@ module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.4.0' = if(!useExistingAiF
accountName:aiFoundryAiServicesResourceName
allowProjectManagement: true
roleAssignments: [
// Service Principal permissions
{
principalId: appIdentity.outputs.principalId
principalType: 'ServicePrincipal'
Expand All @@ -761,6 +799,17 @@ module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.4.0' = if(!useExistingAiF
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User
}
// Deployer permissions for local debugging
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
}
{
principalId: deployingUserPrincipalId
principalType: deployingUserType
roleDefinitionIdOrName: 'Cognitive Services User'
}
]
// Remove networking configuration to avoid AML workspace creation issues
networking: enablePrivateNetworking? {
Expand Down Expand Up @@ -791,7 +840,7 @@ module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.4.0' = if(!useExistingAiF
}
}

var aiServicesName = useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundry.outputs.aiServicesName
var aiServicesName = useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundryAiServicesResourceName
module appConfiguration 'br/public:avm/res/app-configuration/configuration-store:0.9.1' = {
name: take('avm.res.app-config.store.${solutionSuffix}', 64)
params: {
Expand Down Expand Up @@ -898,6 +947,8 @@ module appConfiguration 'br/public:avm/res/app-configuration/configuration-store
sku: 'Standard'
publicNetworkAccess: 'Enabled'
}
// Add explicit dependency
dependsOn: useExistingAiFoundryAiProject ? [] : [aiFoundry]
}

module avmAppConfigUpdated 'br/public:avm/res/app-configuration/configuration-store:0.6.3' = if (enablePrivateNetworking) {
Expand Down Expand Up @@ -971,7 +1022,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
platformReservedDnsIP: '172.17.17.17'
zoneRedundant: (enablePrivateNetworking) ? true : false // Enable zone redundancy if private networking is enabled
infrastructureSubnetResourceId: (enablePrivateNetworking)
? virtualNetwork.outputs.containersSubnetResourceId // Use the container app subnet
? virtualNetwork!.outputs.containersSubnetResourceId // Use the container app subnet
: null // Use the container app subnet
}
}
Expand Down Expand Up @@ -1210,3 +1261,7 @@ output AZURE_SUBSCRIPTION_ID string = subscription().subscriptionId

@description('The Azure resource group name.')
output AZURE_RESOURCE_GROUP string = resourceGroup().name

// Log deployer information for debugging
output deployerObjectId string = deployingUserPrincipalId
output deployerType string = deployingUserType
Loading